Pegamos varias fotos en una larga usando visión artificial

Los artículos anteriores describieron el método de seis puntos para desenvolver etiquetas y cómo entrenamos la red neuronal . Este artículo describe cómo pegar fragmentos hechos desde diferentes ángulos en una imagen larga.





Las etiquetas son presegmentadas y desplegadas por la red neuronal descrita en el artículo anterior.







¿Cómo funciona el encolado en general? Debe tomar dos fotografías superpuestas, calcular el desplazamiento mutuo y superponer una encima de la otra. Suena bastante simple, pero repasemos cada uno de los pasos.



Para calcular el cambio mutuo, debe encontrar algunos objetos que estén presentes en ambas imágenes y de alguna manera calcular la transformación de puntos de una imagen a otra. Este cambio se puede representar mediante una matriz de transformación, donde los elementos de la matriz codifican varias transformaciones a la vez: escalado, traslación y rotación.



Hay una excelente tabla en wikipedia que muestra cómo y qué elementos afectan la transformación.



Como puede ver en la imagen siguiente, hay bastantes objetos comunes:







pero hay un problema con los objetos seleccionados: son difíciles de detectar algorítmicamente. En cambio, se acostumbra buscar objetos más simples, los llamados "rincones", también son descriptores ("descriptores", "características").



Hay un gran artículo en la documentación de OpenCV sobre por qué las esquinas; en resumen, definir una línea es fácil, pero solo te da una coordenada. Por lo tanto, también es necesario detectar la segunda línea (no paralela). Si convergen en un punto, entonces este lugar es ideal para encontrar un descriptor, también es una esquina (aunque los descriptores reales no son esquinas en el sentido geométrico de la palabra).



Uno de los algoritmos para encontrar descriptores es SIFT (Transformación de características de escala invariable). A pesar de que fue inventado en 1999, es bastante popular debido a su simplicidad y fiabilidad. Este algoritmo ha sido patentado, pero la patente expiró esta primavera (2020). Sin embargo, no lograron transferirlo al ensamblaje principal de OpenCV, por lo que debe usar una compilación especial no libre.



Así que busquemos esquinas similares en ambas imágenes:



sift = cv2.xfeatures2d.SIFT_create()
features_left = sift.detectAndCompute(left_image, None)






features_right = sift.detectAndCompute(left_image, None)






Usemos el comparador de Flann: tiene un buen rendimiento incluso si el número de descriptores es grande.



KNN = 2
LOWE = 0.7
TREES = 5
CHECKS = 50

matcher = cv2.FlannBasedMatcher({'algorithm': 0, 'trees': TREES}, {'checks': CHECKS})
matches = matcher.knnMatch(left_descriptors, right_descriptors, k=KNN)

logging.debug("filtering matches with lowe test")

positive = []
for left_match, right_match in matches:
    if left_match.distance < LOWE * right_match.distance:
        positive.append(left_match)


Las líneas amarillas muestran cómo el comparador encontró coincidencias.







Como puede ver claramente, solo hay aproximadamente la mitad de las coincidencias correctas. Sin embargo, si las coincidencias correctas siempre dan la misma transformación, las incorrectas muestran una dirección caóticamente nueva. Aquellos. teóricamente, de alguna manera se pueden separar entre sí:







uno de los algoritmos para encontrar la transformación correcta es RANSAC. Este algoritmo funciona muy bien cuando desea separar buenos valores del ruido; este es exactamente el caso.



Afortunadamente, OpenCV ya tiene funciones que encontrarán la matriz de transformación mediante coincidencias usando RANSAC, es decir, de hecho, no es necesario que escriba nada.



Usemos la función estimaciónAffinePartial2D que busca las siguientes transformaciones: rotación, escalado y traslación (4 grados de libertad).



H, _ = cv2.estimateAffinePartial2D(right_matches, left_matches, False)


Una vez que se encuentra la matriz de transformación, podemos transformar la imagen correcta para pegar.



Fragmento izquierdo: Fragmento





derecho:







primero, usemos la forma más sencilla de pegar fragmentos, cuando cada píxel de su intersección se calcula como un promedio. Desafortunadamente, el resultado es regular: la imagen se duplica notablemente, especialmente cerca de la línea de pegado.







En la animación, la diferencia entre los dos cuadros es más claramente visible:







esto no es sorprendente: las fotos se tomaron desde diferentes ángulos, la red neuronal también las giró de manera ligeramente diferente y, como resultado, hubo pequeñas discrepancias.



Para un pegado perfecto, es necesario compensar la distorsión no lineal. La distorsión se puede representar como un campo vectorial de la misma resolución que la imagen original, solo que en lugar de color, se codificará un desplazamiento en cada píxel. Este campo vectorial se denomina "flujo óptico".



En general, existen diferentes métodos para calcular el flujo óptico; algunos de ellos están integrados directamente en OpenCV y también existen redes neuronales especiales.



En nuestro caso, omitiré la técnica específica, pero publicaré el resultado:







Pero la compensación debe realizarse en proporción a ambos fragmentos. Para ello, lo dividiremos en dos matrices: El







fragmento izquierdo se compensará de izquierda a derecha de forma creciente, mientras que el derecho - viceversa.



Ahora ambos fragmentos se superponen casi a la perfección:







Ahora la superposición es geométricamente correcta, pero observamos un salto muy notable en el brillo en las costuras:







este problema se puede corregir fácilmente si en lugar de valores promedio, se superponen con un gradiente:







con este enfoque, la costura no es visible en absoluto:







en principio, también hay otras técnicas de encolado, por ejemplo , mezcla multibanda, que se utilizan para unir panoramas, pero no funcionan bien con texto; solo la compensación de flujo óptico puede eliminar completamente las imágenes fantasma en el texto.



Ahora pegamos la imagen completa:







Versión final:







Otras mejoras podrían ser la compensación del efecto de sombra (lado derecho de la imagen) o incluso más posprocesamiento del color y el contraste. También puede ver que la geometría global ha sufrido un poco: las líneas de la derecha se han deslizado ligeramente hacia arriba. Teóricamente, este problema también se puede corregir agregando una corrección de escala global, pero esta tampoco es una tarea completamente trivial.



Examinamos cómo funciona el encolado, una solución lista está disponible aquí en forma de una API REST, También recomiendo buscar en los siguientes enlaces:






All Articles