Sò unu di i sviluppatori di u sistema operatore
Se scrivite qualcosa cum'è "OpenCV on STM32 board" in un mutore di ricerca, pudete truvà parechje persone chì anu interessatu à utilizà sta libreria nantu à schede STM32 o altri microcontrollers.
Ci hè parechje video chì, à ghjudicà da u nome, deve dimustrà ciò chì hè necessariu, ma di solitu (in tutti i video chì aghju vistu) nantu à a tavula STM32, solu l'imaghjina hè stata ricevuta da a camera è u risultatu hè statu affissatu nantu à u screnu. è u prucessu di l'imaghjini stessu hè statu fattu sia nantu à un ordinatore regulare, sia in schede più putenti (per esempiu, Raspberry Pi).
Perchè hè difficiule?
A pupularità di e dumande di ricerca hè spiegata da u fattu chì OpenCV hè a biblioteca di visione di l'informatica più populari, chì significa chì più sviluppatori sò familiarizati cù questu, è a capacità di eseguisce codice prontu per desktop in un microcontroller simplifica assai u prucessu di sviluppu. Ma perchè ùn ci sò ancu ricetti populari pronti per risolve stu prublema?
U prublema di utilizà OpenCV nantu à picculi scialli hè ligatu à duie caratteristiche:
- Se compilate a biblioteca ancu cù un settore minimu di moduli, simpricimenti ùn si mette micca in a memoria flash di u stessu STM32F7Discovery (ancu senza piglià in contu l'OS) per via di un codice assai grande (parechji megabytes d'istruzzioni)
- A biblioteca stessa hè scritta in C++, chì significa
- Avete bisognu di supportu per runtime pusitivu (eccezzioni, etc.)
- Pocu supportu per LibC/Posix, chì si trova di solitu in OS per i sistemi integrati - avete bisognu di una libreria standard plus è una biblioteca di mudelli STL standard (vettore, etc.)
Porting à Embbox
Comu solitu, prima di portà qualsiasi prugramma à u sistema upirativu, hè una bona idea di pruvà à custruisce in a forma chì i sviluppatori l'intendevanu. In u nostru casu, ùn ci sò micca prublemi cù questu - u codice fonte pò esse truvatu
A bona nutizia hè chì OpenCV pò esse custruitu cum'è una biblioteca statica fora di a scatula, chì facilita u porting. Cullemu una biblioteca cù una cunfigurazione standard è vede quantu spaziu occupanu. Ogni modulu hè recullatu in una biblioteca separata.
> 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)
Comu pudete vede da l'ultima linea, .bss è .data ùn occupanu assai spaziu, ma u codice hè più di 70 MiB. Hè chjaru chì s'ellu hè stata ligata à una applicazione specifica, u codice diventerà menu.
Pruvemu di scaccià quant'è moduli pussibule in modu chì un esempiu minimu hè assemblatu (chì, per esempiu, simplificà a versione OpenCV), cusì fighjemu cmake .. -LA
è spegne in l'opzioni tuttu ciò chì si spegne.
-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)
Da una banda, questu hè solu un modulu di a biblioteca, da l'altra banda, questu hè senza ottimisazione di compilatore per a dimensione di codice (-Os
). ~ 3 MiB di codice hè sempre assai, ma dà digià speranza di successu.
Eseguite in l'emulatore
Hè assai più faciule per debug nantu à l'emulatore, cusì prima assicuratevi chì a biblioteca travaglia in qemu. Cum'è una piattaforma emulata, aghju sceltu Integrator / CP, perchè prima, hè ancu ARM, è in segundu, Embbox supporta l'output graficu per questa piattaforma.
Embox hà un mecanismu per a custruzzione di biblioteche esterne, aduprendu l'aghjunghje OpenCV cum'è un modulu (passendu tutte e listesse opzioni per a custruzzione "minimale" in forma di biblioteche statiche), dopu aghjunghje una applicazione simplice chì pare cusì:
version.cpp:
#include <stdio.h>
#include <opencv2/core/utility.hpp>
int main() {
printf("OpenCV: %s", cv::getBuildInformation().c_str());
return 0;
}
Assemblamu u sistema, eseguimu - avemu u risultatu previstu.
root@embox:/#opencv_version
OpenCV:
General configuration for OpenCV 4.0.1 =====================================
Version control: bd6927bdf-dirty
Platform:
Timestamp: 2019-06-21T10:02:18Z
Host: Linux 5.1.7-arch1-1-ARCH x86_64
Target: Generic arm-unknown-none
CMake: 3.14.5
CMake generator: Unix Makefiles
CMake build tool: /usr/bin/make
Configuration: Debug
CPU/HW features:
Baseline:
requested: DETECT
disabled: VFPV3 NEON
C/C++:
Built as dynamic libs?: NO
< Дальше идут прочие параметры сборки -- с какими флагами компилировалось,
какие модули OpenCV включены в сборку и т.п.>
U prossimu passu hè di eseguisce qualchì esempiu, preferibile unu di i standard offerti da i sviluppatori stessi.
L'esempiu duvia esse riscritta ligeramente per vede l'imaghjini cù u risultatu direttamente in u buffer di frame. Aviu avutu à fà questu, perchè. funzione imshow()
pò disegnà l'imaghjini attraversu l'interfacce QT, GTK è Windows, chì, sicuru, ùn serà micca definitu in a cunfigurazione per STM32. In fattu, QT pò ancu esse eseguitu nantu à STM32F7Discovery, ma questu serà discututu in un altru articulu 🙂
Dopu una breve chjarificazione in quale formatu u risultatu di u detector di bordu hè guardatu, avemu una maghjina.
stampa originale
risultatu
Esecuzione nantu à STM32F7Discovery
In 32F746GDISCOVERY ci sò parechje sezioni di memoria di hardware chì pudemu usà un modu o un altru
- 320 KiB RAM
- 1 MiB flash per l'imaghjini
- 8 MiB di SDRAM
- 16 MiB QSPI NAND Flash
- slot per carta microSD
Una carta SD pò esse usata per almacenà l'imaghjini, ma in u cuntestu di eseguisce un esempiu minimu, questu ùn hè micca assai utile.
A visualizazione hà una risuluzione di 480 × 272, chì significa chì a memoria di framebuffer serà 522 bytes à una prufundità di 240 bits, i.e. questu hè più di a dimensione di RAM, cusì u framebuffer è u munzeddu (chì serà necessariu, cumpresu per OpenCV, per almacenà dati per l'imaghjini è strutture ausiliarii) seranu situati in SDRAM, tuttu u restu (memoria per stacks è altri bisogni di u sistema). ) anderà in RAM.
Se pigliamu a cunfigurazione minima per STM32F7Discovery (scaccià tutta a reta, tutti i cumandamenti, fate pile u più chjucu pussibule, etc.) è aghjunghje OpenCV cù esempii quì, a memoria necessaria serà a siguenti:
text data bss dec hex filename
2876890 459208 312736 3648834 37ad42 build/base/bin/embox
Per quelli chì ùn sò micca assai familiarizati cù quali rùbbriche vanu induve, spiegheraghju: in .text
и .rodata
struzzioni è custanti (in generale, dati di lettura) si trovanu .data
i dati sò mutabili, .bss
ci sò variabili "nullati", chì, però, anu bisognu di un locu (sta sezione "andà" à a RAM).
A bona nutizia hè chì .data
/.bss
duverebbe adattà, ma cun .text
u prublema hè chì ci hè solu 1MiB di memoria per l'imaghjini. Pò esse cacciatu fora .text
u ritrattu da l'esempiu è leghje, per esempiu, da a carta SD in memoria à l'iniziu, ma fruits.png pesa circa 330KiB, cusì ùn risolve micca u prublema: più .text
custituitu di u codice OpenCV.
In generale, ci hè solu una cosa - carica una parte di u codice in un lampu QSPI (hà un modu speciale di funziunamentu per mapping memoria à l'autobus di u sistema, perchè u processatore pò accede à sta dati direttamente). In questu casu, sorge un prublema: prima, a memoria di una unità flash QSPI ùn hè micca dispunibule immediatamente dopu chì u dispusitivu hè riavviatu (avete bisognu di inizializà separatamente u modu di mappa di memoria), è in segundu, ùn pudete micca "flash" sta memoria cù un bootloader familiar.
In u risultatu, hè statu decisu di ligà tuttu u codice in QSPI, è lampà cù un caricatore auto-scrittu chì riceverà u binariu necessariu via TFTP.
risultatu
L'idea di portà sta bibliuteca à Embox hè apparsa circa un annu fà, ma una volta è una volta hè stata posposta per diversi motivi. Unu di elli hè u supportu per libstdc++ è a biblioteca di mudelli standard. U prublema di u supportu C++ in Embox hè fora di u scopu di questu articulu, cusì quì diceraghju solu chì avemu riesciutu à ottene stu supportu in a quantità ghjusta per questa biblioteca per travaglià 🙂
In fine, sti prublemi sò stati superati (almenu abbastanza per l'esempiu OpenCV per travaglià), è l'esempiu curria. Ci vole 40 seconde longhi per u bordu per circà e fruntiere cù u filtru Canny. Questu, sicuru, hè troppu longu (ci sò cunsiderazioni nantu à cumu ottimisà sta materia, serà pussibule di scrive un articulu separatu nantu à questu in casu di successu).
In ogni casu, u scopu intermediu era di creà un prototipu chì mostrarà a pussibilità fundamentale di eseguisce OpenCV in STM32, rispettivamente, stu scopu hè statu rializatu, evviva!
tl;dr: istruzioni passo per passo
0: Scaricate e fonti di Embox, cum'è questu:
git clone https://github.com/embox/embox && cd ./embox
1: Cuminciamu da assemblendu un bootloader chì "flash" una unità flash QSPI.
make confload-arm/stm32f7cube
Avà vi tocca à cunfigurà a reta, perchè. Caricà l'imaghjini via TFTP. Per stabilisce l'indirizzi IP di u bordu è l'ospiti, avete bisognu di edità a conf/rootfs/network.
Esempiu di cunfigurazione:
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:02
gateway
- indirizzu di l'ospite da induve l'imaghjina serà caricata, address
- indirizzu di u tribunale.
Dopu quì, cullemu u bootloader:
make
2: A carica abituale di u bootloader (scusate per u pun) nantu à u bordu - ùn ci hè nunda di specificu quì, avete bisognu di fà cum'è per qualsiasi altra applicazione per STM32F7Discovery. Se ùn sapete micca cumu fà, pudete leghje nantu à questu
3: Cumpilà l'imaghjini cù a cunfigurazione per OpenCV.
make confload-platform/opencv/stm32f7discovery
make
4: Estratto da e sezioni ELF da scrive in QSPI in 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=.data
Ci hè un script in u repertoriu conf chì face questu, perchè pudete eseguisce
./conf/qspi_objcopy.sh # Нужный бинарник -- build/base/bin/qspi.bin
5: Utilizendu tftp, scaricate qspi.bin.bin à una unità flash QSPI. Nant'à l'ospiti, per fà questu, copiate qspi.bin à u cartulare radicali di u servitore tftp (di solitu /srv/tftp/ o /var/lib/tftpboot/; i pacchetti per u servitore currispundenti sò dispunibuli in i distribuzioni più populari, generalmente chjamati). tftpd o tftp-hpa, qualchì volta avete da fà systemctl start tftpd.service
per cumincià).
# вариант для tftpd
sudo cp build/base/bin/qspi.bin /srv/tftp
# вариант для tftp-hpa
sudo cp build/base/bin/qspi.bin /var/lib/tftpboot
In Embbox (vale à dì in u bootloader), avete bisognu di eseguisce u cumandimu seguitu (assumemu chì u servitore hà l'indirizzu 192.168.2.1):
embox> qspi_loader qspi.bin 192.168.2.1
6: Cù cumandimu goto
avete bisognu di "saltà" in a memoria QSPI. U locu specificu varierà secondu cumu l'imaghjina hè ligata, pudete vede stu indirizzu cù u cumandamentu mem 0x90000000
(l'indirizzu iniziale si mette in a seconda parolla di 32 bit di l'imaghjini); vi sarà dinù bisognu di bandiera a pila -s
, l'indirizzu di stack hè in 0x90000000, esempiu:
embox>mem 0x90000000
0x90000000: 0x20023200 0x9000c27f 0x9000c275 0x9000c275
↑ ↑
это адрес это адрес
стэка первой
инструкции
embox>goto -i 0x9000c27f -s 0x20023200 # Флаг -i нужен чтобы запретить прерывания во время инициализации системы
< Начиная отсюда будет вывод не загрузчика, а образа с OpenCV >
7: Lanciata
embox> edges 20
è gode di a ricerca di cunfini di 40 seconde 🙂
Se qualcosa va male - scrivite un prublema in
Source: www.habr.com