Hogyan tervezzünk Nyelvi-agnosztikus platformokon átívelő számítógépes látás SDK: gyakorlati útmutató

(Cyrus Behroozi) (2020. október 21.)

Nemrég volt alkalmam bemutatkozni a Venice Computer Vision találkozón. Ha még nem ismeri, ez egy olyan esemény, amelyet a Trueface támogat, ahol a számítógépes látás fejlesztői és rajongói egyaránt bemutathatják az élvonalbeli számítógépes látáskutatást, az alkalmazásokat és a gyakorlati megoldásokat. oktatóanyagok.

Ebben a cikkben áttekintem a bemutató előadásomat arról, hogyan tervezzek nyelvi-agnosztikus számítógépes látásszoftver-fejlesztőkészletet (SDK) a platformok közötti telepítéshez és a maximális bővíthetőséghez. Ha meg szeretné tekinteni a prezentáció élő felvételét , megteheti itt . A teljes projektet nyílt forráskódúvá készítettem is, ezért nyugodtan használja sablonként a következő számítógépes látásprojektjéhez.

cyrusbehr / sdk_design

Nyelv-agnosztikus SDK tervezése a platformok közötti telepítéshez és a maximális kiterjesztéshez. A velencei számítógépes látomás …

github.com

Miért fontos ez az oktatóanyag

Tapasztalataim szerint soha nem találtam mindent átfogó útmutatót, amely összefoglalja a nyelv-agnosztikus, platformokon átívelő SDK létrehozásához szükséges összes releváns lépést. Át kellett fésülnöm az eltérő dokumentációt a megfelelő információrészletekért, külön-külön meg kellett tanulnom az egyes összetevőket, majd magam is darabokra kellett osztanom. Frusztráló volt. Sok időbe telt. És most Ön, kedves olvasó, részesülhet minden munkámból. Előtte megtanulja, hogyan készítsen nyelvi agnosztikus, platformokon átívelő SDK-t. Minden lényeges megvan. Egyik szösz sem, mentsen el néhány mémet. Élvezze.

Ebben az oktatóanyagban számíthat arra, hogy megtanulja:

  • építeni egy alapvető számítógépes látáskönyvtárat a C ++ nyelven
  • fordítani és keresztbe tenni fordítsa le az AMD64, ARM64 és ARM32 könyvtárakat
  • Csomagolja a könyvtárat és az összes függőséget egyetlen statikus könyvtárba
  • Az egység tesztelésének automatizálása
  • Folyamatos beállítás integrációs (CI) csővezeték
  • python-összerendelések írása a könyvtárunkhoz
  • Dokumentumok generálása közvetlenül az API-junkból

A bemutató érdekében MTCNN nevű nyílt forráskódú arcérzékelővel arc- és tereptárgy-észlelő SDK-t épít.

Példa arckorlátozó dobozok és arcleírások

API-függvényünk egy képutat választ, majd visszaadja az arckorlátozó doboz és az arcpontok koordinátáit. Az arcok észlelésének képessége nagyon hasznos a számítógépes látásmódban, mivel ez az első lépés számos csővezetékben, beleértve az arcfelismerést, az életkor előrejelzését és az automatikus arcelmosódást.

Megjegyzés: Ehhez oktatóanyag, az Ubuntu 18.04-en fogok dolgozni.

Miért érdemes a C ++ -t használni a könyvtárunkhoz?

A hatékony C ++ kód futtatása ezt így érezheti

Könyvtárunk nagy része C ++ nyelven íródik, egy fordított és statikusan beírt nyelvre. Nem titok, hogy a C ++ nagyon gyors programozási nyelv; elég alacsony ahhoz, hogy megkapja a kívánt sebességet, és minimális a hozzáadott futásidejű rezsi.

A számítógépes vizuális alkalmazásokban általában sok képet manipulálunk, mátrix műveleteket hajtunk végre, gépi tanulási következtetéseket futtatunk. hatalmas mennyiségű számítástechnika. A végrehajtás sebessége ezért kritikus. Ez különösen fontos a valós idejű alkalmazásokban, ahol csökkenteni kell a késleltetést a kívánt képkockasebesség elérése érdekében – gyakran csak milliszekundumokkal rendelkezünk az összes kódunk futtatásához.

A C ++ másik előnye, hogy ha fordítson le egy bizonyos architektúrára, és az összes függőséget statikusan kapcsolja össze, akkor futtathatjuk azt az adott hardveren anélkül, hogy további értelmezőkre vagy könyvtárakra lenne szükség. Ha hiszed, ha nem, akár egy csupasz fémbe ágyazott eszközön is futtathatunk operációs rendszer nélkül!

