Lo que haremos sera colocar la imagen de la izquierda con la misma orientación y escala que la imagen de la derecha. Tomaremos de referencia las características comunes entre ambas imágenes (el libro principalmente). ¿Cómo encontramos estos puntos? En 2004 David Lowe publicó un algoritmo llamado SIFT (Scale-Invariant Feature Transform) que permite encontrar puntos clave invariantes a las rotaciones y, en buena medida, a los cambios de iluminación. Los puntos clave con mejor correspondencia entre ambas imágenes se ven así:
Este algoritmo está patentado y no aparece en la instalación estándar de OpenCV. Deben seguir las instrucciones que puse en mi entrada anterior para poderlo utilizar. El código que escribí es una modificación para SIFT del código que pueden encontrar acá. Lo he reducido y comentado para mejor claridad:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Created on Sat Sep 21 10:22:29 2019 | |
@author: Rodolfo Escobar [version para SIFT] | |
""" | |
import cv2 | |
import numpy as np | |
import matplotlib.pyplot as plt | |
# Importar imagenes como escala de grises | |
ImA = cv2.imread('Ref.JPG',0) | |
ImB = cv2.imread('Des.JPG',0) | |
#--------------------- SIFT ------------------------------- | |
sift = cv2.xfeatures2d.SIFT_create() | |
keypointsA, descriptorsA = sift.detectAndCompute(ImA, None) | |
keypointsB, descriptorsB = sift.detectAndCompute(ImB, None) | |
#---------------------------------------------------------- | |
#---------------- Correspondencias ------------------------ | |
#NOTA: para SIFT no debe usarse la norma de Hamming | |
matcher = cv2.BFMatcher(cv2.NORM_L2,crossCheck=True) | |
matches = matcher.match(descriptorsA, descriptorsB, None) | |
# Ordenacion de correspondencias por distancias | |
matches.sort(key=lambda x: x.distance, reverse=False) | |
# Elegir solo un porcentaje de las correspondencias | |
# (las que tengan distancias más cortas) | |
Porcentaje_Corr = 0.05 | |
numMatches = int(len(matches) * Porcentaje_Corr) | |
matches = matches[:numMatches] | |
#--------------------------------------------------------- | |
# Grafica de correspondencias | |
imMatches = cv2.drawMatches(ImA, keypointsA, ImB, keypointsB, matches, None) | |
plt.imshow(imMatches) | |
plt.axis("off") | |
plt.show() | |
# Localizar correpondencias | |
points1 = np.zeros((len(matches), 2), dtype=np.float32) | |
points2 = np.zeros((len(matches), 2), dtype=np.float32) | |
# Arrays de puntos de la forma [[x0,y0],...,[xn,yn]] | |
for i, match in enumerate(matches): | |
points1[i, :] = keypointsA[match.queryIdx].pt | |
points2[i, :] = keypointsB[match.trainIdx].pt | |
# Encontrae matriz de homografía | |
h, mask = cv2.findHomography(points1, points2, cv2.RANSAC) | |
print(h) | |
# Aplicar homografía | |
height, width= ImB.shape | |
im1Reg = cv2.warpPerspective(ImA, h, (width, height)) | |
# Grafica de imagen alineada | |
plt.figure(2) | |
plt.imshow(im1Reg,cmap='gray') | |
plt.axis("off") | |
plt.show() |
No hay comentarios:
Publicar un comentario