Cucitura di immagini con OpenCV e Python

In questo tutorial, imparerete come eseguire la cucitura di immagini usando Python, OpenCV e le funzioni cv2.createStitcher e cv2.Stitcher_create. Usando il codice di oggi sarete in grado di cucire più immagini insieme, creando un panorama di immagini cucite.

Poco meno di due anni fa ho pubblicato due guide sullo stitching di immagini e sulla costruzione di panorami:

  1. Fondamenti di stitching di immagini
  2. Panorama in tempo reale e stitching di immagini

Entrambi questi tutorial coprivano i fondamenti del tipico algoritmo di stitching di immagini, che, come minimo, richiede quattro passi chiave:

  1. Rilevamento dei punti chiave (DoG, Harris, ecc.) ed estrazione di descrittori locali invarianti (SIFT, SURF, ecc.) da due immagini di input
  2. Corrispondendo i descrittori tra le immagini
  3. Utilizzando l’algoritmo RANSAC per stimare una matrice di omografia usando i nostri vettori di caratteristiche abbinati
  4. Applicando una trasformazione di warping usando la matrice di omografia ottenuta dal passo #3

Tuttavia, il problema maggiore delle mie implementazioni originali è che non erano capaci di gestire più di due immagini di input.

Nel tutorial di oggi, rivisiteremo la cucitura di immagini con OpenCV, incluso come cucire più di due immagini insieme in un’immagine panoramica.

Per imparare a cucire immagini con OpenCV e Python, continuate a leggere!

Image Stitching with OpenCV and Python

Nella prima parte del tutorial di oggi, esamineremo brevemente l’algoritmo di stitching delle immagini di OpenCV che è incorporato nella libreria OpenCV stessa attraverso le funzioni cv2.createStitcher e cv2.Stitcher_create.

Da lì rivedremo la struttura del nostro progetto e implementeremo uno script Python che può essere usato per lo stitching delle immagini.

Esamineremo i risultati di questo primo script, noteremo le sue limitazioni, e poi implementeremo un secondo script Python che può essere usato per risultati di stitching delle immagini più esteticamente piacevoli.

Infine, esamineremo i risultati del nostro secondo script e noteremo nuovamente le limitazioni o gli svantaggi.

Algoritmo di stitching dell’immagine di OpenCV

Figura 1: La pipeline del modulo di stitching implementato nella classe Stitcher (fonte).

L’algoritmo che useremo qui oggi è simile al metodo proposto da Brown e Lowe nel loro articolo del 2007, Automatic Panoramic Image Stitching with Invariant Features.

A differenza dei precedenti algoritmi di stitching di immagini che sono sensibili all’ordine delle immagini di input, il metodo di Brown e Lowe è più robusto, rendendolo insensibile a:

  • Ordinamento delle immagini
  • Orientamento delle immagini
  • Modifiche dell’illuminazione
  • Immagini rumorose che non fanno parte del panorama

Inoltre, il loro metodo di cucitura delle immagini è in grado di produrre immagini panoramiche più gradevoli esteticamente attraverso l’uso della compensazione del guadagno e la fusione delle immagini.

Una recensione completa e dettagliata dell’algoritmo è al di fuori dello scopo di questo post, quindi se sei interessato a saperne di più, fai riferimento alla pubblicazione originale.

Struttura del progetto

Vediamo come è organizzato questo progetto con il comando 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

Le immagini di input vanno nella cartella images/. Ho scelto di creare una sottocartella per il mio scottsdale/ set di immagini nel caso in cui volessi aggiungere ulteriori sottocartelle qui in seguito.

Oggi esamineremo due script Python:

  • image_stitching_simple.py : La nostra semplice versione di cucitura di immagini può essere completata in meno di 50 righe di codice Python!
  • image_stitching.py : Questo script include il mio trucco per estrarre un ROI dell’immagine cucita per un risultato esteticamente piacevole.

L’ultimo file, output.png , è il nome dell’immagine cucita risultante. Usando gli argomenti della linea di comando, puoi facilmente cambiare il nome del file + il percorso dell’immagine di uscita.

Le funzioni cv2.createStitcher e cv2.Stitcher_create

Figura 2: La firma del costruttore per creare un oggetto di classe Stitcher con OpenCV.

OpenCV ha già implementato un metodo simile a quello di Brown e Lowe tramite le funzioni cv2.createStitcher (OpenCV 3..x) e cv2.Stitcher_create (OpenCV 4).

