Harris角点检测的思想是通过图像的局部小窗口观察图像,角点的特征是窗口沿任意方向移动都会导致灰度发生明显变化,如下图所示:
将上述思想转换为数学的形式,即将局部窗口向各个方向移动(u,v)并计算所有灰度差异的总和,表达式如下:
其中I(x, y)是局部窗口的图像灰度,I(x+u, y+v)是平移后的图像灰度,w(x, y)是窗口函数,可以是矩形窗口,也可以是对每个像素赋予不同权重的高斯窗口,如下图所示:
角点检测中使E(u, v)的值最大,利用一阶泰勒展开有:
其中Ix和Iy是沿x和y方向的导数,可用sobel算子计算。
推导如下:
M矩阵决定了E(u, v)的取值,下面我们利用M来求角点,M是Ix和Iy的二次项函数,可以表示成椭圆的形状,椭圆的长短半轴由M的特征值 λ 1 \lambda_1 λ1和 λ 2 \lambda_2 λ2决定,方向由特征矢量决定,如下图所示:
椭圆函数特征值与图像中的角点、直线(边缘)和平面之间的关系如下图所示:
从上图可以看出,共分为三种情况:
Harris给出的角点计算方法并不需要计算具体的特征值,而是计算一个角点响应值R来判断角点。R的计算公式为:
式中,detM为矩阵M的行列式;traceM是矩阵M的迹;α为常数,取值范围为0.04~0.06.事实上,特征是隐含在detM和traceM中,因为:
那么我们这样去判断是否是角点:如下图所示:
在OpenCV中实现Harris检测使用的API是:
dst=cv.cornerHarris(src, blockSize, ksize, k)
参数
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 1 读取图像,并转换成灰度图像
img = cv.imread('./image/chessboard.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 2 角点检测
# 2.1 输入图像必须是 float32
gray = np.float32(gray)
# 2.2 最后一个参数在 0.04 到 0.05 之间
dst = cv.cornerHarris(gray,2,3,0.04)
# 3 设置阈值,将角点绘制出来,阈值根据图像进行选择
img[dst>0.001*dst.max()] = [0,0,255]
# 4 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('Harris角点检测')
plt.xticks([]), plt.yticks([])
plt.show()
优点:
- 旋转不变性,椭圆转过一定角度但是其形状保持不变(特征值保持不变)
- 对于图像灰度的仿射变换具有部分的不变性,由于仅仅使用了图像的一阶导数,对于图像灰度平移变换不变;对于图像灰度尺度变化不变。
缺点:
- 对尺度很敏感,不具备几何尺度不变性
- 提取的角点是像素级的。
Shi-Tomasi算法是对Harris角点检测算法的改进,一般会比Harris算法得到更好的角点。Harris算法的角点响应函数是将矩阵M的行列式值与M的迹相减,利用差值判断是否为角点。后来Shi和Tomasi提出改进的方法是:若矩阵M的两个特征值中较小的一个大于阈值,则认为他是角点,即:
如下图所示:
从这幅图中,可以看出只有 λ 1 \lambda_1 λ1和 λ 2 \lambda_2 λ2都大于最小值时,才被认为是角点。
在OpenCV中实现Shi-Tomasi角点检测使用API:
corners = cv2.goodFeaturesToTrack ( image, maxcorners, qualityLevel, minDistance )
参数
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 读取图像
img = cv.imread('./image/tv.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 2 角点检测
corners = cv.goodFeaturesToTrack(gray,1000,0.01,10)
# 3 绘制角点
for i in corners:
x,y = i.ravel()
cv.circle(img,(x,y),2,(0,0,255),-1)
# 4 图像展示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('shi-tomasi角点检测')
plt.xticks([]), plt.yticks([])
plt.show()
得到处理过的图像如下所示:
思想:通过图像的局部小窗口观察图像,角点的特征是窗口沿任意方向移动都会导致图像灰度明显变化。
API:
cv2.cornerHarris()
对Harris算法的改进,能更好的检测角点。
API:
cv2.goodFeatureToTrack()