Billedstitching med OpenCV og Python

I denne vejledning lærer du, hvordan du udfører billedstitching ved hjælp af Python, OpenCV og funktionerne cv2.createStitcher og cv2.Stitcher_create. Ved hjælp af dagens kode vil du være i stand til at sy flere billeder sammen og skabe et panorama af syede billeder.

For knap to år siden udgav jeg to vejledninger om billedstitching og panoramaopbygning:

  1. Fundamentals of image stitching
  2. Real-time panorama and image stitching

Både disse vejledninger dækkede de grundlæggende elementer i den typiske algoritme for billedstitching, som som som minimum kræver fire vigtige trin:

  1. Detektering af nøglepunkter (DoG, Harris osv.) og udvinding af lokale invariante deskriptorer (SIFT, SURF osv.) fra to indgangsbilleder
  2. Matching af deskriptorerne mellem billederne
  3. Anvendelse af RANSAC-algoritmen til at estimere en homografimatrix ved hjælp af vores matchede featurevektorer
  4. Anvendelse af en warping-transformation ved hjælp af den homografimatrix, der er opnået fra trin 3

Det største problem med mine oprindelige implementeringer er imidlertid, at de ikke var i stand til at håndtere mere end to indgangsbilleder.

I dagens tutorial vil vi gense billedstitching med OpenCV, herunder hvordan man syr mere end to billeder sammen til et panoramabillede.

For at lære, hvordan man syr billeder med OpenCV og Python, skal du bare fortsætte med at læse!

Image Stitching with OpenCV and Python

I første del af dagens tutorial vil vi kort gennemgå OpenCV’s algoritme til billedstitching, som er bagt ind i selve OpenCV-biblioteket via cv2.createStitcher og cv2.Stitcher_create-funktioner.

Derfra gennemgår vi vores projektstruktur og implementerer et Python-script, der kan bruges til billedstitching.

Vi gennemgår resultaterne af dette første script, noterer os dets begrænsninger og implementerer derefter et andet Python-script, der kan bruges til mere æstetisk tiltalende billedstitching-resultater.

Sluttelig gennemgår vi resultaterne af vores andet script og noterer igen eventuelle begrænsninger eller ulemper.

OpenCV’s billede stitching-algoritme

Figur 1: Stitching-modulets pipeline implementeret i Stitcher-klassen (kilde).

Algoritmen, som vi skal bruge her i dag, ligner den metode, som Brown og Lowe foreslog i deres artikel fra 2007, Automatic Panoramic Image Stitching with Invariant Features.

I modsætning til tidligere algoritmer til sammensyning af billeder, som er følsomme over for rækkefølgen af indgangsbilleder, er Brown og Lowes metode mere robust, hvilket gør den ufølsom over for:

  • Rækkefølge af billeder
  • Orientering af billeder
  • Illuminationsændringer
  • Støjende billeder, der faktisk ikke er en del af panoramaet

Dertil kommer, at deres billede-stitchingmetode er i stand til at producere mere æstetisk tiltalende udgangspanoramabilleder ved hjælp af gainkompensation og billedblanding.

En fuldstændig, detaljeret gennemgang af algoritmen ligger uden for rammerne af dette indlæg, så hvis du er interesseret i at lære mere, henvises du til den originale publikation.

Projektstruktur

Lad os se, hvordan dette projekt er organiseret med kommandoen 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

Inputbillederne kommer i mappen images/. Jeg valgte at lave en undermappe til mit scottsdale/ sæt billeder, hvis jeg senere skulle ønske at tilføje yderligere undermapper her.

I dag skal vi gennemgå to Python-scripts:

  • image_stitching_simple.py : Vores enkle version af billedstitching kan gennemføres på mindre end 50 linjer Python-kode!
  • image_stitching.py : Dette script indeholder mit hack til at udtrække en ROI af det syede billede for at opnå et æstetisk tiltalende resultat.

Den sidste fil, output.png , er navnet på det resulterende syede billede. Ved hjælp af kommandolinjeargumenter kan du nemt ændre filnavn + sti til outputbilledet.

Funktionerne cv2.createStitcher og cv2.Stitcher_create

Figur 2: Konstruktorsignaturen for oprettelse af et Stitcher-klasseobjekt med OpenCV.

OpenCV har allerede implementeret en metode svarende til Brown og Lowes artikel via cv2.createStitcher (OpenCV 3.x) og cv2.Stitcher_create (OpenCV 4) funktioner.

