gradientDescents2/Panorama
1
1import cv22import numpy as np3 4def computeDes(img1, img2):5 6 # Convert images to grayscale7 gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)8 gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)9 10 # Initialize the feature detector and extractor (e.g., SIFT)11 sift = cv2.SIFT_create()12 13 # Detect keypoints and compute descriptors for both images14 keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)15 keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)16 17 return (keypoints1, descriptors1), (keypoints2, descriptors2)18 19def feature_matching(keypoints1, descriptors1, keypoints2, descriptors2):20 21 # Initialize the feature matcher using FLANN matching22 index_params = dict(algorithm=0, trees=5)23 search_params = dict(checks=50)24 flann = cv2.FlannBasedMatcher(index_params, search_params)25 26 # Select the top N matches27 num_matches = 5028 # Match descriptors using FLANN29 matches_flann = flann.match(descriptors1, descriptors2)30 31 # Sort the matches by distance (lower is better)32 matches= sorted(matches_flann, key=lambda x: x.distance)[:num_matches]33 34 # Draw the top N matches35 # image_matches_flann = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches_flann[:num_matches], None)36 37 # Extract matching keypoints38 src_points = np.float32([keypoints1[match.queryIdx].pt for match in matches]).reshape(-1, 1, 2)39 dst_points = np.float32([keypoints2[match.trainIdx].pt for match in matches]).reshape(-1, 1, 2)40 41 return src_points, dst_points42 43def findHomography(src_points, dst_points):44 homography, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5.0)45 return homography46 47def stitImage(right_img, left_img):48 49 (keypoints1, descriptors1), (keypoints2, descriptors2) = computeDes(right_img, left_img)50 51 src_points, dst_points = feature_matching(keypoints1, descriptors1, keypoints2, descriptors2)52 53 homography = findHomography(src_points, dst_points)54 55 h1, w1 = right_img.shape[:2]56 h2, w2 = left_img.shape[:2]57 result = cv2.warpPerspective(right_img, homography, (w1+w2, max(h1,h2)))58 # result[0:h2, 0:w2] = left_img59 result = blend_imgs(left_img, result, 50)60 # cv2.imwrite("r2.jpg", result)61 62 result = crop(result)63 64 return result65 66def blend_imgs(img1, img2, width_overlap):67 h1, w1 = img1.shape[:2]68 h2, w2 = img2.shape[:2]69 for y in range(h1):70 for x in range(w1):71 if x >= (w1 - width_overlap):72 img1[y,x] = img1[y,x]*((w1-x)/width_overlap)73 74 for y in range(h2):75 for x in range(w1):76 if x >= (w1 - width_overlap):77 img2[y,x] = img2[y,x]*((x+width_overlap - w1)/width_overlap)78 79 img2[:,w1 - width_overlap: w1] += img1[:,-width_overlap:]80 81 img2[0:h1, 0:w1 - width_overlap] = img1[:,0:w1 - width_overlap]82 83 return img284 85def crop(img):86 87 # if img.dtype == np.float64:88 # img = (img * 255).astype(np.uint8)89 90 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)91 92 # Create binary mask to identify dest image93 _, binary_mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)94 95 # Find contours around dest image96 contours, _ = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)97 98 # Find the min boundary 99 x, y, w, h = cv2.boundingRect(contours[0])100 101 # crop image102 cropped_image = img[y:y+h, x:x+w]103 104 return cropped_image105 106l_img = cv2.imread("images/left.jpg")107r_img = cv2.imread("images/right.jpg")108 109if __name__ == "__main__":110 111 result = stitImage(r_img, l_img)112 cv2.imshow("Stit Image", result)113 cv2.waitKey(0)114 cv2.destroyAllWindows()