Spaces:
Runtime error
Runtime error
| import cv2 | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import pdb | |
| def rotate_to_horizontal(image): | |
| # Rotate the image to horizontal (90 degrees counterclockwise) | |
| rotated_image = cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE) | |
| return rotated_image | |
| def rotate_to_vertical(image): | |
| # Rotate the image back to vertical (90 degrees clockwise) | |
| rotated_image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE) | |
| return rotated_image | |
| def plot_images(images): | |
| num_images = len(images) | |
| for i, image in enumerate(images): | |
| plt.figure(figsize=(6, 6)) | |
| plt.imshow(image) | |
| plt.title(f"Image {i+1}/{num_images}") | |
| plt.axis('off') | |
| plt.show() | |
| def image_stitching(image_paths): | |
| images = [cv2.imread(path) for path in image_paths] | |
| images = [image.astype(np.uint8) for image in images] | |
| images = [rotate_to_horizontal(image) for image in images] | |
| images = list(reversed(images)) | |
| if len(images) == 15: | |
| images = images[2:12] | |
| #plot_images(images) | |
| # Create a list to store the stitched images | |
| stitched_images = [] | |
| # Accumulated homography matrix for stitching | |
| accumulated_homography = np.eye(3) | |
| # Iterate through pairs of adjacent images and stitch them together | |
| for i in range(len(images) - 1): | |
| # Perform keypoint and feature descriptor extraction | |
| orb = cv2.ORB_create() | |
| keypoints_and_descriptors = [orb.detectAndCompute(image, None) for image in [images[i], images[i + 1]]] | |
| # Match the keypoints using Brute-Force Matcher | |
| bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) | |
| matches = bf.match(keypoints_and_descriptors[0][1], keypoints_and_descriptors[1][1]) | |
| # Filter the matches to remove outliers using RANSAC | |
| src_pts = np.float32([keypoints_and_descriptors[0][0][m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) | |
| dst_pts = np.float32([keypoints_and_descriptors[1][0][m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) | |
| M, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) | |
| # Accumulate the homography matrices | |
| accumulated_homography = np.dot(M, accumulated_homography) | |
| # Warp perspective and stitch the images | |
| stitched_image = cv2.warpPerspective(images[i + 1], accumulated_homography, | |
| (images[i].shape[1] + images[i + 1].shape[1], images[i].shape[0])) | |
| stitched_image[0:images[i].shape[0], 0:images[i].shape[1]] = images[i] | |
| # Remove the empty pixels and retain maximum image information | |
| # stitched_image = remove_empty_pixels(stitched_image) | |
| stitched_images.append(stitched_image) | |
| # Combine all stitched images into a final panorama | |
| final_panorama = stitched_images[0] | |
| for i in range(1, len(stitched_images)): | |
| final_panorama = cv2.warpPerspective(stitched_images[i], np.eye(3), | |
| (final_panorama.shape[1] + stitched_images[i].shape[1], final_panorama.shape[0])) | |
| final_panorama[0:stitched_images[i].shape[0], 0:stitched_images[i].shape[1]] = stitched_images[i] | |
| gray_images = [cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) for image in images[:2]] | |
| # Draw the keypoints on the images | |
| keypoints_drawn = [cv2.drawKeypoints(gray_image, kp[0], None, color=(0, 255, 0), | |
| flags=cv2.DrawMatchesFlags_DRAW_RICH_KEYPOINTS) for gray_image, kp in | |
| zip(gray_images, keypoints_and_descriptors[:2])] | |
| # Draw the matches on the images | |
| matches_drawn = cv2.drawMatches(images[0], keypoints_and_descriptors[0][0], images[1], | |
| keypoints_and_descriptors[1][0], matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) | |
| # Crop the final image to 512x512 centered around the middle | |
| cropped_final_panorama = final_panorama[:512, :512] | |
| rotated_final_panorama = rotate_to_vertical(cropped_final_panorama) | |
| return rotated_final_panorama |