Såfremt du har OpenCV korrekt konfigureret og installeret, vil du kunne undersøge funktionssignaturen for cv2.createStitcher for OpenCV 3.x:

createStitcher(...) createStitcher() -> retval

Bemærk, hvordan denne funktion kun har en enkelt parameter, try_gpu, som kan bruges til at forbedre din hele din billede stitching pipeline. OpenCV’s GPU-understøttelse er begrænset, og jeg har aldrig været i stand til at få denne parameter til at fungere, så jeg anbefaler altid at lade den være False .

cv2.Stitcher_create-funktionen til OpenCV 4 har en lignende signatur:

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.

For at udføre selve billedstitching skal vi kalde .stitch-metoden:

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.

Denne metode accepterer en liste af input images , og forsøger derefter at stitche dem til et panorama og returnerer outputpanoramabilledet til den kaldende funktion.

Variablen status angiver, om det lykkedes at sy billedet eller ej, og kan være en af fire variabler:

  • OK = 0 : Det lykkedes at sy billedet.
  • ERR_NEED_MORE_IMGS = 1 : Hvis du modtager denne statuskode, skal du bruge flere indgangsbilleder til at konstruere dit panorama. Typisk opstår denne fejl, hvis der ikke er fundet nok nøglepunkter i dine indgangsbilleder.
  • ERR_HOMOGRAPHY_EST_FAIL = 2 : Denne fejl opstår, når RANSAC-homografi-estimationen mislykkes. Igen har du måske brug for flere billeder, eller dine billeder har ikke nok karakteristiske, unikke teksturer/objekter til, at nøglepunkterne kan matches nøjagtigt.
  • ERR_CAMERA_PARAMS_ADJUST_FAIL = 3 : Jeg er aldrig stødt på denne fejl før, så jeg har ikke meget viden om den, men essensen er, at den er relateret til, at det ikke lykkes at estimere kameraets intrinsics/extrinsics korrekt ud fra indgangsbillederne. Hvis du støder på denne fejl, skal du muligvis henvise til OpenCV-dokumentationen eller endda dykke ned i OpenCV C++-koden.

Nu da vi har gennemgået cv2.createStitcher , cv2.Stitcher_create og .stitch-metoderne, skal vi gå videre til faktisk at implementere billedstitching med OpenCV og Python.

Implementering af billedstitching med Python

Lad os gå i gang med at implementere vores billedstitching-algoritme!

Åbn image_stitching_simple.py-filen og indsæt følgende kode:

# 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())

Vores nødvendige pakker er importeret på linje 2-6. Navnlig skal vi bruge OpenCV og imutils. Hvis du ikke allerede har gjort det, skal du gå i gang med at installere dem:

  • For at installere OpenCV skal du blot følge en af mine OpenCV-installationsvejledninger.
  • Imutils-pakken kan installeres/opdateres med pip: pip install --upgrade imutils . Sørg for at opgradere den, da der ofte tilføjes nye funktioner.

Derfra analyserer vi to kommandolinjeargumenter på linje 9-14:

  • --images : Stien til mappen med de indgangsbilleder, der skal stitches.
  • --output : Stien til det udgangsbillede, hvor resultatet skal gemmes.

Hvis du ikke er bekendt med begreberne argparse og kommandolinjeargumenter, skal du læse dette blogindlæg.

Lad os indlæse vores indgangsbilleder:

# 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)

Her henter vi vores imagePaths (linje 18).

Dernæst indlæser vi for hvert imagePath image og føjer det til images-listen (linje 19-25).

Nu, hvor images er i hukommelsen, skal vi gå videre og sy dem sammen til et panorama ved hjælp af OpenCV’s indbyggede mulighed:

# 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)

Objektet stitcher oprettes i linje 30. Bemærk, at afhængigt af, om du bruger OpenCV 3 eller 4, kaldes en anden konstruktør.

Derpå kan vi videregive vores images til .stitch-metoden (linje 31). Kaldet til .stitch returnerer både et status og vores stitched-billede (hvis vi antager, at stitchingprocessen var vellykket).

Slutteligt vil vi både (1) skrive det syede billede til disken og (2) vise det på skærmen:

# 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))

Antages det, at vores status-flag indikerer succes (linje 35), skriver vi stitched-billedet til disken (linje 37) og viser det, indtil der trykkes på en tast (linje 40 og 41).