Assumendo che abbiate OpenCV correttamente configurato e installato sarete in grado di esaminare la firma della funzione cv2.createStitcher per OpenCV 3.x:

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

Nota come questa funzione abbia un solo parametro, try_gpu che può essere usato per migliorare la vostra pipeline di stitching delle immagini. Il supporto GPU di OpenCV è limitato e non sono mai stato in grado di far funzionare questo parametro, quindi consiglio di lasciarlo sempre come False.

La funzione cv2.Stitcher_create per OpenCV 4 ha una firma simile:

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.

Per eseguire l’effettiva cucitura dell’immagine avremo bisogno di chiamare il metodo .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.

Questo metodo accetta una lista di input images, e poi cerca di cucirli in un panorama, restituendo l’immagine panoramica in uscita alla funzione chiamante.

La variabile status indica se la cucitura dell’immagine ha avuto successo o meno e può essere una di quattro variabili:

  • OK = 0 : La cucitura dell’immagine ha avuto successo.
  • ERR_NEED_MORE_IMGS = 1 : Nel caso in cui si riceve questo codice di stato, è necessario avere più immagini di input per costruire il panorama. Tipicamente questo errore si verifica se non ci sono abbastanza punti chiave rilevati nelle tue immagini di input.
  • ERR_HOMOGRAPHY_EST_FAIL = 2 : Questo errore si verifica quando la stima dell’omografia RANSAC fallisce. Di nuovo, potresti aver bisogno di più immagini o le tue immagini non hanno abbastanza texture/oggetti unici e distintivi per far corrispondere accuratamente i punti chiave.
  • ERR_CAMERA_PARAMS_ADJUST_FAIL = 3 : Non ho mai incontrato questo errore prima, quindi non ho molte conoscenze in merito, ma il succo è che è legato al fallimento della stima corretta delle intrinseche/estrinseche della fotocamera dalle immagini di input. Se incontrate questo errore potreste aver bisogno di fare riferimento alla documentazione di OpenCV o anche di immergervi nel codice OpenCV C++.

Ora che abbiamo rivisto i metodi cv2.createStitcher , cv2.Stitcher_create e .stitch, passiamo all’implementazione effettiva dello stitching di immagini con OpenCV e Python.

Implementazione dello stitching di immagini con Python

Andiamo avanti e iniziamo ad implementare il nostro algoritmo di stitching di immagini!

Apri il file image_stitching_simple.py e inserisci il seguente codice:

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

I nostri pacchetti necessari sono importati alle linee 2-6. In particolare, useremo OpenCV e imutils. Se non l’hai ancora fatto, vai avanti e installali:

  • Per installare OpenCV, segui una delle mie guide all’installazione di OpenCV.
  • Il pacchetto imutils può essere installato/aggiornato con pip: pip install --upgrade imutils . Assicuratevi di aggiornarlo in quanto vengono aggiunte spesso nuove funzionalità.

Da lì analizzeremo due argomenti della riga di comando sulle linee 9-14:

  • --images : Il percorso alla directory delle immagini di input da cucire.
  • --output : Il percorso dell’immagine di uscita dove il risultato sarà salvato.

Se non hai familiarità con i concetti di argparse e gli argomenti della linea di comando, leggi questo post del blog.

Carichiamo le nostre immagini di input:

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

Qui prendiamo il nostro imagePaths (Linea 18).

Poi per ogni imagePath , carichiamo il image e lo aggiungiamo alla lista images (Linee 19-25).

Ora che i images sono in memoria, andiamo avanti e cuciamoli insieme in un panorama usando la capacità integrata di 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’oggetto stitcher viene creato alla linea 30. Notate che a seconda che stiate usando OpenCV 3 o 4, viene chiamato un costruttore diverso.

Di conseguenza, possiamo passare il nostro images al metodo .stitch (linea 31). La chiamata a .stitch restituisce sia un status che la nostra immagine stitched (supponendo che la cucitura sia riuscita).

Finalmente, noi (1) scriviamo l’immagine cucita sul disco e (2) la visualizziamo sullo schermo:

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

Assumendo che il nostro flag status indichi il successo (Linea 35), scriviamo l’immagine stitched sul disco (Linea 37) e la visualizziamo finché non viene premuto un tasto (Linee 40 e 41).

