Képfűzés OpenCV-vel és Pythonnal

Ezzel a bemutatóval megtanulhatja, hogyan végezhet képfűzést Python, OpenCV, valamint a cv2.createStitcher és cv2.Stitcher_create függvények segítségével. A mai kód segítségével képes leszel több képet összefűzni, így létrehozva egy összefűzött képekből álló panorámát.

Kicsivel kevesebb mint két évvel ezelőtt két útmutatót tettem közzé a képek összefűzéséről és a panorámakészítésről:

  1. A képösszeillesztés alapjai
  2. A valós idejű panoráma és képösszeillesztés

Mindkét útmutató a tipikus képösszeillesztési algoritmus alapjaival foglalkozott, amelyekhez minimálisan négy kulcsfontosságú lépés szükséges:

  1. A kulcspontok felismerése (DoG, Harris, stb.) és a helyi invariáns deszkriptorok kinyerése (SIFT, SURF stb.) két bemeneti képből
  2. A leírók illesztése a képek között
  3. A RANSAC algoritmus használata egy homográfiai mátrix becslésére az illesztett jellemzővektoraink felhasználásával
  4. Egy warping transzformáció alkalmazása a 3. lépésből kapott homográfiai mátrix felhasználásával

A legnagyobb probléma az eredeti implementációimmal azonban az, hogy nem voltak képesek kétnál több bemeneti kép kezelésére.

A mai bemutatóban újra áttekintjük a képek összeillesztését az OpenCV-vel, beleértve azt is, hogyan lehet kettőnél több képet egy panorámaképpé összeilleszteni.

Ha meg akarod tanulni, hogyan kell képeket összeilleszteni az OpenCV-vel és Pythonnal, csak olvass tovább!

Képfűzés OpenCV-vel és Pythonnal

A mai bemutató első részében röviden áttekintjük az OpenCV képfűzési algoritmusát, amely a cv2.createStitcher és cv2.Stitcher_create függvényeken keresztül magába az OpenCV könyvtárba van beépítve.

Ezután áttekintjük a projektünk felépítését, és implementálunk egy Python szkriptet, amelyet képfűzésre használhatunk.

Megnézzük ennek az első szkriptnek az eredményeit, megjegyezzük a korlátait, majd implementálunk egy második Python szkriptet, amelyet esztétikusabb képfűzési eredményekhez használhatunk.

Végül áttekintjük a második szkriptünk eredményeit, és ismét megjegyezzük a korlátokat vagy hátrányokat.

OpenCV képfűzési algoritmusa

1. ábra: A Stitcher osztályban implementált fűzési modul csővezetéke (forrás).

Az algoritmus, amelyet ma használni fogunk, hasonló a Brown és Lowe által a 2007-es Automatic Panoramic Image Stitching with Invariant Features című tanulmányukban javasolt módszerhez.

A korábbi képösszeillesztési algoritmusokkal ellentétben, amelyek érzékenyek a bemeneti képek sorrendjére, a Brown és Lowe-féle módszer robusztusabb, így érzéketlen a következőkre:

  • A képek sorrendje
  • A képek orientációja
  • Fényviszonyok változása
  • Zajos képek, amelyek valójában nem részei a panorámának

Ezeken túlmenően, képfűzési módszerük képes esztétikusabb kimeneti panorámaképek előállítására az erősítéskompenzáció és a képkeverés alkalmazásával.

Az algoritmus teljes, részletes áttekintése meghaladja ennek a bejegyzésnek a kereteit, ezért ha többet szeretne megtudni, olvassa el az eredeti publikációt.

Projekt felépítése

Lássuk, hogyan szerveződik ez a projekt a tree paranccsal:

$ 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

A bemeneti képek a images/ mappába kerülnek. Én úgy döntöttem, hogy készítek egy almappát a scottsdale/ képkészletemnek, arra az esetre, ha később további almappákat szeretnék itt elhelyezni.

