Eg er ein av utviklarane av operativsystemet , og i denne artikkelen vil eg fortelje om korleis eg fekk OpenCV til Ä fungere pÄ STM32746G-brettet.
Dersom ein sÞker etter noko som «OpenCV on STM32 board», kan ein finne ganske mange som er interessert i Ä bruke dette biblioteket pÄ STM32-brett eller andre mikrokontrollarar.
Det fins fleire videoar som, ut frÄ tittelen, skal demonstrere det som er nÞdvendig, men som regel (i alle videoar eg har sett) vart det pÄ STM32-brettet berre henta bilde frÄ eit kamera og vist resultatet pÄ skjermen, medan sjÞlve bildebehandlinga vart gjort enten pÄ ein vanlig datamaskin eller pÄ kraftigare brett (for eksempel Raspberry Pi).
Kvifor er dette vanskeleg?
Populariteten til sÞkjerane kan forklarast med at OpenCV er det mest populÊre biblioteket for datamaskinsyn, noko som betyr at fleire utviklarar er kjent med det, og moglegheita for Ä kÞyre ferdig kode for desktop pÄ ein mikrokontroller gjer utviklingsprosessen mykje enklare. Men kvifor finst det fortsatt inga populÊre konkrete lÞysing pÄ dette problemet?
Problemet med Ä bruke OpenCV pÄ smÄ brett heng saman med to sÊrtrekk:
- Dersom ein kompilerer biblioteket med til og med det minimale settet av moduler, vil det rett og slett ikkje fÄ plass i flash-minnet til STM32F7Discovery (utan Ä ta med OS) pÄ grunn av den store stÞrrelsen pÄ koden (flere megabyte instruksjonar)
- Selve biblioteket er skrive i C++, og det betyr
- At ein treng stĂžtte for C++-runtime (unntak m.m.)
- Lite stĂžtte for LibC/Posix, som vanlegvis finst i operativsystem for innebygde system - ein treng standardbibliotek for C++ og standardmalbiblioteket STL (vektor m.m.)
Portering til Embox
Som vanleg, fÞr ein porterer programvare til operativsystemet, bÞr ein prÞve Ä bygge det slik utviklarane hadde tenkt. I vÄrt tilfelle oppstÄr det ikkje problem med dette - kjeldene kan bli funne pÄ , biblioteket kan bli bygd for GNU/Linux med vanleg cmake.
Av gode nyheiter er at OpenCV kan bli bygd som eit statisk bibliotek, noko som gjer porteringa enklare. Me byggjer biblioteket med standardkonfigurasjonen og sjÄ kor mykje plass det tar. Kvar modul blir bygd som eit eige bibliotek.
> 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)Som syns i den siste linjen, tar .bss og .data ikke sÄ mye plass, men kodene er over 70 MiB. Det er klart at dersom dette bindes statisk med en spesifikk applikasjon, vil koden bli mindre.
La oss prÞve Ä fjerne sÄ mange moduler som mulig for Ä samle et minimalt eksempel (som for eksempel bare viser versjonen av OpenCV), sÄ vi ser. cmake .. -LA og deaktiverer alle opsjoner som kan deaktiveres.
-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)PÄ den ene siden er dette bare én modul av biblioteket, men pÄ den andre siden er dette uten optimalisering av kompilatoren for kode stÞrrelse (-Os). ~3 MiB kode er fortsatt en god del, men gir allerede hÄp om suksess.
KjĂžring i emulator
Det er mye enklere Ä feilsÞke i emulator, sÄ fÞrst skal vi sikre oss at biblioteket fungerer pÄ qemu. Som emulert plattform valgte jeg Integrator/CP, fordi dette er ogsÄ ARM, og i tillegg stÞtter Embox grafikkutgang for denne plattformen.
I Embox er det et system for Ă„ bygge eksterne biblioteker, med det kan vi legge til OpenCV som modul (ved Ă„ sende alle de samme opsjonene for "minimal" bygging som statiske biblioteker), og etter det legger jeg til en enkel applikasjon som ser slik ut:
version.cpp:
#include
#include
int main() {
printf("OpenCV: %s", cv::getBuildInformation().c_str());
return 0;
}Vi bygger systemet, starter det â og fĂ„r den forventede utgangen.
root@embox:/$opencv_version
OpenCV:
Generell konfigurasjon for OpenCV 4.0.1 =====================================
Versjonskontroll: bd6927bdf-dirty
Plattform:
Tidsstempel: 2019-06-21T10:02:18Z
Vert: Linux 5.1.7-arch1-1-ARCH x86_64
MÄl: Generisk arm-unknown-none
CMake: 3.14.5
CMake-generator: Unix Makefiles
CMake byggeverktĂžy: /usr/bin/make
Konfigurasjon: Debug
CPU/HW-funksjoner:
Grunnlinje:
forespurt: DETECT
deaktivert: VFPV3 NEON
C/C++:
Bygget som dynamiske biblioteker?: NEINeste steg er Ă„ kjĂžre et eksempel, helst et standard eksempel fra utviklerne selv . Jeg valgte .
Eksemplet mĂ„tte skrives om litt for Ă„ vise bildet med resultatet direkte i framebuffer. Dette mĂ„tte gjĂžres fordi funksjonen imshow() kan tegne bilder via grensesnittene QT, GTK og Windows, som selvfĂžlgelig ikke vil vĂŠre i konfigurasjonen for STM32. Faktisk kan QT ogsĂ„ kjĂžres pĂ„ STM32F7Discovery, men det vil bli behandlet i en annen artikkel đ
Etter en kort avklaring om hvilket format resultatet fra kantdetektoren lagres i, fÄr vi bildet.