I modsat fald udskriver vi blot en fejlmeddelelse (linje 45 og 46).

Basisresultater af billedstitching

For at give vores billedstitching-script en chance, skal du sørge for at bruge afsnittet “Downloads” i vejledningen for at downloade kildekoden og eksempelbillederne.

Inden for mappen images/scottsdale/ finder du tre billeder, som jeg tog, da jeg besøgte Frank Lloyd Wrights berømte Taliesin West-hus i Scottsdale, AZ:

Figur 3: Tre billeder til at teste OpenCV-billedstitching med. Disse billeder blev taget af mig i Scottsdale, AZ, ved Frank Lloyd Wrights berømte Taliesin West-hus.

Vores mål er at sammenføje disse tre billeder til et enkelt panoramabillede. For at udføre stitching skal du åbne en terminal, navigere til det sted, hvor du har downloadet koden + billederne, og udføre følgende kommando:

$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
Figur 4: Billed-stitching udført med OpenCV. Dette billede har gennemgået stitching, men er endnu ikke beskåret.

Se, hvordan vi med succes har udført image stitching!

Men hvad med de sorte områder omkring panoramaet? Hvad er det?

Disse områder stammer fra udførelsen af de perspektivforvrængninger, der er nødvendige for at konstruere panoramaet.

Der er en måde at slippe af med dem på … men vi skal implementere noget ekstra logik i næste afsnit.

En bedre billedstitcher med OpenCV og Python

Figur 5: I dette afsnit lærer vi, hvordan vi kan forbedre billedstitching med OpenCV ved at beskære det område af panoramaet inden for den røde streggrænse, der er vist i figuren.

Vores første billedstitching-script var en god start, men de sorte områder omkring selve panoramaet er ikke noget, vi ville kalde “æstetisk tiltalende”.

Og mere præcist ville du ikke se et sådant output-billede fra populære billedstitching-programmer indbygget i iOS, Android osv.

Derfor vil vi hacke vores script en smule og inkludere noget ekstra logik for at skabe mere æstetisk tiltalende panoramaer.

Jeg vil igen gentage, at denne metode er et hack.

Vi vil gennemgå grundlæggende billedbehandlingsoperationer, herunder tærskelværdi, konturudtrækning, morfologiske operationer osv. for at opnå vores ønskede resultat.

Så vidt jeg ved, giver OpenCV’s Python-bindinger os ikke de nødvendige oplysninger til manuelt at udtrække det maksimale indre rektangulære område af panoramaet. Hvis OpenCV gør det, så lad mig vide det i kommentarerne, da jeg meget gerne vil vide det.

Lad os gå i gang – åbn image_stitching.py-scriptet og indsæt følgende kode:

# 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 denne kode er identisk med vores tidligere script med én undtagelse.

Det --crop-kommandolinjeargument er blevet tilføjet. Når der er angivet et 1 for dette argument i terminalen, går vi videre og udfører vores beskæringshack.

Det næste trin er der, hvor vi begynder at implementere yderligere funktionalitet:

# 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)

Bemærk, hvordan jeg har lavet en ny blok for, hvornår --crop-flaget er indstillet på linje 40. Lad os begynde at gennemgå denne blok:

  • Først tilføjer vi en 10 pixelrand til alle sider af vores stitched-billede (linje 43 og 44), hvilket sikrer, at vi senere i dette afsnit kan finde konturerne af det komplette panoramaomrids.
  • Dernæst opretter vi en gray-version af vores stitched-billede (linje 49).
  • Og derfra sætter vi tærsklen for gray-billedet (linje 50).

Her er resultatet (thresh ) af disse tre trin:

Figur 6: Efter tærskelværdiberegningen præsenteres vi for denne tærskelværdimask, der fremhæver, hvor det OpenCV-stitched + warped billede befinder sig.

Vi har nu et binært billede af vores panorama, hvor hvide pixels (255) er forgrunden og sorte pixels (0) er baggrunden.

Givet vores tærskelbillede kan vi anvende konturudtrækning, beregne den afgrænsende boks af den største kontur (dvs, selve panoramaets omrids), og tegne den afgrænsende boks:

# 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)

Konturerne udtrækkes og analyseres på linje 55-57. Linje 58 tager derefter konturen med det største område (dvs. selve omridset af det sammensyede billede).

