Python OpenCV9:OpenCV 图像特征提取

1. Harris 角点检测

Harris 角点检测通过图像的一个小部分窗口观察图像。角点的特点是窗口向任意方向移动都会引起图像灰度的显著变化。

Python OpenCV9:OpenCV 图像特征提取_第1张图片

将上述思想转化为数学形式,即将局部窗口向各个方向移动(u,v),计算所有灰度差的总和。

其中 I(x,y) 是局部窗口的图像灰度, I(x+u,y+v) 为平移后的图像灰度,w(x,y) 是窗口函数。窗口可以是矩形窗口,也可以是为每个像素分配不同权重的高斯窗口,如下图: 

Python OpenCV9:OpenCV 图像特征提取_第2张图片

在角点检测中,E(u,v) 的值被最大化。 使用一阶泰勒展开式:

其中 Ix 和 Iy 沿着 x 和 y 方向的导数可以用sobel算子计算。 推导如下: 

 Python OpenCV9:OpenCV 图像特征提取_第3张图片

M 矩阵确定 E(u,v) 的值。 下面我们使用 M 来寻找角点。 M 是 Ix 和 Iy 的二次项函数,可以用椭圆来表示。 椭圆的长短半轴由M的特征值λ1​​和λ2​​决定,方向由特征向量决定,如下图:

Python OpenCV9:OpenCV 图像特征提取_第4张图片

Harris 给出的角点计算方法不需要计算具体的特征值,而是计算一个角点响应值R来判断角点。 R的计算公式为:

其中detM是矩阵M的行列式,traceM 是矩阵 M 的迹,α为常数,取值范围为0.04~0.06。

由于:

Python OpenCV9:OpenCV 图像特征提取_第5张图片

特征值隐含在detM和traceM中。

如下图所示:

Python OpenCV9:OpenCV 图像特征提取_第6张图片

当R为正数且取值较大时为角点;当 R 为负数且绝对值较大时为边界;当 R 是较小的数时为平坦区域。

cv.cornerHarris(src, blockSize, ksize, k)

参数:

img 输入图像,数据类型为 float32。

blockSize 角点检测中要考虑的邻域大小

ksize sobel求导使用的核大小

k 角点检测方程中的自由参数,取值参数为 [0.04,0.06]。

Harris 角点检测的优点:

旋转不变性,椭圆旋转一定角度但形状保持不变,特征值保持不变。 图像灰度级的仿射变化是部分不变的。 因为只使用了图像的一阶导数,所以图像灰度平移变化不变,图像灰度尺度变化不变。

Harris 角点检测的缺点: 它对尺度非常敏感,不具有几何尺度不变性。提取的角点是像素级的。

2. Shi-Tomasi算法

Shi-Tomasi算法是Harris角点检测算法的改进。Harris 算法的角点响应函数是从矩阵 M 的行列式值 中减去 M 的迹,利用差值来判断是否为角点。 后来Shi和Tomasi提出了一种改进方法,如果矩阵M的两个特征值中较小的一个大于阈值,则认为是角点,即R=min(λ​1​​,λ​2​​)。如下图所示:

Python OpenCV9:OpenCV 图像特征提取_第7张图片

可以看出,只有当λ1和λ2均大于最小值时,才认为是角点。 

cv.goodFeaturesToTrack(image, maxcorners, qualityLevel, minDistance)

参数:

image 输入灰度图像

maxcorners 获取角点数的数目

qualityLevel 该参数指出最低可接受的角点质量水平,在0-1之间。

minDistance 角点之间最小的欧氏距离,避免得到相邻特征点。

返回值:

搜索到的角点。

3. SIFT 算法

SIFT 算法的本质是在不同尺度空间中寻找关键点(特征点)并计算关键点的方向。 SIFT查找到的关键点是一些非常突出的点,不会因为光照、仿射变换和噪声等因素而改变,比如角点、边缘点、暗区的亮点、亮区的暗点。

SIFT算法可以分解为以下四个步骤:

1)尺度空间极值检测:在所有尺度上搜索图像位置。通过高斯差分函数识别对尺度和旋转不变的潜在关键点。

2)关键点定位:在每个候选位置,使用一个精细拟合的模型来确定位置和尺度。关键点的选择取决于它们的稳定性程度。

3)关键点方向确定:根据图像的局部梯度方向,为每个关键点位置分配一个或多个方向。所有后续对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而保证了这些变换的不变性。

4)关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像的局部梯度。这些梯度用作关键点描述符,允许相对较大的局部形状变形或光照变化。

cv.xfeatures2d.SIFT_create()

返回值:SIFT对象

sift.detectAndCompute(gray)

参数:

gray 进行关键点检测的灰度图像

返回值:

kp 关键点信息,包括位置,尺度,方向信息。

des 关键点描述符,每个关键点对应128个梯度信息的特征向量。 

cv.drawKeypoints(image, keypoints, outputimage, color, flags)

参数:

image 原始图像

keypoints 关键点信息,将其绘制在图像上。

outputimage 输出图片,可以是原始图像。

color 颜色设置,通过修改(b, g, r)的值,更改画笔的颜色。

flags 绘图功能的标识设置:

cv.DRAW_MATCHES_FLAGS_DEFAULT 创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,对每一个关键点只绘制中间点 。   

cv.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG 不创建输出图像矩阵,而是在输出图像上绘制匹配对。

cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS 对每一个特征点绘制带大小和方向的关键点图形。

cv.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS 单点的特征点不被绘制。

例:对下面的图像使用Harris、Shi-Tomas和SIFT方法检测角点。

Python OpenCV9:OpenCV 图像特征提取_第8张图片

import matplotlib
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

font = {
    "family": "Microsoft YaHei"
}
matplotlib.rc("font", **font)

img = cv.imread("./image/tv.jpg")

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray_32 = np.float32(gray)

# Harris
dst = cv.cornerHarris(gray_32, 2, 3, 0.04)

# 绘制角点
img[dst > 0.001 * dst.max()] = [0, 0, 255]

plt.imshow(img[:, :, ::-1])
plt.title("Harris角点检测")
plt.show()

# Shi-Thomas
corners = cv.goodFeaturesToTrack(gray, 1000, 0.01, 10)

# 绘制角点
for i in corners:
    x, y = i.ravel()
    cv.circle(img, (x, y), 2, (0, 0, 255), -1)

plt.imshow(img[:, :, ::-1])
plt.title("Shi-Thomas角点检测")
plt.show()

# SIFT
sift = cv.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(gray, None)

# 绘制角点
cv.drawKeypoints(img, kp, img, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

plt.imshow(img[:, :, ::-1])
plt.title("SIFT角点检测")
plt.show()

输出:

Python OpenCV9:OpenCV 图像特征提取_第9张图片

Python OpenCV9:OpenCV 图像特征提取_第10张图片

Python OpenCV9:OpenCV 图像特征提取_第11张图片

你可能感兴趣的:(Python,python,opencv)