OpenCV saidil STM32F7-Discovery

OpenCV saidil STM32F7-Discovery Olen üks operatsioonisüsteemi arendajatest Embox, ja selles artiklis räägin sellest, kuidas mul õnnestus OpenCV-d STM32746G plaadil käivitada.

Kui sisestate otsingumootorisse midagi sellist nagu "OpenCV STM32 plaadil", võite leida päris palju inimesi, kes on huvitatud selle teegi kasutamisest STM32 plaatidel või muudel mikrokontrolleritel.
On mitmeid videoid, mis nime järgi otsustades peaksid näitama, mida on vaja, kuid tavaliselt (kõikides videotes, mida nägin) STM32 tahvlil võeti kaamerast vastu ainult pilt ja tulemus kuvati ekraanil, ja pilditöötlus ise toimus kas tavalisel arvutil, või võimsamatel tahvlitel (näiteks Raspberry Pi).

Miks on see keeruline?

Otsingupäringute populaarsust seletatakse sellega, et OpenCV on kõige populaarsem arvutinägemise teek, mis tähendab, et sellega on tuttavad rohkem arendajad ning võimalus käivitada mikrokontrolleris töölauale sobivat koodi lihtsustab arendusprotsessi oluliselt. Kuid miks pole endiselt populaarseid valmisretsepte selle probleemi lahendamiseks?

OpenCV kasutamise probleem väikestel suurrätikutel on seotud kahe funktsiooniga:

  • Kui koostate raamatukogu isegi minimaalse moodulite komplektiga, ei mahu see väga suure koodi (mitu megabaiti juhiseid) tõttu lihtsalt sama STM32F7Discovery välkmällu (isegi ilma operatsioonisüsteemi arvesse võtmata)
  • Teek ise on kirjutatud C++ keeles, mis tähendab
    • Vajab positiivse käitusaja tuge (erandid jne)
    • Väike tugi LibC/Posixi jaoks, mida tavaliselt leidub manustatud süsteemide OS-is – vajate tavalist plussteeki ja standardset STL-i malliteeki (vektor jne).

Emboxi teisaldamine

Nagu tavaliselt, on enne mis tahes programmide teisaldamist operatsioonisüsteemi hea mõte proovida see ehitada sellisel kujul, nagu arendajad selle kavandasid. Meie puhul pole sellega probleeme - lähtekoodi leiate aadressilt githabe, on teek ehitatud GNU/Linuxi alla tavalise cmake-ga.

Hea uudis on see, et OpenCV saab karbist välja ehitada staatilise raamatukoguna, mis muudab teisaldamise lihtsamaks. Kogume standardse konfiguratsiooniga raamatukogu ja vaatame, kui palju ruumi need võtavad. Iga moodul on kogutud eraldi teeki.

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

Nagu viimaselt realt näha, ei võta .bss ja .data palju ruumi, kuid kood on üle 70 MiB. On selge, et kui see on staatiliselt seotud konkreetse rakendusega, väheneb kood.

Proovime võimalikult palju mooduleid välja visata, et oleks kokku pandud minimaalne näide (mis näiteks lihtsalt väljastab OpenCV versiooni), nii et vaatame cmake .. -LA ja lülitage valikutes välja kõik, mis lülitub välja.

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

Ühest küljest on see ainult üks teegi moodul, teisest küljest on see ilma kompilaatori optimeerimiseta koodi suuruse jaoks (-Os). ~3 MiB koodi on ikka päris palju, aga annab juba lootust edule.

Käivitage emulaatoris

Emulaatoris on silumine palju lihtsam, seega veendu esmalt, et teek qemu puhul töötab. Emuleeritud platvormina valisin Integrator / CP, kuna esiteks on see ka ARM ja teiseks toetab Embox selle platvormi graafikaväljundit.

Emboxil on mehhanism väliste teekide loomiseks, seda kasutades lisame moodulina OpenCV (edastades kõik samad valikud "minimaalse" ehitamise jaoks staatiliste teekide kujul), pärast seda lisan lihtsa rakenduse, mis näeb välja selline:

version.cpp:

#include <stdio.h>
#include <opencv2/core/utility.hpp>