Bemærk: imutils.grab_contours-funktionen er ny i imutils==0.5.2 for at imødekomme OpenCV 2.4, OpenCV 3 og OpenCV 4 og deres forskellige retursignaturer for cv2.findContours .

Linje 62 allokerer hukommelse til vores nye rektangulære maske. Linje 63 beregner derefter den afgrænsende boks for vores største kontur. Ved hjælp af oplysningerne om det afgrænsende rektangel tegner vi i linje 64 et solidt hvidt rektangel på masken.

Opdatet af ovenstående kodeblok ville se ud som følger:

Figur 7: Det mindste rektangulære område, som hele OpenCV-panoramaet kan passe ind i.

Denne afgrænsende boks er det mindste rektangulære område, som hele panoramaet kan passe ind i.

Nu kommer et af de største hacks, jeg nogensinde har sammensat til et blogindlæg:

# 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)

På linje 70 og 71 opretter vi to kopier af vores mask-billede:

  1. Den første maske, minMask , vil langsomt blive reduceret i størrelse, indtil den kan passe ind i den indre del af panoramaet (se figur 5 øverst i dette afsnit).
  2. Den anden maske, sub , vil blive brugt til at afgøre, om vi skal blive ved med at reducere størrelsen af minMask .

Linje 75 starter en while sløjfe, der vil fortsætte sløjfen, indtil der ikke er flere forgrundspixels i sub .

Linje 79 udfører en erosionsmorfologisk operation for at reducere størrelsen af minRect .

Linje 80 subtraherer derefter thresh fra minRect – når der ikke er flere forgrundspixels i minRect, kan vi bryde løkken.

Jeg har inkluderet en animation af hack’et nedenfor:

Figur 8: En animation af det hack, jeg fandt på for at udtrække minRect-regionen af OpenCV-panoramabilledet, hvilket giver et æstetisk tiltalende stitched image

Overst har vi vores sub-billede og nederst har vi minRect-billedet.

Bemærk, hvordan størrelsen af minRect reduceres gradvist, indtil der ikke er flere forgrundspixels tilbage i sub – på dette tidspunkt ved vi, at vi har fundet den mindste rektangulære maske, der kan passe ind i det største rektangulære område af panoramaet.

Givet det mindste indre rektangel kan vi igen finde konturer og beregne den afgrænsende boks, men denne gang udtrækker vi blot ROI’en fra stitched-billedet:

# 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

Her har vi:

  • Fundet konturer i minRect (linje 84 og 85).
  • Håndteret parsering af konturer for flere OpenCV-versioner (linje 86). Du skal bruge imutils>=0.5.2 for at bruge denne funktion.
  • Grabbed the largest contour (linje 87).
  • Computed the bounding box of the largest contour (linje 88).
  • Extracted the ROI from our stitched using the bounding box information (linje 92).

Det endelige stitched-billede kan vises på vores skærm og derefter gemmes på disk:

# 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))

Linjerne 95-99 håndterer lagring og visning af billedet, uanset om vores beskæringshack er udført eller ej.

Som før, hvis status-flaget ikke kom tilbage som en succes, udskriver vi en fejlmeddelelse (linje 103 og 104).

Lad os gå videre og tjekke resultaterne af vores forbedrede billede stitching + OpenCV-pipeline.

Forbedrede billede stitching-resultater

Sørg igen for, at du har brugt afsnittet “Downloads” i dagens tutorial for at downloade kildekoden og eksempelbillederne.

Åbn en terminal derfra, og udfør følgende kommando:

$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
Figur 8: Resultatet af vores multiple image stitching med OpenCV og Python.

Bemærk, hvordan vi denne gang har fjernet de sorte områder fra de output-stitchede billeder (forårsaget af warping-transformationerne) ved at anvende vores hack, der er beskrevet i afsnittet ovenfor.

Begrænsninger og ulemper

I en tidligere vejledning demonstrerede jeg, hvordan du kan opbygge en realtidspanorama- og billedstitching-algoritme – denne vejledning var afhængig af, at vi manuelt udførte keypoint-detektion, feature-udtrækning og keypoint-matching, hvilket gav os adgang til den homografimatrix, der blev brugt til at warpe vores to indgangsbilleder til et panorama.

Og selv om OpenCV’s indbyggede cv2.createStitcher og cv2.Stitcher_create-funktioner bestemt er i stand til at konstruere præcise, æstetisk tiltalende panoramaer, er en af de primære ulemper ved metoden, at den abstraherer enhver adgang til homografimatricerne.

