OpenCV-识别图中目标点和方向

背景:

这个问题也是在CV群里,有位同志问的,我给她解决了,就写个博客记录下!这个图形如下所示,要定位到图中的6个黑点和判断他们的方向,如图的方向为指向左边!

分析

1、定位到目标点(图中那6个)

怎么定位到图中的6个小黑点捏?我的方法是二值化后寻找图形的外部连通域,很显然利用此方法后可以很容易的索引到图中的索引白色圆,然后怎么确定小黑点位置捏?我是利用这些连通域求出所有轮廓的重心,这里是圆形的也就是他们的圆心,然后判断圆心坐标位置的像素值是否为黑色像素(0),如果是的话那么该重心就是目标点。(我还想到另一种方法:利用霍夫变换检测图中的所有圆形,我们就可以很容易的得到半径,判断方法和上面一样,判断圆心的像素即可),但是我为嘛采用连通域然后求重心勒,因为,用霍夫变换求圆心的话有局限性,这个圆要比较大一点才好检测,而且如果变成正方形咋办了,而利用连通域和重心的话,只要是对称的图像都可以检测到他们的重心!

2、利用这6个点判断他们的方向

经过步骤一,我们可以获取到图中的6个目标点(他们的坐标),接下来我就利用这6个点的坐标求出他们的方向的,仔细观察规律,不难发现,对图中的6个点的X轴坐标求和,在求均值得到xAve。然后用每一个点的X坐标与这个均值做差的绝对值|Xi - xAve|得到的结果的最大值就是水平方向的箭头的位置,如上图,做6次差值后,其中差值绝对值最大的会是最左边的哪一个点,也就是箭头的位置点,所以可以判断出方向了!(我还想到了另一种方法,就是利用莫办匹配法,事先先去提取上下左右方向的模板,然后我们获得目标模板后与事先提取的模板进行匹配,就可以判断方向了,系不系啊!)。

实现:

代码如下:

void findDirect(){
    // to gray
    cv::cvtColor(cellImage,result1d,CV_BGR2GRAY);
    cv::cvtColor(cellImage,result3d,CV_BGR2GRAY);
    // threshold
    cv::threshold(result1d,result1d,128,255,cv::THRESH_BINARY);
    cv::threshold(result3d,result3d,128,255,cv::THRESH_BINARY);
    // find contours and got contours sum
    cv::findContours(result1d,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
    int ctsSum = contours.size();

    int ptn_cnt = 0;
    int px[6];
    int py[6];

    for(int i=0;i<ctsSum;i++){
        //cv::drawContours(cellImage,contours,i,cv::Scalar(255,0,0),1);

        // 计算重心
        cv::Moments mom = cv::moments(cv::Mat(contours[i]));
        uchar *data = result3d.ptr<uchar>(static_cast<int >(mom.m01/mom.m00));
        int x = static_cast<int >(mom.m10/mom.m00);
        if(data[x] == 0){
            cv::circle(cellImage,cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),3,cv::Scalar(0,0,255),2);

            px[ptn_cnt] = mom.m10/mom.m00;
            py[ptn_cnt] = mom.m01/mom.m00;

            ptn_cnt++;
        }
    }
    qDebug() << "ptn cnt = " << ptn_cnt;

    int xsum = 0;
    int ysum = 0;
    for(int i=0;i<ptn_cnt;i++){
        xsum += px[i];
        ysum += py[i];
    }
    int xave = xsum/ptn_cnt;
    int yave = ysum/ptn_cnt;


    int dismax = fabs(xave - px[0]);
    int obj_index = 0;
    for(int i=1;i<ptn_cnt;i++){

        if(fabs(xave - px[i]) > dismax){
            dismax = fabs(xave - px[i]);
            obj_index = i;
        }
    }
    cv::circle(cellImage,cv::Point(px[obj_index],py[obj_index]),3,cv::Scalar(255,0,0),2);

    // show marked in cellImage
    cv2QtImageAndShow(cellImage);
}
效果图如下:


如上图,图中绿色位置是索引到的全部连通域,红色位置是所以得6个黑点(那个蓝色的圆心也是红色的,被后面的代码再次用蓝色覆盖而已),而蓝色的位置显然就是方向咯!

OK!3KS 2 SEE!!!

oh!对了,也许你会问图像怎么变大了,那是因为我放大了!!!

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值