学习记录------------------图像特征计算Harris角点检测和Sift
前言
今天,我们来聊下Harris和sift这两个经常在论文里面提到的图像特征计算的算法吧。
预备知识
1.泰勒级数
引用当年考研时,汤老师说过话吧,一切函数我都能产开成这个算式。其中包括多元函数。
多元微分泰勒:
2.现代知识
矩阵A为n阶方阵,若存在n阶矩阵B,使得矩阵A、B的乘积为单位阵,则称A为可逆阵,B为A的逆矩阵。若方阵的逆阵存在,则称为可逆矩阵或非奇异矩阵,且其逆矩阵唯一。
补充:对称矩阵首先是一个方阵,然后它一主对角线做对称轴做对称,元素相同。dao可以理解为把一个正方形沿对角线折叠的样子。
实对称矩阵首先是一个对称矩阵,然后它的每一个元素都是实数。
极值点
极值的必要条件:f’(a)=0
极值的第一充分条件:f’(a)=0且f’(x)在x=a两侧变号
极值的第二充分条件:f’(a)=0且f’’(a)\neq 0(f’’(a)>0为极小值,f’’(a)<0为极大值)
极值的第三充分条件:设f(x)在x=a处最低阶不为零的导数的阶为n,若n为偶数x=a是极值点。若n为奇数x=a是不是极值点
Harris角点检测原理
什么是角点?
从一方面来说我们可以理解为角点为级值点。它沿着任何一方向的特征就很突出。在一副图像中,我们可以认为角点是物体轮廓线的连接点(见图),当拍摄视角变化的时候,这些特征点仍能很好地保持稳定的属性
平面点:x 和 y 方向变化不大
边界点:x 或 y 方向变化大
角点:x 和 y 方向的变化都大
总结:使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
Harris 角点检测算法的原理
Harris 角点检测角点检测最原始的想法就是取某个像素的一个邻域窗口,当这个窗口在各个方向上进行小范围移动时,观察窗口内平均的像素灰度值的变化.
I为灰度变化,W为高斯加权,增强不同位置的权重
感觉下面讲的很好引用:
本质上可以看做椭圆方向的变化:
椭圆的长短轴是与结构张量M的两个特征值相对应的量。通过判断的情况我们就可以区分出‘flat’,‘edge’,‘corner’这三种区域,因为最直观的印象:
角点:在水平、竖直两个方向上变化均较大的点,即Ix、Iy都较大;
边界点 :仅在水平、或者仅在竖直方向有较大的点,即Ix和Iy只有其一较大
平面点: 在水平、竖直方向的变化量均较小的点,即Ix、Iy都较小;
代码:
import cv2
import numpy as np
img = cv2.imread('test_1.jpg')
print ('img.shape:',img.shape)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
print ('dst.shape:',dst.shape)
# 设置为其他倍数
img[dst>0.01*dst.max()]=[0,0,255]
cv2.imshow('dst',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
参数说明:
cv2.cornerHarris(img, blockSize, k)
img: 数据类型为 float32 的入图像
blockSize: 角点检测中指定区域的大小,前面提到的w(u,v),可能是个高斯函数
ksize: 就像Sobel求导中使用的窗口大小
k: 取值参数为 [0,04,0.06]. 默认0.04
dst.max是最大值,一定是角点
只要dst中满足0.01倍的最大值,就判定为角点,要求较高的也可以调大点
Sift 角点检测
Sift前言
图像尺度空间
当用一个机器视觉系统分析未知场景时,计算机没有办法预先知识图像中物体尺度,因此,我们需要同时考虑图像在多尺度下的描述,获知感兴趣物体的最佳尺度。所以在很多时候,我们会在将图像构建为一系列不同尺度的图像集,在不同的尺度中去检测我们感兴趣的特征。
图像金字塔化的一般步骤:(1)图像经过一个低通滤波器进行平滑(这个步骤会使图像变模糊,好像模仿人的视觉中远处的物体没有近处的清晰的原理)一般使用使用高斯模糊来实现。
(2)对这个平滑后的图像进行抽样(一般抽样比例在水平和竖直方向上都为1/2),从而得到一系列的缩小的图像。
总结:
1.图像金字塔金字塔有多个层级
2.同一层级中,有不同的高斯滤波
Sift 步骤
1. 高斯差分金字塔(DOG)
首先两个高斯模糊后的特征相减,得到DOG。
2.计算极值点
DoG空间极值检测
为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间-8个点)和尺度域(相邻的尺度空间-上下各9个 共18个)的所有相邻点(共26)进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。如下图所示,中间的检测点要和其所在图像的3×3邻域8个像素点,以及其相邻的上下两层的3×3领域18个像素点,共26个像素点进行比较。
最上/下层无法比较,故4层特征图中只有2层才能检测极值点。
但这步检测的离散极值点 不一定是 最终的极值点,故需要精确定位
.关键点的精确定位
关键点是DOG空间的局部极值点,而且这些极值点均为离散的点,精确定位极值点的一种方法是,对尺度空间DoG函数进行曲线拟合,计算其极值点,从而实现关键点的精确定位。
具体实在看不懂计算可以忽略
消除边界相应
生成特征描述
在完成关键点的计算后,使用直方图统计邻域内像素的梯度和方向。
为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转θ角度,即将坐标轴旋转为特征点的主方向。
旋转之后的主方向为中心取8x8的窗口,求每个像素的梯度幅值和方向,箭头方向代表梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算,最后在每个4x4的小块上绘制8个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,即每个特征的由4个种子点组成,每个种子点有8个方向的向量信息。
代码
import cv2
import numpy as np
img = cv2.imread('chessboard.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
#获得角点
kp = sift.detect(gray, None)
#画出图
img = cv2.drawKeypoints(gray, kp, img)
cv2.imshow('drawKeypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
如果
module ‘cv2.cv2’ has no attribute ‘xfeatures2d’
OpenCV大于3.4版本 就对sift进行专利保护了,所以想免费使用的,看看sift效果的,降低一下版本吧
pip uninstall opencv-python
pip install opencv-contrib-python==3.4.1.15
pip install opencv-contrib-python==3.4.1.15
- 1
- 2
- 3
文章来源: blog.csdn.net,作者:快了的程序猿小可哥,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_35914625/article/details/108246979
- 点赞
- 收藏
- 关注作者
评论(0)