En af forudsætningerne for panoramaopbygning i realtid er, at selve scenen ikke ændrer sig meget med hensyn til indhold.

Når vi først har beregnet den indledende homografi-estimation, bør vi kun lejlighedsvis skulle have behov for at genberegne matricen.

Det, at vi ikke behøver at udføre en komplet keypoint-matching og RANSAC-estimation, giver os et enormt boost af hastighed, når vi opbygger vores panorama, så uden adgang til de rå homografimatricer ville det være en udfordring at tage OpenCV’s indbyggede billedstitching-algoritme og konvertere den til realtid.

Løber du ind i fejl, når du udfører billedstitching ved hjælp af OpenCV?

Det er muligt, at du kan løbe ind i fejl, når du forsøger at bruge enten cv2.createStitcher-funktionen eller cv2.Stitcher_create-funktionerne.

De to “nemme at løse” fejl, som jeg ser folk støde på, er at glemme, hvilken version af OpenCV de bruger.

For eksempel, hvis du bruger OpenCV 4, men forsøger at kalde cv2.createSticher, vil du støde på følgende fejlmeddelelse:

>>> cv2.createStitcherTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'createStitcher'

Du bør i stedet bruge cv2.Stitcher_create-funktionen.

Sådan er det også, hvis du bruger OpenCV 3, og du forsøger at kalde cv2.Sticher_create, vil du få denne fejl:

>>> cv2.Stitcher_createTraceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: module 'cv2' has no attribute 'Stitcher_create'

Brug i stedet cv2.createSticher-funktionen.

Hvis du er usikker på, hvilken OpenCV-version du bruger, kan du kontrollere det ved hjælp af cv2.__version__ :

>>> cv2.__version__'4.0.0'

Her kan du se, at jeg bruger OpenCV 4.0.0.0.

Du kan udføre den samme kontrol på dit system.

Den sidste fejl, du kan støde på, og vel nok den mest almindelige, er relateret til, at OpenCV (1) ikke har contrib-understøttelse og (2) er kompileret uden at OPENCV_ENABLE_NONFREE=ON-indstillingen er aktiveret.

For at løse denne fejl skal du have opencv_contrib-modulerne installeret sammen med OPENCV_ENABLE_NONFREE-indstillingen indstillet til ON .

Hvis du støder på en fejl relateret til OpenCV’s non-free- og contrib-moduler, skal du sørge for at henvise til mine OpenCV-installationsvejledninger for at sikre, at du har den fulde installation af OpenCV.

Bemærk venligst, at jeg ikke kan hjælpe med at fejlfinde din egen OpenCV-installation, hvis du ikke har fulgt en af mine installationsvejledninger, så sørg for, at du bruger mine OpenCV-installationsvejledninger, når du konfigurerer dit system.

Summary

I dagens tutorial har du lært, hvordan du kan udføre stitching af flere billeder ved hjælp af OpenCV og Python.

Ved hjælp af både OpenCV og Python var vi i stand til at sy flere billeder sammen og skabe panoramabilleder.

Vores outputpanoramabilleder var ikke kun nøjagtige i deres stitchingplacering, men også æstetisk tiltalende også.

En af de største ulemper ved at bruge OpenCV’s indbyggede billedstitching-klasse er imidlertid, at den abstraherer meget af den interne beregning, herunder selve de resulterende homografimatricer.

Hvis du forsøger at udføre realtidsbilledstitching, som vi gjorde i et tidligere indlæg, kan du måske finde det fordelagtigt at cache homografimatricen og kun lejlighedsvis udføre keypoint-detektion, featureudtrækning og feature matching.

Skipping disse trin og brug af den cachelagrede matrix til at udføre perspective warping kan reducere den beregningsmæssige byrde i din pipeline og i sidste ende fremskynde realtidsbilledstitching-algoritmen, men desværre giver OpenCV’s cv2.createStitcher Python-bindinger os ikke adgang til de rå matricer.

Hvis du er interesseret i at lære mere om panoramaopbygning i realtid, henvises du til mit tidligere indlæg.

Jeg håber, at du nød dagens tutorial om billedstitching!

For at downloade kildekoden til dagens indlæg og få besked om, at tutorials offentliggøres her på PyImageSearch, skal du blot indtaste din e-mail-adresse i formularen nedenfor!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.