I am using following code for matching surf features of the two images but unable to crop and align the image.
The original image,the rotated image and matched image are as follow.
I want to straight the rotated image just like the original image and crop the straight aligned image. I have tried geometric transform but failed to align the image.
import numpy
import cv2
############### Image Matching ###############
def match_images(img1, img2):
"""Given two images, returns the matches"""
detector = cv2.SURF(400, 5, 5)
matcher = cv2.BFMatcher(cv2.NORM_L2)
kp1, desc1 = detector.detectAndCompute(img1, None)
kp2, desc2 = detector.detectAndCompute(img2, None)
raw_matches = matcher.knnMatch(desc1, trainDescriptors = desc2, k = 2)
kp_pairs = filter_matches(kp1, kp2, raw_matches)
return kp_pairs
def filter_matches(kp1, kp2, matches, ratio = 0.75):
mkp1, mkp2 = [], []
for m in matches:
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
m = m[0]
mkp1.append( kp1[m.queryIdx] )
mkp2.append( kp2[m.trainIdx] )
kp_pairs = zip(mkp1, mkp2)
return kp_pairs
############### Match Diplaying ###############
def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
vis = numpy.zeros((max(h1, h2), w1+w2), numpy.uint8)
vis[:h1, :w1] = img1
vis[:h2, w1:w1+w2] = img2
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
if H is not None:
corners = numpy.float32([[0, 0], [w1, 0], [w1, h1], [0, h1]])
corners = numpy.int32( cv2.perspectiveTransform(corners.reshape(1, -1, 2), H).reshape(-1, 2) + (w1, 0) )
cv2.polylines(vis, [corners], True, (255, 255, 255))
if status is None:
status = numpy.ones(len(kp_pairs), numpy.bool_)
p1 = numpy.int32([kpp[0].pt for kpp in kp_pairs])
p2 = numpy.int32([kpp[1].pt for kpp in kp_pairs]) + (w1, 0)
green = (0, 255, 0)
red = (0, 0, 255)
white = (255, 255, 255)
kp_color = (51, 103, 236)
for (x1, y1), (x2, y2), inlier in zip(p1, p2, status):
if inlier:
col = green
cv2.circle(vis, (x1, y1), 2, col, -1)
cv2.circle(vis, (x2, y2), 2, col, -1)
else:
col = red
r = 2
thickness = 3
cv2.line(vis, (x1-r, y1-r), (x1+r, y1+r), col, thickness)
cv2.line(vis, (x1-r, y1+r), (x1+r, y1-r), col, thickness)
cv2.line(vis, (x2-r, y2-r), (x2+r, y2+r), col, thickness)
cv2.line(vis, (x2-r, y2+r), (x2+r, y2-r), col, thickness)
vis0 = vis.copy()
for (x1, y1), (x2, y2), inlier in zip(p1, p2, status):
if inlier:
cv2.line(vis, (x1, y1), (x2, y2), green)
cv2.imshow(win, vis)
cv2.waitKey(0)
cv2.destroyAllWindows()
def draw_matches(window_name, kp_pairs, img1, img2):
"""Draws the matches for """
mkp1, mkp2 = zip(*kp_pairs)
p1 = numpy.float32([kp.pt for kp in mkp1])
p2 = numpy.float32([kp.pt for kp in mkp2])
if len(kp_pairs) >= 4:
H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0)
else:
H, status = None, None
if len(p1):
explore_match(window_name, img1, img2, kp_pairs, status, H)
############### Test ###############
img1 = cv2.imread('orig.jpg', 0)
img2 = cv2.imread('rota.jpg', 0)
cv2.imshow('REAL',img1)
cv2.imshow('Rotated',img2)
#img_1= cv2.resize(img1,(500,600))
#img_2= cv2.resize(img2,(500,600))
kp_pairs = match_images(img1, img2)
if kp_pairs:
draw_matches('Matching Features', kp_pairs, img1, img2)
else:
print "No matches found"
Use the norm() Function of OpenCV to Compare Images If the two images that we want to compare have the same size and orientation, we can use the norm() function of OpenCV. This function finds errors present in identical pixels of the two images.
It takes the descriptor of one feature in first set and is matched with all other features in second set using some distance calculation. And the closest one is returned. For BF matcher, first we have to create the BFMatcher object using cv.
Maybe you want the result like follow.
Found matches in the scene:
Crop the object:
Env: Python 3.5 + OpenCV 3.3
Here is sample code to crop the object(img1) from the scene(img2).
## Crop the matched region from scene
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)
perspectiveM = cv2.getPerspectiveTransform(np.float32(dst),pts)
found = cv2.warpPerspective(img2,perspectiveM,(w,h))
cv2.imwrite("found.png", found)
Full code with description in my another answer:
How do I use the relationships between Flann matches to determine a sensible homography?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With