In deze tutorial leert u hoe u afbeeldingen aan elkaar kunt hechten met Python, OpenCV en de functies cv2.createStitcher
en cv2.Stitcher_create
. Met behulp van de code van vandaag zul je in staat zijn om meerdere beelden aan elkaar te stitchen, waardoor een panorama van gestikte beelden ontstaat.
Nog geen twee jaar geleden publiceerde ik twee gidsen over het stitchen van afbeeldingen en het maken van panorama’s:
- Fundamentals of image stitching
- Real-time panorama and image stitching
Beide van deze handleidingen behandelden de grondbeginselen van het typische image stitching algoritme, die, op zijn minst, vier belangrijke stappen vereisen:
- Het detecteren van sleutelpunten (DoG, Harris, enz.) en het extraheren van lokale invariante descriptoren (SIFT, SURF, enz.) uit twee invoerbeelden
- De descriptoren tussen de beelden matchen
- Het RANSAC-algoritme gebruiken om een homografiematrix te schatten met behulp van onze gematchte kenmerkvectoren
- Een warping-transformatie toepassen met behulp van de homografiematrix verkregen uit stap #3
Het grootste probleem met mijn oorspronkelijke implementaties is echter dat ze niet in staat waren om meer dan twee invoerbeelden te verwerken.
In de tutorial van vandaag bekijken we het stitchen van afbeeldingen met OpenCV, inclusief het samenvoegen van meer dan twee afbeeldingen tot een panoramisch beeld.
Om te leren hoe u afbeeldingen kunt stitchen met OpenCV en Python, lees gewoon verder!
- Op zoek naar de broncode van dit bericht?
- Afbeelding stitchen met OpenCV en Python
- OpenCV’s algoritme voor het stitchen van afbeeldingen
- Projectstructuur
- De functies cv2.createStitcher en cv2.Stitcher_create
- Implementeren van image stitching met Python
- Resultaten van het stitchen van afbeeldingen
- Een betere beeldstikker met OpenCV en Python
- Verbeterde image stitching resultaten
- Limitaties en nadelen
- Storingen bij het gebruik van OpenCV?
- Samenvatting
Op zoek naar de broncode van dit bericht?
Spring direct naar de downloadsectie
Afbeelding stitchen met OpenCV en Python
In het eerste deel van de tutorial van vandaag zullen we kort OpenCV’s afbeelding stitching algoritme bespreken dat in de OpenCV bibliotheek zelf is ingebakken via cv2.createStitcher
en cv2.Stitcher_create
functies.
Van daaruit zullen we onze projectstructuur bekijken en een Python script implementeren dat kan worden gebruikt voor image stitching.
We zullen de resultaten van dit eerste script bekijken, de beperkingen ervan opmerken, en vervolgens een tweede Python script implementeren dat kan worden gebruikt voor meer esthetisch aangename resultaten van image stitching.
Ten slotte zullen we de resultaten van ons tweede script bekijken en opnieuw de beperkingen of nadelen opmerken.
OpenCV’s algoritme voor het stitchen van afbeeldingen
Het algoritme dat we hier vandaag gebruiken, is vergelijkbaar met de methode die Brown en Lowe hebben voorgesteld in hun paper uit 2007, Automatic Panoramic Image Stitching with Invariant Features.
In tegenstelling tot eerdere algoritmen voor het stitchen van beelden, die gevoelig zijn voor de volgorde van de invoerbeelden, is de methode van Brown en Lowe robuuster, waardoor deze ongevoelig is voor:
- Ordering van beelden
- Oriëntatie van beelden
- Illuminatieveranderingen
- Storende beelden die eigenlijk geen deel uitmaken van het panorama
Daarnaast is hun image stitching methode in staat om esthetischer uitvoer panoramabeelden te produceren door het gebruik van gain compensation en image blending.
Een volledige, gedetailleerde bespreking van het algoritme valt buiten het bestek van deze post, dus als u meer wilt weten, raadpleeg dan de oorspronkelijke publicatie.
Projectstructuur
Laten we eens kijken hoe dit project is georganiseerd met het tree
commando:
$ 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
De invoerafbeeldingen gaan in de images/
map. Ik heb ervoor gekozen om een submap te maken voor mijn scottsdale/
set afbeeldingen voor het geval ik hier later extra submappen aan wil toevoegen.
Vandaag zullen we twee Python scripts bekijken:
-
image_stitching_simple.py
: Onze eenvoudige versie van het stitchen van afbeeldingen kan worden voltooid in minder dan 50 regels Python code! -
image_stitching.py
: Dit script bevat mijn hack om een ROI van de gestikte afbeelding te extraheren voor een esthetisch mooi resultaat.
Het laatste bestand, output.png
, is de naam van de resulterende gestikte afbeelding. Met behulp van commandoregel-argumenten kunt u eenvoudig de bestandsnaam + het pad van de uitvoerafbeelding wijzigen.
De functies cv2.createStitcher en cv2.Stitcher_create
OpenCV heeft al een methode geïmplementeerd die vergelijkbaar is met Brown en Lowe’s paper via de cv2.createStitcher
(OpenCV 3.x) en cv2.Stitcher_create
(OpenCV 4) functies.
Aannemende dat je OpenCV correct hebt geconfigureerd en geïnstalleerd, kun je de functiehandtekening van cv2.createStitcher
voor OpenCV 3.x onderzoeken:
createStitcher(...) createStitcher() -> retval
Merk op dat deze functie slechts een enkele parameter heeft, try_gpu
die kan worden gebruikt om de hele pipeline van het stitchen van afbeeldingen te verbeteren. OpenCV’s GPU ondersteuning is beperkt en ik heb deze parameter nog nooit aan de praat gekregen, dus ik raad aan om hem altijd op False
te laten staan.
De cv2.Stitcher_create
functie voor OpenCV 4 heeft een vergelijkbare signatuur:
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.
Om het eigenlijke stitchen van de beelden uit te voeren, moeten we de .stitch
methode aanroepen:
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.
Deze methode accepteert een lijst van input images
, en probeert ze dan te stitchen in een panorama, waarbij het output panorama beeld wordt geretourneerd aan de aanroepende functie.
De status
variabele geeft aan of het stitchen van de beelden al dan niet is gelukt en kan een van de volgende vier variabelen zijn:
-
OK = 0
: Het stitchen van de beelden is gelukt. -
ERR_NEED_MORE_IMGS = 1
: In het geval dat u deze status code ontvangt, heeft u meer invoer beelden nodig om uw panorama te construeren. Typisch deze fout treedt op als er niet genoeg keypoints gedetecteerd in uw input beelden. -
ERR_HOMOGRAPHY_EST_FAIL = 2
: Deze fout treedt op wanneer de RANSAC homografie schatting mislukt. Nogmaals, het kan zijn dat u meer beelden nodig hebt of dat uw beelden niet genoeg onderscheidende, unieke textuur/objecten hebben om de sleutelpunten nauwkeurig te kunnen matchen. -
ERR_CAMERA_PARAMS_ADJUST_FAIL = 3
: Ik ben deze fout nog nooit tegengekomen, dus ik heb er niet veel kennis over, maar de essentie is dat het gerelateerd is aan het niet goed schatten van de camera intrinsiek/extrinsiek van de invoerbeelden. Als u deze fout tegenkomt, moet u wellicht de OpenCV documentatie raadplegen of zelfs in de OpenCV C++ code duiken.
Nu dat we de cv2.createStitcher
, cv2.Stitcher_create
, en .stitch
methoden hebben bekeken, laten we verder gaan met het daadwerkelijk implementeren van image stitching met OpenCV en Python.
Implementeren van image stitching met Python
Laten we aan de slag gaan met het implementeren van ons image stitching algoritme!
Open het image_stitching_simple.py
bestand en voeg de volgende code in:
# 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())
Onze benodigde pakketten worden geïmporteerd op regel 2-6. In het bijzonder zullen we OpenCV en imutils gebruiken. Als je dat nog niet gedaan hebt, ga je gang en installeer ze:
- Om OpenCV te installeren, volg gewoon een van mijn OpenCV installatie gidsen.
- Het imutils pakket kan worden geinstalleerd/bijgewerkt met pip:
pip install --upgrade imutils
. Zorg ervoor dat u het upgradet, omdat er vaak nieuwe functies worden toegevoegd.
Van daaruit zullen we twee opdrachtregelargumenten ontleden op regel 9-14:
-
--images
: Het pad naar de map met invoerafbeeldingen om te naaien. -
--output
: Het pad naar de uitvoerafbeelding waar het resultaat zal worden opgeslagen.
Als u niet bekend bent met de concepten van argparse
en commandoregel argumenten, lees dan deze blog post.
Laten we onze input afbeeldingen laden:
# 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)
Hier pakken we onze imagePaths
(Lijn 18).
Dan voor elke imagePath
, laden we de image
en voegen het toe aan de images
lijst (Lijnen 19-25).
Nu de images
in het geheugen staan, laten we ze samenvoegen tot een panorama met behulp van OpenCV’s ingebouwde mogelijkheden:
# 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)
Het stitcher
object wordt gemaakt op Lijn 30. Merk op dat afhankelijk van of u OpenCV 3 of 4 gebruikt, een andere constructor wordt aangeroepen.
Daarna kunnen we onze images
doorgeven aan de .stitch
methode (Lijn 31). De aanroep van .stitch
retourneert zowel een status
als onze stitched
afbeelding (ervan uitgaande dat de stitching succesvol was).
Eindelijk zullen we zowel (1) het gestikte beeld naar schijf schrijven en (2) het op het scherm tonen:
# 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))
Aannemende dat onze status
vlag succes aangeeft (Lijn 35), schrijven we het stitched
beeld naar schijf (Lijn 37) en tonen het tot een toets wordt ingedrukt (Lijnen 40 en 41).
Anders zullen we gewoon een foutmelding printen (Lijnen 45 en 46).
Resultaten van het stitchen van afbeeldingen
Om ons script voor het stitchen van afbeeldingen uit te proberen, moet u de sectie “Downloads” van de tutorial gebruiken om de broncode en voorbeeldafbeeldingen te downloaden.
In de images/scottsdale/
directory vindt u drie foto’s die ik nam toen ik Frank Lloyd Wright’s beroemde Taliesin West huis in Scottsdale, AZ bezocht:
Het doel is om deze drie afbeeldingen samen te voegen tot één panoramische afbeelding. Om het stikken uit te voeren, opent u een terminal, navigeert u naar de plaats waar u de code + afbeeldingen hebt gedownload en voert u het volgende commando uit:
$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
Merk op hoe we succesvol beeldstikken hebben uitgevoerd!
Maar hoe zit het met die zwarte gebieden rond het panorama? Wat zijn dat?
Die regio’s komen van de perspectivische krommingen die nodig zijn om het panorama te maken.
Er is een manier om ze te verwijderen… maar we moeten wat extra logica implementeren in de volgende sectie.
Een betere beeldstikker met OpenCV en Python
Het eerste script voor het stitchen van beelden was een goed begin, maar die zwarte gebieden rondom het panorama zelf zijn niet iets wat we “esthetisch aantrekkelijk” zouden noemen.
En meer ter zake, je zou een dergelijke output afbeelding niet zien van populaire beeld stiksels toepassingen ingebouwd in iOS, Android, enz.
Daarom gaan we ons script een beetje hacken en een aantal extra logica opnemen om meer esthetisch aangename panorama’s te maken.
Ik ga nogmaals herhalen dat deze methode een hack is.
We zullen de basisbewerkingen van beeldverwerking doornemen, waaronder drempelwaarde, contourextractie, morfologische bewerkingen, enz. om ons gewenste resultaat te verkrijgen.
Voor zover ik weet, bieden OpenCV’s Python-bindingen ons niet de vereiste informatie om handmatig het maximale binnenste rechthoekige gebied van het panorama te extraheren. Als OpenCV dat wel doet, laat het me dan weten in de commentaren, want ik zou het graag willen weten.
Laten we aan de slag gaan – open het image_stitching.py
script en voeg de volgende code in:
# 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)
Al deze code is identiek aan ons vorige script met één uitzondering.
Het --crop
commandoregel argument is toegevoegd. Wanneer een 1
wordt gegeven voor dit argument in de terminal, zullen we doorgaan en onze bijsnijden hack uitvoeren.
De volgende stap is waar we beginnen met het implementeren van extra functionaliteit:
# 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)
Merk op hoe ik een nieuw blok heb gemaakt voor wanneer de --crop
vlag is ingesteld op regel 40. Laten we beginnen met het doorlopen van dit blok:
- Eerst voegen we een
10
pixel rand toe aan alle kanten van onzestitched
afbeelding (Lijnen 43 en 44), zodat we later in deze sectie de contouren van het complete panorama kunnen vinden. - Daarna maken we een
gray
versie van onzestitched
afbeelding (Lijn 49). - En vanaf daar drempelen we de
gray
afbeelding (Lijn 50).
Hier is het resultaat (thresh
) van deze drie stappen:
We hebben nu een binaire afbeelding van ons panorama waarbij witte pixels (255) de voorgrond vormen en zwarte pixels (0) de achtergrond.
Gezien onze gedrempelde afbeelding kunnen we contounextractie toepassen, de begrenzingsbox van de grootste contour berekenen (d.w.z, de omtrek van het panorama zelf), en de omtrek tekenen:
# 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)
De contouren worden geëxtraheerd en ontleed op de lijnen 55-57. Lijn 58 pakt dan de contour met het grootste gebied (dat wil zeggen, de omtrek van de gestikte afbeelding zelf).
Note: De imutils.grab_contours
functie is nieuw in imutils==0.5.2
om OpenCV 2.4, OpenCV 3, en OpenCV 4 en hun verschillende terugkeer handtekeningen voor cv2.findContours
tegemoet te komen.
Lijn 62 wijst geheugen toe voor onze nieuwe rechthoekige masker. Lijn 63 berekent dan de begrenzende rechthoek van onze grootste contour. Met behulp van de informatie over de begrenzende rechthoek tekenen we op regel 64 een stevige witte rechthoek op het masker.
De uitvoer van het bovenstaande codeblok zou er als volgt uitzien:
Deze begrenzende rechthoek is de kleinste rechthoekige regio waarin het volledige panorama kan passen.
Nu komt een van de grootste hacks die ik ooit voor een blog post heb gemaakt:
# 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)
Op regel 70 en 71 maken we twee kopieën van onze mask
afbeelding:
- Het eerste masker,
minMask
, wordt langzaam verkleind totdat het binnen het binnenste gedeelte van het panorama past (zie figuur 5 bovenaan deze sectie). - Het tweede masker,
sub
, wordt gebruikt om te bepalen of weminMask
moeten blijven verkleinen.
Lijn 75 start een while
lus die doorloopt tot er geen voorgrondpixels meer zijn in sub
.
Lijn 79 voert een erosiemorphologische operatie uit om minRect
te verkleinen.
Line 80 trekt vervolgens thresh
af van minRect
– zodra er geen voorgrondpixels meer zijn in minRect
dan kunnen we de lus onderbreken.
Ik heb hieronder een animatie van de hack opgenomen:
Bovenaan hebben we ons sub
-beeld en onderaan hebben we het minRect
-beeld.
Zie hoe de grootte van minRect
geleidelijk wordt verkleind totdat er geen voorgrondpixels meer over zijn in sub
– op dit punt weten we dat we het kleinste rechthoekige masker hebben gevonden dat in het grootste rechthoekige gebied van het panorama past.
Gezien de minimale binnenste rechthoek kunnen we opnieuw contouren vinden en de bounding box berekenen, maar deze keer halen we gewoon de ROI uit de stitched
afbeelding:
# 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
Hier hebben we:
- Gevonden contouren in
minRect
(Lijnen 84 en 85). - Geparseerde contouren voor meerdere OpenCV versies (Lijn 86). U hebt
imutils>=0.5.2
nodig om deze functie te gebruiken. - Graveerde de grootste contour (Lijn 87).
- Berekende de bounding box van de grootste contour (Lijn 88).
- Haalde de ROI uit onze
stitched
met behulp van de bounding box informatie (Lijn 92).
De uiteindelijke stitched
afbeelding kan worden weergegeven op ons scherm en vervolgens opgeslagen op schijf:
# 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))
Lijnen 95-99 behandelen het opslaan en weergeven van de afbeelding, ongeacht of onze bijsnijden hack is uitgevoerd of niet.
Net als voorheen, als de status
vlag niet terug kwam als een succes, zullen we een foutmelding afdrukken (lijnen 103 en 104).
Laten we verder gaan en de resultaten bekijken van onze verbeterde image stitching + OpenCV pipeline.
Verbeterde image stitching resultaten
Zorg er opnieuw voor dat je de “Downloads” sectie van de tutorial van vandaag hebt gebruikt om de broncode en voorbeeld afbeeldingen te downloaden.
Daarna opent u een terminal en voert u het volgende commando uit:
$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
Merk op dat we deze keer de zwarte gebieden uit de output van de gestikte beelden hebben verwijderd (veroorzaakt door de krommingstransformaties) door onze hack toe te passen die in de sectie hierboven is beschreven.
Limitaties en nadelen
In een eerdere tutorial heb ik laten zien hoe je een real-time panorama en image stitching algoritme kunt bouwen – deze tutorial hing af van het feit dat we handmatig sleutelpuntdetectie, feature-extractie en sleutelpuntmatching uitvoerden, waardoor we toegang kregen tot de homografiematrix die werd gebruikt om onze twee invoerafbeeldingen te vervormen tot een panorama.
En terwijl OpenCV’s ingebouwde cv2.createStitcher
en cv2.Stitcher_create
functies zeker in staat zijn om nauwkeurige, esthetisch aantrekkelijke panorama’s te construeren, is een van de belangrijkste nadelen van de methode dat het elke toegang tot de homografie matrices weg abstraheert.
Een van de aannames van real-time panorama constructie is dat de scène zelf niet veel verandert in termen van inhoud.
Als we eenmaal de initiële homografieschatting hebben berekend, hoeven we de matrix slechts af en toe opnieuw te berekenen.
Het niet hoeven uitvoeren van een volledige sleutelpuntmatching en RANSAC-schatting geeft ons een enorme snelheidsboost bij het bouwen van ons panorama, dus zonder toegang tot de ruwe homografiematrices zou het een uitdaging zijn om OpenCV’s ingebouwde algoritme voor het stitchen van beelden te nemen en het om te zetten naar real-time.
Storingen bij het gebruik van OpenCV?
Het is mogelijk dat u fouten tegenkomt wanneer u probeert de cv2.createStitcher
functie of cv2.Stitcher_create
functies te gebruiken.
De twee “eenvoudig op te lossen” fouten die ik mensen zie tegenkomen is vergeten welke versie van OpenCV ze gebruiken.
Als u bijvoorbeeld OpenCV 4 gebruikt en cv2.createSticher
probeert aan te roepen, krijgt u de volgende foutmelding:
>>> cv2.createStitcherTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'createStitcher'
U zou in plaats daarvan de cv2.Stitcher_create
functie moeten gebruiken.
Ook als u OpenCV 3 gebruikt en cv2.Sticher_create
probeert aan te roepen, krijgt u deze foutmelding:
>>> cv2.Stitcher_createTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'Stitcher_create'
Gebruik in plaats daarvan de cv2.createSticher
functie.
Als u niet zeker weet welke OpenCV versie u gebruikt, kunt u dat controleren met cv2.__version__
:
>>> cv2.__version__'4.0.0'
Hier kunt u zien dat ik OpenCV 4.0.0 gebruik.
U kunt dezelfde controle op uw systeem uitvoeren.
De laatste fout die u kunt tegenkomen, en waarschijnlijk de meest voorkomende, is gerelateerd aan OpenCV (1) dat geen contrib ondersteuning heeft en (2) is gecompileerd zonder dat de OPENCV_ENABLE_NONFREE=ON
optie is ingeschakeld.
Om deze fout op te lossen moet u de opencv_contrib
modules geinstalleerd hebben samen met de OPENCV_ENABLE_NONFREE
optie ingesteld op ON
.
Als u een fout tegenkomt die gerelateerd is aan OpenCV’s niet-vrije en contrib modules, zorg er dan voor dat u mijn OpenCV installatie gidsen raadpleegt om er zeker van te zijn dat u de volledige installatie van OpenCV heeft.
Note: Merk op dat ik niet kan helpen bij het debuggen van uw eigen OpenCV installatie als u niet een van mijn installatiegidsen heeft gevolgd, dus zorg ervoor dat u mijn OpenCV installatiegidsen gebruikt bij het configureren van uw systeem.
Samenvatting
In de tutorial van vandaag heeft u geleerd hoe u meerdere afbeeldingen kunt stitchen met behulp van OpenCV en Python.
Met behulp van zowel OpenCV als Python konden we meerdere afbeeldingen aan elkaar hechten en panoramische afbeeldingen maken.
Onze panoramische afbeeldingen waren niet alleen nauwkeurig in hun hechting, maar ook esthetisch aantrekkelijk.
Een van de grootste nadelen van het gebruik van OpenCV’s ingebouwde klasse voor het stitchen van afbeeldingen is echter dat het veel van de interne berekeningen weg abstraheert, inclusief de resulterende homografiematrices zelf.
Als je probeert om realtime beeldstiksels uit te voeren, zoals we in een eerdere post deden, kun je het voordelig vinden om de homografiematrix in de cache op te slaan en slechts af en toe sleutelpuntdetectie, feature-extractie en feature-matching uit te voeren.
Het overslaan van deze stappen en het gebruik van de cache-matrix om perspectief warping uit te voeren, kan de computationele last van uw pijplijn verminderen en uiteindelijk het real-time image stitching-algoritme versnellen, maar helaas bieden OpenCV’s cv2.createStitcher
Python-bindingen ons geen toegang tot de ruwe matrices.
Als u geïnteresseerd bent in het leren van meer over real-time panorama constructie, verwijzen wij u naar mijn vorige post.
Ik hoop dat u genoten heeft van de tutorial van vandaag over image stitching!
Om de broncode van de post van vandaag te downloaden, en op de hoogte gehouden te worden van tutorials die hier op PyImageSearch worden gepubliceerd, vul uw email adres in op het formulier hieronder!