Most két Python szkriptet fogunk áttekinteni:

  • image_stitching_simple.py : A képek összefűzésének egyszerű változatát kevesebb mint 50 sor Python kóddal el tudjuk végezni!
  • image_stitching.py : Ez a szkript tartalmazza az én hackemet az összeillesztett kép ROI-jának kivonására az esztétikus eredmény érdekében.

Az utolsó fájl, output.png , az eredményül kapott összeillesztett kép neve. A parancssori argumentumok segítségével könnyen megváltoztathatjuk a kimeneti kép fájlnevét + elérési útját.

A cv2.createStitcher és cv2.Stitcher_create függvények

2. ábra: A Stitcher osztály objektumának OpenCV-vel történő létrehozására szolgáló konstruktor aláírása.

Az OpenCV már implementált egy Brown és Lowe cikkéhez hasonló módszert a cv2.createStitcher (OpenCV 3.x) és cv2.Stitcher_create (OpenCV 4) függvények segítségével.

Feltételezve, hogy az OpenCV megfelelően van konfigurálva és telepítve, megvizsgálhatjuk a cv2.createStitcher függvény szignatúráját az OpenCV 3.x esetében:

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

Figyeljük meg, hogy ennek a függvénynek csak egyetlen paramétere van, a try_gpu, amelyet felhasználhatunk a képfűző csővezetékünk egészének javítására. Az OpenCV GPU támogatása korlátozott, és soha nem tudtam rávenni ezt a paramétert, hogy működjön, ezért azt javaslom, hogy mindig hagyja False .

Az OpenCV 4 cv2.Stitcher_create függvénye hasonló aláírással rendelkezik:

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.

A tényleges képfűzés elvégzéséhez meg kell hívnunk a .stitch módszert:

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.

Ez a módszer elfogad egy listát a bemeneti images , majd megpróbálja őket egy panorámává fűzni, visszaadva a kimeneti panorámaképet a hívó függvénynek.

A status változó jelzi, hogy a képösszeillesztés sikeres volt-e, és a négy változó egyike lehet:

  • OK = 0 : A képösszeillesztés sikeres volt.
  • ERR_NEED_MORE_IMGS = 1 : Abban az esetben, ha ezt az állapotkódot kapja, további bemeneti képekre lesz szüksége a panoráma összeállításához. Ez a hiba általában akkor fordul elő, ha a bemeneti képeken nem észlelt elég kulcspontot.
  • ERR_HOMOGRAPHY_EST_FAIL = 2 : Ez a hiba akkor jelentkezik, ha a RANSAC homográfia becslése sikertelen. Ismét előfordulhat, hogy több képre van szüksége, vagy a képein nincs elég megkülönböztető, egyedi textúra/tárgy ahhoz, hogy a kulcspontok pontosan illeszkedjenek.
  • ERR_CAMERA_PARAMS_ADJUST_FAIL = 3 : Ezzel a hibával még soha nem találkoztam, így nincs sok tudásom róla, de a lényege az, hogy azzal függ össze, hogy nem sikerült megfelelően becsülni a kamera intrinsic/extrinsic értékeit a bemeneti képekből. Ha ezzel a hibával találkozol, akkor lehet, hogy az OpenCV dokumentációhoz kell fordulnod, vagy akár az OpenCV C++ kódjába is bele kell merülnöd.

Most, hogy áttekintettük a cv2.createStitcher , cv2.Stitcher_create és .stitch módszereket, térjünk rá a képfűzés tényleges megvalósítására OpenCV-vel és Pythonnal.

Képfűzés megvalósítása Pythonnal

Lássunk hozzá a képfűzési algoritmusunk megvalósításához!

Nyissuk meg a image_stitching_simple.py fájlt, és illesszük be a következő kódot:

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

A szükséges csomagjainkat a 2-6. sorban importáljuk. Nevezetesen az OpenCV-t és az imutils-t fogjuk használni. Ha még nem tetted meg, menj előre és telepítsd őket:

  • Az OpenCV telepítéséhez kövesd az OpenCV telepítési útmutatóim egyikét.
  • Az imutils csomagot a pip segítségével telepítheted/frissítheted: pip install --upgrade imutils . Győződjön meg róla, hogy frissíti, mivel gyakran új funkciókkal bővül.

