How to draw bounding box on best matches?
Asked Answered
I

1

13

How can I draw a bounding box on best matches in BF MATCHER using Python?

Iodine answered 31/7, 2018 at 5:51 Comment(1)
Please read Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - the summary is that this is not an ideal way to address volunteers, and is probably counterproductive to obtaining answers. Please refrain from adding this to your questions.Forego
C
24

Here is a summary of the approach it should be a proper solution:

  1. Detect keypoints and descriptors on the query image (img1)
  2. Detect keypoints and descriptors on the target image (img2)
  3. Find the matches or correspondences between the two sets of descriptors
  4. Use the best 10 matches to form a transformation matrix
  5. Transform the rectangle around img1 based on the transformation matrix
  6. Add offset to put the bounding box at the correct position
  7. Display the result image (as below).

BF Matching Result Image (Preview)

Here is the code:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png', 0)          # query Image
img2 = cv2.imread('box_in_scene.png',0)  # target Image

# Initiate SIFT detector
orb = cv2.ORB_create()

# find the keypoints and descriptors with ORB
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Match descriptors.
matches = bf.match(des1,des2)

# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)

good_matches = matches[:10]

src_pts = np.float32([ kp1[m.queryIdx].pt for m in good_matches     ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good_matches ]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w = img1.shape[:2]
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)

dst = cv2.perspectiveTransform(pts,M)
dst += (w, 0)  # adding offset

draw_params = dict(matchColor = (0,255,0), # draw matches in green color
               singlePointColor = None,
               matchesMask = matchesMask, # draw only inliers
               flags = 2)

img3 = cv2.drawMatches(img1,kp1,img2,kp2,good_matches, None,**draw_params)

# Draw bounding box in Red
img3 = cv2.polylines(img3, [np.int32(dst)], True, (0,0,255),3, cv2.LINE_AA)

cv2.imshow("result", img3)
cv2.waitKey()
# or another option for display output
#plt.imshow(img3, 'result'), plt.show()
Caressa answered 31/7, 2018 at 6:49 Comment(10)
Please add further descriptions to your answer that will enable people to understand it and know why it is a good solution. Code only dumps do not make good answers (worthy of being voted up)!Pyne
I have added comments in the code. Is it not enough?Caressa
The comments explain the individual statements but not why your solution should be chosen over another.Pyne
I would not suggest putting much more effort into this answer anyway - the question is too vague and is likely to close.Forego
Please do not add complaints about voting into posts - voting is anonymous and broadly, people are to be allowed to vote how they will. We try to resist urgent begging anyway - if you see a zero-effort question that asks to jump the queue, you can answer it if you want, but I'd advise you not to if you can. Stack Overflow has a non-trivial help vampire problem, and the downvote you received may have been in that vein.Forego
OK, I am sorry, Thank you for the suggestion, I will edit the answer.Caressa
I want to draw bounding box/rectangle only on matches not draw the matches.Iodine
You can delete these two lines if you don't want to draw the matches: "draw_params = dict(matchColor = (0,255,0), # draw matches in green color singlePointColor = None, matchesMask = matchesMask, # draw only inliers flags = 2)" "img3 = cv2.drawMatches(img1,kp1,img2,kp2,good_matches, None,**draw_params)"Caressa
okay i removed these lines but how to draw bounding box around matches??Iodine
"draw bounding box around matches", do you mean draw a rectangle around the green lines? or draw a rectangle around the two sets of matched keypoints?Caressa

© 2022 - 2024 — McMap. All rights reserved.