OpenCV学习——角点检测、SIFT算法的学习

  • 图像的特征提取和描述
  • 角点特征
  • Harris角点检测
  • Shi-Tomasi角点检测
  • SIFT/SURF算法
  • SIFT算法(尺度不变特征转换)
  • 实现


图像的特征提取和描述

图像特征:图像特征主要有图像的颜色特征、纹理特征、形状特征和空间关系特征。

角点特征

角点:两条边的交点,严格的讲,角点是两个不同区域的不同方向的边界

Harris角点检测

原理:通过图像的局部小窗口观察图像,角点的特诊是窗口沿任意方向移动都会导致灰度的明显变化。

将黑塞矩阵M 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较

(由于其原理实现的数学公式导致作者大脑宕机,故直接跳过,讲述如何利用OpenCV实现)

opencv 判断当前点是极值点 opencv识别角点_计算机视觉

# Harris检测
dst = cv.cornerHarris(img, blockSize, ksize, k)
# img:数据类型为float32的输入图像
# blockSize:角点检测中要考虑的领域大小(窗口)
# ksize:sobel求导使用的核大小(奇数哦)
# k:角点检测方程中的自由参数,取值参数为[0.04, 0.06]

代码测试

import cv2 as cv
import numpy as np

# 读取图像,转换成灰度图
img = cv.imread('img/img.png')
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 讲获得的灰度图像转成float32格式
gray_img = np.float32(gray_img)

# 角点检测
dst = cv.cornerHarris(gray_img, 2, 3, 0.05)

# 绘制窗口(dst大于dst中最大值的0.001倍的均绘制出来)
img[dst>0.001 * dst.max()] = [0,0,255]

cv.imshow("Harris_img", img)

cv.waitKey(0)

opencv 判断当前点是极值点 opencv识别角点_python_02

Shi-Tomasi角点检测

原理:若黑塞矩阵M中较小的一个大于阈值,则认为是角点。

是对Harris检测的改进,可以更好的检测角点

opencv 判断当前点是极值点 opencv识别角点_计算机视觉_03

API

corners = cv2.goodFeaturesToTrack(img, maxcorners, qualityLevel, minDistance)
# img:灰度图像
# maxcorners:获取角点的数目
# qualityLevel:该参数指出最低可接收的角点质量水平,0-1之间
# minDistance:角点之间最小的欧式距离,避免得到相邻特征点
# corners:搜索到的角点

代码测试:

import cv2 as cv
import numpy as np

# 读取图像,转换成灰度图
img = cv.imread('img/25.png')
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 角点检测(指定1000个角点)
corners = cv.goodFeaturesToTrack(gray_img, 1000, 0.01, 10)
# 绘制角点
for i in corners:
    x, y = i.ravel()  # 平铺成坐标
    cv.circle(img, (x, y), 2, (0, 0, 255), -1)
# 绘制窗口(dst大于dst中最大值的0.001倍的均绘制出来)
cv.imshow("Shi-Tomasi", img)
cv.waitKey(0)

opencv 判断当前点是极值点 opencv识别角点_opencv_04

Harris算法和Shi-Tomasi算法具有旋转不变性,但是不具有尺度不变性!

SIFT/SURF算法

SIFT算法(尺度不变特征转换)

原理:在不同的尺度空间上查找关键点,并计算关键点的方向。也就是说在空间尺度中寻找极值点,并提取位置、尺度、旋转不变量。

SIFT查找的关键点:一些十分突出的点,不会因光照、仿射变化和噪音等因素而变化的点,如角点、边缘点、暗区中的亮点以及亮区中的暗点。

基本流程

第一步:尺度空间机制检测:搜索所有尺度的图像位置,通过高斯差分函数来识别潜在的对于尺度和旋转不变的关键点

第二步:关键点定位:在每个候选位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择一句与它们得稳定程度

第三步:关键点方向确定:基于图像局部得梯度方向,分配给每个关键点位置一个或多个方向

第四步:关键点描述:在每个关键点周围邻域内,在选定得尺度上测量图像局部梯度。

SIFT

SURF

特征点检测

使用不同尺度的图片与高斯函数进行卷积

使用不同大小的盒滤波器与原始图像做卷积,易于并行

方向

关键点邻接矩形区域内,利用梯度直方图计算

关键点灵界圆域内,计算x、y方向的harris小波

描述符生成

关键点邻域内划分d*d个子区域,每个子区域计算8个方向的直方图

关键点邻域内划分的d*d个子区域,每个子区域计算采样点的harr小波响应,记录:Σdx,Σdy,Σ|dx|,Σ|dy|

实现

# 实例化sift
sift = cv.SIFT_create()

# 检测关键点
kp, des = sift.detectAndCompute(gray, None)
# gray:灰度图像
# kp:关键点信息(位置、尺度、方向)
# des:关键点描述符,每个关键点对应28个梯度信息的特征向量

# 绘制关键点信息
cv.drawKeypoints(img, keypoints, outputimage, color, flags)
# img:原始图像
# keypoints:关键点信息
# outputimage:输出图片
# color:颜色设置
# flags:绘图功能的标识设置
# cv.DRAW_MATCHS_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,每一个关键点只绘制中间点
# cv.DRAW_MATCHS_fLAGS_DRAW_OVER_OUTIMG:不创建图像矩阵,在输出图像上绘制匹配对
# cv.DRAW_MATCHS_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形
# CV.DRAW_MATCHS_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制

代码测试

import cv2 as cv
import numpy as np

# 读取图像,转换成灰度图
img = cv.imread('img/25.png')
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# sift检测cv2.SIFT_create()
sift = cv.SIFT_create()
kp, des = sift.detectAndCompute(gray_img, None)

# 绘制检测结果
cv.drawKeypoints(img, kp, img, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv.imshow("Shi-Tomas", img)

cv.waitKey(0)

opencv 判断当前点是极值点 opencv识别角点_计算机视觉_05

圆形越大表示尺度越大,圆形越小表示尺度越小,圆中的半径是方向