Afbeeldingen aan elkaar hechten met OpenCV en Python

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:

  1. Fundamentals of image stitching
  2. 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:

  1. Het detecteren van sleutelpunten (DoG, Harris, enz.) en het extraheren van lokale invariante descriptoren (SIFT, SURF, enz.) uit twee invoerbeelden
  2. De descriptoren tussen de beelden matchen
  3. Het RANSAC-algoritme gebruiken om een homografiematrix te schatten met behulp van onze gematchte kenmerkvectoren
  4. 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!

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

Figuur 1: De pijplijn van de stitchmodule, geïmplementeerd in de klasse Stitcher (bron).

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

Figuur 2: De constructor signatuur voor het maken van een Stitcher klasse-object met OpenCV.

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:

Figuur 3: Drie foto’s om OpenCV beeldstiksels mee te testen. Deze afbeeldingen zijn door mij gemaakt in Scottsdale, AZ bij het beroemde Taliesin West-huis van Frank Lloyd Wright.

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...
Figuur 4: Het stikken van afbeeldingen uitgevoerd met OpenCV. Deze afbeelding is gestikt, maar moet nog worden bijgesneden.

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

Figuur 5: In dit gedeelte leren we hoe we het stitchen van beelden met OpenCV kunnen verbeteren door het gebied van het panorama binnen de rode streepjesrand in de figuur uit te snijden.

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 onze stitched 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 onze stitched afbeelding (Lijn 49).
  • En vanaf daar drempelen we de gray afbeelding (Lijn 50).

Hier is het resultaat (thresh ) van deze drie stappen:

Figuur 6: Na het dorsen krijgen we dit drempelmasker te zien, dat aangeeft waar de door OpenCV samengevoegde en vervormde afbeelding zich bevindt.

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:

Figuur 7: De kleinste rechthoekige regio waarin het volledige OpenCV-panorama kan passen.

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:

  1. Het eerste masker, minMask , wordt langzaam verkleind totdat het binnen het binnenste gedeelte van het panorama past (zie figuur 5 bovenaan deze sectie).
  2. Het tweede masker, sub , wordt gebruikt om te bepalen of we minMask 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:

Figuur 8: Een animatie van de hack die ik heb bedacht om het minRect-gebied van het OpenCV-panoramabeeld te extraheren, wat een esthetisch aantrekkelijk gestikt beeld oplevert

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...
Figuur 8: Het resultaat van onze meervoudige beeldstitching met OpenCV en Python.

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!

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.