参考文章:
图像梯度的基本原理.
canny算法(2)——图像梯度的计算(sobel算子)
GaussianBlur
2.转灰度图cvtColor
3.求X和Y方向的梯度Sobel
。cv2.Sobel
方法,一般的sobel算子是,右减左,下减上,进而得到图像中某一点的x方向上的梯度或者y方向上的梯度。另外,因为进行减法操作后不一定得到的是正值,也可能是负值,但是uint8不允许负值的存在,因此要指定ddepth = cv2.CV_64F 以包容负值的存在(eg:cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
),此时进行图像的展示,会先将数组中的负值视为0。但是随后会调用其他方法(cv2.convertScaleAbs
)以进行绝对值化的操作,此时进行展示时,会使得负值转化为正值,得到我们完整的特征图。CornerHarris
的参数的。而sobel算子是Harris角点检测过程中使用的算子,但是CornerHarris的参数中似乎只能指定sobel算子的大小即ksize,而不能指定具体使用的核是啥,而这一点有待深挖,因为我也看到过自定义算子,比如,高斯滤波器曾作为图像降噪的方式,也可用来计算梯度并赋予到某些方法(eg.erode
)中的情况。参考文献:
OpenCV-Python教程
Sobel边缘检测
canny算法(2)——图像梯度的计算
cv2.cornerHarris(img,blocksize,ksize,k)
》 计算每个blocksize大小的窗口的灰度值变化(也可以称为“自相似性”)。而变化值可以由自相似函数给出。
其中, W ( u , v ) W(u,v) W(u,v)是以点 ( u , v ) (u,v) (u,v)为中心的窗口,既可以是常数,又可以是高斯加权函数。
w ( u , v ) w(u,v) w(u,v)是一个权重矩阵,shape大小为blocksize,注意它并不是sobel算子,确切地说,他们都是权重矩阵,但是目的并不同,用处不同,sobel算子用于计算每一个点的梯度, w w w则用于反映窗口灰度值总体变化大小中各带位置的像素点的权重、贡献度如何。所以ksize和blocksize并不是一回事,且没有关系。
w ( u , v ) w(u,v) w(u,v)由常数或者高斯加权构成时,常常分别为以下两种:
[ 1 1 1 1 1 1 1 1 1 ] \left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{matrix} \right] ⎣⎡111111111⎦⎤
1 16 [ 1 2 1 2 4 2 1 2 1 ] \frac 1 {16} \left[ \begin{matrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \end{matrix} \right] 161⎣⎡121242121⎦⎤
但是似乎在cornerHarris中无法人为指定具体权重,只能指定blocksize。
( u , v ) (u,v) (u,v)是窗口区域中点的坐标,如果blocksize=3,则 ( u , v ) (u,v) (u,v)一共有9个。
Δ x Δ y \Delta x \Delta y ΔxΔy表示每个 ( u , v ) (u,v) (u,v)向右向下的移动单位,而其基本单位是1像素。
I ( u , v ) I(u,v) I(u,v)表示图像中在 ( u , v ) (u,v) (u,v)点的灰度值。
至此,对于自相似函数的计算,在指定blocksize,给定img后,仅 I ( u + Δ x , v + Δ y ) I(u+\Delta x,v+\Delta y) I(u+Δx,v+Δy) 不知如何求解。
》》而这个项式的计算,需要借助泰勒公式的一阶展开式近似计算。
即 I ( u + Δ x , v + Δ y ) = I ( u , v ) + I x ( u , v ) Δ x + I y ( u , v ) Δ y + o ( Δ x 2 , Δ y 2 ) 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) I(u+Δx,v+Δy)=I(u,v)+Ix(u,v)Δx+Iy(u,v)Δy+o(Δx2,Δy2)
此时, I ( u + Δ x , v + Δ y ) − I ( u , v ) ≈ I x ( u , v ) Δ x + I y ( u , v ) Δ y I(u+\Delta x,v+\Delta y) - I(u,v) \approx I_x(u,v) \Delta x+I_y(u,v) \Delta y I(u+Δx,v+Δy)−I(u,v)≈Ix(u,v)Δx+Iy(u,v)Δy ,可以看出 I ( u , v ) I(u,v) I(u,v)被抵消,而 o ( Δ x 2 , Δ y 2 ) o({\Delta x}^2,{\Delta y}^2) o(Δx2,Δy2)佩亚诺余项作为高阶无穷小,可以被忽略掉,因此上式为近似求解。
同时,注意此时的 I x ( u , v ) I y ( u , v ) I_x(u,v) I_y(u,v) Ix(u,v)Iy(u,v)即是我们之前讲的每一个点的水平梯度值和纵向梯度值 !
但是即使如此,我们还是不能很好的处理 Δ x Δ y \Delta x \Delta y ΔxΔy的取值。
由此需要借助线性代数中的二次型来间接解决这么个问题,而之所以说是间接解决自相似函数的计算问题,是因为利用二次型是用来计算特征值,再通过响应函数R可计算得到score分数,以用来跟系统设定的阈值比较判断是否该窗口中包含角点。而在这个过程中,包括特征值的求解过程, Δ x Δ y \Delta x \Delta y ΔxΔy一直都没有参与计算。
在具体解释特征值计算过程之前,需要解释一个问题,为什么泰勒展开式要展开到一阶而不是二阶,原因很简单,我们想通过泰勒展开式引入导数以实现近似的计算(因为准确计算不可能),而一阶二阶等更高阶都可以做到,只是计算二阶导数会引起计算量的大大增加,且一阶导数的近似效果已经足够了。因此就没有考虑二阶展开式。
》》》接下来,进一步推算,开始前,先告诉大家,这一步是为了求出自相似函数的特征值,避免因为其他内容的介绍而糊涂。
先展示一下泰勒展开式之后的自相似函数的近似结果:
c ( s , y ; Δ x , Δ y ) ≈ ∑ w ( I x ( u , v ) Δ x + I y ( u , v ) Δ y ) 2 c(s,y;\Delta x,\Delta y) \approx \displaystyle \sum_{w}{(I_x(u,v) \Delta x+I_y(u,v) \Delta y)^2} c(s,y;Δx,Δy)≈w∑(Ix(u,v)Δx+Iy(u,v)Δy)2 。
为了简洁,讲 w ( x , y ) w(x,y) w(x,y)先不具体展示出来了。被收纳到了求和运算符下面。
然后,二次型的结果就是如此:
c ( s , y ; Δ x , Δ y ) ≈ [ Δ x , Δ y ] M ( x , y ) [ Δ x Δ y ] c(s,y;\Delta x,\Delta y) \approx [\Delta x ,\Delta y]M(x,y)\left[ \begin{matrix} \Delta x \\ \Delta y \end{matrix}\right] c(s,y;Δx,Δy)≈[Δx,Δy]M(x,y)[ΔxΔy]
(接下来的一小段内容是说:该自相似函数可以视为一个椭圆,而椭圆的形状与特征值的大小相关)
而对于
c ( s , y ; Δ x , Δ y ) ≈ A Δ x 2 + 2 C Δ x Δ y + B Δ y 2 c(s,y;\Delta x,\Delta y) \approx A{\Delta x}^2 + 2C{\Delta x}{\Delta y} + B{\Delta y}^2 c(s,y;Δx,Δy)≈AΔx2+2CΔxΔy+BΔy2,如果把c视为一个常数,那么这就是一个二次型方程,而二次型方程在二维图像中就是一个椭圆。而常数的具体取值并不影响椭圆的形状。而椭圆的形状又恰好是我们要重点研究的,**准确的说是它的长短轴与我们想要求得特征值密切相关。**因此在此我们姑且将该二次型方程视为:
A Δ x 2 + 2 C Δ x Δ y + B Δ y 2 = 1 A{\Delta x}^2 + 2C{\Delta x}{\Delta y} + B{\Delta y}^2 = 1 AΔx2+2CΔxΔy+BΔy2=1。
其中,椭圆图像因为有 2 C Δ x Δ y 2C{\Delta x}{\Delta y} 2CΔxΔy的存在,而具有一定的倾斜程度。
图来自二次型的意义是什么?有什么应用? - 马同学的回答 - 知乎 非常赞的回答!推荐阅读。
(接下里这段是说,求特征值为什么借助矩阵,且特征值的意义是什么)
首先,求特征值为什么借助矩阵,这个问题我不该问的,因为求特征值本身就需要借助矩阵运算。
其次,特征值或者确切说特征矩阵意味这什么?首先,矩阵代表着运动,且当矩阵维度没有发生改变时,一个矩阵就包含了两个运动:旋转和拉伸。而如果想把这两个运动分解,可以对矩阵进行正交化操作和特征值分解,由此得到两个矩阵正交矩阵和对角矩阵。
而正交矩阵就单纯的意味着旋转运动,而对角矩阵就单纯地意味着左右上下拉伸运动。
而对于一个二次方程的二次型矩阵即M(x,y)更换成它对应的对角矩阵,则一个倾斜的椭圆就扶正了。
结合下图进行理解上一段话,如果没能理解,那一定不是你的原因,一定是我没说清楚,具体可以参考文章:二次型的意义是什么?有什么应用? - 马同学的回答 - 知乎 。
有了前面的基础知识,我们不难理解,其实我上面的那么多文字,有点啰嗦了。因为只要我们知道了二次型矩阵,经过“特征值分解”就可以得到对角矩阵,得到特征值。
因为是二维的矩阵,所以最后的特征值只有两个,而这两个特征值又对应了椭圆的长短轴关系
还记得之前提起过,一张图像是由三类区域构成:
三种类型的特点是:
- 角点(特征点)是当窗口向各方向移动,都会引起像素值发生很大变化的一个位置点;
- 边缘特征是仅当窗口单方向(要么水平,要么垂直方向)上来回移动,才会引起像素值发生较大变化的一个位置区域;
- 平坦区域是无论窗口移动方向如何,都不会引起像素值发生很大的变化的区域。
对应的,参考下面一张图片内容:
也就是说,这两个特征值分别对应水平和垂直两个方向。
如果某个窗口下在向水平方向移动时,水平特征值很大,而在垂直方向上移动时,垂直特征值较小,那么表示,该窗口下存在一片区域是边界特征。
而如果某个窗口在水平和垂直方向上的特征值都非常大,那么就表示,该窗口下的一片区域存在角点
那么最后的问题是,怎么根据特征值来衡量该窗口下存在的是角点还是其他其他。
注意,因为我们这里使用的是Harris角点检测,所以从衡量方法上来看,我们只关注其是否是角点,而关注如果该窗口下不包含角点,那么窗口下的区域到底是平坦还是边界!
衡量方法即是:响应函数R。
R = d e t M ( x , y ) − k ⋅ ( t r M ( x , y ) ) 2 R = \mathrm{det} M^{(x,y)} - k \cdot \left ( \mathrm{tr} M^{(x,y)} \right )^2 R=detM(x,y)−k⋅(trM(x,y))2
我们看到了cornerHarris
方法的第四个参数k,是由用户自行指定的。
注意这个阈值应该时内置的,但是为了实现对角点检测数量的控制,因此给R中添加了k参数,通过调整参数k,可以判断窗口下识别的点是否可以称得上是满足自己要求的角点。
参考内容:
Opencv计算机视觉实战(Python版)
Markdown / KaTex数学公式汇总
Harris特征点检测器-兴趣点检测|Task01
cornerHarris函数
还有一些文章在文中已经提及,再次就不再赘述。
至此,全部内容结束。第一次写这么多的博文,文章的布局,我也尽力了。我也是看了很多的文章才得到这样的一个总结,我不是数学专业的学生,只是Opencv方向的小白,如果有错误,或者编辑上的不便,烦请赐教,哪怕只是提出问题!感谢!