Opencv学习笔记——特征提取


一、图像特征-harris角点检测

什么是图像角点

  角点检测 (Corner Detection) 是图像的重要特征.。角点可以帮助我们实现图像对其, 图像拼接, 目标识别等等重要用途。在角点的地方,无论你向哪个方向移动小图,结果都会有很大的不同。
  角点是图像很重要的特征,某方面属性特别突出的点,是在某些属性上强度最大或者最小的孤立点、线段的终点等。对图像图形的理解和分析有很重要的作用。角点在保留图像图形重要特征的同时,可以有效地减少信息的数据量,使其信息的含量很高,有效地提高了计算的速度,有利于图像的可靠匹配,使得实时处理成为可能。
在这里插入图片描述

基本原理

  Harris 角点检测 (Harris Corner Detection) 是最基础也是最重要的一种角点检测算法, 通过计算图像在 x, y 上平移的自相似性 (Self-Similarity) 来判断图像是否为角点。
在这里插入图片描述
  角点检测时图像可以分为3个区域,平坦区,边界和角点。取一个区域I(x,y),这个区域在x轴和y轴移动时区域内的灰度变换不大,认为这个区域是平坦区;当这个区域在x轴移动时变换较大,y轴移动时则没有什么变换(或者相反),则认为这个区域为边界;当这个区域在x轴和y轴移动是灰度变换都较大则认为是角点。
在这里插入图片描述
上述公式经过一系列的近似化简后可以等效为一个椭圆函数;
在这里插入图片描述
  这样就可以得到两个λ,λ1和λ2,用两个λ值来等效图像在x轴和y轴变换的快慢,通过比较两个λ值可以判断图像区域是否为角点。

边界:一个特征值大一个特征值小,λ1>>λ2(或者λ12>>λ1),即图像在一个方向变换较大,在另一个方向变化较小。

平面:两个λ值都比较小,且近似相等。即图像在任意方向变化都不大。

角点:λ1和λ2都比较大,且近似相等。即图像在任意方向变化都比较大。
在这里插入图片描述
  也可以用角点响应值R来判断,当R<0时,认为时边界;当R=0或者接近与0,认识时平坦区;当R>0时,认为时角点。

R = detM-α(traceM)^2
detM = λ1*λ2
traceM = λ1+λ2
α取值为0.04-0.06

代码实现

角点检测函数

cv2.cornerHarris(img,blockSize,ksize,k)

img: 数据类型为 float32 的入图像
blockSize: 角点检测中指定区域的大小
ksize: Sobel求导中使用的窗口大小
k: 取值参数为 [0,04,0.06]
代码:

import cv2
import numpy as np

def show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img = cv2.imread('D:/qipan.jpg')
#show("img",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度图
# gray = np.float32(gray)#转换格式为floa32
dst = cv2.cornerHarris(gray,5,5,0.04)#角点检测
img[dst>0.1*dst.max()]=[0,0,255]#非极大值抑制
show("img",img)

效果:
在这里插入图片描述

二、SIFT特征提取

SITF概述

  SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述。这种描述具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子。 该方法于1999年由David Lowe首先发表于计算机视觉国际会议(International Conference on Computer Vision,ICCV),2004年再次经David Lowe整理完善后发表于International journal of computer vision(IJCV)。

图像尺度空间

在一定的范围内,无论物体是大还是小,人眼都可以分辨出来,然而计算机要有相同的能力却很难,所以要让机器能够对物体在不同尺度下有一个统一的认知,就需要考虑图像在不同的尺度下都存在的特点。尺度空间的获取通常使用高斯模糊来实现。
在这里插入图片描述
不同σ的高斯函数决定了对图像的平滑程度,越大的σ值对应的图像越模糊。
在这里插入图片描述

图像金字塔

  一幅图像的图像金字塔是一系列以金字塔形状(自下而上)逐步降低,且来源于同一张原始图的图像分辨率集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。图像金字塔可以用与不同层时的特征提取,每层的特征不一样,起到的效果也不一样。
  金字塔的每一层都要经过数次高斯滤波。
在这里插入图片描述

高斯差分金字塔(DOG)

  DoG (Difference of Gaussian) 即高斯差分金字塔, 用在上面的图像金字塔每一层都经过了数次高斯滤波,假设为5次,用前一次减去后一次得到的结果就是高斯差分,金字塔的每一次都是这样的操作的到的结果就是高斯差分金字塔。
在这里插入图片描述

DoG空间极值检测

在这里插入图片描述
为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。如下图所示,中间的检测点要和其所在图像的3×3邻域8个像素点,以及其相邻的上下两层的3×3领域18个像素点,共26个像素点进行比较。
在这里插入图片描述
因为后面计算会涉及到大量的数学计算,有需要的可以去看SIFT算法的论文解析,点击《SIFT算法原文解析》

代码实现

在OpenCV 3.4之后因专利版权问题移除了SIFT/SURF的相关库,申请了专利,好消息是2020年3月17日之后算法SIFT专利到期了,但是直接用原来的接口sift = cv2.xfeatures2d.SIFT_create()是会有警告cv::xfeatures2d::SIFT_create DEPRECATED: cv.xfeatures2d.SIFT_create() is deprecated due SIFT tranfer to the main repository.原因是原来的接口已经弃用,改为sift = cv2.SIFT_create()即可。
代码:

import cv2
import numpy as np

def show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img = cv2.imread('D:/gaolou.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#灰度图
sift = cv2.SIFT_create()#sift算法实例化
kp = sift.detect(gray, None)#关键点检测
img = cv2.drawKeypoints(gray, kp, img)
show("img",img)
#计算特征
kp, des = sift.compute(gray, kp)
print (np.array(kp).shape)

效果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Thousand_drive/article/details/124948909