文章目录
- 一篇文章搞懂OpenCV之图像特征
- 纹理特征
- 形状特征
- 哈里斯角检测
- Shi-Tomasi角点检测
- 尺度不变特征变换算法
一篇文章搞懂OpenCV之图像特征
图像特征即图像中独特的,易于跟踪和比较的特定模板或特定结构,例如我们肉眼可见的颜色、形状、轮廓以及亮度等等这些都可以认为是图像特征。
图像特征主要有图像的颜色特征、纹理特征、形状特征和空间关系特征。
- 颜色特征(全局特征):描述了图像或图像区域所对应的景物的表面性质(颜色直方图、颜色空间、颜色分布)
- 纹理特征(全局特征):描述了图像或图像区域所对应的景物的表面性质。但纹理只是一种物体表面的特性,并不能完全反映出物体的本质属性,所以仅仅利用纹理是无法获得高层次图像内容的。
- 形状特征:轮廓主要针对物体的外边界,而区域特征则描述的是图像中的局部形状特征。即①轮廓特征②区域特征。
- 空间关系特征:指图像中分割出来的多个目标之间的相互的空间位置或相对方向关系(连接/邻接关系、交叠/重叠关系和包含/独立关系等)。
对于颜色直方图大家可以看OpenCV基础之模板匹配与直方图里面的讲解。
纹理特征
LBP(Local Binary Pattern,局部二值模式),是一种用来描述图像局部纹理特征的算子,它具有旋转不变性和灰度不变性等显著的优点。
步骤:LBP算子定义一个3x3的窗口,以窗口中心值为像素的阈值,与相邻的8个像素的灰度值比较,如果大于中心像素值,则该位置被标记为1,否则标记为0, 如此得到一个8为二进制数,(通常还要转换为10进制,即LBP码,共256种)
原理:记录中心像素与领域像素点之间的差值,LBP对光照变化不敏感,仅检测图像的纹理信息。
# 读取一张灰度图像
img = cv.imread('img/orange.png', cv.IMREAD_GRAYSCALE)
# 计算LBP特征
radius = 1
n_points = 8 * radius
lbp = np.zeros_like(img)
for i in range(radius, img.shape[0] - radius):
for j in range(radius, img.shape[1] - radius):
center = img[i, j]
code = 0
for k in range(n_points):
x = i + int(radius * np.cos(2 * np.pi * k / n_points))
y = j - int(radius * np.sin(2 * np.pi * k / n_points))
if img[x, y] >= center:
code += 2 ** k
lbp[i, j] = code
# 显示LBP特征图
cv.imshow('LBP', lbp)
cv.waitKey(0)
cv.destroyAllWindows()
LBP算法以及实现中对于实现以及LBP的原理进行了详细的描述。
形状特征
- 角点:即拐角①两个边缘的交点;②邻域内具有两个主方向的特征点。
- 角点计算方法:①通过图像边缘计算,计算量大,图像局部变化会对结果产生较大的影响;②基于图像灰度的方法通过计算点的曲率及梯度来检测角点。
哈里斯角检测Harris、方向梯度直方图HOG原理、尺度不变特征变换算法SIFT。
哈里斯角检测
- 实现过程:计算图像在x和y方向的梯度,计算图像两个方向梯度的乘积,使用高斯函数对三者进行高斯加权,生成矩阵M的A,B,C,计算每个像素的HarrisR,并对小于某一阈值t的R置为零,在3x3或5x5的领域内进行非最大值抑制,局部最大值点即为图像中的角点。
- 优点:Harris角点具有旋转不变特性。
- 缺点:缩放之后,原来的角有可能就不是角了。
cv.cornerHarris() 是 OpenCV 中用于进行角点检测的函数之一。它可以检测图像中的角点,并将其标记出来,返回一个与输入图像大小相同的浮点型矩阵,其中每个像素的值表示该像素是角点的可能性大小。它的主要参数包括:
- src:输入图像,必须为灰度图像。
- blockSize:角点检测中要考虑的邻域大小。
- ksize:Sobel 求导算子的大小。
- k:计算响应函数时的自由参数,通常取值为 0.04 到 0.06。
img = cv2.imread('img/corner.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# cornerHarris角点检测,img输入图像,blockSize领域大小,ksize求导窗口大小,k角点检测方程中的自由参数[0.04,0.06]
dst = cv.cornerHarris(gray,blockSize=2, ksize=3, k=0.04)
# 进行膨胀操作
dst = cv.dilate(dst,None)
# 最佳值的阈值,将大于阈值 0.01 * dst.max() 的像素赋值为红色
img[dst>0.01*dst.max()]=[0,0,255]
cv.imshow('dst',img)
cv.waitKey(0)
cv.destroyAllWindows()
Shi-Tomasi角点检测
cv2.goodFeaturesToTrack() 可以检测图像中的角点,并返回一个包含检测到的角点坐标的数组。
- image:输入图像,必须为灰度图像。
- maxCorners:返回的最大角点数量(0表示无限制)。
- qualityLevel:角点的最小质量水平(小于1.0的正数,一般在0.01-0.1之间)。
- minDistance:角点之间的最小欧式距离。
- blockSize:计算协方差矩阵时使用的邻域大小。
- useHarrisDetector:是否使用 Harris 角点检测方法。
- k:计算 Harris 角点响应函数时的自由参数,通常取值为 0.04 到 0.06。
img = cv2.imread('img/corner.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(gray,maxCorners=10,qualityLevel=0.01,minDistance=10)
corners = np.int0(corners)# 将浮点型32位的转换为整形的
for i in corners:# 遍历角并绘制
x,y = i.ravel()
cv.circle(img,(x,y),3,(255,0,0),-1)
cv.imshow('Shi-Tomasi',img)
cv.waitKey(0)
cv.destroyAllWindows()
尺度不变特征变换算法
SIFT(Scale-Invariant Feature Transform)是一种基于尺度空间的特征提取算法,可在不同尺度和旋转下提取出稳定的特征点,并且对于缩放、旋转、平移等变化具有不变性。
sift = cv.SIFT_create([, nfeatures[, nOctaveLayers[, contrastThreshold[, edgeThreshold[, sigma]]]]])
- nfeatures:提取的最大特征点数,默认为0,表示不限制。
- nOctaveLayers:金字塔每组的层数,默认为3。
- contrastThreshold:用于特征点提取的阈值,取值范围为0到1之间。
- edgeThreshold:边缘阈值,用于排除边缘响应过大的点。
- sigma:高斯滤波系数,用于构建高斯金字塔。
注:SIFT算法是一种计算密集的算法,对于大型图像或大量特征点的场景,可能会耗费很长时间。特征点的数量和质量决定了SIFT算法的效果,可以根据需要调整算法参数以获得更好的效果。
img = cv2.imread('img/corner.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 创建一个 SIFT 特征检测器
sift = cv.SIFT_create()
# 进行检测,返回关键点数组 keypoints
kp = sift.detect(gray, None)
# cv.drawKeypoints()是OpenCV 中用于绘制关键点的函数之一。它可以将检测到的关键点绘制在图像上,以便于我们观察和分析。
img = cv.drawKeypoints(img, kp,outImage=None)
cv.imshow('SIFT',img)
cv.waitKey(0)
cv.destroyAllWindows()
sift.detectAndCompute() 是 OpenCV 中用于提取 SIFT 特征的函数之一。它可以在给定的图像中检测关键点,并计算这些关键点的 SIFT 描述符。
- image:输入图像,必须为灰度图像。
- mask:掩膜图像,用于指定哪些像素需要进行特征提取。
- keypoints:表示检测到的关键点,是一个N x 1的数组,其中N表示关键点的数量,每个关键点由一个cv2.KeyPoint对象表示,其中包括关键点的坐标、尺寸、方向等信息。
- descriptors:表示检测到的关键点的特征描述子,是一个N x M的数组,其中N表示关键点的数量,M表示每个关键点的特征向量的维度。
img = cv2.imread('img/corner.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv.SIFT_create()
# 进行检测,kp为关键点列表,des为numpy的数组,为关键点数目*128
kp,des = sift.detectAndCompute(gray, None)# None表示可以对指定区域mask进行关键点描述
# 可以将检测到的关键点绘制在图像上,以便于我们观察和分析
img = cv.drawKeypoints(img, kp,outImage=None)
cv.imshow('SIFT detectAndCompute',img)
cv.waitKey(0)
cv.destroyAllWindows()
ORB 是 Oriented FAST and Rotated BRIEF 的缩写,是一种快速且具有旋转不变性的特征检测算法。
img = cv2.imread('img/corner.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 注意也可以在创建ORB对象时,声明一些参数,即要提取的特征点数量为 1000,金字塔层数为 8,尺度因子为 1.2,边缘阈值为 15,窗口大小为 31
orb = cv.ORB_create(nfeatures=500, scaleFactor=1.2, nlevels=8, edgeThreshold=15, patchSize=31)
# 进行检测
kp,des = orb .detectAndCompute(gray, None)
# 绘制keypoints
img = cv.drawKeypoints(img, kp,outImage=None)
cv.imshow('ORB',img)
cv.waitKey(0)
cv.destroyAllWindows()