A 9-14. sorokban két parancssori argumentumot elemezünk:

  • --images : Az összefűzendő bemeneti képek könyvtárának elérési útja.
  • --output : A kimeneti kép elérési útvonala, ahová az eredményt elmentjük.

Ha nem ismeri a argparse és a parancssori argumentumok fogalmát, akkor olvassa el ezt a blogbejegyzést.

Töltsük be a bemeneti képeinket:

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

Itt megragadjuk a imagePaths képünket (18. sor).

Majd minden egyes imagePath , betöltjük a image és hozzáadjuk a images listához (19-25. sor).

Most, hogy a images a memóriában vannak, menjünk tovább, és illesszük össze őket egy panorámává az OpenCV beépített képességének segítségével:

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

A stitcher objektumot a 30. sorban hozzuk létre. Vegyük észre, hogy attól függően, hogy OpenCV 3-at vagy 4-et használunk, más konstruktort hívunk meg.

Ezután átadhatjuk a images objektumunkat a .stitch metódusnak (31. sor). A .stitch hívása egy status és a mi stitched képünket is visszaadja (feltéve, hogy az összefűzés sikeres volt).

Végül (1) kiírjuk az összeillesztett képet a lemezre, és (2) megjelenítjük a képernyőn:

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

Amennyiben a status jelzőnk sikert jelez (35. sor), kiírjuk a stitched képet a lemezre (37. sor), és megjelenítjük, amíg egy billentyűt meg nem nyomunk (40. és 41. sor).

Máskülönben egyszerűen kiírunk egy hibaüzenetet (45. és 46. sor).

Egyszerű képfűzési eredmények

Hogy kipróbálhassuk a képfűzési szkriptünket, mindenképpen használjuk a bemutató “Letöltések” részét a forráskód és a példaképek letöltéséhez.

A images/scottsdale/ könyvtárban találsz három fényképet, amelyeket Frank Lloyd Wright híres Taliesin West házának meglátogatásakor készítettem a Scottsdale-ben, AZ-ban:

3. ábra: Három fénykép az OpenCV képfűzés teszteléséhez. Ezeket a képeket én készítettem az AZ-beli Scottsdale-ben, Frank Lloyd Wright híres Taliesin West házában.

A célunk az, hogy ezt a három képet egyetlen panorámaképpé illesszük össze. Az összeillesztés elvégzéséhez nyissunk meg egy terminált, navigáljunk oda, ahonnan letöltöttük a kódot + a képeket, és hajtsuk végre a következő parancsot:

$ python image_stitching_simple.py --images images/scottsdale --output output.png loading images... stitching images...
4. ábra: Az OpenCV-vel végzett képösszeillesztés. Ez a kép már átesett az összefűzésen, de még nem lett levágva.

Lássuk, hogy sikeresen elvégeztük a képösszefűzést!

De mi van azokkal a fekete régiókkal, amelyek a panorámát körülveszik? Mik azok?

Ezek a régiók a panoráma elkészítéséhez szükséges perspektivikus torzítások elvégzéséből származnak.

Meg lehet szabadulni tőlük… de a következő részben további logikát kell implementálnunk.

Egy jobb képösszeillesztés OpenCV-vel és Pythonnal

5. ábra: Ebben a szakaszban megtanuljuk, hogyan javíthatjuk a képösszeillesztést OpenCV-vel azáltal, hogy kivágjuk a panorámából az ábrán látható piros-vonalkázott határon belüli területet.

Az első képösszeillesztési szkriptünk jó kezdet volt, de azok a fekete régiók, amelyek magát a panorámát veszik körül, nem valami “esztétikusnak” nevezhetőek.

És ami még fontosabb, ilyen kimeneti képet nem látnánk az iOS-be, Androidba stb. épített népszerű képfűző alkalmazásoktól.

Ezért egy kicsit meghekkeljük a szkriptünket, és beépítünk néhány további logikát, hogy esztétikusabb panorámákat hozzunk létre.