Det originale bildet

Resultatet
KjÞring pÄ STM32F7Discovery
PÄ 32F746GDISCOVERY er det flere maskinvareminnesegmenter som vi kan bruke pÄ forskjellige mÄter
- 320KiB RAM
- 1MiB flashminne for bildet
- 8MiB SDRAM
- 16MiB QSPI NAND-flash
- Grensesnitt for microSD-kort
SD-kortet kan brukes til Ă„ lagre bilder, men i sammenheng med Ă„ kjĂžre et minimalt eksempel er det ikke veldig nyttig.
Skjermen har en opplĂžsning pĂ„ 480Ă272, sĂ„ minnet for framebufferen vil vĂŠre 522 240 byte med dybde pĂ„ 32 biter, sĂ„ dette er mer enn stĂžrrelsen pĂ„ RAM, sĂ„ framebufferen og stabelen (som ogsĂ„ er nĂždvendig for OpenCV for Ă„ lagre data for bilder og hjelpestrukturer) vil bli plassert i SDRAM, alt annet (minne for stakker og andre systembehov) vil gĂ„ til RAM.
Hvis vi tar en minimal konfigurasjon for STM32F7Discovery (fjerner alt nettverk, alle kommandoer, gjÞr stakkene sÄ smÄ som mulig osv.) og legger til OpenCV med eksempler, vil minnebehovet vÊre fÞlgende:
text data bss dec hex filename
2876890 459208 312736 3648834 37ad42 build/base/bin/emboxFor those who are not very familiar with how sections are arranged, let me explain: in .text og .rodata are stored instructions and constants (roughly speaking, readonly data), in .data are mutable data stored, in .bss are "zeroed" variables, which still need space (this section will go to RAM).
The good news is that .data/.bss should fit, but there's a problem â there is only 1MiB of memory for the image. You can discard the image from the example and read it, for instance, from an SD card into memory at startup, but fruits.png weighs about 330KiB, so that won't solve the problem: a large part .text consists precisely of OpenCV code. .text Basically, there is only one solution left â to load part of the code onto the QSPI flash chip (it has a special operating mode for mapping memory onto the system bus, so the processor can directly access this data). However, there is a problem: firstly, the memory of the QSPI flash is not available immediately after resetting the device (you need to separately initialize the memory-mapped mode), and secondly, you cannot "flash" this memory with the usual bootloader. .text As a result, it was decided to link all the code into QSPI and flash it with a custom bootloader that will obtain the necessary binary via TFTP.
The idea to port this library to Embox came about roughly a year ago, but it was postponed repeatedly for various reasons. One of them is the support of libstdc++ and the standard template library. The issue of supporting C++ in Embox goes beyond the scope of this article, so I will only say here that we managed to achieve this support to the extent required for the operation of this library đ
Ultimately, these problems were overcome (at least to a sufficient extent for the OpenCV example to work), and the example ran. The board takes 40 long seconds to find edges with the Canny filter. This is, of course, too long (there are ideas on how to optimize this, and I could write a separate article on it if successful).
Resultatet
Nevertheless, the intermediate goal was to create a prototype that demonstrates the principle possibility of running OpenCV on STM32, and thus, this goal was achieved, hooray!
tl;dr: step-by-step guide

0: Download the Embox sources, for instance, like this:
git clone https://github.com/embox/embox && cd ./embox
1: Let's start with building the bootloader that will "flash" the QSPI flash.
make confload-arm/stm32f7cube1: La oss begynne med Ă„ bygge en bootloader som 'programmerer' QSPI-flashminnet.
make confload-arm/stm32f7cubeNÄ mÄ vi konfigurere nettverket, ettersom vi skal laste opp bildet via TFTP. For Ä angi IP-adressene til kortet og verten, mÄ du endre filen conf/rootfs/network.
Eksempel pÄ konfigurasjon:
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 â adressen til verten som bildet skal lastes opp fra, address â adressen til kortet.
Etter dette bygger vi oppstartslasteren:
lag2: Alminnelig lasting av oppstartslasteren (unnskyld ordspillet) pĂ„ kortet â det er ingenting spesifikt her, det mĂ„ gjĂžres som med hvilken som helst annen applikasjon for STM32F7Discovery. Hvis du ikke vet hvordan dette gjĂžres, kan du lese om det .
3: Kompilering av bildet med konfigurasjon for OpenCV.
make confload-platform/opencv/stm32f7discovery
make4: Utdrag fra ELF-seksjoner som mÄ skrives til QSPI, i 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=.dataI katalogen conf finnes det et skript som gjÞr dette, sÄ du kan starte det
./conf/qspi_objcopy.sh # NÞdvendig binÊr -- build/base/bin/qspi.bin5: Ved hjelp av tftp laster vi opp qspi.bin.bin til QSPI-flashminnet. PÄ verten mÄ du kopiere qspi.bin til rotmappen til tftp-serveren (vanligvis er dette /srv/tftp/ eller /var/lib/tftpboot/; pakkene for den aktuelle serveren finnes i de fleste populÊre distribusjoner, ofte kalt tftpd eller tftp-hpa, noen ganger mÄ du gjÞre systemctl start tftpd.service for Ä starte).
# ĐČаŃĐžĐ°ĐœŃ ĐŽĐ»Ń tftpd
sudo cp build/base/bin/qspi.bin /srv/tftp
# ĐČаŃĐžĐ°ĐœŃ ĐŽĐ»Ń tftp-hpa
sudo cp build/base/bin/qspi.bin /var/lib/tftpbootPÄ Embox (dvs. i oppstartslasteren) mÄ du utfÞre fÞlgende kommando (vi antar at serverens adresse er 192.168.2.1):
embox> qspi_loader qspi.bin 192.168.2.16: Med kommandoen goto mÄ du "hoppe" inn i QSPI-minnet. Den spesifikke plasseringen vil variere avhengig av hvordan bildet er lenket; du kan se denne adressen med kommandoen mem 0x90000000 (startadressen ligger i det andre 32-bits ordet i bildet); det vil ogsÄ vÊre nÞdvendig Ä sette stakken med flagg -s, stakkens adresse ligger pÄ adressen 0x90000000, eksempel:
embox>mem 0x90000000
0x90000000: 0x20023200 0x9000c27f 0x9000c275 0x9000c275
â â
dette er adressen dette er adressen
til stakken til den fĂžrste
instruksjonen
embox>goto -i 0x9000c27f -s 0x20023200 # Flagget -i er nĂždvendig for Ă„ forhindre avbrudd under systeminitialisering7: KjĂžr
embox> edges 20og nyt 40 sekunder med kantdeteksjon đ
Hvis noe gĂ„r galt â skriv en issue i , eller pĂ„ mailinglisten embox-devel@googlegroups.com, eller i kommentarene her.
Kilde: habr.com