Altrimenti, stampiamo semplicemente un messaggio di fallimento (Linee 45 e 46).

Risultati di base della cucitura delle immagini

Per provare il nostro script di cucitura delle immagini, assicurati di usare la sezione “Download” del tutorial per scaricare il codice sorgente e le immagini di esempio.

Nella directory images/scottsdale/ troverai tre foto che ho scattato visitando la famosa casa Taliesin West di Frank Lloyd Wright a Scottsdale, AZ:

Figura 3: Tre foto per testare lo stitching di immagini di OpenCV. Queste immagini sono state scattate da me a Scottsdale, AZ nella famosa casa Taliesin West di Frank Lloyd Wright.

Il nostro obiettivo è quello di cucire queste tre immagini in una singola immagine panoramica. Per eseguire lo stitching, aprite un terminale, navigate fino a dove avete scaricato il codice + le immagini, ed eseguite il seguente comando:

$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
Figura 4: Stitching delle immagini eseguito con OpenCV. Questa immagine è stata sottoposta a stitching ma deve ancora essere ritagliata.

Nota come abbiamo eseguito con successo lo stitching dell’immagine!

Ma che dire di quelle regioni nere che circondano il panorama? Cosa sono?

Queste regioni sono dovute all’esecuzione delle deformazioni prospettiche necessarie per costruire il panorama.

C’è un modo per sbarazzarsene… ma avremo bisogno di implementare qualche logica aggiuntiva nella prossima sezione.

Un migliore stitcher di immagini con OpenCV e Python

Figura 5: In questa sezione, impareremo come migliorare lo stitching di immagini con OpenCV ritagliando la regione del panorama all’interno del bordo a linee rosse mostrato in figura.

Il nostro primo script di stitching di immagini era un buon inizio ma quelle regioni nere che circondano il panorama stesso non sono qualcosa che potremmo definire “esteticamente piacevole”.

E più precisamente, non vedreste un’immagine di output di questo tipo da applicazioni popolari di stitching di immagini integrate in iOS, Android, ecc.

Pertanto, andremo a modificare un po’ il nostro script e a includere qualche logica aggiuntiva per creare panorami più gradevoli esteticamente.

Voglio ribadire ancora una volta che questo metodo è un hack.

Passeremo in rassegna le operazioni di base di elaborazione delle immagini, tra cui la soglia, l’estrazione dei contorni, le operazioni morfologiche, ecc. per ottenere il nostro risultato desiderato.

A mia conoscenza, i binding Python di OpenCV non ci forniscono le informazioni necessarie per estrarre manualmente la regione rettangolare interna massima del panorama. Se OpenCV lo fa, fatemelo sapere nei commenti perché mi piacerebbe saperlo.

Andiamo avanti e cominciamo – aprite lo script image_stitching.py e inserite il seguente codice:

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

Tutto questo codice è identico al nostro script precedente con un’eccezione.

È stato aggiunto l’argomento --crop della linea di comando. Quando viene fornito un 1 per questo argomento nel terminale, andremo avanti ed eseguiremo il nostro hack di ritaglio.

Il prossimo passo è dove iniziamo ad implementare funzionalità aggiuntive:

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

Nota come ho fatto un nuovo blocco per quando il flag --crop è impostato sulla linea 40. Cominciamo a passare attraverso questo blocco:

  • Primo, aggiungeremo un bordo di 10 pixel a tutti i lati della nostra immagine stitched (Linee 43 e 44), assicurandoci di poter trovare i contorni del profilo completo del panorama più avanti in questa sezione.
  • Poi creeremo una versione gray della nostra immagine stitched (Linea 49).
  • E da lì soglieremo l’immagine gray (Linea 50).

Ecco il risultato (thresh ) di questi tre passi:

Figura 6: Dopo la soglia, ci viene presentata questa maschera di soglia che evidenzia dove risiede l’immagine cucita + deformata di OpenCV.

Ora abbiamo un’immagine binaria del nostro panorama dove i pixel bianchi (255) sono il primo piano e i pixel neri (0) sono lo sfondo.

Data la nostra immagine sogliata possiamo applicare l’estrazione dei contorni, calcolare il bounding box del contorno più grande (cioè il contorno del panorama stesso), e disegnare il rettangolo di delimitazione:

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

I contorni sono estratti e analizzati nelle linee 55-57. La linea 58 prende poi il contorno con l’area più grande (cioè il contorno dell’immagine cucita stessa).

