Python使⽤Opencv实现图像特征检测与匹配
----------欢迎加⼊学习交流QQ:657341423
特征检测是计算机对⼀张图像中最为明显的特征进⾏识别检测并将其勾画出来。⼤多数特征检测都会涉及图像的⾓点、边和斑点的识别、或者是物体的对称轴。
⾓点检测 是由Opencv的cornerHarris函数实现,其他函数参数说明如下:
# cornerHarris参数:
# src - 数据类型为 float32 的输⼊图像。
# blockSize - ⾓点检测中要考虑的领域⼤⼩。
# ksize - Sobel 求导中使⽤的窗⼝⼤⼩
# k - Harris ⾓点检测⽅程中的⾃由参数,取值参数为 [0,04,0.06].
以国际象棋为例,这是计算机视觉最为常见的分析对象,如图所⽰:
⾓点检测代码如下:
import cv2
import numpy as np
img = cv2.imread('chess_board.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cornerHarris函数图像格式为 float32 ,因此需要将图像转换 float32 类型
gray = np.float32(gray)
# cornerHarris参数:
# src - 数据类型为 float32 的输⼊图像。
# blockSize - ⾓点检测中要考虑的领域⼤⼩。
# ksize - Sobel 求导中使⽤的窗⼝⼤⼩
# k - Harris ⾓点检测⽅程中的⾃由参数,取值参数为 [0,04,0.06].
dst = Harris(src=gray, blockSize=9, ksize=23, k=0.04)
# 变量a的阈值为0.01 * dst.max(),如果dst的图像值⼤于阈值,那么该图像的像素点设为True,否则为False # 将图⽚每个像素点根据变量a的True和False进⾏赋值处理,赋值处理是将图像⾓点勾画出来
a = dst>0.01 * dst.max()
img[a] = [0, 0, 255]
# 显⽰图像
while (True):
cv2.imshow('corners', img)
if cv2.waitKey(120) & 0xff == ord("q"):
break
cv2.destroyAllWindows()
运⾏代码,结果如图所⽰:
但有时候,图像的像素⼤⼩对⾓点存在⼀定的影响。⽐如图像越⼩,⾓点看上去趋向近似⼀条直线,这样很容易造成⾓点的丢失。如果按照上述的检测⽅法,会造成⾓点检测结果不相符,因此引⼊DoG和SIFT算法进⾏检测。Opencv的SIFT类是DoG和SIFT算法组合。
DoG是对同⼀图像使⽤不同⾼斯滤波器所得的结果。
SIFT是通过⼀个特征向量来描述关键点周围区域的情况。
我们以下图为例:
import cv2
# 读取图⽚并灰度处理
imgpath = 'varese.jpg'
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建SIFT对象
sift = cv2.xfeatures2d.SIFT_create()
# 将图⽚进⾏SURF计算,并出⾓点keypoints,keypoints是检测关键点
# descriptor是描述符,这是图像⼀种表⽰⽅式,可以⽐较两个图像的关键点描述符,可作为特征匹配的⼀种⽅法。
keypoints, descriptor = sift.detectAndCompute(gray, None)
# cv2.drawKeypoints() 函数主要包含五个参数:
# image: 原始图⽚
# keypoints:从原图中获得的关键点,这也是画图时所⽤到的数据
# outputimage:输出
# color:颜⾊设置,通过修改(b,g,r)的值,更改画笔的颜⾊,b=蓝⾊,g=绿⾊,r=红⾊。
# flags:绘图功能的标识设置,标识如下:
# cv2.DRAW_MATCHES_FLAGS_DEFAULT  默认值
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
# cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
# cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
img = cv2.drawKeypoints(image=img, outImage=img, keypoints = keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT, color = (51, 163, 236))
# 显⽰图⽚
cv2.imshow('sift_keypoints', img)
while (True):
if cv2.waitKey(120) & 0xff == ord("q"):
break
cv2.destroyAllWindows()
运⾏代码,结果如图所⽰:
除了SIFT算法检测之外,还有SURF特征检测算法,⽐SIFT算法快,并吸收了SIFT算法的思想。SURF采⽤Hessian算法检测关键点,⽽SURF是提取特征,这个与SIFT很像。Opencv的SURF类是Hessian算法和SURF算法组合。我们根据SIFT的代码进⾏修改,代码如下:
import cv2
# 读取图⽚并灰度处理
imgpath = 'varese.jpg'
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建SURF对象,对象参数float(4000)为阈值,阈值越⾼,识别的特征越⼩。
sift = cv2.xfeatures2d.SURF_create(float(4000))
# 将图⽚进⾏SURF计算,并出⾓点keypoints,keypoints是检测关键点
# descriptor是描述符,这是图像⼀种表⽰⽅式,可以⽐较两个图像的关键点描述符,可作为特征匹配
的⼀种⽅法。
keypoints, descriptor = sift.detectAndCompute(gray, None)
# cv2.drawKeypoints() 函数主要包含五个参数:
# image: 原始图⽚
# keypoints:从原图中获得的关键点,这也是画图时所⽤到的数据
# outputimage:输出
# color:颜⾊设置,通过修改(b,g,r)的值,更改画笔的颜⾊,b=蓝⾊,g=绿⾊,r=红⾊。
# flags:绘图功能的标识设置,标识如下:
# cv2.DRAW_MATCHES_FLAGS_DEFAULT  默认值
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
# cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
# cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
img = cv2.drawKeypoints(image=img, outImage=img, keypoints = keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT, color = (51, 163, 236))
# 显⽰图⽚
cv2.imshow('sift_keypoints', img)
while (True):
if cv2.waitKey(120) & 0xff == ord("q"):
break
rectangle函数opencvcv2.destroyAllWindows()
上述代码我们只修改sift = cv2.xfeatures2d.SURF_create(float(4000))即可实现SURF特征检测算法。运⾏结果如图所⽰: