Unë jam një nga zhvilluesit e sistemit të operimit , dhe në këtë artikull do të flas për mënyrën se si arrita të aktivizoj OpenCV në pllakën STM32746G.
Nëse shkruani në motorin e kërkimit diçka si 'OpenCV on STM32 board', mund të gjeni mjaft njerëz që janë të interesuar për përdorimin e kësaj biblioteke në pllakat STM32 ose në mikrokontrollera të tjerë.
Ekzistojnë disa video që, sipas titullit, duhet të demonstrojnë atë që duhet, por zakonisht (në të gjitha videoto që kam parë) në pllakën STM32 është kryer vetëm marrja e pamjes nga Kamera dhe shfaqja e rezultatit në ekran, ndërsa vetë përpunimi i imazhit bëhej ose në një kompjuter të zakonshëm, ose në pllaka më të fuqishme (p.sh., Raspberry Pi).
Pse është e vështirë?
Popullariteti i kërkimeve shpjegohet me faktin se OpenCV është biblioteka më popullore e vizionit kompjuterik, dhe kjo do të thotë se shumë më shumë zhvillues janë të njohur me të, dhe mundësia për të aktivizuar kodin e gatshëm për desktop në mikrokontroller e thjeshton ndjeshëm procesin e zhvillimit. Por pse ende nuk ka ndonjë recetë të njohur të gatshme për zgjidhjen e kësaj problemi?
Problemi i përdorimit të OpenCV në pllaka të vogla është i lidhur me dy karakteristika:
- Nëse e kompiloni bibliotekën madje edhe me një grup minimal module, në memorien flash të po asaj STM32F7Discovery ajo thjesht nuk do të hyjë (madje pa marrë parasysh OS-në) për shkak të kodit shumë të madh (disa megabajt instrukcionesh)
- Biblioteka vetë është shkruar në C++, dhe kjo do të thotë
- Duhet mbështetje për runtime-in e C++ (përjashtime etj.)
- Ka pak mbĂ«shtetje LibC/Posix, tĂ« cilat zakonisht janĂ« nĂ« OS-tĂ« pĂ«r sisteme tĂ« integruara â nevojitet biblioteka standarde e C++ dhe biblioteka standarde e templatit STL (vektori etj.)
Portimi në Embox
Si zakonisht, para se tĂ« portoni ndonjĂ« program nĂ« njĂ« sistem operativ, nuk do tĂ« ishte keq tĂ« provoni ta ndĂ«rtoni atĂ« nĂ« formĂ«n qĂ« e kanĂ« menduar zhvilluesit. NĂ« rastin tonĂ« nuk ka probleme me kĂ«tĂ« â burimet mund tĂ« gjenden nĂ« , biblioteka ndĂ«rtrohet nĂ«n GNU/Linux me cmake tĂ« zakonshĂ«m.
Nga lajmet e mira â OpenCV nga kutia mund tĂ« ndĂ«rtohet nĂ« formĂ«n e njĂ« biblioteke statike, gjĂ« qĂ« e bĂ«n portimin mĂ« tĂ« lehtĂ«. NdĂ«rtojmĂ« bibliotekĂ«n me konfigurimin standard dhe shikojmĂ« sa hapĂ«sirĂ« po zĂ«. Ădo modul ndĂ«rtohet nĂ« njĂ« bibliotekĂ« tĂ« veçantĂ«.
> size lib/*so --totals
text data bss dec hex filename
1945822 15431 960 1962213 1df0e5 lib/libopencv_calib3d.so
17081885 170312 25640 17277837 107a38d lib/libopencv_core.so
10928229 137640 20192 11086061 a928ed lib/libopencv_dnn.so
842311 25680 1968 869959 d4647 lib/libopencv_features2d.so
423660 8552 184 432396 6990c lib/libopencv_flann.so
8034733 54872 1416 8091021 7b758d lib/libopencv_gapi.so
90741 3452 304 94497 17121 lib/libopencv_highgui.so
6338414 53152 968 6392534 618ad6 lib/libopencv_imgcodecs.so
21323564 155912 652056 22131532 151b34c lib/libopencv_imgproc.so
724323 12176 376 736875 b3e6b lib/libopencv_ml.so
429036 6864 464 436364 6a88c lib/libopencv_objdetect.so
6866973 50176 1064 6918213 699045 lib/libopencv_photo.so
698531 13640 160 712331 ade8b lib/libopencv_stitching.so
466295 6688 168 473151 7383f lib/libopencv_video.so
315858 6972 11576 334406 51a46 lib/libopencv_videoio.so
76510375 721519 717496 77949390 4a569ce (TOTALS)Siç duket nga rreshti i fundit, .bss dhe .data nuk zënë aq shumë hapësirë, por ka mbi 70 MiB kod. E qartë është se nëse kjo lidhet statikisht me një aplikacion të caktuar, kodi do të zvogëlohet.
Le të përpiqemi të heqim sa më shumë module që të jetë e mundur, në mënyrë që të krijojmë një shembull minimal (i cili, për shembull, thjesht do të tregojë versionin e OpenCV), kështu që po shohim cmake .. -LA dhe fikim në opsione gjithçka që mund të fiket.
-DBUILD_opencv_java_bindings_generator=OFF
-DBUILD_opencv_stitching=OFF
-DWITH_PROTOBUF=OFF
-DWITH_PTHREADS_PF=OFF
-DWITH_QUIRC=OFF
-DWITH_TIFF=OFF
-DWITH_V4L=OFF
-DWITH_VTK=OFF
-DWITH_WEBP=OFF> size lib/libopencv_core.a --totals
text data bss dec hex filename
3317069 36425 17987 3371481 3371d9 (TOTALS)Nga njĂ«ra anĂ«, ky Ă«shtĂ« vetĂ«m njĂ« modul i bibliotekĂ«s, nga ana tjetĂ«r, ky Ă«shtĂ« pa optimizimin e kompilerit pĂ«r madhĂ«sinĂ« e kodit (-Os). ~3 MiB kod â kjo Ă«shtĂ« ende e konsiderueshme, por tashmĂ« jep shpresĂ« pĂ«r sukses.
Ekzekutimi në emulator
Në emulator është shumë më e lehtë të bësh debug, prandaj, fillimisht sigurohemi që biblioteka funksionon në qemu. Si platformë e emuluar kam zgjedhur Integrator/CP, sepse, nga njëra anë, është gjithashtu ARM dhe, nga ana tjetër, Embox mbështet daljen grafike për këtë platformë.
Në Embox ka një mekanizëm për ndërtimin e bibliotekave të jashtme, me ndihmën e tij e shtoj OpenCV si modul (duke kaluar të gjithë ato opsione për ndërtimin "minimal" në formën e bibliotekave statike), pas kësaj shtoj një aplikacion të thjeshtë që duket kështu:
version.cpp:
#include
#include
int main() {
printf("OpenCV: %s", cv::getBuildInformation().c_str());
return 0;
}NdĂ«rtojmĂ« sistemin, e ekzekutojmĂ« â dhe marrim rezultatin e pritur.
root@embox:/*opencv_version */
OpenCV:
Konfigurimi i përgjithshëm për OpenCV 4.0.1 =====================================
Kontrolli i versionit: bd6927bdf-dirty
Platforma:
Data e kohës: 2019-06-21T10:02:18Z
Host: Linux 5.1.7-arch1-1-ARCH x86_64
Objektivi: Generic arm-unknown-none
CMake: 3.14.5
Generatori i CMake: Unix Makefiles
Instrumenti për ndërtimin e CMake: /usr/bin/make
Konfigurimi: Debug
Tiparet e CPU/HW:
Bazë:
e kërkuar: DETECT
e ndaluar: VFPV3 NEON
C/C++:
Ndërtuar si biblioteka dinamike?: JOHapi tjetër është të ekzekutoni një shembull, më mirë ndonjë standard nga ata që ofrohen nga vetë zhvilluesit . Kam zgjedhur .
Shembulli ishte paksa e nevojshme ta rregulloja, pĂ«r tĂ« shfaqur imazhin me rezultatin direkt nĂ« frame-buffer. Duhej ta bĂ«ja kĂ«tĂ«, pasi funksioni imshow() di tĂ« vizatojĂ« imazhe pĂ«rmes interface-ve QT, GTK dhe Windows, tĂ« cilat, natyrisht, nĂ« konfigurimin pĂ«r STM32 nuk do tĂ« jenĂ«. NĂ« tĂ« vĂ«rtetĂ«, QT gjithashtu mund tĂ« ekzekutohet nĂ« STM32F7Discovery, por pĂ«r kĂ«tĂ« do tĂ« flitet nĂ« njĂ« artikull tjetĂ«r đ
Pas një sqarimi të shkurtër mbi se në cilin format ruhet rezultati i punës së detektorit të skajeve, marrim imazhin.

