Python计算机视觉——Harris角点检测

文章目录

  • Python计算机视觉——Harris角点检测
    • 写在前面
    • 1 Harris角点检测基本思想
    • 2 Harris角点检测公式推导
    • 3 实验分析

写在前面

在传统目标识别中,特征提取是最终目标识别效果好坏的一个重要决定因素,因此,在这项工作里,有很多研究者把主要精力都放在特征提取方向。在传统目标识别中,主要使用的特征主要有如下几类:

  • 边缘特征(Canny算子)
  • 纹理特征(小波Gabor算子)
  • 角点特征(Harris算子)

那何为角点?

  • 局部窗口沿各方向移动,均产生明显变化的点
  • 图像局部曲率突变的点

1 Harris角点检测基本思想

角点检测的算法思想是:选取一个固定的窗口在图像上以任意方向的滑动,如果灰度都有较大的变化,那么久认为这个窗口内部存在角点。人眼对角点的识别通常是在一个局部的小区域或小窗口完成的。如果在各个方向上移动这个特征的小窗口,窗口内区域的灰度发生了较大的变化,那么就认为在窗口内遇到了角点。如果这个特定的窗口在图像各个方向上移动时,窗口内图像的灰度没有发生变化,那么窗口内就不存在角点;如果窗口在某一个方向移动时,窗口内图像的灰度发生了较大的变化,而在另一些方向上没有发生变化,那么,窗口内的图像可能就是一条直线的线段。

2 Harris角点检测公式推导

将窗口平移[u, v]产生的灰度变化E(u, v),根据上述的基本思想可知,若E(u, v)越大,则是角点的概率就越大。公式如下:
E(u,v)=∑x,yw(x,y)[I(x+u,y+v)−I(x,y)]2E(u, v)=\sum_{x, y} w(x, y)[I(x+u, y+v)-I(x, y)]^{2} E(u,v)=x,y∑​w(x,y)[I(x+u,y+v)−I(x,y)]2
w(x, y)是窗口函数,以点(x,y)为中心的窗口。I(x+u, y+v)是平移后的图像灰度,I(x, y)是平移前的灰度。
f(x+u,y+v)=f(x,y)+ufx(x,y)+vfy(x,y)+First−partial−derivatives12![u2fxx(x,y)+uvfxyx,y+v2fyy(x,y)]+Second−partial−derivatives……f(x+u, y+v)=f(x, y)+u f_{x}(x, y)+v f_{y}(x, y)+\\First-partial- derivatives\\\frac{1}{2 !}\left[u^{2} f_{x x}(x, y)+u v f_{x y} x, y+v^{2} f_{y y}(x, y)\right]+\\Second-partial-derivatives\\…… f(x+u,y+v)=f(x,y)+ufx​(x,y)+vfy​(x,y)+First−partial−derivatives2!1​[u2fxx​(x,y)+uvfxy​x,y+v2fyy​(x,y)]+Second−partial−derivatives……
所以,可以约等于
f(x+u,y+v)≈f(x,y)+ufx(x,y)+vfy(x,y)即等于:I(x+u,y+v)≈I(x,y)+uIx(x,y)+vIy(x,y)f(x+u, y+v) \approx f(x, y)+u f_{x}(x, y)+v f_{y}(x, y)\\即等于:\\I(x+u, y+v) \approx I(x, y)+u I_{x}(x, y)+v I_{y}(x, y) f(x+u,y+v)≈f(x,y)+ufx​(x,y)+vfy​(x,y)即等于:I(x+u,y+v)≈I(x,y)+uIx​(x,y)+vIy​(x,y)
因此得到如下推导:

于是对于局部微小的移动量 [u, v],可以近似得到下面的表达式:
E(u,v)≅[u,v]M[uv]E(u, v) \cong[u, v] M\left[\begin{array}{l} u \\ v \end{array}\right] E(u,v)≅[u,v]M[uv​]
其中M是 2×2 矩阵,可由图像的导数求得:
M=∑x,yw(x,y)[Ix2IxIyIxIyIy2]M=\sum_{x, y} w(x, y)\left[\begin{array}{cc} I_{x}^{2} & I_{x} I_{y} \\ I_{x} I_{y} & I_{y}^{2} \end{array}\right] M=x,y∑​w(x,y)[Ix2​Ix​Iy​​Ix​Iy​Iy2​​]
窗口移动导致的图像变化量:实对称矩阵M的 特征值分析:
E(u,v)≅[u,v]M[uv]记 M的特征值为 λ1,λ2\begin{array}{l} E(u, v) \cong[u, v] M\left[\begin{array}{l} u \\ v \end{array}\right]\\ \text { 记 } M \text { 的特征值为 } \lambda_{1}, \lambda_{2} \end{array} E(u,v)≅[u,v]M[uv​] 记 M 的特征值为 λ1​,λ2​​
则根据两个特征值得到结论

  • 如果矩阵对应的两个特征值都较大,那么窗口内含有角点
  • 如果特征值一个大一个小,那么窗口内含有线性边缘
  • 如果两个特征值都很小,那么窗口内为平坦区域