int main() {
    printf("OpenCV: %s", cv::getBuildInformation().c_str());

    return 0;
}

Me paneme süsteemi kokku, käivitame selle - saame oodatud väljundi.

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 включены в сборку и т.п.>

Järgmine samm on käivitada mõni näide, eelistatavalt mõni arendajate endi pakutavatest standardsetest. teie saidil. ma valisin kaval piiridetektor.

Näidet tuli veidi ümber kirjutada, et kuvada pilt koos tulemusega otse kaadripuhvris. Ma pidin seda tegema, sest. funktsiooni imshow() saab joonistada pilte läbi QT, GTK ja Windowsi liideste, mida STM32 konfiguratsioonis muidugi kindlasti ei ole. Tegelikult saab QT-d käivitada ka STM32F7Discovery abil, kuid sellest tuleb juttu teises artiklis 🙂

Pärast lühikest selgitust, millises formaadis servadetektori tulemus salvestatakse, saame pildi.

OpenCV saidil STM32F7-Discovery

originaal pilt

OpenCV saidil STM32F7-Discovery

Tulemus

Töötab STM32F7Discoveryga

Seadmel 32F746GDISCOVERY on mitu riistvaramälu sektsiooni, mida saame ühel või teisel viisil kasutada

  1. 320KiB RAM
  2. 1 MB välklamp pildi jaoks
  3. 8 MiB SDRAM
  4. 16 MiB QSPI NAND välklamp
  5. microSD-kaardi pesa

SD-kaarti saab kasutada piltide salvestamiseks, kuid minimaalse näite käivitamise kontekstis pole see eriti kasulik.
Ekraani eraldusvõime on 480×272, mis tähendab, et kaadripuhvri mälu saab olema 522 240 baiti 32 biti sügavusel, s.o. see on rohkem kui RAM-i suurus, nii et kaadripuhver ja hunnik (mida on vaja, sealhulgas OpenCV jaoks piltide ja abistruktuuride andmete salvestamiseks) asuvad SDRAM-is, kõik muu (mälu virnade ja muude süsteemi vajaduste jaoks ) läheb RAM-i.

Kui võtta STM32F7Discovery jaoks minimaalne konfiguratsioon (visata välja kogu võrk, kõik käsud, teha virnad võimalikult väikseks jne) ja lisada sinna OpenCV koos näidetega, on vajalik mälu järgmine:

   text    data     bss     dec     hex filename
2876890  459208  312736 3648834  37ad42 build/base/bin/embox

Neile, kes pole väga kursis, millised jaotised kuhu lähevad, selgitan: sisse .text и .rodata juhised ja konstandid (jämedalt öeldes kirjutuskaitstud andmed) peituvad .data andmed on muutlikud, .bss on "nulleeritud" muutujaid, mis siiski vajavad kohta (see jaotis "läheb" RAM-i).

Hea uudis on see .data/.bss peaks sobima, aga koos .text häda on selles, et pildi jaoks on ainult 1MiB mälu. Võib välja visata .text pilti näitest ja lugege see näiteks SD-kaardilt käivitamisel mällu, kuid fruits.png kaalub umbes 330KiB, nii et see probleemi ei lahenda: enamik .text koosneb OpenCV koodist.

Laias laastus jääb üle vaid üks - osa koodi laadimine QSPI-välklampe (sellel on spetsiaalne töörežiim mälu kaardistamiseks süsteemisiiniga, et protsessor saaks nendele andmetele otse ligi). Sel juhul tekib probleem: esiteks pole QSPI-mälupulga mälu kohe pärast seadme taaskäivitamist saadaval (peate mälukaardistatud režiimi eraldi initsialiseerima) ja teiseks ei saa te seda mälu "välkutada" tuttav alglaadur.

Selle tulemusena otsustati linkida kogu kood QSPI-s ja flashida ise kirjutatud laadijaga, mis saab vajaliku binaarfaili TFTP kaudu.

Tulemus