Imazhi origjinal

Rezultati
Ekzekutimi në STM32F7Discovery
Në 32F746GDISCOVERY ka disa seksione të ndryshme të memories që mund t'i përdorim në një mënyrë ose në një tjetër
- 320KiB memorie të përkohshme
- 1MiB memorie flash për figurën
- 8MiB SDRAM
- 16MiB QSPI NAND-flash
- Priza për kartën microSD
SD-karta mund të përdoret për ruajtjen e imazheve, por në kontekstin e ekzekutimit të një shembulli minimal nuk është shumë e dobishme.
Ekrani ka njĂ« resolutĂ« prej 480Ă272, dhe kĂ«shtu, memoria pĂ«r frame-buffer do tĂ« ketĂ« 522 240 byte nĂ« thellĂ«si 32 bit, pra kjo Ă«shtĂ« mĂ« shumĂ« se sa sasia e memories sĂ« pĂ«rkohshme, kĂ«shtu qĂ« frame-buffer dhe heaps (tĂ« cilat do tĂ« kĂ«rkohen edhe pĂ«r OpenCV, pĂ«r tĂ« ruajtur tĂ« dhĂ«nat pĂ«r imazhet dhe pĂ«r strukturat ndihmĂ«se) do tĂ« vendosen nĂ« SDRAM, çdo gjĂ« tjetĂ«r (memoria pĂ«r steka dhe nevojat e tjera sistemore) do tĂ« shkojĂ« nĂ« RAM.
Nëse merrni konfigurimin minimal për STM32F7Discovery (hiqni të gjithë rrjetin, të gjitha komandat, bëni stekat sa më të vogla dhe etj.) dhe e shtoni OpenCV me shembuj, kjo do të ishte për sa i përket memories së kërkuar:
text data bss dec hex filename
2876890 459208 312736 3648834 37ad42 build/base/bin/emboxPër ata që nuk janë shumë të njohur me sekuencat që shkojnë ku, le të shpjegoj: në .text dhe .rodata janë ruajtur instruksionet dhe konstantet (për ta thënë thjesht, të dhënat pa lexim), në .data janë të dhënat e ndryshueshme, në .bss janë variablat "e zeruara", të cilat, megjithatë, kanë nevojë për hapësirë (kjo seksion "do të dërgohet" në RAM).
Lajmi i mirĂ« Ă«shtĂ« se .data/.bss duhen vendosur, por me .text problem â pĂ«r imazhin ka vetĂ«m 1MiB memorie. Mund ta heqim nga .text imazhin e shembujve dhe ta lexojmĂ«, pĂ«r shembull, nga karta SD nĂ« memorie gjatĂ« aktivizimit, por fruits.png ka peshĂ« rreth 330KiB, kĂ«shtu qĂ« kjo problem nuk e zgjidh: pjesa mĂ« e madhe .text pĂ«rbĂ«het pikĂ«risht nga kodi OpenCV.
NĂ« thelb, mbetet vetĂ«m njĂ« zgjidhje â ngarkimi i pjesĂ«s sĂ« kodit nĂ« QSPI-flash (ajo ka njĂ« mod utilizimi tĂ« veçantĂ« pĂ«r mapimin e memories nĂ« autobusin sistemor, kĂ«shtu qĂ« procesori mund t'i qaset kĂ«tyre tĂ« dhĂ«nave direkt). MegjithatĂ«, lind problemi: sĂ« pari, memoria e QSPI-flash nuk Ă«shtĂ« e arritshme menjĂ«herĂ« pas rinisjes sĂ« pajisjes (duhet tĂ« inizializoni veçmas modin e mapeuar tĂ« memories), sĂ« dyti, nuk mund tĂ« "flash" kĂ«tĂ« memorie me boot loader-in e zakonshĂ«m.
Në fund, u vendos të lidhet i gjithë kodi në QSPI, dhe ta flashojmë me një boot loader të shkruar nga vetë, i cili do të merrte binarin e nevojshëm përmes TFTP.
Rezultati
Ideja pĂ«r tĂ« portuar kĂ«tĂ« bibliotekĂ« nĂ« Embox ka lindur rreth njĂ« viti mĂ« parĂ«, por herĂ« pas here Ă«shtĂ« shtyrĂ« pĂ«r shkak tĂ« arsyeve tĂ« ndryshme. NjĂ«ra prej tyre Ă«shtĂ« mbĂ«shtetje pĂ«r libstdc++ dhe standardin e bibliotekave tĂ« templatuara. Problemi i mbĂ«shtetjes C++ nĂ« Embox del pĂ«rtej kĂ«tij artikulli, ndaj kĂ«tu do tĂ« them vetĂ«m se arritĂ«m tĂ« sigurojmĂ« kĂ«tĂ« mbĂ«shtetje nĂ« masĂ«n e nevojshme pĂ«r funksionimin e kĂ«saj biblioteke đ
Në fund, këto probleme u kapërcyen (të paktën, në masën e mjaftueshme për funksionimin e shembujve OpenCV), dhe shembulli u aktivizua. 40 sekonda të gjata kërkon blloku për të gjetur kufijtë me filtrin Canny. Kjo, natyrisht, është shumë e gjatë (ka propozime se si ta optimizojmë këtë proces, për këtë mund të shkruajmë një artikull të veçantë në rast suksesi).

Megjithatë, qëllimi ndërmjetës ishte krijimi i një prototipi që do të tregonte mundësinë themelore të aktivizimit të OpenCV në STM32, përkatësisht, ky qëllim u arrit, urime!
tl;dr: udhëzim hap pas hapi
0: Shkarkoni burimet e Embox, për shembull kështu:
git clone https://github.com/embox/embox && cd ./embox1: Le të fillojmë me ndërtimin e boot loader-it, i cili "do ta flash" QSPI-flash.
make confload-arm/stm32f7cubeTani duhet të konfiguroni rrjetin, sepse do ta ngarkojmë imazhin përmes TFTP. Për të caktuar adresat IP të kartës dhe hostit, duhet të modifikoni skedarin conf/rootfs/network.
Shembulli i konfigurimit:
iface eth0 inet static
address 192.168.2.2
netmask 255.255.255.0
gateway 192.168.2.1
hwaddress aa:bb:cc:dd:ee:02gateway â adresa e hostit nga ku do tĂ« ngarkohet imazhi, address â adresa e kartĂ«s.
Pasi të keni bërë këtë, ndjekim krijimin e ngarkuesit:
make2: Ngarkimi normal i ngarkuesit (falni pĂ«r lojĂ«n me fjalĂ«) nĂ« kartĂ« â kĂ«tu nuk ka asgjĂ« specifike, duhet bĂ«rĂ« si pĂ«r çdo tjetĂ«r aplikacion pĂ«r STM32F7Discovery. NĂ«se nuk e dini se si bĂ«het, mund tĂ« lexoni pĂ«r kĂ«tĂ« .
3: Kompilimi i imazhit me konfigurimin për OpenCV.
make confload-platform/opencv/stm32f7discovery
make4: Nxjerrja nga ELF e seksioneve që duhet të shkruhen në QSPI, në qspi.bin
arm-none-eabi-objcopy -O binary build/base/bin/embox build/base/bin/qspi.bin
--only-section=.text --only-section=.rodata
--only-section='.ARM.ex*'
--only-section=.dataNë direktorinë conf ndodhet një skript që e bën këtë, kështu që mund ta filloni atë
../conf/qspi_objcopy.sh # Binaries i nevojshëm -- build/base/bin/qspi.bin5: Me ndihmën e tftp ngarkoni qspi.bin.bin në QSPI-flash. Në host, për këtë duhet të kopjoni qspi.bin në dosjen rrënjësore të serverit tftp (zakonisht është /srv/tftp/ ose /var/lib/tftpboot/; paketat për serverin përkatës janë të disponueshme në shumicën e shpërndarjeve popullore, zakonisht quhen tftpd ose tftp-hpa, ndonjëherë duhet të bëni systemctl start tftpd.service për të filluar).
# ĐČаŃĐžĐ°ĐœŃ ĐŽĐ»Ń tftpd
sudo cp build/base/bin/qspi.bin /srv/tftp
# ĐČаŃĐžĐ°ĐœŃ ĐŽĐ»Ń tftp-hpa
sudo cp build/base/bin/qspi.bin /var/lib/tftpbootNë Embox (pra, në ngarkues) duhet të ekzekutoni këtë komandë (duke supozuar se adresa e serverit është 192.168.2.1):
embox> qspi_loader qspi.bin 192.168.2.16: Me ndihmën e komandës goto duhet "të hidheni" në memorien QSPI. Lokacioni specifik do të ndryshojë në varësi të mënyrës se si imazhi është lidhur, këtë adresë mund ta shihni me komandën mem 0x90000000 (adresa e fillimit përdoret në fjalën e dytë 32-bit të imazhit); gjithashtu do të kërkohet të vendosni flamurin e stack-ut -s, adresa e stack-ut ndodhet në adresën 0x90000000, shembull:
embox>mem 0x90000000
0x90000000: 0x20023200 0x9000c27f 0x9000c275 0x9000c275
â â
kjo është adresa kjo është adresa
e stack-ut e parë
e instrukcionit
embox>goto -i 0x9000c27f -s 0x20023200 # Flamuri -i është i nevojshëm për të ndaluar ndërprerjet gjatë inicimit të sistemit7: Nisim
embox> edges 20dhe shijoni kĂ«rkimin e kufijve pĂ«r 40 sekonda đ
NĂ«se ndodhi ndonjĂ« problem â shkruani njĂ« çështje nĂ« , ose nĂ« listĂ«n e postimeve embox-devel@googlegroups.com, ose nĂ« komentet kĂ«tu.
Burimi: habr.com
