特征检测是计算机视觉和图像处理中的一个概念。它是指使用计算机提取图像信息,决定每个图像的点是否属于一个图像特征。特征检测的结果是把图像上的点分为不同的子集,这些子集往往属于孤立的点、连续的曲线或者连续的区域
特征检测包括边缘检测、角检测、区域检测和脊检测
特征检测应用场景:
因此:
A、B(蓝色框)不是特征 ——> 不是唯一的
C、D(黑色框)不是特指 ——> 不是唯一的
E、F(红色框)是特征 ——> 唯一、可追踪、能比较
我们发现:
图像特征就是值有意义的区域,具有独特性、易于识别性
在图像特征中最重要的就是角点,哪些是角点呢?
三幅图对应三种情况:
图一在平坦位置向四周移动,灰度值变化都不大;图二上下移动灰度值变化不大,左右移动灰度值变化剧烈;图三无论朝着哪个方向移动,灰度值都剧烈变化
图像I(x,y)
,当在点(x,y)
处平移(△x,△y)
后的自相似性:
自相似性:移动后与原来点相似度有多少,其实就是差异;具体是上一个位置框的像素值 - 下一个框的像素值
加平方是因为我们只在变化量的大小,而不在乎灰度值变量还是变暗
我们的框框相当于一个卷积核,而卷积核对应每一个位置的像素都有一个权重,因此w(u,v)
是这个像素框自带的权重(高斯加权:越靠近中心位置,加权系数越大)
我们需要把I(u + △x,v + △y)
用泰勒公式展开,对图像图像I(x,y)
在(x,y)
处平移(△x,△y)
后进行一阶近似:
其中Ix、Iy
是图像I(x,y)
的偏导数
近似可得:
二次项函数本质是一个椭圆函数,方程为:
即λ
越大,图像灰度值变化越大(其中λ1、λ2
分别为矩阵M
中:λ1 = 1 / A²、λ2 = 1 / B²
)
opencv
提供了API,这也是我们调用Harris角点检测
的返回值:
角点响应:
其中detM = λ1 × λ2
,traceM = λ1 + λ2
,α = 0.04 ~ 0.06(自己选择)
角点响应结果:返回值
检测窗口在图像中移动,上图对应着三种情况
关键API:cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
其中:
src
:操作的图片(必须是灰度图)blockSize
:检测窗口的大小(没有要求必须是奇数,我们不是做卷积操作),设置的值越小越能检测出角点,值太大的话会扫描的一大块,不好检测ksize
:Sobel算子
的大小(原理处用到了偏导数,Sobel算子
就是用于计算偏导数的)k
:相当于角点响应公式中的α
,取值为0.04 ~ 0.06(默认值为0.04 )
import cv2
import numpy as np
img = cv2.imread('./chess.png')
# img = cv2.imread('./hand.png')
# 变成灰度图片
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
##----------------------------------------------------------
# 角点检测 ——> 返回角点响应R,每一个像素都可以计算出一个角点响应
R = cv2.cornerHarris(gray,blockSize = 2,ksize = 3,k = 0.04)
# 显示角点
# 设定阈值来判断角点 怎么设置?
# 返回值R中有一个最大的R值R.max(),即最大的角点响应,但我们不可能只用最大的角点,因为我们还有很多个角点,所以我们找一个关系来设置阈值
# R > ( 0.01 * R.max()) # 用ndarray和单个数字相比,返回值为bool类型:该点的角点响应大于最大角点响应的0.01倍,我们认为它就是角点
# 我们把它作为一个条件,直接对图片进行筛选
img[R > ( 0.01 * R.max() )] = [0,0,255] # 颜色改成红色
##----------------------------------------------------------
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
图片的角点响应
与角点响应阈值做比较,大于就是True,小于就是False:R > ( 0.01 * R.max() )
将R > ( 0.01 * R.max() )
作为条件img[R > ( 0.01 * R.max() )]
直接对图片进行筛选,将满足角点要求的像素点筛选出来,有:
把这些点都赋值为红色(0,0,255)