Idee see teek Emboxi portida tekkis umbes aasta tagasi, kuid ikka ja jälle lükkus see erinevatel põhjustel edasi. Üks neist on libstdc++ ja standardse malliteegi tugi. Emboxi C++ toe probleem jääb sellest artiklist välja, nii et siinkohal ütlen vaid, et meil õnnestus see tugi saavutada õiges mahus, et see teegi toimiks 🙂

Lõpuks saadi need probleemid üle (vähemalt piisavalt, et OpenCV näide töötaks) ja näide jooksis. Tahvlil kulub Canny filtri abil piiride otsimiseks 40 pikka sekundit. See on muidugi liiga pikk (seal on kaalutlusi, kuidas seda asja optimeerida, edu korral on võimalik sellest eraldi artikkel kirjutada).

OpenCV saidil STM32F7-Discovery

Vaheeesmärk oli aga luua prototüüp, mis näitaks põhimõttelist võimalust OpenCV käivitamiseks vastavalt STM32 peal, see eesmärk sai täidetud, hurraa!

tl;dr: samm-sammult juhised

0: laadige alla Emboxi allikad, näiteks:

    git clone https://github.com/embox/embox && cd ./embox

1: Alustame alglaaduri kokkupanemisest, mis "vilgub" QSPI-mälupulgale.

    make confload-arm/stm32f7cube

Nüüd peate võrgu konfigureerima, kuna. Laadime pildi üles TFTP kaudu. Tahvli ja hosti IP-aadresside määramiseks peate redigeerima faili conf/rootfs/network.

Konfiguratsiooni näide:

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 - hosti aadress, kust pilt laaditakse, address - juhatuse aadress.

Pärast seda kogume alglaaduri:

    make

2: Tavaline alglaaduri laadimine (vabandan sõnamängu pärast) tahvlil - siin pole midagi konkreetset, peate seda tegema nagu iga muu STM32F7Discovery rakenduse puhul. Kui te ei tea, kuidas seda teha, võite selle kohta lugeda siin.
3: OpenCV konfiguratsiooniga pildi koostamine.

    make confload-platform/opencv/stm32f7discovery
    make

4: väljavõte ELF-i sektsioonidest, mis kirjutatakse QSPI-sse faili 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

Conf kataloogis on skript, mis seda teeb, nii et saate seda käivitada

    ./conf/qspi_objcopy.sh # Нужный бинарник -- build/base/bin/qspi.bin

5: tftp abil laadige qspi.bin.bin alla QSPI-mälupulgale. Selleks kopeerige hostis qspi.bin tftp-serveri juurkausta (tavaliselt /srv/tftp/ või /var/lib/tftpboot/; vastava serveri paketid on saadaval enamikes populaarsetes distributsioonides, tavaliselt nn. tftpd või tftp-hpa, mõnikord peate seda tegema systemctl start tftpd.service alustama).

    # вариант для tftpd
    sudo cp build/base/bin/qspi.bin /srv/tftp
    # вариант для tftp-hpa
    sudo cp build/base/bin/qspi.bin /var/lib/tftpboot

Emboxis (st alglaaduris) peate täitma järgmise käsu (oletame, et serveri aadress on 192.168.2.1):

    embox> qspi_loader qspi.bin 192.168.2.1

6: käsuga goto peate "hüppama" QSPI mällu. Konkreetne asukoht varieerub sõltuvalt sellest, kuidas pilt on lingitud, näete seda aadressi käsuga mem 0x90000000 (algusaadress mahub pildi teise 32-bitise sõna sisse); peate ka virna märgistama -s, virna aadress on 0x90000000, näiteks:

    embox>mem 0x90000000
    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275
                      ↑           ↑
              это адрес    это  адрес 
                стэка        первой
                           инструкции

    embox>goto -i 0x9000c27f -s 0x20023200 # Флаг -i нужен чтобы запретить прерывания во время инициализации системы

    < Начиная отсюда будет вывод не загрузчика, а образа с OpenCV >

7: Käivitage

    embox> edges 20

ja naudi 40-sekundilist piiriotsingut 🙂

Kui midagi läheb valesti, kirjutage probleem meie hoidlavõi meililistile [meiliga kaitstud], või siin kommentaaris.

Allikas: www.habr.com

Lisa kommentaar