Még egyszer megismétlem, hogy ez a módszer egy hack.

Áttekintjük az alapvető képfeldolgozási műveleteket, beleértve a küszöbértéket, a kontúrkinyerést, a morfológiai műveleteket stb. annak érdekében, hogy elérjük a kívánt eredményt.

Tudomásom szerint az OpenCV Python kötései nem adják meg nekünk a szükséges információkat ahhoz, hogy manuálisan kivonjuk a panoráma maximális belső téglalap alakú régióját. Ha az OpenCV rendelkezik ilyennel, kérem, ossza meg velem a hozzászólásokban, mert nagyon szeretném tudni.

Lássunk hozzá – nyissuk meg a image_stitching.py szkriptet, és illesszük be a következő kódot:

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

Ez a kód egy kivétellel megegyezik az előző szkriptünkkel.

A --crop parancssori argumentumot hozzáadtuk. Ha a terminálban egy 1-t adunk meg ehhez az argumentumhoz, akkor folytatjuk és végrehajtjuk a vágási hackünket.

A következő lépésben elkezdjük a további funkciók megvalósítását:

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

Észrevehetjük, hogy a 40. sorban egy új blokkot készítettem arra az esetre, ha a --crop jelző be van állítva. Kezdjük el végigjárni ezt a blokkot:

  • Először egy 10 pixeles keretet adunk a stitched képünk minden oldalához (43. és 44. sor), biztosítva, hogy később ebben a részben megtaláljuk a teljes panoráma körvonalának kontúrjait.
  • Ezután létrehozzuk a stitched képünk gray változatát (49. sor).
  • Az gray képet pedig ebből a gray képből küszöböljük ki (50. sor).

Itt van ennek a három lépésnek az eredménye (thresh ):

6. ábra: A küszöbölés után ezt a küszöbmaszkot kapjuk, amely kiemeli, hogy hol található az OpenCV által összeillesztett + eltorzított kép.

Most már van egy bináris képünk a panorámánkról, ahol a fehér pixelek (255) jelentik az előteret, a fekete pixelek (0) pedig a hátteret.

A küszöbértékkel ellátott képünk alapján alkalmazhatjuk a kontúrkinyerést, kiszámíthatjuk a legnagyobb kontúr határoló dobozát (ill, magának a panorámának a körvonalát), és megrajzoljuk a határoló dobozt:

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

A kontúrok kivonása és elemzése az 55-57. sorban történik. Az 58. sor ezután megragadja a legnagyobb területű kontúrt (azaz magának az összeillesztett képnek a körvonalát).

Megjegyzés: A imutils.grab_contours függvény új a imutils==0.5.2-ban, hogy alkalmazkodjon az OpenCV 2.4, OpenCV 3 és OpenCV 4 és azok különböző visszatérési aláírásaihoz a cv2.findContours .

A 62. sor memóriát rendel az új négyszögletes maszkunkhoz. A 63. sor ezután kiszámítja a legnagyobb kontúrunk határoló dobozát. A határoló téglalap információt felhasználva a 64. sorban egy tömör fehér téglalapot rajzolunk a maszkra.

A fenti kódblokk kimenete a következőképpen nézne ki:

7. ábra: A legkisebb téglalap alakú régió, amelybe a teljes OpenCV panoráma befér.

Ez a határoló doboz a legkisebb téglalap alakú régió, amelybe a teljes panoráma befér.

Most következik az egyik legnagyobb hack, amit valaha is összeállítottam egy blogbejegyzéshez:

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

A 70. és 71. sorban létrehozzuk a mask képünk két másolatát:

  1. Az első maszkot, minMask , lassan kicsinyítjük, amíg el nem fér a panoráma belső részén (lásd az 5. ábrát a fejezet tetején).
  2. A második maszk, sub alapján fogjuk meghatározni, hogy tovább kell-e csökkenteni a minMask méretét .

A 75. sor elindít egy while hurkot, amely addig folytatja a hurkot, amíg nincs több előtér pixel a sub-ben .

