Spaces:
Sleeping
Sleeping
import numpy as np | |
import cv2 | |
from PIL import Image | |
class HomographicAlignment: | |
""" | |
Apply homographic alignment on background to match with the source image. | |
""" | |
def __init__(self): | |
self.detector = cv2.ORB_create() | |
self.matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE) | |
def __call__(self, src, bgr): | |
src = np.asarray(src) | |
bgr = np.asarray(bgr) | |
keypoints_src, descriptors_src = self.detector.detectAndCompute(src, None) | |
keypoints_bgr, descriptors_bgr = self.detector.detectAndCompute(bgr, None) | |
matches = self.matcher.match(descriptors_bgr, descriptors_src, None) | |
matches.sort(key=lambda x: x.distance, reverse=False) | |
num_good_matches = int(len(matches) * 0.15) | |
matches = matches[:num_good_matches] | |
points_src = np.zeros((len(matches), 2), dtype=np.float32) | |
points_bgr = np.zeros((len(matches), 2), dtype=np.float32) | |
for i, match in enumerate(matches): | |
points_src[i, :] = keypoints_src[match.trainIdx].pt | |
points_bgr[i, :] = keypoints_bgr[match.queryIdx].pt | |
H, _ = cv2.findHomography(points_bgr, points_src, cv2.RANSAC) | |
h, w = src.shape[:2] | |
bgr = cv2.warpPerspective(bgr, H, (w, h)) | |
msk = cv2.warpPerspective(np.ones((h, w)), H, (w, h)) | |
# For areas that is outside of the background, | |
# We just copy pixels from the source. | |
bgr[msk != 1] = src[msk != 1] | |
src = Image.fromarray(src) | |
bgr = Image.fromarray(bgr) | |
return src, bgr | |