哈里斯角检测
1.角
从名称来看,哈里斯角检测将会标记出图片中的角,那么计算机怎么在一堆像素值中辨别出角呢?
看看上面这张图吧,聚焦一小块区域,并对区域进行移动。
- 若上下左右移动时区域内的像素都产生变化,则为角。
- 若对特定方向移动时像素值才产生变化,则为边缘。如图②左右移动不变,上下移动发生变化。
- 若向所有方向移动区域都不发生变化则为物体内部。
顺带一提,角、边缘、物体内部即是物体的特征。
2.opencv函数
1.哈里斯角检测函数:dst = cv.cornerHarris( src, blockSize, ksize, k[, dst[, borderType]] )
了解各参数前记一下下面计算公式,可以找到图像中的角点作为该响应图的局部最大值:
- src:源图像。
- blockSize:邻域大小,通过邻域计算其上的2×2梯度协方差矩阵M。
- ksize:Sobel运算符的光圈参数,使用的Sobel算子计算导数。
- k:哈里斯检测器自由参数。见上面的公式。
- dst:结果图像。
- borderType:边界填充类型,之前讲过。
示例:
import numpy as np
import cv2 as cv
img = cv.imread('motianlun_new.jpg')
img_copy = img.copy()
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 哈里斯角检测
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
# 膨胀函数,使点显示更明显
dst = cv.dilate(dst,None)
# 最佳值的阈值,因图像而异。
img_copy[dst > 0.01*dst.max()]=[0,0,255]
cv.namedWindow('src', 0)
cv.imshow('src',img)
cv.namedWindow('dst', 0)
cv.imshow('dst',img_copy)
if cv.waitKey(0) & 0xff == 27:
cv.destroyAllWindows()
成果:
2.corners = cv.cornerSubPix( image, corners, winSize, zeroZone, criteria )
此函数在哈里斯角的基础上迭代细化角点位置。
import numpy as np
import cv2 as cv
img = cv.imread('motianlun_new.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 寻找哈里斯角
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
dst = cv.dilate(dst,None)
ret, dst = cv.threshold(dst,0.01*dst.max(),255,0)
dst = np.uint8(dst)
# 寻找质心
ret, labels, stats, centroids = cv.connectedComponentsWithStats(dst)
# 定义停止和完善拐角的条件
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
# 绘制
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]
img = cv.dilate(img,None)
cv.namedWindow('src', 0)
cv.imshow('src',img)
if cv.waitKey(0) & 0xff == 27:
cv.destroyAllWindows()