A 79. sor eróziós morfológiai műveletet hajt végre a minRect méretének csökkentésére.

A 80. sor ezután kivonja thresh-et a minRect-ből – ha már nincs több előtér pixel a minRect-ben, akkor megszakíthatjuk a hurkot.

Az alábbiakban csatoltam egy animációt a hackről:

8. ábra: Animáció a hackről, amit az OpenCV panorámakép minRect régiójának kivonására találtam ki, így egy esztétikusan tetszetős összefűzött képet kapunk

Fent a sub képünk, lent pedig a minRect kép.

Figyeljük meg, hogy a minRect mérete fokozatosan csökken, amíg a sub-ben már nem marad előtér képpont – ezen a ponton tudjuk, hogy megtaláltuk a legkisebb téglalap alakú maszkot, amely elfér a panoráma legnagyobb téglalap alakú régiójában.

A minimális belső téglalapot megadva ismét megtalálhatjuk a kontúrokat és kiszámíthatjuk a határoló dobozt, de ezúttal egyszerűen kivonjuk a ROI-t a stitched képből:

# 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

Ezek után:

  • Kontúrokat találtunk a minRect-ben (84. és 85. sor).
  • Kontúrok elemzése több OpenCV verzióhoz (86. sor). Szükséged lesz a imutils>=0.5.2-re a funkció használatához.
  • Grabbed the largest contour (87. sor).
  • Computed the bounding box of the largest contour (88. sor).
  • Extracted the ROI from our stitched using the bounding box information (92. sor).

A végleges stitched képet megjeleníthetjük a képernyőnkön, majd elmenthetjük a lemezre:

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

A 95-99. sorok kezelik a kép mentését és megjelenítését, függetlenül attól, hogy elvégeztük-e a vágási hackünket vagy sem.

Az előzőekhez hasonlóan, ha a status flag nem jött vissza sikerként, kiírunk egy hibaüzenetet (103. és 104. sor).

Menjünk tovább, és nézzük meg a továbbfejlesztett képfűzés + OpenCV csővezetékünk eredményeit.

A továbbfejlesztett képfűzés eredményei

Még egyszer győződjünk meg róla, hogy a mai bemutató “Letöltések” részében letöltöttük a forráskódot és a példaképeket.

Nyissunk meg onnan egy terminált, és hajtsuk végre a következő parancsot:

$ python image_stitching.py --images images/scottsdale --output output.png \--crop 1 loading images... stitching images... cropping...
8. ábra: Az OpenCV és Python segítségével végzett többszörös képfűzésünk eredménye.

Figyeljük meg, hogy ezúttal eltávolítottuk a fekete tartományokat a kimeneti összefűzött képekből (amelyeket a warping transzformációk okoztak) a fenti részben részletezett hackünk alkalmazásával.

Korlátozások és hátrányok

Egy korábbi bemutatóban bemutattam, hogyan készíthetünk valós idejű panoráma- és képösszeillesztési algoritmust – ez a bemutató azon múlott, hogy manuálisan végeztük el a kulcspontok felismerését, a jellemzők kinyerését és a kulcspontok illesztését, ami hozzáférést biztosított számunkra a homográfiai mátrixhoz, amelyet a két bemeneti képünk panorámává warpolásához használtunk.

És bár az OpenCV beépített cv2.createStitcher és cv2.Stitcher_create függvényei kétségtelenül képesek pontos, esztétikus panorámák készítésére, a módszer egyik fő hátránya, hogy absztrahál minden hozzáférést a homográfiamátrixokhoz.

A valós idejű panorámakészítés egyik feltételezése, hogy maga a jelenet tartalmilag nem sokat változik.

Mihelyt kiszámítottuk a kezdeti homográfia becslést, csak időnként kell újra kiszámítanunk a mátrixot.

Az, hogy nem kell teljes körű kulcspontillesztést és RANSAC becslést végeznünk, óriási sebességnövekedést ad a panorámaépítés során, így a nyers homográfia mátrixokhoz való hozzáférés nélkül kihívást jelentene az OpenCV beépített képfűzési algoritmusának valós idejűvé alakítása.

