我猜对于目标检测,我个人使用并推荐的是使用SIFT(尺度不变特征转换)或SURF算法,但请注意这些算法现在已被专利保护,不再包含在OpenCV 3中,仍然可在OpenCV2中使用。作为这个的良好替代方案,我更喜欢使用ORB,它是SIFT / SURF的开源实现。
使用SIFT描述符和比率测试的暴力匹配
在这里,我们使用BFMatcher.knnMatch()来获取k个最佳匹配项。在本例中,我们将取k=2,以便我们可以应用D.Lowe在他的论文中解释的比率测试。
import numpy as np
import cv2
from matplotlib import pyplot as plt
img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)
sift = cv2.SIFT()
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2)
plt.imshow(img3),plt.show()
![上述代码的示例输出如下图所示:](https://istack.dev59.com/b7MIi.webp)
使用FLANN进行匹配
FLANN代表Fast Library for Approximate Nearest Neighbors(快速最近邻库)。它包含一组针对大型数据集和高维特征的快速最近邻搜索优化算法。对于大型数据集,它比BFMatcher更快。我们将看到使用基于FLANN的匹配器的第二个示例。
对于基于FLANN的匹配器,我们需要传递两个字典,其中指定要使用的算法、相关参数等。第一个是IndexParams。对于各种算法,需要传递的信息在FLANN文档中有解释。总的来说,对于像SIFT、SURF等算法:
使用SIFT和FLANN的示例代码:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)
sift = cv2.SIFT()
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)
matchesMask = [[0,0] for i in xrange(len(matches))]
for i,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:
matchesMask[i]=[1,0]
draw_params = dict(matchColor = (0,255,0),
singlePointColor = (255,0,0),
matchesMask = matchesMask,
flags = 0)
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)
plt.imshow(img3,),plt.show()
请看下面的结果:
请参见下面的结果:
![enter image description here](https://istack.dev59.com/z4pui.webp)
但我建议使用ORB描述符进行暴力匹配
在此示例中,我使用ORB和Bruteforce匹配器。该代码从实时摄像头捕获帧,并从输入帧计算关键点、描述符并将其与存储的查询图像进行比较,通过执行相同的操作并返回匹配关键点长度,可以将其应用于上述使用SIFT算法而不是ORB的代码中。
import numpy as np
import cv2
from imutils.video import WebcamVideoStream
from imutils.video import FPS
MIN_MATCH_COUNT = 10
img1 = cv2.imread('input_query.jpg', 0)
orb = cv2.ORB()
kp1, des1 = orb.detectAndCompute(img1, None)
webcam = WebcamVideoStream(src=0).start()
fps = FPS().start()
while True:
img2 = webcam.read()
key = cv2.waitKey(10)
cv2.imshow('',img2)
if key == 1048603:
break
kp2, des2 = orb.detectAndCompute(img2, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
if not len(matches) > MIN_MATCH_COUNT:
print "Not enough matches are found - %d/%d" % (len(matches), MIN_MATCH_COUNT)
matchesMask = None
print len(matches)
fps.update()
fps.stop()
更详细的视频教程可以在这里找到:
https://www.youtube.com/watch?v=ZW3nrP2OyLQ,而且它是开源的:
https://gitlab.com/josemariasoladuran/object-recognition-opencv-python.git。