【opencv学习之四十】角点检测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abcvincent/article/details/79343819

图像的角点通常被定义为两条边的交点,或者灰度值急剧变化的点;角点作为图像上的特征点,在很多图像识别等应用具有很好特征识别性;openCV实现的角点算法主要有:cornerHarris(),goodFeaturesToTrack(Shi-Tomasi)和cornerSubPix();

其中cornerHarris()角点检测是一种直接基于灰度值的角点提取算法,其原理是通过对每一个像素(x,y)在blockSize*blockSize邻域内计算2*2梯度协方差矩阵M(x,y),式子如下:


这样就可以找到局部最大值,也就是角点;

goodFeaturesToTrack(Shi-Tomasi)算法:是cornerHarris()的改进,对特征值中较小的值大于最小阈值则可以得到强角点;

cornerSubPix():这个是亚像素级别的角点特征,精度比较高,可以提供浮点级别的精度,而前面两种方法只能提供整数级,多用于相机标定,三维重构等方面;

下面是简单实例:

void imgCornerAll()//图像角点检测
{
    Mat img = imread("D:/ImageTest/pic1.png");
    Mat img_gray;//存储灰度图
    imshow("img",img);
    cvtColor(img, img_gray, CV_BGR2GRAY);

    /////// 1、cornerHarris
    Mat corner;//存放Harris角点检测结果, 类型为CV_32FC1, 大小和原图一样
    cornerHarris(img_gray, corner, 3, 3, 0.04);    //corner是32位浮点型,值都很小
    Mat dst;//存放对cornerImg阈值化筛选后的结果
    threshold(corner,dst,0.08,255,CV_THRESH_BINARY);//阈值为什么选择小数还不是很清楚,可能corner是32位浮点型有关
    imshow("dst", dst);
    //遍历标记的角点并用圆画出
    for (int i = 0;i<dst.rows;i++)
    {
        for (int j = 0;j<dst.cols;j++)
        {
            if (dst.at<float>(i, j) == 255)
            {
                circle(img, Point(j, i), 10, Scalar(255,0,0),2);
            }
        }
    }
    imshow("cornerHarris", img);

    //////2、goodFeaturesToTrack(Shi-Tomasi)
    vector<Point2f> corners;//记录检测到的角点的输出向量
    goodFeaturesToTrack(img_gray, corners, 100, 0.01, 10);
    cout << corners.size() << endl;
    cout << corners << endl;
    for (int i = 0; i < corners.size(); i++)//遍历存放检测到角点的向量
    {
        circle(img,corners[i],5,Scalar(0,255,0),2);//画出角点
    }
    imshow("Shi-Tomasi", img);

    //////3、cornerSubPix()
    TermCriteria criteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001); //TermCriteria类型的对象, 表示求角点的迭代过程的终止条件
    //亚像素角点检测将前面的角点检测方法得到的像素级坐标,变为更高的精度比如亚像素(浮点坐标)精度
    //所以对于亚像素角点检测,corners既是输入也是输出
    cornerSubPix(img_gray,corners,Size(5,5),Size(-1,-1),criteria);
    cout << corners.size() << endl;
    cout << corners << endl;
    for (int i = 0; i < corners.size(); i++)//遍历存放检测到角点的向量
    {
        circle(img, corners[i], 3, Scalar(0, 0, 255), 2);
    }
    imshow("cornerSubPix", img);
    waitKey(0);
}

效果:



猜你喜欢

转载自blog.csdn.net/abcvincent/article/details/79343819