Reputation: 5580
When I run the Flann KNN matcher, then there are certain times when the KNN matcher only returns one point because of which code after the matcher that relies on there being two points fails:
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(descriptors1, descriptors2, k=2)
# Retrieve good matches
good_matches = []
# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
if m.distance < 0.7*n.distance:
good_matches.append((m, n))
Throws this error:
Traceback (most recent call last):
File "main.py", line 161, in <module>
main(vid, video_file)
...
File "main.py", line 73, in consume_for_homography_error
matches = flann_matcher(descriptors1, descriptors2)
File "main.py", line 48, in flann_matcher
for i, (m, n) in enumerate(matches):
ValueError: need more than 1 value to unpack
What seems to be the problem here?
Upvotes: 3
Views: 2590
Reputation: 3030
Sometimes the algorithm can't find 2 potential matches for a single descriptor in the query image. When this happens you might get only 1, or possibly zero DMatch items in the list for that index. If there is one DMatch entry in the list, then that is the best entry for that descriptor and there is nothing else to compare it to, so we should simply accept it as a good match. For example:
good = []
for i in range(0, len(matches)):
if len(matches[i]) == 1:
m = matches[i][0]
good.append([m])
if len(matches[i]) > 1:
(m,n) = matches[i]
if m.distance < 0.75*n.distance:
good.append([m])
Upvotes: 0
Reputation: 73
The issue is that matches seems to be populated as a fixed length list of lists, in this case len(matches) == 500
even if the number of matches found is less than that.
Try adding this:
matches = [match for match in matches if len(match) == 2]
(or even better)
good_matches = [match[0] for match in matches if len(match) == 2 and match[0].distance
< .7*match[1].distance]
before the for loop to delete these (empty lists?).
Upvotes: 2
Reputation: 131
The matches collection returned by the knnMatch function is of List type where each element is again a list of 2 DMatch objects (because of k=2). So, when you apply enumerator on matches list, you will get index value and a List object in each iteration. Your code expects index value and a tuple in each iteration. That's where the problem is. Check out following code instead.
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(descriptors1, descriptors2, k=2)
# Retrieve good matches
good_matches = []
# ratio test as per Lowe's paper
for m,n in matches:
if m.distance < 0.7*n.distance:
good_matches.append((m, n))
Upvotes: 0