Sešívání obrázků pomocí OpenCV a Pythonu

V tomto kurzu se naučíte provádět sešívání obrázků pomocí Pythonu, OpenCV a funkcí cv2.createStitcher a cv2.Stitcher_create. Pomocí dnešního kódu budete schopni sešít více obrázků dohromady a vytvořit panorama sešitých obrázků.

Před necelými dvěma lety jsem vydal dva návody na sešívání obrázků a tvorbu panoramat:

  1. Základy sešívání obrázků
  2. Real-time panorama a sešívání obrázků

Obě tyto příručky se zabývaly základy typického algoritmu sešívání obrázků, který minimálně vyžaduje čtyři klíčové kroky:

  1. Detekce klíčových bodů (DoG, Harris, atd.) a extrakce lokálních invariantních deskriptorů (SIFT, SURF atd.).) ze dvou vstupních obrazů
  2. Srovnání deskriptorů mezi obrazy
  3. Použití algoritmu RANSAC k odhadu homografické matice pomocí našich srovnaných příznakových vektorů
  4. Použití deformační transformace pomocí homografické matice získané z kroku č. 3

Největším problémem mých původních implementací však bylo, že nebyly schopny zpracovat více než dva vstupní obrazy.

V dnešním tutoriálu se vrátíme ke spojování obrázků pomocí OpenCV, včetně toho, jak spojit více než dva obrázky do panoramatického snímku.

Chcete-li se naučit spojovat obrázky pomocí OpenCV a Pythonu, stačí číst dál!

Sešívání obrázků pomocí OpenCV a Pythonu

V první části dnešního tutoriálu si stručně projdeme algoritmus OpenCV pro sešívání obrázků, který je zabudován do samotné knihovny OpenCV prostřednictvím funkcí cv2.createStitcher a cv2.Stitcher_create.

Poté si prohlédneme strukturu našeho projektu a implementujeme skript v jazyce Python, který lze použít pro sešívání obrázků.

Přezkoumáme výsledky tohoto prvního skriptu, všimneme si jeho omezení a poté implementujeme druhý skript v jazyce Python, který lze použít pro estetičtější výsledky sešívání obrázků.

Nakonec si prohlédneme výsledky našeho druhého skriptu a opět si všimneme případných omezení nebo nedostatků.

Algoritmus sešívání obrázků v OpenCV

Obrázek 1: Pipeline modulu sešívání implementovaná ve třídě Stitcher (zdrojový kód).

Algoritmus, který zde dnes budeme používat, je podobný metodě, kterou navrhli Brown a Lowe ve svém článku Automatic Panoramic Image Stitching with Invariant Features z roku 2007.

Na rozdíl od předchozích algoritmů sešívání snímků, které jsou citlivé na pořadí vstupních snímků, je metoda Browna a Loweho robustnější, takže není citlivá na:

  • Pořadí snímků
  • Orientace snímků
  • Změny osvětlení
  • Hlučné snímky, které ve skutečnosti nejsou součástí panoramatu

Dále je jejich metoda sešívání snímků schopna vytvářet estetičtější výstupní panoramatické snímky díky použití kompenzace zisku a prolínání snímků.

Kompletní a podrobný přehled algoritmu je mimo rozsah tohoto příspěvku, takže pokud máte zájem dozvědět se více, podívejte se na původní publikaci.

Struktura projektu

Podívejme se, jak je tento projekt organizován pomocí příkazu 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

Vstupní snímky patří do složky images/. Rozhodl jsem se vytvořit podsložku pro sadu obrázků scottsdale/ pro případ, že bych sem chtěl později přidat další podsložky.

Dnes si projdeme dva skripty Pythonu:

  • image_stitching_simple.py : Naši jednoduchou verzi sešívání obrázků lze dokončit na méně než 50 řádcích kódu Pythonu!
  • image_stitching.py : Tento skript obsahuje můj hack pro extrakci ROI sešívaného obrázku pro estetický výsledek.

Poslední soubor, output.png , je název výsledného sešívaného obrázku. Pomocí argumentů příkazového řádku můžete snadno změnit název souboru + cestu k výstupnímu obrázku.

Funkce cv2.createStitcher a cv2.Stitcher_create

Obrázek 2: Signatura konstruktoru pro vytvoření objektu třídy Stitcher pomocí OpenCV.

OpenCV již implementoval podobnou metodu jako Brown a Lowe ve svém článku prostřednictvím cv2.createStitcher (OpenCV 3.).x) a cv2.Stitcher_create (OpenCV 4).