Könyvtárstruktúra

A következő könyvtárstruktúrát fogjuk használni a projektünkhöz.

3rdparty tartalmazza a projektünkben megkövetelt harmadik fél függőségi könyvtárakat.

dist azokat a fájlokat tartalmazza, amelyeket az SDK végfelhasználói számára terjesztenek. Esetünkben ez maga a könyvtár és a hozzá tartozó fejlécfájl lesz.

docker tartalmazza a dokkoló fájlt, amelyet a dokkoló kép előállításához fognak használni. mert a CI épít.

docs tartalmazza a build szkripteket, amelyek szükségesek a dokumentáció generálásához közvetlenül a fejlécfájlunkból.

include tartalmazni fog bármilyen nyilvános API-hoz tartozó fájlot.

models az arcfelismerés mély tanulási modell fájljait tartalmazza.

python tartalmazza a python-összerendelések létrehozásához szükséges kódot.

src tartalmazza az összes lefordított cpp fájlt, és minden olyan fejlécfájl is, amelyet nem terjesztenek az SDK-val (belső fejlécfájlok).

test tartalmazni fogják az egység tesztjeinket.

tools tartalmazza a keresztfordításhoz szükséges CMake eszközláncfájljainkat.

A függőségi könyvtárak telepítése

Ennél a projektnél a harmadik fél szükséges függőségi könyvtárak: ncnn , egy könnyű gépi tanulási következtetés könyvtár, OpenCV , egy képbővítő könyvtár, Catch2 , az egységet tesztelő könyvtár, végül pybind11 , egy könyvtár python-összerendelések előállítására használják. Az első két könyvtárat önálló könyvtárként kell összeállítani, míg az utóbbi kettő csak fejléc, ezért csak a forrásra van szükségünk.

Ezeknek a könyvtáraknak a projektjeinkhez való hozzáadásának egyik módja a git almodulok . Bár ez a megközelítés működik, én személy szerint rajongok a shell szkriptek használatáért, amelyek megkapják a forráskódot, majd felépítik a kívánt platformokra: esetünkben AMD64, ARM32 és ARM64.

Íme egy példa, hogy melyik ezeknek a build szkripteknek a következőképpen néz ki:

A szkript meglehetősen egyszerű. Úgy kezdődik, hogy előhúzza a kívánt kiadási forráskódot a git-tárból. Ezután a CMake-t használják az összeállítás előkészítésére, majd a make parancs meghívásra kerül a fordító meghajtására a forráskód összeállításához.

Amit észre fog venni, az a fő különbség az AMD64 és az ARM buildek között, hogy az ARM épít egy további CMake paramétert, amely CMAKE_TOOLCHAIN_FILE nevet viseli. Ez az argumentum arra szolgál, hogy a CMake megadja, hogy a build célarchitektúra (ARM32 vagyARM64) eltér a gazdagép architektúrájától (AMD64 / x86_64). A CMake ezért arra utasítást kap, hogy használja a kiválasztott eszközláncfájlban megadott keresztfordítót a könyvtár felépítéséhez (erről az oktatóanyagról később bővebben az eszközlánc-fájlokon olvashat). Ahhoz, hogy ez a shell parancsfájl működjön, telepítenie kell a megfelelő keresztfordítókat az Ubuntu gépre. Ezeket egyszerűen telepíteni lehet a apt-get használatával, és ennek módjára vonatkozó utasításokat itt mutatjuk be.

Könyvtári API-nk

Könyvtári API-nk így néz ki:

Mivel szuper kreatív vagyok, úgy döntöttem, hogy megnevezem az SDK-t MySDK. Az API-nkban van egy ErrorCode nevű enum, van egy Point nevű struktúránk, és végül van egy nyilvános tagfüggvényünk, az úgynevezett getFaceBoxAndLandmarks. Ennek az oktatóanyagnak a vonatkozásában nem foglalkozom az SDK megvalósításának részleteivel. A lényeg az, hogy az OpenCV használatával beolvassuk a képet a memóriába, majd az ncnn és a nyílt forráskódú modellek segítségével gépi tanulási következtetéseket hajtunk végre az arckorlátozó mező és a tereptárgyak felderítésére. Ha bele akarna merülni a megvalósításba, megteheti itt .

