Assemblage d'images OpenCV

L'assemblage d'images est une application importante en vision par ordinateur. Il permet d'assembler plusieurs images comportant des régions qui se chevauchent en une image plus grande.

Les scénarios d'application courants incluent la génération de panoramas, l'assemblage d'images satellites, etc.

OpenCV est une puissante bibliothèque de vision par ordinateur qui fournit de nombreux outils pour l'assemblage d'images.

Cet article détaillera comment utiliser OpenCV pour l'assemblage d'images, en mettant l'accent sur les techniques de détection et de mise en correspondance des points caractéristiques.

Scénarios d'application

  • Génération de panoramas : assembler plusieurs images en un panorama.
  • Assemblage de cartes : assembler plusieurs images de carte en une carte plus grande.
  • Traitement d'images médicales : assembler plusieurs images médicales en une image complète.

Processus de base de l'assemblage d'images

Le processus de base de l'assemblage d'images peut être divisé selon les étapes suivantes :

  1. Lecture des images: Lire les images à assembler.
  2. Détection des points caractéristiques: Détecter les points clés (points caractéristiques) dans chaque image.
  3. Mise en correspondance des points caractéristiques: Mettre en correspondance ces points caractéristiques entre différentes images.
  4. Calcul de la matrice de transformation: Calculer la matrice de transformation entre les images en fonction des points caractéristiques mis en correspondance.
  5. Fusion d'images: Assemblez les images selon la matrice de transformation, puis effectuez une fusion pour éliminer les artefacts d'assemblage.

Ensuite, nous expliquerons en détail l'implémentation de chaque étape.


1. Lecture des images

Tout d'abord, nous devons lire les images à assembler. OpenCV fournit lacv2.imread()fonction pour lire les images.

Exemple

import cv2

# Lire les images
image1 = cv2.imread('image1.jpg')
image2 = cv2.imread('image2.jpg')

# Vérifier si les images ont été lues avec succès
if image1 is None or image2 is None:
    print("Erreur : impossible de lire l'image")
    exit()

2. Détection des points caractéristiques

La détection des points caractéristiques est une étape clé dans l'assemblage d'images. OpenCV fournit une variété d'algorithmes de détection de points caractéristiques, tels que SIFT, SURF, ORB, etc. Ici, nous utilisons SIFT comme exemple.

Exemple

# Créer un détecteur SIFT
sift = cv2.SIFT_create()

# Détecter les points caractéristiques et les descripteurs
keypoints1, descriptors1 = sift.detectAndCompute(image1, None)
keypoints2, descriptors2 = sift.detectAndCompute(image2, None)

detectAndCompute()La fonction renvoie deux valeurs : les points clés et les descripteurs. Les points clés sont des points saillants de l'image, et les descripteurs sont des descriptions de ces points clés, utilisés pour l'appariement ultérieur.


3. Appariement des points caractéristiques

Après avoir détecté les points caractéristiques, nous devons faire correspondre ces points caractéristiques entre différentes images. OpenCV fournit leBFMatcherouFlannBasedMatcherpour effectuer l'appariement des points caractéristiques.

Exemple

# Créer un objet BFMatcher
bf = cv2.BFMatcher()

# Utiliser la mise en correspondance KNN
matches = bf.knnMatch(descriptors1, descriptors2, k=2)

# Appliquer le test de ratio pour filtrer les bonnes correspondances
good_matches = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good_matches.append(m)

knnMatch()La fonction renvoie les deux meilleures correspondances pour chaque point caractéristique. Nous utilisons le test de ratio (test de ratio de Lowe) pour filtrer les bons points de correspondance.


4. Calculer la matrice de transformation

Après avoir obtenu de bons points de correspondance, nous pouvons utiliser ces points pour calculer la matrice de transformation entre les images. Une matrice de transformation courante est la matrice d'homographie, qui peut projeter des points d'une image sur une autre.

Exemple

# Extraire les coordonnées des points de correspondance
src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

# Calculer la matrice d'homographie
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

findHomography()La fonction renvoie une matrice d'homographie 3x3H, qui peut mettre en correspondanceimage1des points de ... versimage2...


5. Mélange d'images

Enfin, nous utilisons la matrice d'homographie calculée pour assembler les images, et effectuons un mélange pour éliminer les artefacts de raccord.

Exemple

# Obtenir les dimensions de l'image
h1, w1 = image1.shape[:2]
h2, w2 = image2.shape[:2]

# Calculer la taille de l'image assemblée
pts = np.float32([[0, 0], [0, h1], [w1, h1], [w1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, H)
[x_min, y_min] = np.int32(dst.min(axis=0).ravel() - 0.5)
[x_max, y_max] = np.int32(dst.max(axis=0).ravel() + 0.5)

# Calculer la matrice de translation
translation_matrix = np.array([[1, 0, -x_min], [0, 1, -y_min], [0, 0, 1]])

# Appliquer la matrice de translation pour l'assemblage d'images
result = cv2.warpPerspective(image1, translation_matrix.dot(H), (x_max - x_min, y_max - y_min))
result[-y_min:h2 - y_min, -x_min:w2 - x_min] = image2

# Afficher le résultat de l'assemblage
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

warpPerspective()La fonction, basée sur la matrice d'homographie,HPairimage1effectue une transformation de perspective et la combine avecimage2pour assembler.


Implémentation de l'application

Voici le code complet pour l'assemblage d'images à l'aide de la détection et de la mise en correspondance de points caractéristiques :

Exemple

import cv2
import numpy as np

# 1. Charger les images
image1 = cv2.imread("path/to/image1.jpg")
image2 = cv2.imread("path/to/image2.jpg")

# 2. Convertir en niveaux de gris
gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# 3. Détection des points caractéristiques
sift = cv2.SIFT_create()
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)

# 4. Mise en correspondance des points caractéristiques
matcher = cv2.BFMatcher()
matches = matcher.knnMatch(descriptors1, descriptors2, k=2)

# 5. Filtrer les points correspondants
good_matches = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good_matches.append(m)

# 6. Calculer la matrice d'homographie
if len(good_matches) > 10:
    src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
    dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
    H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
else:
    print("Pas assez de correspondances trouvées.")
    exit()

# 7. Transformation d'image
height1, width1 = image1.shape[:2]
height2, width2 = image2.shape[:2]
warped_image = cv2.warpPerspective(image1, H, (width1 + width2, height1))

# 8. Assemblage d'images
warped_image[0:height2, 0:width2] = image2

# 9. Affichage du résultat
cv2.imshow("Image assemblée", warped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Autres extensions