I’m using opencv-python, and I am trying to visualize results from AKAZE keypoint matching for multiple images. While playing around with drawMatches, several questions arose. Below is the code, and my questions:
import cv2
template_image cv2.imread("img1.tif")
target_image cv2.imread("img2.tif")
akaze = cv2.AKAZE_create()
kp1, des1 = akaze.detectAndCompute(template_image, None)
kp2, des2 = akaze.detectAndCompute(target_image, None)
matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
matches = matcher.knnMatch(des1, des2, 2)
good = []
for m, n in matches:
if m.distance < 0.8 * n.distance:
good.append(m)
results = cv2.drawMatches(template_image,kp1,
target_image,kp2,
good,None,
(0,255,0),
flags=1)
What is the correct use of the DRAW_OVER_OUTIMG flag (flag “1”)? I tried the following, but I get an error: results = cv2.drawMatches(template_image, kp1, target_image, kp2, good, target_image, flags=1)
error: OpenCV(3.4.9) C:\projects\opencv-python\opencv\modules\features2d\src\draw.cpp:156: error: (-201:Incorrect size of input array) outImg has size less than need to draw img1 and img2 together in function 'cv::_prepareImgAndDrawKeypoints'
drawMatches takes takes only two images, but I would like to visualize keypoint matches between the template and multiple target images - is there any way to do this?
Can I change the image-matrix layout in drawMatches?
thanks - but, sorry, I think you misunderstood me: it was working fine with any of the flags before, except for flag 1 ( DRAW_OVER_OUTIMG: Output image matrix will not be created (Mat::create). Matches will be drawn on existing content of output image.)
is for the case, where you already have a preallocated image, that you want to reuse for drawing. it should have outimg.rows == a.rows == b.rows and outimg.cols = a.cols + b.cols (so they both fit in horizontally next to each other)
you’d also have to pass this image as argument 6 (where you have None)
if you don’t have such an image, pass None as outimg and use the DEFAULT flag, so it will automatically be allocated
and no, you cannot do this with multiple query images at the same time
it’s also a very good idea to NEVER use magic numbers. use the named constants that exist.
cv2.DrawMatchesFlags_DRAW_OVER_OUTIMG
these identifiers aren’t easy to find but it’s possible:
>>> [x for x in dir(cv2) if 'DrawMatchesFlags' in x]
['DrawMatchesFlags_DEFAULT', 'DrawMatchesFlags_DRAW_OVER_OUTIMG', 'DrawMatchesFlags_DRAW_RICH_KEYPOINTS', 'DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS']
drawMatches is a convenience function: it is easy but not flexible. And because of this often you come out with your own implementation. drawMatches takes only two images, and that’s it.
The function can’t change the layout. If you want a vertical layout, you can rotate both input images, rotate matches, and rotate back the output image. Not nice nor clean.
You can change the layout by generating your own output image and manipulating matches coordinates. Then you are one step away from making your own implementation.
Note: The main purpose of DRAW_OVER_OUTIMG is to let you draw different matches lines with different colors, like green for inliers and red for outliers. With this flag the function already needs input images to get the output coordinates of the second image on the output one.