Předpokládáme, že máte OpenCV správně nakonfigurován a nainstalován, budete moci prozkoumat signaturu funkce cv2.createStitcher pro OpenCV 3.x:

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

Všimněte si, že tato funkce má pouze jediný parametr, try_gpu, který lze použít ke zlepšení vaší celé pipeline sešívání obrazu. Podpora GPU v OpenCV je omezená a nikdy se mi nepodařilo tento parametr zprovoznit, takže ho doporučuji vždy ponechat jako False .

Funkce cv2.Stitcher_create pro OpenCV 4 má podobnou signaturu:

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.

Pro provedení vlastního sešívání obrázků budeme muset zavolat metodu .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.

Tato metoda přijme seznam vstupních images , poté se je pokusí sešít do panoramatu a vrátí volající funkci výstupní panoramatický obrázek.

Proměnná status udává, zda bylo sešití obrázku úspěšné, a může být jednou ze čtyř proměnných:

  • OK = 0 : Sešití obrázku bylo úspěšné.
  • ERR_NEED_MORE_IMGS = 1 : V případě, že obdržíte tento stavový kód, budete k sestavení panoramatu potřebovat další vstupní obrázky. Obvykle k této chybě dochází, pokud na vstupních snímcích není zjištěn dostatečný počet klíčových bodů.
  • ERR_HOMOGRAPHY_EST_FAIL = 2 : Tato chyba nastane, pokud se nepodaří odhad homografie RANSAC. Opět můžete potřebovat více snímků nebo vaše snímky nemají dostatek rozlišujících, jedinečných textur/objektů pro přesné přiřazení klíčových bodů.
  • ERR_CAMERA_PARAMS_ADJUST_FAIL = 3 : S touto chybou jsem se nikdy předtím nesetkal, takže o ní nemám mnoho znalostí, ale podstata je, že souvisí s tím, že se nepodařilo správně odhadnout vnitřní/extrinsické vlastnosti kamery ze vstupních snímků. Pokud se s touto chybou setkáte, možná budete muset nahlédnout do dokumentace OpenCV nebo se dokonce ponořit do kódu OpenCV C++.

Teď, když jsme si prošli metody cv2.createStitcher , cv2.Stitcher_create a .stitch, přejděme ke skutečné implementaci sešívání obrazu pomocí OpenCV a Pythonu.

Implementace sešívání obrázků pomocí Pythonu

Pustíme se do implementace našeho algoritmu sešívání obrázků!

Otevřete soubor image_stitching_simple.py a vložte následující kód:

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

Na řádcích 2-6 jsou importovány naše potřebné balíčky. Pozoruhodné je, že budeme používat OpenCV a imutils. Pokud jste tak ještě neučinili, pokračujte v jejich instalaci:

  • Pro instalaci OpenCV stačí postupovat podle jednoho z mých návodů na instalaci OpenCV.
  • Balíček imutils lze nainstalovat/aktualizovat pomocí pip: pip install --upgrade imutils . Nezapomeňte jej aktualizovat, protože často přibývají nové funkce.

Odtud budeme analyzovat dva argumenty příkazového řádku na řádcích 9-14:

  • --images : Cesta k adresáři vstupních obrázků, které se mají sešít.
  • --output : Cesta k výstupnímu obrázku, kam bude výsledek uložen.

Pokud neznáte pojmy argparse a argumenty příkazového řádku, přečtěte si tento příspěvek na blogu.

Načteme naše vstupní obrázky:

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

Tady uchopíme náš imagePaths (řádek 18).

Poté pro každý imagePath , načteme image a přidáme ho do seznamu images (řádky 19-25).

Teď, když jsou images v paměti, přistoupíme k jejich sešití do panoramatu pomocí vestavěných schopností 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)

Objekt stitcher je vytvořen na řádku 30.

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

Objekt stitcher je vytvořen na řádku 30. Všimněte si, že podle toho, zda používáte OpenCV 3 nebo 4, se volá jiný konstruktor.

Následně můžeme předat náš images metodě .stitch (řádek 31). Volání .stitch vrátí jak status, tak náš obrázek stitched (za předpokladu, že se sešití podařilo).

Nakonec jednak (1) zapíšeme sešitý obrázek na disk a (2) zobrazíme jej na obrazovce:

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

