python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测
角点检测(Corner Detection)是计算机视觉和图像处理中重要的步骤,主要用于提取图像中的关键特征,以便进行后续的任务,比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。
1. Harris角点检测
Harris角点检测是一种经典的角点检测算法,基于图像的局部特征,通过计算图像的自相关矩阵来判断一个点是否为角点。
-
原理:
- 计算局部窗口内的图像梯度,并构造自相关矩阵。
- 通过计算赫希因子(Harris Matrix),确定强度响应,响应值大于一定阈值的点被认为是角点。
-
优点:
- 对于噪声具有一定的鲁棒性。
- 可以检测到多种类型的角点。
OpenCV 中的 cv.cornerHarris() 函数用来实现 Harris 角点检测。它的参数是:
img - 输入图像,应为 float32 类型的灰度图。
blockSize - 角点检测所考虑的邻域大小。
ksize - Sobel 导数的内核大小。
k - Harris 检测器方程中的自由参数。
OpenCV 带有一个函数 cv.cornerSubPix() ,它进一步细化了角点检测,以达到亚像素级精度。
import numpy as np
import cv2 as cv
filename = 'output.png'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# find Harris corners
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
dst = cv.dilate(dst,None)
ret, dst = cv.threshold(dst,0.01*dst.max(),255,0)
dst = np.uint8(dst)
# find centroids
ret, labels, stats, centroids = cv.connectedComponentsWithStats(dst)
# define the criteria to stop and refine the corners
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
# Now draw them
res = np.hstack((centroids,corners))
res = np.intp(res)
img[res[:,1],res[:,0]]=[0,0,255]
img[res[:,3],res[:,2]] = [0,255,0]
cv.imshow('sobely',img)
cv.waitKey(0)
2. Shi-Tomasi角点检测
Shi-Tomasi角点检测法是对Harris方法的改进,更注重测量响应函数的特征。
-
原理:
- 通过计算两个特征值,选择具有较大特征值的点作为角点。
- 角点的选择更为简洁和高效。
-
优点:
- 对图像旋转和尺度变化具有更好的鲁棒性。
- 适合实时应用,如视频监控。
OpenCV 有一个函数, cv.goodFeaturesToTrack() 。它通过 Shi-Tomasi 方法(或 Harris 角点检测,如果你指定它)在图像中找到 N 个最佳的角点。输入图像应该是灰度图像。然后指定要查找的角点数量。然后指定质量等级,该等级是 0-1 之间的值,所有低于这个质量等级的角点都将被忽略。最后设置检测到的两个角点之间的最小欧氏距离。
例如尝试找到 25 个最佳角点:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('f:/apple.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(gray,25,0.01,10)
corners = np.intp(corners)
for i in corners:
x,y = i.ravel()
cv.circle(img,(x,y),3,255,-1)
plt.imshow(img),plt.show()
3. SIFT(尺度不变特征变换)
SIFT是一种用于检测和描述局部特征的算法,具有对尺度、旋转和光照变化的高鲁棒性。
-
原理:
- 检测图像中多个尺度的关键点。
- 生成每个关键点的描述符,以便进行特征匹配。
-
优点:
- 高鲁棒性,适用于图像匹配、拼接等应用。
- 可以处理遮挡和光照变化。
SIFT算法主要可以分成以下几个步骤:
-
构建高斯金字塔(Gaussian Pyramid)
- 对于给定的图像,首先通过对图像进行不同尺度的高斯模糊,构建一个高斯金字塔。这涉及到对原图像逐层进行模糊,每一层的尺度增大。通常,金字塔中的每一层是上一层的平滑图像。
-
构建差分高斯金字塔(Difference of Gaussian)
- 通过相邻的高斯图像层之间进行减法来计算差分高斯(DoG),该过程可以近似计算图像的拉普拉斯金字塔(Laplacian Pyramid)。
- 公式为:
3. 关键点检测
- 对于每个像素点,寻找极值点,即在当前尺度和相邻的尺度(上层和下层)中具有极大或极小值的点。具体步骤如下:
- 遍历图像的每个像素,检查其是否在其邻域内(包括尺度上和空间上)是最大或最小点。
- 一般使用3x3x3的邻域,即考虑9个临近像素的3个尺度。
4. 精确定位关键点
- 对检测到的关键点进行细化,以提高其定位精度。常用的方法是通过泰勒级数展开。即优化关键点的位置,利用Hessian矩阵或者主导方向计算来细化关键点的位置和尺度。
5. 选择主方向
- 为每个关键点分配一个或多个主方向,以使得描述符具有旋转不变性。
- 计算关键点周围一定半径内的梯度值,并确定主方向。
- 形成一个方向直方图,用于统计方向,并选择最大直方图峰值作为关键点的主方向。
6. 生成关键点描述符
- 在每个关键点的周围区域中,计算其特征描述符。通常,这个区域被划分为多个子区块,并在每个子区块内计算梯度方向和幅值。
- 将每个子块的梯度信息汇总,形成一个包含多维信息的特征向量。
7. 特征点匹配(可选)
- 利用上述计算得到的描述符,针对不同图像中的特征点进行匹配。通常采取欧几里德距离或二元汉明距离来计算描述符之间的相似度。
具体步骤
-
构建高斯金字塔:对图像进行多次高斯模糊,生成一系列不同尺度的图像。
-
计算差分高斯:通过相邻两层的高斯图像做差,提取出潜在的特征点。
-
找到极值点:例如,对于某个像素,比较它与相邻8个像素以及上面和下面的对应像素,如果它是最大的或最小的,则记为一个关键点。
-
关键点精确定位:利用插值方法进行位置微调,去除那些边缘响应较强或低对比度的关键点。
-
计算方向:统计关键点周围像素的梯度直方图,确定主要方向。
-
生成描述符:以关键点的主方向为基准,计算关键点周围小块的描述符。
-
匹配过程:对于每个图像的特征点,可以使用最近邻法或比例测试进行匹配。
import numpy as np
import cv2 as cv
img = cv.imread('f:/apple.jpg')
gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)
img=cv.drawKeypoints(gray,kp,img)
img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imshow('SIFT',img)
cv.waitKey(0)
4. SURF算法
SURF的基本理念是在SIFT的基础上,通过加快特征点检测和描述过程,取得更高的效率。SURF的主要步骤如下:
1.1 特征点检测
-
Hessian矩阵:SURF使用Hessian矩阵的行列式来检测特征点。通过计算每个像素点的Hessian矩阵,可以快速找到潜在的特征点。Hessian矩阵具有以下形式:
- 盒子滤波:为了计算Hessian矩阵的行列式,SURF使用的是快速的Haar小波卷积。这种方法通过将图像分为不同大小的盒子,并使用加权和减少计算复杂度。
-
梯度计算:SURF在特征点周围的邻域内计算图像的梯度值,并将其组织成一个描述符。描述符的生成过程涉及多个子块,各子块的特征会被汇总成一个固定长度的描述符。
-
方向归一化:为了确保特征描述符具有方向不变性,SURF根据特征点的主方向进行方向归一化。
1.2 特征描述符生成
-
梯度计算:SURF在特征点周围的邻域内计算图像的梯度值,并将其组织成一个描述符。描述符的生成过程涉及多个子块,各子块的特征会被汇总成一个固定长度的描述符。
-
方向归一化:为了确保特征描述符具有方向不变性,SURF根据特征点的主方向进行方向归一化。
import cv2 as cv
from matplotlib import pyplot as plt
# 读取图像
img = cv.imread('f:/apple.jpg', 0)
# Create SURF object. You can specify params here or later.
# Here I set Hessian Threshold to 400
surf = cv.xfeatures2d.SURF_create(400)
# Find keypoints and descriptors directly
kp, des = surf.detectAndCompute(img,None)
# Check present Hessian threshold
print( surf.getHessianThreshold() )
# We set it to some 50000. Remember, it is just for representing in picture.
# In actual cases, it is better to have a value 300-500
surf.setHessianThreshold(50000)
# Again compute keypoints and check its number.
kp, des = surf.detectAndCompute(img,None)
print( len(kp) )
img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)
plt.imshow(img2),plt.show()
5. ORB(Oriented FAST and Rotated BRIEF)
ORB结合了FAST特征检测和BRIEF特征描述,可以更快速地进行角点检测和描述。ORB 基本上是 FAST 特征点检测器和 Brief 描述子的融合,并进行了许多修改以增强性能。首先,它使用 FAST 查找特征点,然后应用 Harris 角点的测量方法来查找其中的前 N 个点。它还使用金字塔来生成多尺度特征。但有一个问题是,FAST 不计算方向。
-
原理:
- 使用FAST算法检测特征点,计算点的方向和角度。
- 采用BRIEF描述符来描述特征。
-
优点:
- 快速高效,适合实时应用。
- 对于图像的旋转具有稳健性。
cv.ORB()使用 feature2d 通用接口创建 ORB 对象。它有许多可选参数。
nFeatures,表示要保留的最大要素数量(默认为 500),
scoreType, 表示对特征点进行排序使用 Harris 得分或 FAST 得分(默认为 Harris 得分)等。
WTA_K, 决定生成一个 oriented BRIEF 描述子的所用的像素点数目。默认情况下它是 2,即一次选择两个点。在这种情况下进行匹配,使用 NORM_HAMMING 距离。如果 WTA_K 为 3 或 4,则需要 3 或 4 个点来产生 BRIEF 描述子,匹配距离由 NORM_HAMMING2 定义。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('f:/apple.jpg',0)
# Initiate ORB detector
orb = cv.ORB_create()
# find the keypoints with ORB
kp = orb.detect(img,None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
# draw only keypoints location,not size and orientation
img2 = cv.drawKeypoints(img, kp, None, color=(0,255,0), flags=0)
plt.imshow(img2), plt.show()
原文地址:https://blog.csdn.net/qq_37481709/article/details/145233596
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!