Amire szeretném, ha mégis figyelne, az a tervezési mintát használunk. A Pointer to implement, vagy röviden pImpl nevű technikát használjuk, amely alapvetően eltávolítja az osztály megvalósítási részleteit azáltal, hogy külön osztályba helyezi őket. A fenti kódban ezt úgy érhetjük el, hogy előre deklaráljuk a Impl osztályt, majd unique_ptr -et adunk ennek az osztálynak, mint privát tag változót. Ennek során nemcsak elrejtjük a megvalósítást a végfelhasználó kíváncsi szemei ​​elől (ami egy kereskedelmi SDK-ban meglehetősen fontos lehet), hanem csökkentjük az API-fejlécektől függő fejlécek számát is (és ezáltal megakadályozzuk API fejléc #include függőségi könyvtár fejléceiből).

Megjegyzés a modellfájlokról

Azt mondtam, hogy nem megyünk át a megvalósítás részleteit, de van valami, amit szerintem érdemes megemlíteni. Alapértelmezés szerint az általunk használt MTCNN nevű nyílt forráskódú arcérzékelő futás közben tölti be a gépi tanulási modell fájlokat. Ez nem ideális, mert azt jelenti, hogy a modelleket el kell terjesztenünk a végfelhasználónak. Ez a kérdés még jelentősebb a kereskedelmi modellek esetében, ahol nem akarja, hogy a felhasználók szabadon hozzáférjenek ezekhez a modellfájlokhoz (gondoljunk csak arra a számtalan órára, amelybe e modelleket oktatták). Az egyik megoldás e modellek fájljainak titkosítása, amit feltétlenül ajánlok.Ez azonban még mindig azt jelenti, hogy a modellfájlokat az SDK-val együtt kell szállítanunk. Végül szeretnénk csökkenteni a felhasználónak küldött fájlok számát, hogy megkönnyítsék számukra a szoftverünk használatát (kevesebb fájl egyenlő azzal, hogy kevesebb hely téved). Ezért az alábbiakban bemutatott módszerrel átalakíthatjuk a modellfájlokat fejlécfájlokká, és beágyazhatjuk magába az SDK-ba.

A xdd bash paranccsal hexadombok generálhatók, és bináris fájlból fejlécfájlok készíthetők vele. Ezért a modellfájlokat a normál fejlécfájlokhoz hasonlóan belefoglalhatjuk kódunkba, és közvetlenül a memóriából tölthetjük be őket. Ennek a megközelítésnek az a korlátja, hogy nagyon nagy modellfájlok esetén nem praktikus, mivel a fordítás idején túl sok memóriát emészt fel. Ehelyett használhat egy olyan eszközt, mint például a ld, hogy ezeket a nagy modellfájlokat közvetlenül objektumfájlokká alakítsa át.

CM Készítse el és állítsa össze a könyvtárunkat

Most már a CMake segítségével generálhatjuk a projektünk build fájljait. Abban az esetben, ha nem ismeri, a CMake egy build rendszer generátor, amelyet a build folyamat kezelésére használnak. Az alábbiakban láthatja, hogy néz ki a gyökér CMakeLists.txt (CMake fájl) része.

Alapvetően egy my_sdk_static nevű statikus könyvtárat hozunk létre a megvalósításunkat tartalmazó két forrásfájllal, my_sdk.cpp és mtcnn.cpp. Statikus könyvtár létrehozásának oka az, hogy tapasztalataim szerint könnyebb terjeszteni a statikus könyvtárat a felhasználók számára, és barátságosabb a beágyazott eszközökkel szemben. Mint fentebb említettem, ha egy futtatható fájl egy statikus könyvtárhoz kapcsolódik, akkor futtatható olyan beágyazott eszközön, amely még operációs rendszerrel sem rendelkezik. Ez egyszerűen nem lehetséges egy dinamikus könyvtár használatával. Ezenkívül a dinamikus könyvtárakkal aggódnunk kell a függőségi verziók miatt. Szükségünk lehet még a könyvtárunkhoz társított jegyzékfájlra. A statikusan összekapcsolt könyvtárak teljesítményprofilja is valamivel jobb, mint dinamikus társaiké.

A következő dolog, amit a CMake szkriptünkben teszünk, megmondja a CMake-nek, hogy hol találja meg a forrásfájljainkhoz szükséges szükséges fejlécfájlokat. Valami megjegyzendő: bár könyvtárunk ezen a ponton összeáll, amikor megpróbálunk összekapcsolódni könyvtárunkkal (például egy futtatható fájlral), abszolút tonna meghatározatlan hivatkozást kapunk a szimbólumhibákra. Ennek oka, hogy egyetlen függőségi könyvtárunkat sem kapcsoltuk össze. Tehát, ha egy futtatható fájlt sikeresen össze akarunk kapcsolni az libmy_sdk_static.a fájlhoz, akkor az összes függőségi könyvtárat (OpenCV modulok, ncnn stb.) Is fel kell találnunk és összekapcsolnunk. A dinamikus könyvtárakkal ellentétben a statikus könyvtárak nem tudják megoldani saját függőségüket. Alapvetően csak egy archívumba csomagolt objektumfájlok gyűjteménye.

A bemutató későbbiben bemutatom, hogyan tudjuk az összes függőségi könyvtárat bekötni statikus könyvtárunkba, hogy a felhasználónak ne kelljen aggódj a függőségi könyvtárak bármelyikével való összekapcsolás miatt.

Könyvtár- és Eszköztár-fájljaink keresztfordítása

Az élszámítás olyan… Edgy

Sok számítógépes látásalkalmazást telepítenek a szélén. Ez általában magában foglalja a kód futtatását alacsony fogyasztású, beágyazott eszközökön, amelyek általában ARM CPU-val rendelkeznek. Mivel a C ++ egy lefordított nyelv, össze kell állítanunk a kódunkat ahhoz a CPU architektúrához, amelyen az alkalmazást futtatni fogják (mindegyik architektúra más-más szerelési utasításokat használ).

Mielőtt belemerülnénk, érintsük meg a különbség az ARM32 és az ARM64 között, más néven AArch32 és AArch64. Az AArch64 az ARM architektúra 64 bites kiterjesztésére utal, és mind a CPU, mind az operációs rendszer függő. Így például annak ellenére, hogy a Raspberry Pi 4 64 bites ARM CPU-val rendelkezik, az alapértelmezett Raspbian operációs rendszer 32 bites. Ezért egy ilyen eszközhöz AArch32 fordított bináris fájl szükséges. Ha 64 bites operációs rendszert futtatnánk, mint például a Gentoo ezen a Pi eszközön, akkor egy AArch64 fordított bináris fájlra lenne szükségünk. A népszerű beágyazott eszközök másik példája az NVIDIA Jetson, amelynek beépített GPU-ja van, és futtatja az AArch64-et.

A keresztfordításhoz meg kell adnunk a CMake-nek, hogy nem a gép, amelyre jelenleg építünk. Ezért meg kell adnunk azt a keresztfordítót, amelyet a CMake használ. AArch64 esetén a aarch64-linux-gnu-g++ fordítót, az AArch32 esetében pedig az arm-linux-gnuebhif-g++ fordítót használjuk (a hf jelentése hard float ).

Az alábbiakban bemutatunk egy példát egy eszközlánc fájlra. Amint láthatja, meghatározzuk az AArch64 keresztfordító használatát.

Vissza a gyökérhez CMakeLists.txt adja hozzá a következő kódot a fájl tetejéhez.

Alapvetően CMake opciókat adunk hozzá, amelyek engedélyezhető a parancssorból a keresztfordítás érdekében. A BUILD_ARM32 vagy a BUILD_ARM64 opciók engedélyezése kiválasztja a megfelelő eszközláncfájlt és konfigurálja a felépítést egy keresztkompilációhoz.

Az SDK csomagolása függőségi könyvtárakba

Amint azt korábban említettük, ha egy fejlesztő ezen a ponton szeretne kapcsolatba lépni a könyvtárunkkal, akkor az összes függőségi könyvtárral is össze kell kapcsolniuk annak érdekében, hogy feloldhassák az összes szimbólumot a függőségi könyvtárak. Annak ellenére, hogy az alkalmazásunk nagyon egyszerű, már van nyolc függőségi könyvtárunk! Az első az ncnn, majd három OpenCV modul-könyvtárunk van, majd négy segédkönyvtárunk van, amelyeket OpenCV-vel építettünk (libjpeg, libpng, zlib, libtiff). Megkövetelhetjük a felhasználótól, hogy maga készítse el a függőségi könyvtárakat, vagy akár a könyvtárunk mellé szállítsa őket, de ez végül is több munkát igényel a felhasználó számára, és mindannyian a használat akadályainak csökkentésén vagyunk. Az ideális helyzet az, ha egyetlen olyan könyvtárat küldhetünk a felhasználónak, amely tartalmazza a könyvtárunkat, valamint a szabványos rendszerkönyvtárakon kívüli összes harmadik féltől származó függőségi könyvtárat. Kiderült, hogy ezt némi CMake varázslat segítségével elérhetjük.

Először hozzáadunk egy egyéni célpontot a CMakeLists.txt, majd hajtsa végre az úgynevezett MRI szkriptet. Ez az MRI szkript átkerül a ar -M bash parancshoz, amely alapvetően az összes statikus könyvtárat egyetlen archívumba egyesíti. Ami nagyon jó ebben a módszerben, az az, hogy kecsesen kezeli az eredeti archívumok egymást átfedő tagneveit, így nem kell aggódnunk az ottani konfliktusok miatt. Ennek az egyéni célnak a felépítésével libmy_sdk.a jön létre, amely tartalmazza az SDK-t és az összes függőségi archívumot.

Tartsa meg egy pillanatig: Vegyük számba, amit mi eddig megtettem.

Vegyél egy levegőt. Fogj egy harapnivalót. Hívja édesanyját.

Ezen a ponton van egy statikus könyvtárunk, az úgynevezett libmy_sdk.a, amely tartalmazza az SDK-t és az összes függőségi könyvtár, amelyeket egyetlen archívumba csomagoltunk. Ezenkívül képesek vagyunk fordítani és keresztfordítani (parancssori argumentumok használatával) minden célplatformunkra.

Egység tesztek

Az első tesztek futtatásakor

Valószínűleg nem kell magyarázza el, miért fontosak az egységtesztek, de alapvetően az SDK tervezésének döntő részét képezik, amely lehetővé teszi a fejlesztő számára, hogy az SDK behúzott módon működjön. Ezenkívül, ha bármilyen töréses változtatás történik a sorban, az segít nyomon követni és gyorsabban kijavítani a javításokat.

Ebben a konkrét esetben az egység teszt futtatható létrehozása lehetőséget ad arra is, hogy linkeljünk a az imént létrehozott kombinált könyvtár annak biztosítása érdekében, hogy a rendeltetésszerűen helyesen tudjunk kapcsolódni (és nem kapunk ilyen csúnya, nem definiált hivatkozás-szimbólum hibákat).

A Catch2-et használjuk egységtesztelési keretrendszerként . A szintaxist az alábbiakban ismertetjük:

Hogyan működik a Catch2, hogy ezt a makrot úgy hívjuk, hogy TEST_CASE és egy másik makró, az úgynevezett SECTION. Minden SECTION esetén a TEST_CASE kezdettől fogva végrehajtásra kerül. Tehát példánkban először a mySdk inicializálásra kerül, majd az első „Nem arckép” nevű szakasz futtatásra kerül. Ezután az mySdk dekonstrukciót elvégzi a rekonstrukció előtt, majd a második „Arcok a képben” című szakasz fut. Ez nagyszerű, mert biztosítja, hogy rendelkezzünk egy új MySDK objektummal, amelyet minden szakaszon működtethetünk. Ezután olyan makrókat használhatunk, mint REQUIRE az állítások megtételéhez.

A CMake segítségével felépíthetünk egy . Amint az alábbi 3. sor target_link_libraries felhívásában láthatjuk, az egyetlen könyvtár, amelyhez linkelnünk kell, a libmy_sdk.a és nem más függőségi könyvtárak.

Dokumentáció

Ha csak a felhasználók olvassák el az átkozott dokumentációt.

A doxygen dokumentáció előállításához közvetlenül a fejlécfájlunkból. Folytathatjuk és dokumentálhatjuk az összes módszerünket és adattípusunkat a nyilvános fejlécünkben az alábbi kódrészletben bemutatott szintaxis segítségével.Ne felejtse el megadni az összes bemeneti és kimeneti paramétert minden funkcióhoz.

A dokumentumok tényleges előállításához , szükségünk van valamire, amit doxyfile-nek nevezünk, ami alapvetően terv a doxygen utasítására, hogyan készítsük el a dokumentációt. Generálhatunk egy általános doxyfile-t a doxygen -g futtatásával a terminálunkban, feltéve, hogy doxigen van telepítve a rendszerére. Ezután szerkeszthetjük a doxyfile fájlt. Meg kell adnunk legalább a kimeneti könyvtárat és a bemeneti fájlokat is.

esetben csak az API fejlécfájlunkból szeretnénk dokumentációt generálni, ezért adtuk meg az include könyvtárat. Végül a CMake segítségével ténylegesen elkészíti a dokumentációt, ami hasonló módon megtehető .

Python-kötések

Unod már a félig releváns gifeket? Igen, én sem.

Legyünk őszinték. A C ++ nem a legkönnyebben vagy legbarátságosabban kifejlesztendő nyelv. Ezért szeretnénk bővíteni könyvtárunkat a nyelvi összerendelések támogatásával, hogy a fejlesztők könnyebben használhassák őket. Ezt a python segítségével fogom bemutatni, mivel ez egy népszerű számítógépes látás prototípus-készítő nyelv, de más nyelvi kötéseket ugyanolyan könnyű írni. Ennek eléréséhez a pybind11-et használjuk:

A makró, amely létrehoz egy függvényt, amelyet akkor hívnak meg, amikor importálási utasítást adnak ki a pythonon belül. Tehát a fenti példában a python modul neve mysdk. Ezután meg tudjuk határozni az osztályainkat és tagjaikat a pybind11 szintaxis használatával.

Íme egy megjegyzendő dolog: A C ++ nyelven meglehetősen gyakori, hogy a változókat átadhatjuk mutábilis referenciával, amely olvasási és írási hozzáférést is lehetővé tesz. Pontosan ezt tettük az API tag függvényünkkel a faceDetected és fbAndLandmarks paraméterekkel. A pythonban az összes argumentum hivatkozással kerül továbbításra. Bizonyos alapvető python típusok azonban változhatatlanok, beleértve a bool fájlt is. Véletlenül a faceDetected paraméterünk egy bool, amelyet mutálható hivatkozással adunk át. Ezért a fenti kódban bemutatott megoldást kell használnunk a 31–34. Sorokra, ahol meghatározzuk a bool értéket a python burkoló függvényünkön belül, majd át kell adnunk a C ++ függvényünknek, mielőtt a változót visszaadnánk egy páros részeként.

Miután elkészítettük a python-összerendelési könyvtárat, könnyen felhasználhatjuk az alábbi kód használatával:

Folyamatos integráció

Folyamatos integrációs folyamatunkhoz a CircleCI nevű eszközt fogjuk használni, ami nagyon tetszik, mert közvetlenül integrálódik a Github-ba. Egy új összeállítás automatikusan elindul, minden alkalommal, amikor elkötelezi magát. A kezdéshez lépjen a CircleCI webhelyre , és csatlakoztassa azt a Github-fiókjához, majd válassza ki a hozzáadni kívánt projektet. A hozzáadás után létre kell hoznia egy .circleci könyvtárat a projekt gyökerében, és létre kell hoznia egy config.yml nevű fájlt a könyvtárban.

Aki nem ismeri, a YAML egy szerializációs nyelv, amelyet általában a konfigurációs fájlokhoz használnak. Használhatjuk arra, hogy utasítsuk, milyen műveleteket akarunk végrehajtani a CircleCI-n. Az alábbi YAML-kódrészletben láthatja, hogyan építjük fel először az egyik függőségi könyvtárat, majd elkészítjük az SDK-t, végül pedig elkészítjük és futtatjuk az egységteszteket.

Ha intelligensek vagyunk (és feltételezem, hogy te is az vagy, ha eddig elérted), akkor a gyorsítótár használatával jelentősen csökkenthetjük a készítés idejét. Például a fenti YAML-ben az OpenCV buildet gyorsítótárba tesszük, a gyorsítótár kulcsaként a build szkript kivonatát használva. Így az OpenCV könyvtár csak akkor épül fel, ha a build szkriptet módosították – ellenkező esetben a gyorsítótárazott buildet használják. Egy másik dolog, amit meg kell jegyezni, hogy az általunk választott dokkoló kép belsejét építjük. Kiválasztottam egy egyéni dokkoló képet ( itt a Dockerfile), amelybe telepítettem az összes rendszerfüggőséget.

Fin.

És megvan. Mint minden jól megtervezett termék, mi is a legkeresettebb platformokat szeretnénk támogatni, és a legtöbb fejlesztő számára könnyen kezelhetővé tenni. A fenti oktatóanyag használatával létrehoztunk egy SDK-t, amely több nyelven elérhető és több platformon is telepíthető. És még a pybind11 dokumentációját sem kellett magának elolvasnia. Remélem, hasznosnak és szórakoztatónak találta ezt az oktatóanyagot. Boldog épület.

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

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük