Nous collons plusieurs photos en une longue en utilisant la vision par ordinateur

Les articles précédents décrivaient la méthode en six points pour déballer les étiquettes et comment nous avons formé le réseau neuronal . Cet article décrit comment coller des fragments réalisés sous différents angles en une seule longue image.





Les étiquettes sont pré-segmentées et déployées par le réseau de neurones décrit dans l'article précédent.







Comment fonctionne généralement le collage? Vous devez prendre deux photos qui se chevauchent, calculer le décalage mutuel et superposer l'une sur l'autre. Cela semble assez simple, mais passons en revue chacune des étapes.



Pour calculer le décalage mutuel, vous devez trouver des objets présents dans les deux images et calculer d'une manière ou d'une autre la transformation des points d'une image à une autre. Ce décalage peut être représenté par une matrice de transformation, où les éléments de la matrice codent plusieurs transformations à la fois - mise à l'échelle, translation et rotation.



Il existe un excellent tableau sur wikipedia qui montre comment et quels éléments affectent la transformation.



Comme vous pouvez le voir dans l'image ci-dessous, il y a assez d'objets communs:







mais il y a un problème avec les objets sélectionnés - ils sont difficiles à détecter de manière algorithmique. Au lieu de cela, il est habituel de rechercher des objets plus simples - les soi-disant «coins», ce sont aussi des descripteurs («descripteurs», «caractéristiques»).



Il y a un excellent article dans la documentation OpenCV sur les raisons pour lesquelles les coins - en bref, définir une ligne est facile, mais cela ne vous donne qu'une coordonnée. Par conséquent, il est également nécessaire de détecter la deuxième ligne (non parallèle). S'ils convergent en un point, alors cet endroit est idéal pour trouver un descripteur, c'est aussi un coin (bien que les vrais descripteurs ne soient pas des coins au sens géométrique du mot).



L'un des algorithmes pour trouver des descripteurs est SIFT (Scale-Invariant Feature Transform). Malgré le fait qu'il ait été inventé en 1999, il est très populaire en raison de sa simplicité et de sa fiabilité. Cet algorithme a été breveté, mais le brevet a expiré ce printemps (2020). Cependant, ils n'ont pas réussi à le transférer vers la version principale d'OpenCV, vous devez donc utiliser une version spéciale non libre.



Alors trouvons des coins similaires dans les deux images:



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






features_right = sift.detectAndCompute(left_image, None)






Utilisons le matcher Flann - il a de bonnes performances même si le nombre de descripteurs est grand.



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)


Les lignes jaunes montrent comment le matcher a trouvé des correspondances.







Comme vous pouvez le voir clairement, il n'y a qu'environ la moitié des correspondances correctes. Cependant, si les correspondances correctes donnent toujours la même transformation, alors les correspondances incorrectes montrent une direction chaotiquement nouvelle. Ceux. théoriquement, ils peuvent être séparés les uns des autres: l'







un des algorithmes permettant de trouver la transformation correcte est RANSAC. Cet algorithme fonctionne très bien lorsque vous souhaitez séparer les bonnes valeurs du bruit - c'est exactement le cas.



Heureusement, OpenCV a déjà des fonctions qui trouveront la matrice de transformation par correspondance en utilisant RANSAC, c'est-à-dire en fait, vous n'avez rien à écrire.



Utilisons la fonction estimationAffinePartial2D qui recherche les transformations suivantes: rotation, mise à l'échelle et translation (4 degrés de liberté).



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


Une fois la matrice de transformation trouvée, nous pouvons transformer la bonne image pour la coller.



Fragment de gauche: Fragment de





droite:







Tout d'abord, utilisons la manière la plus simple de coller des fragments ensemble, lorsque chaque pixel de leur intersection est calculé comme une moyenne. Malheureusement, le résultat est médiocre - l'image double sensiblement, en particulier près de la ligne de collage.







Dans l'animation, la différence entre les deux images est plus clairement visible:







ce n'est pas surprenant - les photos ont été prises sous des angles différents, le réseau de neurones les a également tournées légèrement différemment et, par conséquent, il y avait de petites différences.



Pour un collage sans couture, il est nécessaire de compenser la distorsion non linéaire. La distorsion peut être représentée comme un champ vectoriel de la même résolution que l'image d'origine, mais au lieu de la couleur, un décalage sera encodé dans chaque pixel. Ce champ vectoriel est appelé «flux optique».



En général, il existe différentes méthodes pour calculer le flux optique - certaines d'entre elles sont directement intégrées à OpenCV, et il existe également des réseaux de neurones spéciaux.



Dans notre cas, j'omettrai la technique spécifique, mais je publierai le résultat:







Mais la compensation doit être effectuée au prorata des deux fragments. Pour ce faire, nous allons le diviser en deux matrices: le







fragment de gauche sera compensé de gauche à droite de manière croissante, tandis que le fragment de droite - vice versa.



Maintenant, les deux fragments se chevauchent presque parfaitement:







Maintenant la superposition est géométriquement correcte, mais on observe un saut de luminosité très perceptible au niveau des coutures:







Ce problème peut être facilement corrigé si au lieu des valeurs moyennes, elles sont superposées avec un dégradé:







Avec cette approche, la couture n'est pas du tout visible:







En principe, il existe aussi d'autres techniques de collage, par exemple , le mélange multibande, qui sont utilisés pour assembler des panoramas, mais ils ne fonctionnent pas bien avec le texte - seule la compensation de flux optique peut supprimer complètement les images fantômes sur le texte.



Maintenant, nous collons l'image complète:







Version finale:







D'autres améliorations pourraient être la compensation de l'effet d'ombre (côté droit de l'image), ou encore plus de post-traitement de la couleur et du contraste. Vous pouvez également voir que la géométrie globale a légèrement souffert - les lignes de droite ont légèrement augmenté. Théoriquement, ce problème peut également être corrigé en ajoutant une correction d'échelle globale, mais ce n'est pas non plus une tâche complètement triviale.



Nous avons examiné le fonctionnement du collage, une solution toute faite est disponible ici sous la forme d'une API REST, je recommande également de consulter les liens suivants:






All Articles