所以上述兜兜转转,把角点的检测转化为数学模型,就是求解窗口内矩阵的特征值并且判断特征值的大小。

再多定义个式子:角点响应函数R
R=det⁡M−k(trace⁡M)2其中:det⁡M=λ1λ2trace M=λ1+λ2(k−empirical constant, k=0.04∼0.06)\begin{array}{c} R=\operatorname{det} M-k(\operatorname{trace} M)^{2} \\其中:\\ \operatorname{det} M=\lambda_{1} \lambda_{2} \\ \text { trace } M=\lambda_{1}+\lambda_{2} \\ (k-\text { empirical constant, } k=0.04 \sim 0.06) \end{array} R=detM−k(traceM)2其中:detM=λ1​λ2​ trace M=λ1​+λ2​(k− empirical constant, k=0.04∼0.06)​
同理可得:

  • 角点:R 为大数值正数
  • 边缘:R为大数值负数
  • 平坦区:R为小数值

3 实验分析

捋一下整个Harris角点检测步骤:

  1. 读取图片,将图片转化成灰度图
  2. 计算响应函数
  3. 基于响应值选择角点
  4. 在原图中画出检测的角点

源码如下:

新建文件Harris_Detector.py

from pylab import *
from numpy import *
from scipy.ndimage import filtersdef compute_harris_response(im,sigma=3):""" Compute the Harris corner detector response function for each pixel in a graylevel image. """# derivativesimx = zeros(im.shape)filters.gaussian_filter(im, (sigma,sigma), (0,1), imx)imy = zeros(im.shape)filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)# compute components of the Harris matrixWxx = filters.gaussian_filter(imx*imx,sigma)Wxy = filters.gaussian_filter(imx*imy,sigma)Wyy = filters.gaussian_filter(imy*imy,sigma)# determinant and traceWdet = Wxx*Wyy - Wxy**2Wtr = Wxx + Wyyreturn Wdet / Wtrdef get_harris_points(harrisim,min_dist=10,threshold=0.1):""" Return corners from a Harris response imagemin_dist is the minimum number of pixels separating corners and image boundary. """# find top corner candidates above a thresholdcorner_threshold = harrisim.max() * thresholdharrisim_t = (harrisim > corner_threshold) * 1# get coordinates of candidatescoords = array(harrisim_t.nonzero()).T# ...and their valuescandidate_values = [harrisim[c[0],c[1]] for c in coords]# sort candidates (reverse to get descending order)index = argsort(candidate_values)[::-1]# store allowed point locations in arrayallowed_locations = zeros(harrisim.shape)allowed_locations[min_dist:-min_dist,min_dist:-min_dist] = 1# select the best points taking min_distance into accountfiltered_coords = []for i in index:if allowed_locations[coords[i,0],coords[i,1]] == 1:filtered_coords.append(coords[i])allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist), (coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0return filtered_coordsdef plot_harris_points(image,filtered_coords):""" Plots corners found in image. """figure()gray()imshow(image)plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords],'*')axis('off')show()

上述三个函数分别代表这步骤中的234。1步骤则新建test_harris.py

from PIL import Image
from numpy import *
# 这就是为啥上述要新建一个的原因,因为现在就可以import
import Harris_Detector
from pylab import *
from scipy.ndimage import filters# filename
im = array(Image.open(r"  ").convert('L'))
harrisim=Harris_Detector.compute_harris_response(im)
filtered_coords=Harris_Detector.get_harris_points(harrisim)
Harris_Detector.plot_harris_points(im,filtered_coords)

实验结果如下:由图可知不同的阈值,检测出的角点个数会不同。阈值越小,则检测出的角点会越多,意味着符合该条件的角点就会多,但同样意味着放低了条件,有些不确定不准确的角点也有可能被检测;增大阈值范围,则检测到的角点会变少,但相对来说每个角点的置信程度较高,所以说阈值的选择就是empirical constant。其实现在opencv也有自带的函数库 cv2.cornerHarris能够直接完成harris角点检测,可直接使用。

