Dans ce tutoriel, vous apprendrez à réaliser un assemblage d’images en utilisant Python, OpenCV, et les fonctions cv2.createStitcher
et cv2.Stitcher_create
. En utilisant le code d’aujourd’hui, vous serez en mesure d’assembler plusieurs images ensemble, créant ainsi un panorama d’images assemblées.
Il y a un peu moins de deux ans, j’ai publié deux guides sur l’assemblage d’images et la construction de panoramas :
- Fondamentaux de l’assemblage d’images
- Panorama en temps réel et assemblage d’images
Ces deux tutoriels couvraient les principes fondamentaux de l’algorithme typique d’assemblage d’images, qui, au strict minimum, nécessitent quatre étapes clés :
- Détection des points clés (DoG, Harris, etc.) et extraction de descripteurs invariants locaux (SIFT, SURF, etc.) à partir de deux images d’entrée
- Faire correspondre les descripteurs entre les images
- Utiliser l’algorithme RANSAC pour estimer une matrice d’homographie en utilisant nos vecteurs de caractéristiques appariés
- Appliquer une transformation de déformation en utilisant la matrice d’homographie obtenue à l’étape #3
Cependant, le plus gros problème avec mes implémentations originales est qu’elles n’étaient pas capables de gérer plus de deux images d’entrée.
Dans le tutoriel d’aujourd’hui, nous allons revisiter l’assemblage d’images avec OpenCV, y compris comment assembler plus de deux images ensemble dans une image panoramique.
Pour apprendre à assembler des images avec OpenCV et Python, continuez à lire !
- Vous cherchez le code source de ce post ?
- Assemblage d’images avec OpenCV et Python
- Algorithme d’assemblage d’images d’OpenCV
- Structure du projet
- Les fonctions cv2.createStitcher et cv2.Stitcher_create
- Mise en œuvre de l’assemblage d’images avec Python
- Résultats de l’assemblage d’images de base
- Un meilleur assembleur d’images avec OpenCV et Python
- Résultats de l’assemblage d’images amélioré
- Limitations et inconvénients
- Rencontrer des erreurs lors de l’exécution de l’assemblage d’images en utilisant OpenCV ?
- Summary
Vous cherchez le code source de ce post ?
Sautez directement à la section des téléchargements
Assemblage d’images avec OpenCV et Python
Dans la première partie du tutoriel d’aujourd’hui, nous passerons brièvement en revue l’algorithme d’assemblage d’images d’OpenCV qui est intégré à la bibliothèque OpenCV elle-même via les fonctions cv2.createStitcher
et cv2.Stitcher_create
.
De là, nous passerons en revue la structure de notre projet et implémenterons un script Python qui peut être utilisé pour l’assemblage d’images.
Nous examinerons les résultats de ce premier script, noterons ses limitations, puis implémenterons un second script Python qui peut être utilisé pour des résultats d’assemblage d’images plus esthétiques.
Enfin, nous examinerons les résultats de notre second script et noterons à nouveau les limitations ou les inconvénients.
Algorithme d’assemblage d’images d’OpenCV
L’algorithme que nous utiliserons ici aujourd’hui est similaire à la méthode proposée par Brown et Lowe dans leur article de 2007, Automatic Panoramic Image Stitching with Invariant Features.
Contrairement aux algorithmes d’assemblage d’images précédents qui sont sensibles à l’ordre des images d’entrée, la méthode de Brown et Lowe est plus robuste, ce qui la rend insensible à :
- L’ordre des images
- L’orientation des images
- Les changements d’illumination
- Les images bruyantes qui ne font pas réellement partie du panorama
En outre, leur méthode d’assemblage d’images est capable de produire des images panoramiques de sortie plus esthétiques grâce à l’utilisation de la compensation de gain et du mélange d’images.
Un examen complet et détaillé de l’algorithme est hors de portée de ce post, donc si vous êtes intéressé à en savoir plus, veuillez vous référer à la publication originale.
Structure du projet
Voyons comment ce projet est organisé avec la commande tree
:
$ tree --dirsfirst.├── images│ └── scottsdale│ ├── IMG_1786-2.jpg│ ├── IMG_1787-2.jpg│ └── IMG_1788-2.jpg├── image_stitching.py├── image_stitching_simple.py└── output.png2 directories, 6 files
Les images d’entrée vont dans le dossier images/
. J’ai choisi de faire un sous-dossier pour mon scottsdale/
ensemble d’images au cas où je voudrais ajouter des sous-dossiers supplémentaires ici plus tard.
Aujourd’hui, nous allons examiner deux scripts Python:
-
image_stitching_simple.py
: Notre version simple de l’assemblage d’images peut être complétée en moins de 50 lignes de code Python ! -
image_stitching.py
: Ce script inclut mon hack pour extraire un ROI de l’image assemblée pour un résultat esthétiquement agréable.
Le dernier fichier, output.png
, est le nom de l’image assemblée résultante. En utilisant les arguments de ligne de commande, vous pouvez facilement changer le nom de fichier + le chemin de l’image de sortie.
Les fonctions cv2.createStitcher et cv2.Stitcher_create
OpenCV a déjà implémenté une méthode similaire à l’article de Brown et Lowe via les cv2.createStitcher
(OpenCV 3.x) et cv2.Stitcher_create
(OpenCV 4).
En supposant que vous avez OpenCV correctement configuré et installé, vous serez en mesure d’enquêter sur la signature de la fonction cv2.createStitcher
pour OpenCV 3.x:
createStitcher(...) createStitcher() -> retval
Notez comment cette fonction a seulement un seul paramètre, try_gpu
qui peut être utilisé pour améliorer votre le long de votre pipeline d’assemblage d’images. Le support GPU d’OpenCV est limité et je n’ai jamais été capable de faire fonctionner ce paramètre, donc je recommande de toujours le laisser comme False
.
La fonction cv2.Stitcher_create
d’OpenCV 4 a une signature similaire:
Stitcher_create(...) Stitcher_create() -> retval . @brief Creates a Stitcher configured in one of the stitching .modes. . . @param mode Scenario for stitcher operation. This is usually .determined by source of images to stitch and their transformation. .Default parameters will be chosen for operation in given scenario. . @return Stitcher class instance.
Pour effectuer l’assemblage d’images réel, nous aurons besoin d’appeler la méthode .stitch
:
OpenCV 3.x:stitch(...) method of cv2.Stitcher instance stitch(images) -> retval, panoOpenCV 4.x:stitch(...) method of cv2.Stitcher instance stitch(images, masks) -> retval, pano . @brief These functions try to stitch the given images. . . @param images Input images. . @param masks Masks for each input image specifying where to .look for keypoints (optional). . @param pano Final pano. . @return Status code.
Cette méthode accepte une liste de images
d’entrée, et tente ensuite de les assembler en un panorama, renvoyant l’image de panorama de sortie à la fonction appelante.
La variable status
indique si l’assemblage des images a réussi ou non et peut être l’une des quatre variables suivantes :
-
OK = 0
: L’assemblage des images a réussi. -
ERR_NEED_MORE_IMGS = 1
: Dans le cas où vous recevez ce code d’état, vous aurez besoin de plus d’images d’entrée pour construire votre panorama. Typiquement, cette erreur se produit s’il n’y a pas assez de points clés détectés dans vos images d’entrée. -
ERR_HOMOGRAPHY_EST_FAIL = 2
: Cette erreur se produit lorsque l’estimation de l’homographie RANSAC échoue. Encore une fois, vous pouvez avoir besoin de plus d’images ou vos images n’ont pas assez de texture/objets uniques et distinctifs pour que les points clés puissent être appariés avec précision. -
ERR_CAMERA_PARAMS_ADJUST_FAIL = 3
: Je n’ai jamais rencontré cette erreur auparavant donc je n’ai pas beaucoup de connaissances à ce sujet, mais l’essentiel est qu’elle est liée à l’échec de l’estimation correcte des intrinsèques/extrinsèques de la caméra à partir des images d’entrée. Si vous rencontrez cette erreur, vous devrez peut-être vous référer à la documentation d’OpenCV ou même plonger dans le code C++ d’OpenCV.
Maintenant que nous avons passé en revue les méthodes cv2.createStitcher
, cv2.Stitcher_create
, et .stitch
, passons à la mise en œuvre effective de l’assemblage d’images avec OpenCV et Python.
Mise en œuvre de l’assemblage d’images avec Python
Allons-y et commençons à mettre en œuvre notre algorithme d’assemblage d’images !
Ouvrez le fichier image_stitching_simple.py
et insérez le code suivant :
# import the necessary packagesfrom imutils import pathsimport numpy as npimport argparseimport imutilsimport cv2# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--images", type=str, required=True,help="path to input directory of images to stitch")ap.add_argument("-o", "--output", type=str, required=True,help="path to the output image")args = vars(ap.parse_args())
Nos paquets requis sont importés aux lignes 2 à 6. Notamment, nous utiliserons OpenCV et imutils. Si vous ne l’avez pas encore fait, allez-y et installez-les:
- Pour installer OpenCV, suivez simplement l’un de mes guides d’installation d’OpenCV.
- Le paquet imutils peut être installé/mise à jour avec pip :
pip install --upgrade imutils
. Assurez-vous de le mettre à jour car de nouvelles fonctionnalités sont souvent ajoutées.
À partir de là, nous allons analyser deux arguments de ligne de commande sur les lignes 9 à 14 :
-
--images
: Le chemin vers le répertoire des images d’entrée à assembler. -
--output
: Le chemin vers l’image de sortie où le résultat sera enregistré.
Si vous n’êtes pas familier avec les concepts de argparse
et d’arguments de ligne de commande, alors lisez cet article de blog.
Chargeons nos images d’entrée :
# grab the paths to the input images and initialize our images listprint(" loading images...")imagePaths = sorted(list(paths.list_images(args)))images = # loop over the image paths, load each one, and add them to our# images to stitch listfor imagePath in imagePaths:image = cv2.imread(imagePath)images.append(image)
Ici nous saisissons notre imagePaths
(Ligne 18).
Puis pour chaque imagePath
, nous chargerons le image
et l’ajouterons à la liste images
(Lignes 19-25).
Maintenant que les images
sont en mémoire, allons-y et assemblons-les dans un panorama en utilisant la capacité intégrée d’OpenCV :
# initialize OpenCV's image stitcher object and then perform the image# stitchingprint(" stitching images...")stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()(status, stitched) = stitcher.stitch(images)
L’objet stitcher
est créé à la ligne 30. Remarquez que selon que vous utilisez OpenCV 3 ou 4, un constructeur différent est appelé.
Par la suite, nous pouvons passer notre images
à la méthode .stitch
(Ligne 31). L’appel à .stitch
renvoie à la fois une status
et notre stitched
image (en supposant que l’assemblage a réussi).
Enfin, nous allons à la fois (1) écrire l’image assemblée sur le disque et (2) l’afficher à l’écran :
# if the status is '0', then OpenCV successfully performed image# stitchingif status == 0:# write the output stitched image to diskcv2.imwrite(args, stitched)# display the output stitched image to our screencv2.imshow("Stitched", stitched)cv2.waitKey(0)# otherwise the stitching failed, likely due to not enough keypoints)# being detectedelse:print(" image stitching failed ({})".format(status))
En supposant que notre drapeau status
indique un succès (Ligne 35), nous écrivons l’image stitched
sur le disque (Ligne 37) et l’affichons jusqu’à ce qu’une touche soit pressée (Lignes 40 et 41).
Sinon, nous allons simplement imprimer un message d’échec (Lignes 45 et 46).
Résultats de l’assemblage d’images de base
Pour essayer notre script d’assemblage d’images, assurez-vous d’utiliser la section « Téléchargements » du tutoriel pour télécharger le code source et les images d’exemple.
Dans le répertoire images/scottsdale/
, vous trouverez trois photos que j’ai prises en visitant la célèbre maison Taliesin West de Frank Lloyd Wright à Scottsdale, AZ :
Notre objectif est d’assembler ces trois images en une seule image panoramique. Pour effectuer l’assemblage, ouvrez un terminal, naviguez vers l’endroit où vous avez téléchargé le code + les images, et exécutez la commande suivante :
$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
Voyez comment nous avons réussi à effectuer un assemblage d’images !
Mais qu’en est-il de ces régions noires qui entourent le panorama ? Qu’est-ce que c’est ?
Ces régions proviennent de l’exécution des déformations de perspective nécessaires pour construire le panorama.
Il y a un moyen de s’en débarrasser…mais nous devrons implémenter une logique supplémentaire dans la section suivante.
Un meilleur assembleur d’images avec OpenCV et Python
Notre premier script d’assemblage d’images était un bon début, mais ces régions noires entourant le panorama lui-même ne sont pas quelque chose que nous appellerions « esthétiquement plaisant ».
Et plus précisément, vous ne verriez pas une telle image de sortie à partir des applications populaires d’assemblage d’images intégrées à iOS, Android, etc.
Par conséquent, nous allons pirater un peu notre script et inclure une logique supplémentaire pour créer des panoramas plus esthétiques.
Je vais encore une fois répéter que cette méthode est un hack.
Nous allons passer en revue les opérations de traitement d’image de base, y compris le seuil, l’extraction de contour, les opérations morphologiques, etc. afin d’obtenir notre résultat souhaité.
À ma connaissance, les liaisons Python d’OpenCV ne nous fournissent pas les informations nécessaires pour extraire manuellement la région rectangulaire intérieure maximale du panorama. Si OpenCV le fait, veuillez me le faire savoir dans les commentaires car j’aimerais le savoir.
Allons-y et commençons – ouvrez le script image_stitching.py
et insérez le code suivant :
# import the necessary packagesfrom imutils import pathsimport numpy as npimport argparseimport imutilsimport cv2# construct the argument parser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--images", type=str, required=True,help="path to input directory of images to stitch")ap.add_argument("-o", "--output", type=str, required=True,help="path to the output image")ap.add_argument("-c", "--crop", type=int, default=0,help="whether to crop out largest rectangular region")args = vars(ap.parse_args())# grab the paths to the input images and initialize our images listprint(" loading images...")imagePaths = sorted(list(paths.list_images(args)))images = # loop over the image paths, load each one, and add them to our# images to stich listfor imagePath in imagePaths:image = cv2.imread(imagePath)images.append(image)# initialize OpenCV's image sticher object and then perform the image# stitchingprint(" stitching images...")stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()(status, stitched) = stitcher.stitch(images)
Tout ce code est identique à notre script précédent à une exception près.
L’argument de ligne de commande --crop
a été ajouté. Lorsqu’un 1
est fourni pour cet argument dans le terminal, nous irons de l’avant et effectuerons notre hack de recadrage.
L’étape suivante est celle où nous commençons à mettre en œuvre des fonctionnalités supplémentaires :
# if the status is '0', then OpenCV successfully performed image# stitchingif status == 0:# check to see if we supposed to crop out the largest rectangular# region from the stitched imageif args > 0:# create a 10 pixel border surrounding the stitched imageprint(" cropping...")stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10,cv2.BORDER_CONSTANT, (0, 0, 0))# convert the stitched image to grayscale and threshold it# such that all pixels greater than zero are set to 255# (foreground) while all others remain 0 (background)gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
Voyez comment j’ai fait un nouveau bloc pour lorsque le drapeau --crop
est activé à la ligne 40. Commençons à parcourir ce bloc:
- Premièrement, nous ajouterons une bordure de
10
pixels sur tous les côtés de notre imagestitched
(Lignes 43 et 44), en nous assurant que nous serons en mesure de trouver les contours du contour complet du panorama plus tard dans cette section. - Puis nous allons créer une version
gray
de notre imagestitched
(Ligne 49). - Et à partir de là, nous seuillons l’image
gray
(Ligne 50).
Voici le résultat (thresh
) de ces trois étapes :
Nous avons maintenant une image binaire de notre panorama où les pixels blancs (255) sont le premier plan et les pixels noirs (0) sont l’arrière-plan.
Donné notre image seuillée, nous pouvons appliquer l’extraction de contour, calculer la boîte de délimitation du plus grand contour (c’est-à-dire, le contour du panorama lui-même), et dessiner la boîte englobante :
# find all external contours in the threshold image then find# the *largest* contour which will be the contour/outline of# the stitched imagecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)# allocate memory for the mask which will contain the# rectangular bounding box of the stitched image regionmask = np.zeros(thresh.shape, dtype="uint8")(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)
Les contours sont extraits et analysés aux lignes 55-57. La ligne 58 saisit ensuite le contour avec la plus grande surface (c’est-à-dire le contour de l’image assemblée elle-même).
Note : La fonction imutils.grab_contours
est nouvelle dans imutils==0.5.2
pour s’adapter à OpenCV 2.4, OpenCV 3, et OpenCV 4 et à leurs différentes signatures de retour pour cv2.findContours
.
La ligne 62 alloue la mémoire pour notre nouveau masque rectangulaire. La ligne 63 calcule ensuite le rectangle de délimitation de notre plus grand contour. En utilisant les informations du rectangle limite, à la ligne 64, nous dessinons un rectangle blanc plein sur le masque.
La sortie du bloc de code ci-dessus ressemblerait à ce qui suit :
Cette boîte limite est la plus petite région rectangulaire dans laquelle le panorama entier peut tenir.
Maintenant, voici l’un des plus gros hacks que j’ai jamais mis en place pour un article de blog:
# create two copies of the mask: one to serve as our actual# minimum rectangular region and another to serve as a counter# for how many pixels need to be removed to form the minimum# rectangular regionminRect = mask.copy()sub = mask.copy()# keep looping until there are no non-zero pixels left in the# subtracted imagewhile cv2.countNonZero(sub) > 0:# erode the minimum rectangular mask and then subtract# the thresholded image from the minimum rectangular mask# so we can count if there are any non-zero pixels leftminRect = cv2.erode(minRect, None)sub = cv2.subtract(minRect, thresh)
Sur les lignes 70 et 71, nous créons deux copies de notre image mask
:
- Le premier masque,
minMask
, sera lentement réduit en taille jusqu’à ce qu’il puisse tenir dans la partie intérieure du panorama (voir la figure 5 en haut de cette section). - Le deuxième masque,
sub
, sera utilisé pour déterminer si nous devons continuer à réduire la taille deminMask
.
La ligne 75 démarre une boucle while
qui continuera à tourner en boucle jusqu’à ce qu’il n’y ait plus de pixels de premier plan dans sub
.
La ligne 79 effectue une opération morphologique d’érosion pour réduire la taille de minRect
.
La ligne 80 soustrait ensuite thresh
de minRect
– une fois qu’il n’y a plus de pixels de premier plan dans minRect
alors nous pouvons rompre la boucle.
J’ai inclus une animation du hack ci-dessous :
En haut, nous avons notre image sub
et en bas, nous avons l’image minRect
.
Notez comment la taille de minRect
est progressivement réduite jusqu’à ce qu’il n’y ait plus de pixels de premier plan dans sub
– à ce stade, nous savons que nous avons trouvé le plus petit masque rectangulaire qui peut s’insérer dans la plus grande région rectangulaire du panorama.
Donné le rectangle intérieur minimum, nous pouvons à nouveau trouver les contours et calculer la boîte englobante, mais cette fois nous allons simplement extraire le ROI de l’image stitched
:
# find contours in the minimum rectangular mask and then# extract the bounding box (x, y)-coordinatescnts = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)(x, y, w, h) = cv2.boundingRect(c)# use the bounding box coordinates to extract the our final# stitched imagestitched = stitched
Voici ce que nous avons:
- Trouvé les contours dans
minRect
(Lignes 84 et 85). - Géré l’analyse des contours pour plusieurs versions d’OpenCV (Ligne 86). Vous aurez besoin de
imutils>=0.5.2
pour utiliser cette fonction. - Graboté le plus grand contour (Ligne 87).
- Calculé la boîte de délimitation du plus grand contour (Ligne 88).
- Extrait le ROI de notre
stitched
en utilisant les informations de la boîte de délimitation (Ligne 92).
L’image stitched
finale peut être affichée sur notre écran puis sauvegardée sur disque :
# write the output stitched image to diskcv2.imwrite(args, stitched)# display the output stitched image to our screencv2.imshow("Stitched", stitched)cv2.waitKey(0)# otherwise the stitching failed, likely due to not enough keypoints)# being detectedelse:print(" image stitching failed ({})".format(status))
Les lignes 95 à 99 gèrent la sauvegarde et l’affichage de l’image, que notre hack de recadrage soit effectué ou non.
Comme précédemment, si le drapeau status
n’est pas revenu comme un succès, nous imprimerons un message d’erreur (lignes 103 et 104).
Allons-y et vérifions les résultats de notre pipeline amélioré d’assemblage d’images + OpenCV.
Résultats de l’assemblage d’images amélioré
De nouveau, assurez-vous d’avoir utilisé la section « Téléchargements » du tutoriel d’aujourd’hui pour télécharger le code source et les images d’exemple.
De là, ouvrez un terminal et exécutez la commande suivante :
$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
Notez comment cette fois-ci nous avons supprimé les régions noires des images assemblées de sortie (causées par les transformations de déformation) en appliquant notre hack détaillé dans la section ci-dessus.
Limitations et inconvénients
Dans un tutoriel précédent, j’ai démontré comment vous pouviez construire un panorama en temps réel et un algorithme d’assemblage d’images – ce tutoriel s’articulait sur le fait que nous effectuions manuellement la détection des points clés, l’extraction des caractéristiques et la correspondance des points clés, ce qui nous donnait accès à la matrice d’homographie utilisée pour déformer nos deux images d’entrée en un panorama.
Et alors que les fonctions cv2.createStitcher
et cv2.Stitcher_create
intégrées d’OpenCV sont certainement capables de construire des panoramas précis et esthétiquement agréables, l’un des principaux inconvénients de la méthode est qu’elle abstrait tout accès aux matrices d’homographie.
L’une des hypothèses de la construction de panoramas en temps réel est que la scène elle-même ne change pas beaucoup en termes de contenu.
Une fois que nous calculons l’estimation initiale de l’homographie, nous ne devrions avoir qu’à recalculer occasionnellement la matrice.
Ne pas avoir à effectuer une correspondance complète des points clés et une estimation RANSAC nous donne un énorme coup de pouce de vitesse lors de la construction de notre panorama, donc sans accès aux matrices brutes d’homographie, il serait difficile de prendre l’algorithme intégré d’assemblage d’images d’OpenCV et de le convertir en temps réel.
Rencontrer des erreurs lors de l’exécution de l’assemblage d’images en utilisant OpenCV ?
Il est possible que vous rencontriez des erreurs en essayant d’utiliser soit la fonction cv2.createStitcher
soit les fonctions cv2.Stitcher_create
.
Les deux erreurs « faciles à résoudre » que je vois les gens rencontrer est d’oublier quelle version d’OpenCV ils utilisent.
Par exemple, si vous utilisez OpenCV 4 mais essayez d’appeler cv2.createSticher
, vous rencontrerez le message d’erreur suivant :
>>> cv2.createStitcherTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'createStitcher'
Vous devriez plutôt utiliser la fonction cv2.Stitcher_create
.
De même, si vous utilisez OpenCV 3 et que vous essayez d’appeler cv2.Sticher_create
, vous recevrez cette erreur :
>>> cv2.Stitcher_createTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'Stitcher_create'
A la place, utilisez la fonction cv2.createSticher
.
Si vous n’êtes pas sûr de la version d’OpenCV que vous utilisez, vous pouvez vérifier en utilisant cv2.__version__
:
>>> cv2.__version__'4.0.0'
Ici vous pouvez voir que j’utilise OpenCV 4.0.0.
Vous pouvez effectuer la même vérification sur votre système.
La dernière erreur que vous pouvez rencontrer, et sans doute la plus courante, est liée au fait qu’OpenCV (1) n’a pas le support contrib et (2) a été compilé sans l’option OPENCV_ENABLE_NONFREE=ON
activée.
Pour résoudre cette erreur, vous devez avoir les modules opencv_contrib
installés ainsi que l’option OPENCV_ENABLE_NONFREE
définie à ON
.
Si vous rencontrez une erreur liée aux modules non-free et contrib d’OpenCV, assurez-vous de vous référer à mes guides d’installation d’OpenCV pour vous assurer que vous avez l’installation complète d’OpenCV.
Note : Veuillez noter que je ne peux pas aider à déboguer votre propre installation d’OpenCV si vous n’avez pas suivi l’un de mes guides d’installation, alors assurez-vous d’utiliser mes guides d’installation d’OpenCV lorsque vous configurez votre système.
Summary
Dans le tutoriel d’aujourd’hui, vous avez appris à effectuer l’assemblage de plusieurs images en utilisant OpenCV et Python.
En utilisant à la fois OpenCV et Python, nous avons été en mesure d’assembler plusieurs images ensemble et de créer des images panoramiques.
Nos images panoramiques de sortie étaient non seulement précises dans leur placement d’assemblage, mais aussi esthétiquement plaisantes.
Cependant, l’un des plus grands inconvénients de l’utilisation de la classe d’assemblage d’images intégrée d’OpenCV est qu’elle abstrait une grande partie du calcul interne, y compris les matrices d’homographie résultantes elles-mêmes.
Si vous essayez d’effectuer un assemblage d’images en temps réel, comme nous l’avons fait dans un post précédent, vous pouvez trouver avantageux de mettre en cache la matrice d’homographie et de n’effectuer qu’occasionnellement la détection des points clés, l’extraction des caractéristiques et la correspondance des caractéristiques.
Sauter ces étapes et utiliser la matrice mise en cache pour effectuer le warping de perspective peut réduire la charge de calcul de votre pipeline et finalement accélérer l’algorithme d’assemblage d’images en temps réel, mais malheureusement, les liaisons Python cv2.createStitcher
d’OpenCV ne nous donnent pas accès aux matrices brutes.
Si vous êtes intéressé à en apprendre davantage sur la construction de panoramas en temps réel, veuillez vous référer à mon post précédent.
J’espère que vous avez apprécié le tutoriel d’aujourd’hui sur l’assemblage d’images!
Pour télécharger le code source du post d’aujourd’hui, et être informé que des tutoriels sont publiés ici sur PyImageSearch, il suffit de saisir votre adresse e-mail dans le formulaire ci-dessous!
.