Pokud náš příznak status indikuje úspěch (řádek 35), zapíšeme obrázek stitched na disk (řádek 37) a zobrazíme jej, dokud nestiskneme klávesu (řádky 40 a 41).

V opačném případě jednoduše vypíšeme zprávu o neúspěchu (řádky 45 a 46).

Základní výsledky sešívání obrázků

Chcete-li si náš skript pro sešívání obrázků vyzkoušet, nezapomeňte si pomocí sekce „Ke stažení“ v návodu stáhnout zdrojový kód a ukázkové obrázky.

V adresáři images/scottsdale/ naleznete tři fotografie, které jsem pořídil při návštěvě slavného domu Taliesin West Franka Lloyda Wrighta ve Scottsdale, AZ:

Obrázek 3: Tři fotografie, na kterých si můžete vyzkoušet sešívání obrázků v OpenCV. Tyto snímky jsem pořídil ve Scottsdale v AZ u slavného domu Taliesin West od Franka Lloyda Wrighta.

Naším cílem je sešít tyto tři snímky do jednoho panoramatického obrazu. Chcete-li provést sešití, otevřete terminál, přejděte na místo, kde jste stáhli kód + obrázky, a spusťte následující příkaz:

$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
Obrázek 4: Sešití obrázků provedené pomocí OpenCV. Tento obrázek prošel sešíváním, ale ještě musí být oříznut.

Všimněte si, jak jsme úspěšně provedli sešívání obrázků!“

A co ty černé oblasti kolem panoramatu? Co to je?“

Tyto oblasti vznikají při provádění perspektivních deformací potřebných ke konstrukci panoramatu.

Existuje způsob, jak se jich zbavit… ale v další části budeme muset implementovat další logiku.

Lepší sešívání obrázků pomocí OpenCV a Pythonu

Obrázek 5: V této části se naučíme, jak vylepšit sešívání obrázků pomocí OpenCV oříznutím oblasti panoramatu uvnitř hranice s červenou pomlčkou zobrazené na obrázku.

Náš první skript pro sešívání obrázků byl dobrým začátkem, ale tyto černé oblasti kolem samotného panoramatu nejsou něčím, co bychom nazvali „esteticky příjemným“.

A co víc, takový výstupní obrázek byste neviděli ani z populárních aplikací pro sešívání obrázků zabudovaných v systémech iOS, Android atd.

Proto náš skript trochu hackneme a zahrneme do něj další logiku, abychom vytvořili estetičtější panoramata.

Znovu zopakuji, že tato metoda je hack.

Pro získání našeho požadovaného výsledku si projdeme základní operace zpracování obrazu včetně prahování, extrakce obrysů, morfologických operací atd.

Pokud je mi známo, vazby OpenCV na Python nám neposkytují potřebné informace pro ruční extrakci maximální vnitřní obdélníkové oblasti panoramatu. Pokud to OpenCV umí, dejte mi prosím vědět v komentářích, protože bych to rád věděl.

Pokračujme a začněme – otevřeme skript image_stitching.py a vložíme následující kód:

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

Všechen tento kód je totožný s naším předchozím skriptem s jednou výjimkou.

Byl přidán argument příkazového řádku --crop. Když je v terminálu pro tento argument zadán příznak 1, budeme pokračovat a provedeme náš ořezávací zásah.

V dalším kroku začneme implementovat další funkce:

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

Všimněte si, jak jsem na řádku 40 vytvořil nový blok pro případ, že je nastaven příznak --crop. Začněme procházet tento blok:

  • Nejprve přidáme 10 pixelový rámeček na všechny strany našeho stitched obrázku (řádky 43 a 44), čímž zajistíme, že později v této části budeme moci najít obrysy kompletního obrysu panoramatu.
  • Poté vytvoříme gray verzi našeho stitched obrázku (řádek 49).
  • A odtud prahujeme gray obrázek (řádek 50).

Tady je výsledek (thresh ) těchto tří kroků:

Obrázek 6: Po prahování se nám zobrazí tato prahová maska zvýrazňující místo, kde se nachází sešitý + deformovaný obraz OpenCV.

Máme nyní binární obraz našeho panoramatu, kde bílé pixely (255) jsou popředí a černé pixely (0) jsou pozadí.

Díky našemu prahovanému obrazu můžeme použít extrakci obrysů, vypočítat ohraničující box největšího obrysu (tj, obrys samotného panoramatu) a nakreslit ohraničující rámeček:

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

Kontury jsou extrahovány a analyzovány na řádcích 55-57.

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