对于图像匹配,在Harris_Detector.py中加入如下5个函数。Harris 角点检测器仅仅能够检测出图像中的兴趣点,但是没有给出通过比较图像间的兴趣点来寻找匹配角点的方法。我们需要在每个点上加入描述子信息,并给出一个比较这些描述子的方法。兴趣点描述子是分配给兴趣点的一个向量,描述该点附近的图像的表观信息。描述子越好,寻找到的对应点越好。我们用对应点或者点的对应来描述相同物体和场景点在不同图像上形成的像素点。

def get_descriptors(image,filtered_coords,wid=5):""" For each point return pixel values around the pointusing a neighbourhood of width 2*wid+1. (Assume points are extracted with min_distance > wid). """desc = []for coords in filtered_coords:patch = image[coords[0]-wid:coords[0]+wid+1,coords[1]-wid:coords[1]+wid+1].flatten()desc.append(patch)return descdef match(desc1,desc2,threshold=0.5):""" For each corner point descriptor in the first image, select its match to second image usingnormalized cross correlation. """n = len(desc1[0])# pair-wise distancesd = -ones((len(desc1),len(desc2)))for i in range(len(desc1)):for j in range(len(desc2)):d1 = (desc1[i] - mean(desc1[i])) / std(desc1[i])d2 = (desc2[j] - mean(desc2[j])) / std(desc2[j])ncc_value = sum(d1 * d2) / (n-1) if ncc_value > threshold:d[i,j] = ncc_valuendx = argsort(-d)matchscores = ndx[:,0]return matchscoresdef match_twosided(desc1,desc2,threshold=0.5):""" Two-sided symmetric version of match(). """matches_12 = match(desc1,desc2,threshold)matches_21 = match(desc2,desc1,threshold)ndx_12 = where(matches_12 >= 0)[0]# remove matches that are not symmetricfor n in ndx_12:if matches_21[matches_12[n]] != n:matches_12[n] = -1return matches_12def appendimages(im1,im2):""" Return a new image that appends the two images side-by-side. """# select the image with the fewest rows and fill in enough empty rowsrows1 = im1.shape[0]    rows2 = im2.shape[0]if rows1 < rows2:im1 = concatenate((im1,zeros((rows2-rows1,im1.shape[1]))),axis=0)elif rows1 > rows2:im2 = concatenate((im2,zeros((rows1-rows2,im2.shape[1]))),axis=0)# if none of these cases they are equal, no filling needed.return concatenate((im1,im2), axis=1)def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):""" Show a figure with lines joining the accepted matches input: im1,im2 (images as arrays), locs1,locs2 (feature locations), matchscores (as output from 'match()'), show_below (if images should be shown below matches). """im3 = appendimages(im1,im2)if show_below:im3 = vstack((im3,im3))imshow(im3)cols1 = im1.shape[1]for i,m in enumerate(matchscores):if m>0:plot([locs1[i][1],locs2[m][1]+cols1],[locs1[i][0],locs2[m][0]],'c')axis('off')

然后新建match_harris.py调用

import Harris_Detector
from pylab import *
from PIL import Imageim1 = array(Image.open(r"  ").convert("L"))
im2 = array(Image.open(r"  ").convert("L"))wid =5
harrisim = Harris_Detector.compute_harris_response(im1,5)
filtered_coords1 = Harris_Detector.get_harris_points(harrisim,wid+1)
d1 = Harris_Detector.get_descriptors(im1,filtered_coords1,wid)harrisim = Harris_Detector.compute_harris_response(im2,5)
filtered_coords2 = Harris_Detector.get_harris_points(harrisim,wid+1)
d2 = Harris_Detector.get_descriptors(im2,filtered_coords2,wid)print('starting mathching')
matches = Harris_Detector.match_twosided(d1,d2)figure()
gray()
Harris_Detector.plot_matches(im1,im2,filtered_coords1,filtered_coords2,matches)
show()

效果如下:


若匹配的图片完全一样,则可以发现,角点匹配完全正确。可是若照片中的目标发生了偏移,发现该算法存在一些不正确的匹配,是由于图像像素块的互相关矩阵具有较弱的描述性,在实际运用中,可以使用更加稳健的方法来处理这些对应匹配。

