c++ - segmentacion - Cómo alinear 2 imágenes según su contenido con OpenCV
reconocimiento de imagenes python (2)
Soy totalmente nuevo en OpenCV y he comenzado a sumergirme en él. Pero necesitaría un poco de ayuda.
Entonces quiero combinar estas 2 imágenes:
Me gustaría que las 2 imágenes coincidan en sus bordes (ignorando la parte derecha de la imagen por el momento)
¿Puede alguien señalarme en la dirección correcta? He intentado usar la función findTransformECC
. Aquí está mi implementación:
cv::Mat im1 = [imageArray[1] CVMat3];
cv::Mat im2 = [imageArray[0] CVMat3];
// Convert images to gray scale;
cv::Mat im1_gray, im2_gray;
cvtColor(im1, im1_gray, CV_BGR2GRAY);
cvtColor(im2, im2_gray, CV_BGR2GRAY);
// Define the motion model
const int warp_mode = cv::MOTION_AFFINE;
// Set a 2x3 or 3x3 warp matrix depending on the motion model.
cv::Mat warp_matrix;
// Initialize the matrix to identity
if ( warp_mode == cv::MOTION_HOMOGRAPHY )
warp_matrix = cv::Mat::eye(3, 3, CV_32F);
else
warp_matrix = cv::Mat::eye(2, 3, CV_32F);
// Specify the number of iterations.
int number_of_iterations = 50;
// Specify the threshold of the increment
// in the correlation coefficient between two iterations
double termination_eps = 1e-10;
// Define termination criteria
cv::TermCriteria criteria (cv::TermCriteria::COUNT+cv::TermCriteria::EPS, number_of_iterations, termination_eps);
// Run the ECC algorithm. The results are stored in warp_matrix.
findTransformECC(
im1_gray,
im2_gray,
warp_matrix,
warp_mode,
criteria
);
// Storage for warped image.
cv::Mat im2_aligned;
if (warp_mode != cv::MOTION_HOMOGRAPHY)
// Use warpAffine for Translation, Euclidean and Affine
warpAffine(im2, im2_aligned, warp_matrix, im1.size(), cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);
else
// Use warpPerspective for Homography
warpPerspective (im2, im2_aligned, warp_matrix, im1.size(),cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);
UIImage* result = [UIImage imageWithCVMat:im2_aligned];
return result;
He intentado jugar con termination_eps
y number_of_iterations
e incrementé / disminuí esos valores, pero realmente no hicieron una gran diferencia.
Así que aquí está el resultado:
¿Qué puedo hacer para mejorar mi resultado?
EDIT: he marcado los bordes problemáticos con círculos rojos. El objetivo es deformar la imagen inferior y hacerla coincidir con las líneas de la imagen de arriba:
Hice un poco de investigación y me temo que la función findTransformECC
no me dará el resultado que me gustaría tener :-(
Algo importante que agregar: en realidad tengo una matriz de esas "rayas" de imagen, 8 en este caso, todas se parecen a las imágenes que se muestran aquí y todas deben procesarse para que coincidan con la línea. Intenté experimentar con la función de stitch
de OpenCV, pero los resultados fueron horribles.
EDITAR:
Aquí están las 3 imágenes de origen:
El resultado debería ser algo como esto:
Transformé cada imagen a lo largo de las líneas que deberían coincidir. Las líneas que están demasiado alejadas entre sí pueden ignorarse (la sombra y el camino en la parte derecha de la imagen)
Por sus imágenes, parece que se superponen. Como dijo que la función de stitch
no le dio los resultados deseados, implemente su propia costura. Estoy tratando de hacer algo parecido a eso también. Aquí hay un tutorial sobre cómo implementarlo en c ++: https://ramsrigoutham.com/2012/11/22/panorama-image-stitching-in-opencv/
Puede usar el algoritmo de Hough con un umbral alto en dos imágenes y luego comparar las líneas verticales en ambos; la mayoría de ellas deberían desplazarse un poco, pero mantener el ángulo.
Esto es lo que obtuve al ejecutar este algoritmo en una de las imágenes:
Filtrar las líneas horizontales debe ser fácil (ya que se representan como Vec4i), y luego puede alinear las líneas restantes.
Aquí está el ejemplo de usarlo en la documentación de OpenCV .
ACTUALIZACIÓN: otro pensamiento. La alineación de las líneas se puede hacer con el concepto similar a cómo funciona la función de correlación cruzada. No importa si la imagen 1 tiene 10 líneas, y la imagen 2 tiene 100 líneas, la posición del turno con la mayoría de las líneas alineadas (que es, en su mayoría, el máximo para CCF) debe ser bastante cercana a la respuesta, aunque esto podría requerir algunos ajustes - por ejemplo, dar peso a cada línea en función de su longitud, ángulo, etc. La visión de la computadora nunca tiene una forma directa, ¿eh? :)
ACTUALIZACIÓN 2: en realidad me pregunto si tomar la línea de los píxeles inferiores de la imagen superior como una matriz 1 y la línea de los píxeles superiores de la imagen inferior como la matriz 2 y ejecutar CCF general sobre ellos, y luego usar su máximo como cambio podría funcionar también ... Pero creo sería un método conocido si funcionó bien.