Harris角点Score计算
在学习Harris角点知识的时候,首先感谢这篇文章
Harris检测原理
Harris本质上就是从Moravec算子进行演变过来的
Moravec算子思想
其实moravec算子比较简单,在图像上取一个w*w大小的窗口,不断移动这个窗口然后检测窗口像素的变化情况E. E的情况有以下三种情况:
- 窗口内图像平坦 -- E的变化不大
- 窗口图像是一条边 -- 沿边滑动E的变化不大 垂直于边滑动,E的变化会很大
- 窗口图像存在一个角点 -- 窗口图像沿任何方向移动E值的变化都很大
所以Moravec算法也只是在几个方向上做移动,并单纯计算像素值 \[ E_{(x, y)}=\sum_{u, v} w_{u, v}\left[I_{x+u, y+v}-I_{u, v}\right]^{2} \] 其中(x,y)就表示四个移动方向(1,0)(0,1)(1,1)(-1,1)
Harris检测思想
相比于Moravec, Harris做了以下改进
- Moravec对于方向依赖性太强,Harris更改使用梯度
- Harris对窗口函数做了高斯平滑
- Harris对函数E进行变形,使其成为二次型
NOTICE 要注意很重要一点就是,E函数是对于一整个窗口中的像素的计算的结果
对于原始的Moravec算子其计算score函数如下 \[ E_{(x, y)}=\sum_{u, v} w_{u, v}\left[I_{x+u, y+v}-I_{u, v}\right]^{2} \] 进行微分化有 \[ E_{(x,y)}=\sum_{u, v}\left[x X+y Y+O\left(x^{2}, y^{2}\right)\right]^{2} \]
\[ \begin{array}{l} \mathrm{X}=\mathrm{I} \otimes(-1,0,1) \approx \frac{\partial \mathrm{I}}{\partial \mathrm{x}} \\ \mathrm{Y}=\mathrm{I} \otimes(-1,0,1)^{T} \approx \frac{\partial I}{\partial y} \end{array} \]
也就是可以使用每个像素点对应的x,y梯度来进行表示E
将等式拆开可以得到 \[ \mathrm{E}(\mathrm{x}, \mathrm{y})=A x^{2}+2 C x y+B y^{2} \]
\[ \begin{array}{l} \mathrm{A}=X^{2} \otimes \mathrm{w} \\ \mathrm{~B}=Y^{2} \otimes \mathrm{w} \\ \mathrm{C}=(\mathrm{XY}) \otimes \mathrm{w} \end{array} \]
w函数也就是之前提到的高斯平滑函数,也就是使用高斯平滑函数对窗口内像素的梯度值进行高斯平滑 \[ w_{u, v}=\exp -\left(u^{2}+v^{2}\right) / 2 \sigma^{2} \] 然后Harris重要的一点就是对响应函数做二次型的变形操作,所以响应函数E就成为了二次型的形式 \[ \mathrm{E}(\mathrm{x}, \mathrm{y})=(x, y) M(x, y)^{T} \] 其中 \[ \mathrm{M}=\left[\begin{array}{ll} A & C \\ C & B \end{array}\right] \] 这个M就是harris特征矩阵,假设其有两个特征值\(\alpha,\beta\),那么新的损失函数可以写成以下的形式 \[ \mathrm{E}(\mathrm{x}, \mathrm{y})=\mathrm{Ep}(\mathrm{x_p}, \mathrm{y_p}) = \alpha\mathrm{x_p^2} + \beta\mathrm{y_p^2} \] 所以\(\alpha,\beta\)两个值表示了该像素点在x和y方向上的一个梯度的分布,画出来就会是一个椭圆
在平坦均一的区域,变化很慢所以椭圆就比较大;边缘区域在一个轴上变化大一个轴上变化小,所以椭圆细长;角点区域各个方向变化都很大,所以椭圆比较小.
所以怎么判断角点位置,只要计算\(\alpha,\beta\)就行,但是计算这俩比较麻烦,所以Harris使用矩阵的两个性质来进行计算代替,也就是使用下式 \[ \mathrm{R}=\text { Det }-\mathrm{k} T_{r}^{2} \]
\[ \begin{array}{l} T_{r}(M)=\alpha+\beta=A+B \\ \operatorname{Det}(\mathrm{M})=\alpha \beta=\mathrm{AB}-C^{2} \end{array} \]
这就是Harris响应函数,其中系数k的值在OPenCV中推荐是0.04,
当R为正值时,检测的是角点,负值时为边,很小时是平坦区域
OpenCV中Harris Response的计算
Opencv中存在检测Harris角点的算法,其声明如下
1 | void cornerHarris( InputArray src, //输入8bit 单通道灰度Mat矩阵 |
但其实还有另一个地方需要计算Harris 的值,也就是在角点计算的时候进行.
以ORB检测为例,其检测指针的构造函数如下所示
1 | static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31, |
其中ScoreType需要对角点response计算函数进行指定,默认使用HarrisScore.
计算完毕后的response会存储在cv::Keypoint实例中的response中.
在角点检测中计算Harris值是为了筛选出最优的nfeature个角点.
计算Harris代码
这里计算Harris代码很值得学习
可以说这类高效的代码实现
1 | /** |