Hibákba ütközik, amikor képfűzést végez az OpenCV segítségével?

Elképzelhető, hogy hibákba ütközik, amikor megpróbálja használni akár a cv2.createStitcher függvényt, akár a cv2.Stitcher_create függvényt.

A két “könnyen megoldható” hiba, amivel az emberek találkoznak, az, hogy elfelejtik, hogy az OpenCV melyik verzióját használják.

Ha például OpenCV 4-et használsz, de megpróbálod meghívni a cv2.createSticher függvényt, a következő hibaüzenettel találkozol:

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

Ehelyett a cv2.Stitcher_create függvényt kellene használnod.

Hasonlóképpen, ha OpenCV 3-at használsz, és megpróbálod meghívni a cv2.Sticher_create függvényt, ezt a hibát fogod kapni:

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

Ehelyett használd a cv2.createSticher függvényt.

Ha nem vagy biztos benne, hogy melyik OpenCV verziót használod, akkor a cv2.__version__ segítségével ellenőrizheted :

>>> cv2.__version__'4.0.0'

Itt láthatod, hogy OpenCV 4.0.0-t használok.

Ezzel az ellenőrzéssel te is elvégezheted a rendszereden.

Az utolsó hiba, amivel találkozhatsz, és vitathatatlanul a leggyakoribb, azzal kapcsolatos, hogy az OpenCV (1) nem rendelkezik contrib támogatással és (2) a OPENCV_ENABLE_NONFREE=ON opció engedélyezése nélkül lett lefordítva.

Ez a hiba elhárításához a opencv_contrib modulokat kell telepíteni, valamint a OPENCV_ENABLE_NONFREE opciót ON-re kell állítani .

Ha az OpenCV non-free és contrib moduljaival kapcsolatos hibával találkozik, mindenképpen olvassa el az OpenCV telepítési útmutatóimat, hogy biztosítsa az OpenCV teljes telepítését.

Figyelem: Kérjük, vegye figyelembe, hogy nem tudok segíteni a saját OpenCV telepítésének hibakeresésében, ha nem az én telepítési útmutatóim egyikét követte, ezért kérjük, győződjön meg róla, hogy az én OpenCV telepítési útmutatóimat használja a rendszer konfigurálásakor.

Összefoglaló

A mai bemutatóban megtanulta, hogyan végezhet több kép összefűzését az OpenCV és a Python segítségével.

Az OpenCV és a Python segítségével képesek voltunk több képet összefűzni és panorámaképeket létrehozni.

A kimeneti panorámaképeink nemcsak pontosak voltak az összefűzési elhelyezésükben, hanem esztétikailag is tetszettek.

Az OpenCV beépített képfűzési osztályának használatának egyik legnagyobb hátránya azonban az, hogy a belső számítások nagy részét absztrahálja, beleértve magukat az eredményül kapott homográfiai mátrixokat is.

Ha valós idejű képfűzést szeretnénk végezni, ahogy azt egy korábbi bejegyzésünkben tettük, akkor hasznosnak találhatjuk a homográfiai mátrix gyorsítótárazását és csak alkalmanként a kulcspontok felismerését, a jellemzők kinyerését és a jellemzők egyeztetését.

Ezek a lépések kihagyása és a gyorsítótárazott mátrix használata a perspektivikus warping elvégzéséhez csökkentheti a pipeline számítási terhét, és végső soron felgyorsíthatja a valós idejű képfűzési algoritmust, de sajnos az OpenCV cv2.createStitcher Python kötései nem biztosítanak számunkra hozzáférést a nyers mátrixokhoz.

Ha többet szeretne megtudni a valós idejű panorámakészítésről, kérjük, olvassa el az előző bejegyzésemet.

Remélem, tetszett a mai bemutató a képfűzésről!

Hogy letöltse a mai bejegyzés forráskódját, és értesítést kapjon a bemutatók közzétételéről itt a PyImageSearch-en, csak adja meg az e-mail címét az alábbi űrlapon!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.