Python计算机视觉——Harris角点检测相关推荐

  1. 计算机视觉——Harris角点检测

    文章目录 1.原理介绍 角点介绍 Harris算子 2.代码设计 3.实验结果 3.1 纹理平坦的图片 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2 垂直或水平边缘多(如建筑物) ...

  2. 计算机视觉 — Harris角点检测

    文章目录 一.角点 二.Harris角点检测基本思想 三.Harris算法数学表达 四.实验结果分析 五.代码 六.总结 一.角点 角点(corner points):局部窗口沿各方向移动,均发生明显 ...

  3. 计算机视觉——harris角点检测之harris角点响应函数R

    文章目录 一.harris角点检测原理 1.1基本思想 1.2 数学模型 3.关于harris角点响应函数R 二.harris角点检测源代码 2.1 计算harris角点响应函数R 2.2harris ...

  4. python 角点检测_python 实现Harris角点检测算法

    算法流程: 将图像转换为灰度图像 利用Sobel滤波器求出 海森矩阵 (Hessian matrix) : 将高斯滤波器分别作用于Ix².Iy².IxIy 计算每个像素的 R= det(H) - k( ...

  5. harris角点检测算法实现

    算法流程: 1.将图像转换为灰度图像: 2.利用Sobel滤波器求出 海森矩阵 (Hessian matrix) : 3.将高斯滤波器分别作用于Ix².Iy².IxIy: 4.计算每个像素的 R= d ...

  6. Harris角点检测python实现及基于opencv实现

    写在前面: 黄宁然, 七月,骄阳似火. 参考文献镇楼: [1]袁志聪,基于harris特征的点云配准方法研究 [2]高亭,基于改进Harris角点检测的印刷体文档图像检索技术 [3]景庆阳,基于har ...

  7. 计算机视觉(二)HARRIS角点检测算法与SIFT

    文章目录 前言 一.HARRIS角点检测算法 1.什么是角点(corner points) 2.角点检测算法的基本思想 3.什么是好的角点检测算法 4.角点特征的数学刻画 5.度量角点响应 6.HAR ...

  8. harris角点检测_角点检测(2) - harris算子 - 理论与Python代码

    数字图像,图像=矩阵,[m*n]从[0,255]的灰度值 角点检测:物体边缘的拐点 ->应用:图像匹配与检索.图像物体形变恢复(摄像机标定).三维重建 Harris角点检测(早期,原理简单,视频 ...

  9. cv2.cornerHarris()详解 python+OpenCV 中的 Harris 角点检测

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8763369.html 参考文献----------OpenCV-Python-Toturial ...

最新文章

  1. spring boot请求后缀匹配的操作
  2. C/C++如何检查系统内存泄露与使用情况?
  3. LINUX应用修改硬件寄存器l,郝健: Linux内存管理学习笔记-第2节课【转】
  4. java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setCharacterStream(ILjava/io/Reader;
  5. 科大星云诗社动态20210403
  6. no.5_得到4升的水
  7. 转: SQL Server Analysis Service中Cube的结构
  8. 顺丰同城:香港IPO发行价定为16.42港元
  9. python调用数据库存储过程_python调用MySql存储过程
  10. android分享,如何移除掉信息这项
  11. jBPM研究情况报告
  12. namenode和datanode的功能分别是什么_海德堡印刷机电路板分别是什么功能
  13. 模糊综合评价的 matlab,模糊综合评价法代码matlab
  14. 软件测试必须知道的缺陷分析
  15. 联想服务器怎么拆硬盘,联想ThinkStation P900工作站高清拆解
  16. Aurix 多核链接文件 lsl --- 上篇
  17. 批量复制到花瓣网上图片素材的原图
  18. 使用Htmlunit工具获取表单中的input
  19. Mac-修改MySQL密码
  20. 高数-数列极限与函数极限

热门文章

  1. Quick Sort ( simple verson )
  2. Redis - String内存开销问题以及基本/扩展数据类型的使用
  3. Android ScrollView去掉右侧滑动条
  4. 3ds Max制作厨房贴图和纹理实例
  5. 闪耀暖暖服务器维护,闪耀暖暖服务器地址失败怎么办
  6. 动画解决TCP 三次握手与四次挥手(附十道面试题)
  7. 计算机系统属性无法显示,电脑计算机右键属性无法打开的解决办法[多图]
  8. 燊酱:致敬百年三烧坊 共饮一燊酱酒魂
  9. 每秒10万并发 mysql_亿级流量系统架构之如何设计每秒十万查询的高并发架构
  10. element UI 封装后的table表头(tooltip)文字提示