Nota: La funzione imutils.grab_contours è nuova in imutils==0.5.2 per adattarsi a OpenCV 2.4, OpenCV 3 e OpenCV 4 e alle loro diverse firme di ritorno per cv2.findContours .

La linea 62 alloca la memoria per la nostra nuova maschera rettangolare. La linea 63 calcola poi il rettangolo di delimitazione del nostro contorno più grande. Usando le informazioni sul rettangolo di delimitazione, alla linea 64, disegniamo un rettangolo bianco solido sulla maschera.

L’output del blocco di codice di cui sopra sarebbe come il seguente:

Figura 7: La più piccola regione rettangolare che l’intero panorama OpenCV può contenere.

Questo rettangolo di delimitazione è la più piccola regione rettangolare che l’intero panorama può contenere.

Ora, ecco che arriva uno dei più grandi hack che abbia mai messo insieme per un post sul 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)

Alle linee 70 e 71 creiamo due copie della nostra immagine mask:

  1. La prima maschera, minMask , sarà lentamente ridotta di dimensioni fino a quando non può entrare nella parte interna del panorama (vedi Figura 5 in cima a questa sezione).
  2. La seconda maschera, sub , sarà usata per determinare se dobbiamo continuare a ridurre le dimensioni di minMask .

La linea 75 inizia un ciclo while che continuerà finché non ci saranno più pixel in primo piano in sub .

La linea 79 esegue un’operazione morfologica di erosione per ridurre le dimensioni di minRect .

La linea 80 poi sottrae thresh da minRect – una volta che non ci sono più pixel in primo piano in minRect allora possiamo interrompere il ciclo.

Ho incluso un’animazione dell’hack qui sotto:

Figura 8: Un’animazione dell’hack che ho ideato per estrarre la regione minRect dell’immagine panoramica OpenCV, creando un’immagine cucita esteticamente piacevole

In alto, abbiamo la nostra immagine sub e in basso abbiamo l’immagine minRect.

Nota come la dimensione di minRect si riduce progressivamente fino a quando non ci sono più pixel in primo piano in sub – a questo punto sappiamo di aver trovato la più piccola maschera rettangolare che può entrare nella più grande regione rettangolare del panorama.

Dato il minimo rettangolo interno possiamo di nuovo trovare i contorni e calcolare il bounding box, ma questa volta estrarremo semplicemente il ROI dall’immagine 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

Ecco che abbiamo:

  • Trovato i contorni in minRect (Linee 84 e 85).
  • Gestito l’analisi dei contorni per più versioni OpenCV (Linea 86). Avrete bisogno di imutils>=0.5.2 per usare questa funzione.
  • Raccolto il contorno più grande (Linea 87).
  • Calcolato il bounding box del contorno più grande (Linea 88).
  • Estratto il ROI dal nostro stitched usando le informazioni del bounding box (Linea 92).

L’immagine finale stitched può essere visualizzata sul nostro schermo e poi salvata su disco:

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

Le linee 95-99 gestiscono il salvataggio e la visualizzazione dell’immagine indipendentemente dal fatto che il nostro hack di ritaglio venga eseguito o meno.

Come prima, se il flag status non ha avuto successo, stamperemo un messaggio di errore (linee 103 e 104).

Andiamo avanti e controlliamo i risultati della nostra pipeline migliorata di cucitura delle immagini + OpenCV.

Risultati migliorati della cucitura delle immagini

Anche in questo caso, assicuratevi di aver usato la sezione “Downloads” del tutorial di oggi per scaricare il codice sorgente e le immagini di esempio.

Da lì, apri un terminale ed esegui il seguente comando:

$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
Figura 8: Il risultato del nostro stitching di immagini multiple con OpenCV e Python.

Nota come questa volta abbiamo rimosso le regioni nere dalle immagini cucite in uscita (causate dalle trasformazioni warping) applicando il nostro hack dettagliato nella sezione precedente.

Limitazioni e svantaggi

In un tutorial precedente, ho dimostrato come è possibile costruire un algoritmo di stitching di immagini e panorami in tempo reale – questo tutorial si basava sul fatto che stavamo eseguendo manualmente il rilevamento dei punti chiave, l’estrazione delle caratteristiche e la corrispondenza dei punti chiave, dandoci accesso alla matrice di omografia utilizzata per deformare le nostre due immagini di input in un panorama.