. Na řádku 58 se pak uchopí obrys s největší plochou (tj. obrys samotného sešitého obrazu).

Poznámka: Funkce imutils.grab_contours je nová v imutils==0.5.2, aby se přizpůsobila OpenCV 2.4, OpenCV 3 a OpenCV 4 a jejich různým návratovým signaturám pro cv2.findContours .

Řádek 62 alokuje paměť pro naši novou obdélníkovou masku. Řádek 63 pak vypočítá ohraničující box našeho největšího obrysu. Na základě informace o ohraničujícím obdélníku na řádku 64 nakreslíme na masku plný bílý obdélník.

Výstup výše uvedeného bloku kódu by vypadal takto:

Obrázek 7: Nejmenší obdélníková oblast, do které se vejde celé panorama OpenCV.

Tento ohraničující obdélník je nejmenší obdélníková oblast, do které se vejde celé panorama.

Nyní přichází jeden z největších hacků, které jsem kdy dal dohromady pro příspěvek na blogu:

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

Na řádcích 70 a 71 vytvoříme dvě kopie našeho obrázku mask:

  1. První maska, minMask , se bude pomalu zmenšovat, dokud se nevejde do vnitřní části panoramatu (viz obrázek 5 na začátku této části).
  2. Druhá maska, sub , bude použita k určení, zda musíme pokračovat ve zmenšování velikosti minMask .

Řádek 75 spustí smyčku while , která bude pokračovat ve smyčce, dokud v sub nebudou žádné další pixely popředí .

Řádek 79 provede morfologickou operaci eroze pro zmenšení velikosti minRect .

Řádek 80 pak od minRect odečte thresh – jakmile už v minRect nejsou žádné pixely popředí, můžeme smyčku přerušit.

Níže přikládám animaci tohoto hacku:

Obrázek 8: Animace hacku, který jsem vymyslel pro extrakci oblasti minRect z panoramatického obrázku OpenCV, čímž vznikne estetický sešitý obrázek

Nahoře máme náš obrázek sub a dole obrázek minRect.

Všimněte si, jak se velikost minRect postupně zmenšuje, dokud v sub nezůstanou žádné pixely popředí – v tomto okamžiku víme, že jsme našli nejmenší obdélníkovou masku, která se vejde do největší obdélníkové oblasti panoramatu.

Díky minimálnímu vnitřnímu obdélníku můžeme opět najít obrysy a vypočítat ohraničující box, ale tentokrát jednoduše extrahujeme ROI z obrázku 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

Tady máme:

  • Nalezené obrysy v minRect (řádky 84 a 85).
  • Zpracované parsování obrysů pro více verzí OpenCV (řádek 86). K použití této funkce budete potřebovat imutils>=0.5.2.
  • Vytvořil největší obrys (řádek 87).
  • Vypočítal ohraničující rámeček největšího obrysu (řádek 88).
  • Vytáhl ROI z našeho stitched pomocí informací o ohraničujícím rámečku (řádek 92).

Výsledný obrázek stitched můžeme zobrazit na obrazovce a poté uložit na 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))

Řádky 95-99 řeší uložení a zobrazení obrázku bez ohledu na to, zda byl proveden náš ořezávací zásah.

Stejně jako dříve, pokud se příznak status nevrátil jako úspěšný, vypíšeme chybové hlášení (řádky 103 a 104).

Pokračujme a podívejme se na výsledky naší vylepšené pipeline sešívání obrázků + OpenCV.

Výsledky vylepšeného sešívání obrázků

Znovu se ujistěte, že jste použili sekci „Ke stažení“ dnešního tutoriálu ke stažení zdrojového kódu a ukázkových obrázků.

Otevřete si terminál a spusťte následující příkaz:

$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
Obrázek 8: Výsledek našeho vícenásobného sešívání obrázků pomocí OpenCV a Pythonu.

Všimněte si, jak jsme tentokrát odstranili černé oblasti z výstupních sešitých obrázků (způsobené deformujícími transformacemi) použitím našeho hacku podrobně popsaného v části výše.

Omezení a nevýhody

V předchozím tutoriálu jsem ukázal, jak lze sestavit algoritmus pro sešívání panoramat a obrázků v reálném čase – tento tutoriál závisel na tom, že jsme ručně prováděli detekci klíčových bodů, extrakci prvků a párování klíčových bodů, což nám umožnilo přístup k homografické matici použité k deformaci našich dvou vstupních obrázků do panoramatu.

