目标
本章节中,
- 我们将结合特征匹配,用calib3d模块查找单应性以达到从复杂图像中识别出已知对象的目的。
基本原理
上节课我们做了什么?我们使用一个queryImage,在其中找到一些特征点,我们使用另一个trainImage,也找到了这个图像中的特征,我们找到了它们之间的最佳匹配。简而言之,我们在另一张杂乱的图像中找到了一个物体的某些部分的位置。这些信息足以准确地在trainImage上找到目标。
为此,我们可以使用calib3d模块中的一个函数,即cv.findHomography()。如果我们从这两幅图像中传递一组点,它就会找到那个物体的透视变换。然后我们可以使用cv.perspective tivetransform()来查找对象。它至少需要四个正确的点来找到转换。我们已经看到,在匹配过程中可能会出现一些可能影响结果的错误。为了解决这个问题,算法使用RANSAC或least_mid(可以由标志决定)。因此,提供正确估计的良好匹配称为内点,其余的称为外点。findhomography()返回一个掩码,该掩码指定内点和外点。我们来测试一下:
代码
首先,像往常一样,让我们在图像中找到SIFT特性,并应用比值测试找到最佳匹配。
import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltMIN_MATCH_COUNT = 10img1 = cv.imread('box.png',0) # queryImageimg2 = cv.imread('box_in_scene.png',0) # trainImage# Initiate SIFT detectorsift = cv.xfeatures2d.SIFT_create()# find the keypoints and descriptors with SIFTkp1, des1 = sift.detectAndCompute(img1,None)kp2, des2 = sift.detectAndCompute(img2,None)FLANN_INDEX_KDTREE = 1index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)search_params = dict(checks = 50)flann = cv.FlannBasedMatcher(index_params, search_params)matches = flann.knnMatch(des1,des2,k=2)# store all the good matches as per Lowe's ratio test.good = []for m,n in matches: if m.distance < 0.7*n.distance: good.append(m)
现在,我们设置了一个条件,即至少有10个匹配项(MIN_MATCH_COUNT定义)在其中查找对象。否则,只需显示一条消息,说明没有足够的匹配项。
如果找到足够的匹配项,我们将提取两个图像中匹配的关键点的位置。它们被传递来寻找透视变换。一旦我们得到这个3x3变换矩阵,我们就用它把queryImage的角变换成trainImage中的对应点。然后画出来。
if len(good)>MIN_MATCH_COUNT: src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2) M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC,5.0) matchesMask = mask.ravel().tolist() h,w,d = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) dst = cv.perspectiveTransform(pts,M) img2 = cv.polylines(img2,[np.int32(dst)],True,255,3, cv.LINE_AA)else: print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) ) matchesMask = NoneFinally we draw our inliers (if successfully found the object) or matching keypoints (if failed).draw_params = dict(matchColor = (0,255,0), # draw matches in green color singlePointColor = None, matchesMask = matchesMask, # draw only inliers flags = 2)img3 = cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)plt.imshow(img3, 'gray'),plt.show()
参见下面的结果。在杂乱的图像中,对象以白色标记:
![bf85733e9f81d2a61672cf5c18dc8181.png](https://i-blog.csdnimg.cn/blog_migrate/b7ada67436f75f580269ba23908fc8a4.jpeg)
到此为止,我们认真过了一遍openCV官网对图像特征点检测提取匹配的各种算法,以及它们各自的优缺点,接下来的章节,看看怎么运用这些算法到我们实际问题中来。