哈里斯角检测

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()

参考:

opencv文档

posted @ 2022-06-17 22:47  东东咚咚东  阅读(110)  评论(0编辑  收藏  举报