我有两个图像的SIFT关键点(用Python + OpenCV 3计算)。 我想用它们的y坐标过滤它们。
具体来说,我想删除y坐标差异高于图像高度除以10的所有匹配点,例如: 如果两个匹配点是A(x1,y1)和B(x2,y2):
if abs(y2 - y1) > imageHeight / 10 then remove that maching points
。
这是我测试过的代码。我正在删除关键点,但不是我要删除的内容。
# Load the two images
img1 = cv2.imread(PATH + "image1.jpg", -1)
img2 = cv2.imread(PATH + "image2.jpg", -1)
# Get their dimensions
height, width = img1.shape[:2]
# Resize them (they are too big)
img1 = cv2.resize(img1, (width / 4, height / 4))
img2 = cv2.resize(img2, (width / 4, height / 4))
# Get the resized image's dimensions
height, width = img1.shape[:2]
# Initiate SIFT detector
sift = X2D.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
### Here the filtering attempt ###
# Alloc a new vector for filtered matches
filteredMatches = [None] * len(matches)
# Counter that will count how many matches I have at the end
counter = 0
# for each match
for i in range(len(matches)):
# Get the "img1" heypoint
leftPoint = kp1[ matches[i][0].queryIdx ].pt #'left' image
# Get the "img2" keypoint
rightPoint = kp2[ matches[i][0].trainIdx ].pt #'right' image
# substract the y-coordinate of both points and compare
# with height / 10
if( abs(leftPoint[1] - rightPoint[1]) < height / 10):
# if the difference is lower than higher / 10, add it
# to the new list and increment the counter:
filteredMatches[counter] = matches[i]
counter += 1
# fix the filtered list size
matches = matches[:counter]
我不确定我是否正确使用queryIdx
和trainIdx
,但根据这篇文章(What is `query` and `train` in openCV features2D)我认为是这样。
答案 0 :(得分:1)
我找到了解决方案。首先,根据drawMatchesKnn
文档:
keypoints1 [i]在keypoints2中有一个对应点[匹配[i]]
在我的代码中,'keypoints1'为kp1
,'keypoints2'为kp2
,'匹配'为matches
。
kp1
和kp2
之间的对应关系为:kp1[i] matches with kp2[ matches[i].trailIdx ].
这里的finally函数过滤关键点,删除所有y坐标高于图像的高度* n ,其中n是给定数字(介于0和1之间):
def filterMatches(kp1, kp2, matches, imgHeight, thresFactor = 0.4):
"""
Removes the matches that correspond to a pair of keypoints (kp1, kp2)
which y-coordinate difference is lower than imgHeight * thresFactor.
Args:
kp1 (array of cv2.KeyPoint): Key Points.
kp2 (array of cv2.KeyPoint): Key Points.
matches (array of cv2.DMATCH): Matches between kp1 and kp2.
imgHeight (Integer): height of the image that has produced kp1 or kp2.
thresFactor (Float): Use to calculate the threshold. Threshold is
imgHeight * thresFactor.
Returns:
array of cv2.DMATCH: filtered matches.
"""
filteredMatches = [None]*len(matches)
counter = 0
threshold = imgHeight * thresFactor
for i in range(len(kp1)):
srcPoint = kp1[ matches[i][0].queryIdx ].pt
dstPoint = kp2[ matches[i][0].trainIdx ].pt
diff = abs(srcPoint[1] - dstPoint[1])
if( diff < threshold):
filteredMatches[counter] = matches[i]
counter += 1
return filteredMatches[:counter]