OpenCV角点检测原理与Harris算法实现
本文详细介绍OpenCV中角点检测的基本概念与Harris算法的实现流程。从角点的定义出发,解析基于灰度图像的Harris检测原理,包括梯度计算、矩阵构造及角点响应值评估。随后展示完整的Python代码实现,涵盖角点提取、阈值筛选及可视化标记步骤,为图像特征匹配提供基础。
Harris 角点检测算法
1. 角点
角点是指图像中在水平方向和垂直方向上灰度变化均显著的像素点。
角点检测算法的基本思想:
该方法通过一个固定大小的窗口在图像上进行任意方向的滑动,对比滑动前后窗口内的像素灰度变化。若在任意滑动方向上均观察到显著的灰度变化,则判定窗口内存在角点。
当前角点检测算法尚未完全成熟,许多方法依赖大量训练集和冗余数据以抑制错误特征的生成。评价角点检测算法的关键指标包括:对多幅图像中相同或相似特征的检测能力,以及应对光照变化和图像旋转等干扰因素的鲁棒性。
关于角点的数学描述通常有以下几种视角:
- 一阶导数(即灰度梯度)局部最大值所对应的像素点;
- 两条或多条边缘线的交点;
- 图像中梯度幅值和梯度方向变化速率极高的点;
- 角点处的一阶导数达到最大,二阶导数为零,指示物体边缘发生不连续变化的方向。
三类角点检测算法:
- 基于二值图像的角点检测;
- 基于轮廓曲线的角点检测;
- 基于灰度图像的角点检测:包括基于梯度、基于模板以及模板与梯度组合三类方法。常见的基于模板的角点检测算法有:Kitchen-Rosenfeld角点检测算法,Harris角点检测算法,KLT角点检测算法及SUSAN角点检测算法。基于模板的方法主要考察像素邻域内灰度的变化,即亮度的变化情况。
2. 流程
(1)找出角点 利用高斯算子计算像素在水平方向和垂直方向的梯度dx, dy,对梯度的平方dxdx, dydy及交叉项dxdy进行滤波得到Wxx, Wxy, Wyy,进而计算(Wxx*Wyy - Wxy**2)/(Wxx + Wyy)作为候选角点的响应值。
(2)筛选角点 设定阈值筛选角点,获取角点坐标,根据坐标确定角点所在的行,并在角点周围区域内进行非极大值抑制,删除邻近的其他角点,最终得到结果result。
(3)标记角点
3. 实现
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
## 1.找出角点
### 1.1 步骤:img求导 --> imx ,imy 滤波-->Wxx ,Wxy,Wyy --> (Wxx*Wyy - Wxy**2)/(Wxx + Wyy)
def compute_harris_response(img,sigma=3):
# 求梯度
imgx,imgy = np.zeros(img.shape),np.zeros(img.shape)
filters.gaussian_filter(img,(sigma,sigma),(0,1),imgx)
filters.gaussian_filter(img,(sigma,sigma),(1,0),imgy) # [260,263]
# 对梯度进行高斯滤波
wxx = filters.gaussian_filter(imgx**2,sigma)
wyy = filters.gaussian_filter(imgy**2,sigma) # [260,263]
wxy = filters.gaussian_filter(imgx*imgy,sigma)# [260,263]
## 求行列式和迹
wdet = wxx*wyy -wxy**2
wtr = wxx + wyy
return wdet/wtr
## 2 筛选角点
### 2.1 步骤:根据阈值筛选角点--> 取得角点的坐标 -->根据角点坐标得到角点所在的行 -->
# --> 在角点周围,删除掉其他角点
def get_harris_points(harri,min_dist=4,threshold=0.1):
corner_thre = harri.max()*threshold # 角点阈值
mask = (harri > corner_thre)*1 # 取出大于阈值的点为候选角点
cords = np.array(mask.nonzero()).T # 取候选角点的坐标
values = [harri[i[0],i[1]] for i in cords] # 候选角点的值
cls = np.argsort(values) # 对角点排序得到排序后的序列号,序列号也是候选角点所在的行
loc = np.zeros(harri.shape) # 划出可行性区域
loc[min_dist:-min_dist,min_dist:-min_dist] = 1
re_cords = []
for i in cls: # 筛选角点。先取出角点,角点周围的点不再取出
if loc[cords[i,0],cords[i,1]] == 1 :
re_cords.append(cords[i])
loc[cords[i,0]-min_dist:cords[i,0]+min_dist,cords[i,1]-min_dist:cords[i,1]+min_dist]=0
return re_cords
def plot_harri(img,cords):
plt.figure()
plt.gray()
plt.imshow(img)
plt.plot([i[1] for i in cords],[i[0] for i in cords],'.')
plt.axis('off')
plt.show()
## 3 测试
if __name__ == '__main__':
img = np.array(Image.open('luna.png').convert('L'))
harri = compute_harris_response(img)
re_cords = get_harris_points(harri)
plot_harri(img,re_cords)到此这篇关于OpenCV角点检测的文章就介绍到这了,更多相关OpenCV角点检测内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













