美文网首页
OpenCV-Python教程:34.Harris角点检测

OpenCV-Python教程:34.Harris角点检测

作者: xxxss | 来源:发表于2017-06-20 11:35 被阅读1515次

    理论

    我们知道角点是图像里在各个方向变化最大的区域。早起尝试找到这些角的是Chris Harris和Mike Stephens,在他们的论文A Combined Corner and Edge Detector里,所以现在叫Harris角点检测。他把这个简单想法用数学形式表达,基本上就是对(u,v)在各个方向移动找强度的变化。表达式如下:

    Window function是一个矩形窗口或者高斯窗口,给其下的像素权重。

    我们应该最大化这个函数E(u, v)来检测角点。这表示,我们应该放大第二个条件,应用泰勒展开上面的等式,然后经过数学步骤,我们可以得到最终的等式:

    其中


    这里,Ix 和Iy 是图像在x和y方向分别的导数(可以用cv2.Sobel()很容易得到)

    然后是主要部分,在这个之后,它们创建了一个分数,基本上市一个等式,来决定一个窗口是否能包含一个角。


    其中:

    ·det(M) = λ1λ2

    ·trace(M) = λ1 + λ2

    ·λ1和λ2是M的特征值

    所以这些特征值决定了区域是否是角,边缘或者无反差的。

    ·当|R|小的时候,也就是λ1和λ2小的时候,区域是无反差的

    ·当R < 0, 页就是λ1 >> λ2时,区域是边缘

    ·当R很大,是λ1和λ2很大并且λ1 ~ λ2时区域是角

    可以用图片来表示:


    所以Harris角点检测是一个有这些分数的灰度图,用一个合适的阈值你就可以得到图像的角。

    OpenCV里的Harris角点检测

    OpenCV有一个函数cv2.cornerHarris()来做这个,参数是:

    img - 输入图像,应该是灰度图和float32类型

    blockSize - 做角点检测的近邻的大小

    ksize - Sobel导数的孔径参数

    k - Harris检测等式里的自由参数

    import cv2
    import numpy as np

    filename = 'chessboard.jpg'
    img = cv2.imread(filename)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    gray = np.float32(gray)
    dst = cv2.cornerHarris(gray,2,3,0.04)

    #result is dilated for marking the corners, not important
    dst = cv2.dilate(dst,None)

    # Threshold for an optimal value, it may vary depending on the image.
    img[dst>0.01*dst.max()]=[0,0,255]

    cv2.imshow('dst',img)
    if cv2.waitKey(0) & 0xff == 27:
        cv2.destroyAllWindows()

    有时候,你可能需要更准确的找到角,OpenCV用函数cv2.cornerSubPix() 通过亚像素精度精炼角点检测。下面是例子,我们需要先找到harris角,然后我们把这些角的质心传进去(可能有一堆点在角上,我们找他们的质心)来精炼他们。Harris角点用红色像素标记,精炼的角点用绿色像素标记,对这个函数,我们要定义什么时候停止迭代。我们也需要定义来搜索角点的近邻的大小。

    import cv2
    import numpy as np

    filename = 'chessboard2.jpg'
    img = cv2.imread(filename)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # find Harris corners
    gray = np.float32(gray)
    dst = cv2.cornerHarris(gray,2,3,0.04)
    dst = cv2.dilate(dst,None)
    ret, dst = cv2.threshold(dst,0.01*dst.max(),255,0)
    dst = np.uint8(dst)

    # find centroids
    ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)

    # define the criteria to stop and refine the corners
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
    corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)

    # Now draw them
    res = np.hstack((centroids,corners))
    res = np.int0(res)
    img[res[:,1],res[:,0]]=[0,0,255]
    img[res[:,3],res[:,2]] = [0,255,0]

    cv2.imwrite('subpixel5.png',img)

    下面是结果,一些重要的位置放大显示了:


    END

    相关文章

      网友评论

          本文标题:OpenCV-Python教程:34.Harris角点检测

          本文链接:https://www.haomeiwen.com/subject/nlthsttx.html