图像特征-harris
概念
- 作用:对图像中的平滑区域、边界区域、角点进行检测
- 大致原理:使用一定大小的窗口在图像中的所有地方进行微小移动,对移动的差异值进行处理,判断是平滑区域、边界区域和角点
平滑区域:
边界区域:
角点区域:
相关数学推导
目标:计算图像中每个像素点的自相似性,由自相似性可以判断出该像素属于哪种类型的区域
自相似性的计算
自相似性的计算公式:
\[c(x,y;\Delta x,\Delta y)=\sum_{(u,v)\in W(x,y)}w(u,v)(I(u,v)-I(u+\Delta x, v+\Delta y))^{2} \\其中W(x,y)是以点(x,y)为中心的窗口,像核一样代表该区域内的权重分布 \\I(x,y)是某点的灰度值 \]对自相似性的计算公式进行转换:
\[I(u+\Delta x, v+\Delta y) \\=I(u,v)+I_{x}(u,v)\Delta x+I_{y}(u,v)\Delta y+O(\Delta x^{2},\Delta y^{2}) \\\approx I(u,v)+I_{x}(u,v)\Delta x+I_{y}(u,v)\Delta y \\\; \\\therefore c(x,y;\Delta x,\Delta y) \\\approx \sum_{w}(I(u,v)+I_{x}(u,v)\Delta x+I_{y}(u,v)\Delta y)^{2} \\=\begin{bmatrix}\Delta x&\Delta y \\\end{bmatrix}M(x,y)\begin{bmatrix}\Delta x \\\Delta y\end{bmatrix} \\其中M(x,y)=\sum_{w}\begin{bmatrix}I_{x}(x,y)^{2} &I_{x}(x,y)I_{y}(x,y) \\I_{x}(x,y)I_{y}(x,y) & I_{y}(x,y)^{2} \\\end{bmatrix} \\=\begin{bmatrix}\sum_{w}I_{x}(x,y)^{2} &\sum_{w}I_{x}(x,y)I_{y}(x,y) \\\sum_{w}I_{x}(x,y)I_{y}(x,y) & \sum_{w}I_{y}(x,y)^{2} \\\end{bmatrix} \\=\begin{bmatrix}A &C \\C &B \\\end{bmatrix} \\\; \\即c(x,y;\Delta x,\Delta y)\approx A\Delta x^{2}+2C\Delta x\Delta y+B\Delta y^{2} \]注意到二次函数\(A\Delta x^{2}+2C\Delta x\Delta y+B\Delta y^{2}\)在平面上本质是一个椭圆函数,是一个中心点在原点的倾斜椭圆,在3维空间上是一个顶点向下的椭圆锥
对其进行坐标转换或者实对称矩阵M进行对角化,可以消去中间项\(2C\Delta x\Delta y\),把倾斜的椭圆放平,其中对角矩阵是\(\begin{bmatrix}\lambda 1 &0 \\0 &\lambda 2 \\
\end{bmatrix}\),\(\lambda 1\)和\(\lambda 2\)对应了椭圆的两个轴
所以直观上来看,椭圆的两个轴长大小发生变化时自相似性的大小也会发生变化
根据自相似性作判断
根据像素点的特征值(\(\lambda 1、\lambda 2\))大小,判断该点在哪种类型区域
- 边界:一个特征值大,另一个特征值小。自相关函数值在某个方向上大,其它方向上小
- 平面:两个特征值都小,且近似相等。自相关函数值在各个方向上都小
- 角点:两个特征值都大,且近似相等。自相关函数值在各个方向上都增大
角点相应R值:对\(\lambda 1、\lambda 2\)进行处理,方便判断
\[R=detM-\alpha(traceM)^{2} 其中detM = \lambda 1\lambda 2 \\traceM = \lambda 1+\lambda 2 \\\alpha在OpenCV中一般取值为0.04 \]- 当R>0:很可能是属于角点区域
- 当R≈0:很可能是属于平滑区域
- 当R<0:很可能是属于边界区域
函数运用
dst = cv2.cornerHarris(src, blockSize, ksize, k)
- src:数据类型为float32的图像
- blockSize: 角点检测中指定区域的大小
- ksize: Sobel求导中使用的窗口大小
- k: 取值参数为 [0,04,0.06],即角点相应R值中的\(\alpha\)
- dst:图中每个像素点的自适应值
运用例子:
import cv2
import numpy as np
# 读入图片,转灰度图
img = cv2.imread('test_1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用cornerHarris函数,指定检测区域大小为2x2,Sobel算子大小为3x3,k取0.04
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 对可能为角点的点标红
img[dst>0.01*dst.max()]=[0,0,255]
# 显示
cv2.imshow('dst',img)
cv2.waitKey(0)
cv2.destroyAllWindows()