E mentre le funzioni integrate cv2.createStitcher e cv2.Stitcher_create di OpenCV sono certamente in grado di costruire panorami accurati ed esteticamente piacevoli, uno degli svantaggi principali del metodo è che astrae qualsiasi accesso alle matrici di omografia.

Uno dei presupposti della costruzione del panorama in tempo reale è che la scena stessa non cambi molto in termini di contenuto.

Una volta calcolata la stima iniziale dell’omografia, dovremmo dover ricomputare la matrice solo occasionalmente.

Non dover eseguire una corrispondenza completa dei punti chiave e una stima RANSAC ci dà un enorme impulso di velocità nella costruzione del nostro panorama, quindi senza accesso alle matrici di omografia grezze, sarebbe difficile prendere l’algoritmo di stitching delle immagini integrato in OpenCV e convertirlo in tempo reale.

Incappare in errori quando si esegue lo stitching di immagini usando OpenCV?

È possibile che si possa incorrere in errori quando si cerca di utilizzare la funzione cv2.createStitcher o le funzioni cv2.Stitcher_create.

I due errori “facili da risolvere” che vedo le persone incontrare è dimenticare quale versione di OpenCV stanno usando.

Per esempio, se state usando OpenCV 4 ma provate a chiamare cv2.createSticher incontrerete il seguente messaggio di errore:

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

Dovreste invece usare la funzione cv2.Stitcher_create.

Similmente, se state usando OpenCV 3 e provate a chiamare cv2.Sticher_create riceverete questo errore:

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

Invece, usate la funzione cv2.createSticher.

Se non sei sicuro di quale versione di OpenCV stai usando puoi controllare usando cv2.__version__ :

>>> cv2.__version__'4.0.0'

Qui puoi vedere che sto usando OpenCV 4.0.0.

Puoi eseguire lo stesso controllo sul tuo sistema.

L’ultimo errore che puoi incontrare, e probabilmente il più comune, è legato al fatto che OpenCV (1) non ha il supporto contrib e (2) è stato compilato senza l’opzione OPENCV_ENABLE_NONFREE=ON abilitata.

Per risolvere questo errore devi avere i moduli opencv_contrib installati insieme all’opzione OPENCV_ENABLE_NONFREE impostata su ON .

Se stai incontrando un errore relativo ai moduli non-free e contrib di OpenCV, assicurati di fare riferimento alle mie guide di installazione di OpenCV per assicurarti di avere l’installazione completa di OpenCV.

Nota: Per favore nota che non posso aiutarti a fare il debug della tua installazione di OpenCV se non hai seguito una delle mie guide di installazione, quindi assicurati di usare le mie guide di installazione di OpenCV quando configuri il tuo sistema.

Sommario

Nel tutorial di oggi hai imparato come eseguire lo stitching di immagini multiple usando OpenCV e Python.

Utilizzando sia OpenCV che Python siamo stati in grado di cucire più immagini insieme e creare immagini panoramiche.

Le nostre immagini panoramiche in uscita non erano solo accurate nel loro posizionamento ma anche esteticamente piacevoli.

Tuttavia, uno dei maggiori svantaggi dell’utilizzo della classe di stitching delle immagini integrata in OpenCV è che astrae gran parte del calcolo interno, comprese le matrici di omografia risultanti stesse.

Se state cercando di eseguire lo stitching delle immagini in tempo reale, come abbiamo fatto in un post precedente, potreste trovare utile memorizzare nella cache la matrice di omografia e solo occasionalmente eseguire il rilevamento dei punti chiave, l’estrazione delle caratteristiche e la corrispondenza delle caratteristiche.

Saltare questi passaggi e utilizzare la matrice memorizzata nella cache per eseguire il warping prospettico può ridurre il carico computazionale della vostra pipeline e, in definitiva, accelerare l’algoritmo di stitching dell’immagine in tempo reale, ma purtroppo, i binding Python di OpenCV cv2.createStitcher non ci forniscono l’accesso alle matrici grezze.

Se siete interessati a saperne di più sulla costruzione di panorami in tempo reale, fate riferimento al mio post precedente.

Spero che vi sia piaciuto il tutorial di oggi sullo stitching delle immagini!

Per scaricare il codice sorgente del post di oggi, ed essere avvisati dei tutorial pubblicati qui su PyImageSearch, basta inserire il vostro indirizzo email nel modulo sottostante!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.