Ačkoli vestavěné funkce cv2.createStitcher a cv2.Stitcher_create v OpenCV jsou jistě schopny konstruovat přesná a esteticky příjemná panoramata, jednou z hlavních nevýhod této metody je, že abstrahuje od jakéhokoli přístupu k homografickým maticím.

Jedním z předpokladů konstrukce panoramat v reálném čase je, že samotná scéna se z hlediska obsahu příliš nemění.

Po výpočtu počátečního odhadu homografie bychom měli matici pouze občas přepočítat.

Nemusíme provádět plnohodnotné porovnávání klíčových bodů a odhad RANSAC, což nám dává obrovské zvýšení rychlosti při sestavování panoramatu, takže bez přístupu k surovým homografickým maticím by bylo náročné vzít vestavěný algoritmus OpenCV pro sešívání obrazu a převést jej na reálný čas.

Narazíte na chyby při provádění sešívání obrazu pomocí OpenCV?

Je možné, že narazíte na chyby při pokusu o použití funkce cv2.createStitcher nebo funkce cv2.Stitcher_create.

Dvě „snadno řešitelné“ chyby, se kterými se lidé setkávají, spočívají v tom, že zapomenou, jakou verzi OpenCV používají.

Příklad pokud používáte OpenCV 4, ale pokusíte se zavolat funkci cv2.createSticher, narazíte na následující chybové hlášení:

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

Měli byste místo toho použít funkci cv2.Stitcher_create.

Podobně pokud používáte OpenCV 3 a pokusíte se zavolat funkci cv2.Sticher_create, zobrazí se tato chyba:

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

Místo toho použijte funkci cv2.createSticher.

Pokud si nejste jisti, jakou verzi OpenCV používáte, můžete to zkontrolovat pomocí cv2.__version__ :

>>> cv2.__version__'4.0.0'

Tady vidíte, že používám OpenCV 4.0.0.

Stejnou kontrolu můžete provést i ve svém systému.

Poslední chyba, se kterou se můžete setkat a která je pravděpodobně nejčastější, souvisí s tím, že OpenCV (1) nemá podporu contrib a (2) je zkompilován bez zapnuté volby OPENCV_ENABLE_NONFREE=ON.

Pro vyřešení této chyby musíte mít nainstalované moduly opencv_contrib spolu s volbou OPENCV_ENABLE_NONFREE nastavenou na ON .

Pokud se setkáváte s chybou související s nesvobodnými moduly OpenCV a moduly contrib, ujistěte se, že máte nainstalovaný celý OpenCV.

Poznámka: Vezměte prosím na vědomí, že vám nemohu pomoci s laděním vaší vlastní instalace OpenCV, pokud jste nepostupovali podle některého z mých instalačních průvodců, takže se prosím ujistěte, že při konfiguraci systému používáte mé instalační průvodce OpenCV.

Shrnutí

V dnešním tutoriálu jste se naučili provádět vícenásobné sešívání obrázků pomocí OpenCV a Pythonu.

Pomocí OpenCV i Pythonu jsme dokázali sešít více obrázků dohromady a vytvořit panoramatické snímky.

Naše výstupní panoramatické snímky byly nejen přesné v umístění sešívání, ale také esteticky příjemné.

Jednou z největších nevýhod použití vestavěné třídy OpenCV pro sešívání obrázků je však to, že abstrahuje velkou část vnitřních výpočtů, včetně samotných výsledných homografických matic.

Pokoušíte-li se provádět sešívání obrázků v reálném čase, jako jsme to dělali v předchozím příspěvku, může být výhodné ukládat homografickou matici do mezipaměti a jen občas provádět detekci klíčových bodů, extrakci prvků a porovnávání prvků.

Vynechání těchto kroků a použití matice uložené v mezipaměti k provedení perspektivní deformace může snížit výpočetní zátěž vaší pipeline a v konečném důsledku urychlit algoritmus sešívání obrazu v reálném čase, ale bohužel vazby jazyka Python v OpenCV cv2.createStitcher nám neposkytují přístup k surovým maticím.

Pokud máte zájem dozvědět se více o konstrukci panoramat v reálném čase, přečtěte si můj předchozí příspěvek.

Doufám, že se vám dnešní návod na sešívání obrázků líbil!

Chcete-li si stáhnout zdrojový kód dnešního příspěvku a být informováni o zveřejňování návodů zde na PyImageSearch, stačí zadat svou e-mailovou adresu do formuláře níže!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.