OpenCV STM32F7-Discovery'l

OpenCV STM32F7-Discovery'l Olen ĂŒks operatsioonisĂŒsteemi arendajatest Embox, ja selles artiklis jutustan, kuidas mul Ă”nnestus OpenCV kĂ€ivitada STM32746G plaadil.

Kui otsida midagi sarnast nagu «OpenCV on STM32 plaadil», vÔib leida pÀris palju inimesi, kes huvituvad selle teegi kasutamisest STM32 vÔi teiste mikrokontrollerite peal.
On mitmeid videoid, mis pealkirja jÀrgi peaksid nÀitama vajalikku, kuid tavaliselt (kÔikides videotest, mida olen nÀinud) tehti STM32 plaadil ainult kaamerapildi saamine ja tulemuse kuvamine ekraanil, samas kui pilditöötlus tehti kas tavalisel arvutil vÔi vÔimsamatel plaatidel (nt Raspberry Pi).

Miks see on keeruline?

OtsingupÀringute populaarsus selgitab, et OpenCV on kÔige populaarsem arvutinÀgemise teek, seega on rohkem arendajaid sellega tuttavad, ja vÔimalus kÀivitada laua jaoks valmis kood mikrokontrolleril lihtsustab arendusprotsessi mÀrkimisvÀÀrselt. Aga miks siiani pole populaarseid valmis lahendusi selle probleemi jaoks?

Probleem OpenCV kasutamisega vÀikestel plaatidel on seotud kahe omadusega:

  • Kui isegi minimaalsete moodulitega kogu teek kompileerida, ei mahu see sama STM32F7Discovery vĂ€lkmĂ€llu (isegi ilma operatsioonisĂŒsteemita) liiga suure koodi tĂ”ttu (mitu megabaidi kĂ€su).
  • Teek ise on kirjutatud C++-s, seega
    • on vajalik C++ kĂ€itusaeg (vĂ€lja arvatud ja muud).
    • Puudub LibC/Posix tugi, mida tavaliselt leidub sisseehitatud sĂŒsteemide operatsioonisĂŒsteemides — vajalik on C++ standardteek ja STL standardteek (nĂ€iteks vektor ja nii edasi).

Portimine Emboxile

Kuna enne mĂ”ne programmi portimist operatsioonisĂŒsteemi on alati hea proovida seda koguda just sellisena, nagu arendajad ette nĂ€gid. Meie juhul ei teki selle probleemiga mingeid raskusi — allikaid saab leida GitHubis, teek kogutakse GNU/Linuxi tavapĂ€rase cmake abil.

Hea uudis on see, et OpenCV-d saab vÀlja pakkuda staatilise teekina, mis muudab portimise lihtsamaks. Kogume teeki tavalise konfigureerimisega ja vaatame, kui palju ruumi see nÔuab. Iga moodul kogutakse eraldi teekina.

> 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 viimasest reast nĂ€ha, vĂ”tab .bss ja .data mitte palju ruumi, kuid kood on ĂŒle 70 MiB. On selge, et kui see linkida staatiliselt konkreetse rakendusega, vĂ€heneb koodi maht.

Proovime eemaldada nii palju mooduleid kui vĂ”imalik, et koguda minimaalne nĂ€ide (mis nĂ€iteks lihtsalt kuvab OpenCV versiooni), seega vaatame cmake .. -LA ja lĂŒlitame valikutes vĂ€lja kĂ”ik, mis vĂ€lja lĂŒlitatav on.

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

Ühelt poolt on see ainult ĂŒks raamatukogu moodul, teiselt poolt, see on ilma koodi suuruse optimeerimiseta (-Os). ~3 MiB koodi — see on endiselt piisavalt palju, kuid juba annab lootust edule.

KĂ€ivitamine emulaatoris

Emulaatoris on palju lihtsam debugida, seega veendume esmalt, et teek töötab qemu-s. Emuleeritavaks platvormiks valisin Integrator/CP, kuna see on ka ARM ja Embox toetab selle platvormi graafikat.

Emboxis on mehhanism vĂ€liste raamatukogude kogumiseks, millega lisame OpenCV moodulina (kandes kĂ”ik samad valikud „minimaalse“ kogumise jaoks staatiliste raamatukogude kujul), seejĂ€rel lisan lihtsa rakenduse, mis nĂ€eb vĂ€lja jĂ€rgmiselt:

version.cpp:

#include 
#include 

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

    return 0;
}

Kogume sĂŒsteemi, kĂ€ivitame — saame oodatud vĂ€ljundi.

root@embox:/#opencv_version                                                     
OpenCV: 
OpenCV 4.0.1 ĂŒldine konfiguratsioon =====================================
  Versioonikontroll:               bd6927bdf-dirty

  Platvorm:
    Ajastamine:                   2019-06-21T10:02:18Z
    Alus:                        Linux 5.1.7-arch1-1-ARCH x86_64
    Siht:                      Üldine arm-unknown-none
    CMake:                       3.14.5
    CMake generaator:             Unix Makefiles
    CMake ehitustööriist:            /usr/bin/make
    Konfiguratsioon:               Debug

  CPU/HW omadused:
    Baas:
      taotletud:                 DETECT
      keelatud:                  VFPV3 NEON

  C/C++:
    Koostatud dĂŒnaamiliste teekidena?:      EI

JÀrgmine samm on kÀivitada mÔni nÀide, parim on valida mÔni standardne, mida pakuvad arendajad ise. oma veebilehelt. Valisin Canny servade detektori.

NĂ€idet tuli veidi ĂŒmber kirjutada, et kuvada tulemust otse raami puhveris. See tuli teha, kuna funktsioon imshow() suudab kuvada pilte lĂ€bi QT, GTK ja Windowsi liideste, mida STM32 kontekstis kindlasti ei ole. Tegelikult saab QT-d samuti kĂ€ivitada STM32F7Discovery-l, aga sellest rÀÀgitakse juba teises artiklis 🙂

PĂ€rast lĂŒhikest uurimist, millises formaadis piiride tuvastamise tulemused salvestatakse, saame pildi.

OpenCV STM32F7-Discovery'l

Originaalpilt

OpenCV STM32F7-Discovery'l

Tulemus

KĂ€ivitus STM32F7Discovery-l

32F746GDISCOVERY-l on mitu riistvara mÀlusegmenti, mida saame kasulikult kasutada.

  1. 320KiB töömÀlu
  2. 1MiB vÀlkmÀlu pildi jaoks
  3. 8MiB SDRAM
  4. 16MiB QSPI NAND-mÀlupulk
  5. MicroSD-kaardi pesa

SD-kaarti vÔib kasutada piltide salvestamiseks, kuid minimaalsete nÀidete kÀivitamise kontekstis pole see eriti kasulik.
Kuva eraldusvĂ”ime on 480×272, seega frame bufferi mĂ€lu suurus on 522 240 baiti 32-bitise sĂŒgavuse juures, mis tĂ€hendab, et see on suurem kui töömĂ€lu, seega paigaldame frame bufferi ja hunniku (mis on vajalik ka OpenCV jaoks piltide ja abistruktuuride andmete salvestamiseks) SDRAM-i, kĂ”ik muu (mĂ€lu rĂ”ngaste ja teiste sĂŒsteemivajaduste jaoks) saadetakse RAM-i.

Kui vÔtta minimaalne konfiguratsioon STM32F7Discovery jaoks (eemaldada kogu vÔrk, kÔik kÀsud, teha virnad vÔimalikult vÀikseks jne) ja lisada sinna OpenCV nÀidetega, siis vajalik mÀlu oleks jÀrgmine:

   tekst    andmed     bss     dec     hex failinimi
2876890  459208  312736 3648834  37ad42 build/base/bin/embox

Need for those who are not very familiar with where the sections go, I'll explain: in .text ja .rodata lie instructions and constants (roughly speaking, readonly data), in .data lie modifiable data, in .bss lie "zeroed" variables, which still need space (this section will "go" into RAM).

The good news is that .data/.bss must fit, but the trouble is .text there's only 1MiB of memory for the image. You can remove 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: most of the .text nÀiteks nÀha ja lugeda pilti SD-kaardilt kÀivitamisel, kuid fruits.png kaalub umbes 330KiB, seega see probleem ei lahenda: enamik .text consists precisely of OpenCV code.

Basically, there’s only one option left — loading part of the code onto the QSPI flash (it has a special operating mode for memory mapping on the system bus, so the processor can directly access this data). However, there’s a problem: first, QSPI flash memory is not available immediately after rebooting the device (you need to separately initialize memory-mapped mode), and second, you can't "flash" this memory with a conventional bootloader.

LĂ”puks otsustati sĂŒnkroonida kogu kood QSPI-sse ja kirjutada see oma laadimisseadmestikku, mis saab vajaliku binaari TFTP kaudu.

Tulemus

Idee portida see teek Emboxile tekkis umbes aasta tagasi, kuid mitmel pĂ”hjusel on see korduvalt edasi lĂŒkatud. Üks neist pĂ”hjustest on libstdc++ ja standardne mallide teek. C++ toe toimetamine Emboxis ĂŒletab selle artikli raames kĂ€sitletava teema ulatuse, seega ĂŒtlen lihtsalt, et oleme suutnud saavutada vajaliku toetuse selle teegi tööks 🙂.

LĂ”puks saadi need probleemid ĂŒletatud (vĂ€hemalt piisavalt, et OpenCV nĂ€ide töötaks) ning nĂ€ide kĂ€ivitus. Plaadil kulus 40 pikemat sekundit servade tuvastamiseks Canny filtriga. See on muidugi liiga kaua (on ideid, kuidas seda optimeerida, sellest vĂ”iks kirjutada eraldi artikli, kui see Ă”nnestub).

OpenCV STM32F7-Discovery'l

KĂŒll aga oli vahe-eesmĂ€rk prototĂŒĂŒbi loomine, mis nĂ€itaks OpenCV kĂ€itamise pĂ”himĂ”ttelise vĂ”imaluse STM32-l, seega on see eesmĂ€rk saavutatud, hurraa!

tl;dr: samm-sammuline juhend

0: Laadige Emboxi lÀhtekood, nÀiteks nii:

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

1: Alustame kÀivituslaadija koostamisest, mis "programmeerib" QSPI mÀlupulga.

    make confload-arm/stm32f7cube

NĂŒĂŒd tuleb seadistada vĂ”rk, kuna laadime kujundi TFTP kaudu. Arvutite ja hosti IP-aadresside mÀÀramiseks tuleb muuta faili conf/rootfs/network.

Konfiguratsiooni nÀidis:

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 — seadme aadress.

PĂ€rast seda koondame laadija:

    make

2: Tavaline laadimine laadijale (palun andke andeks mĂ€ng sĂ”nadega) seadmesse — siin pole midagi spetifilist, tuleb seda teha nagu igasuguste muude rakenduste puhul STM32F7Discovery jaoks. Kui te ei tea, kuidas seda teha, vĂ”ite sellest lugeda siin.
3: Pildi kompileerimine OpenCV konfigureerimisega.

    make confload-platform/opencv/stm32f7discovery
    make

4: Sektsioonide vÀljavÔtmine ELF-ist, mis tuleb QSPI-sse kirjutada, failis 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

Kaustas conf on skript, mis seda teeb, nii et saate selle kÀivitada

    ./conf/qspi_objcopy.sh # Vajalik binaar -- build/base/bin/qspi.bin

5: Tftp abil laadime qspi.bin.bin QSPI-mÀlupulgale. Selleks tuleb hostis kopeerida qspi.bin tftp-serveri juurkatalooge (tavaliselt on see /srv/tftp/ vÔi /var/lib/tftpboot/; vajalikud paketid on saadaval enamikus tuntud distributsioonides, neid nimetatakse tavaliselt tftpd vÔi tftp-hpa, mÔnikord tuleb teha systemctl start tftpd.service kÀivitamiseks).

    # ĐČĐ°Ń€ĐžĐ°ĐœŃ‚ ĐŽĐ»Ń tftpd
    sudo cp build/base/bin/qspi.bin /srv/tftp
    # ĐČĐ°Ń€ĐžĐ°ĐœŃ‚ ĐŽĐ»Ń tftp-hpa
    sudo cp build/base/bin/qspi.bin /var/lib/tftpboot

Emboxis (st laadijana) tuleb tÀita jÀrgmine kÀsk (eeldame, et serveri aadress on 192.168.2.1):

    embox> qspi_loader qspi.bin 192.168.2.1

6: KĂ€sk goto on vajalik, et "hĂŒppata" QSPI-mĂ€llu. Konkreetne asukoht varieerub sĂ”ltuvalt sellest, kuidas pilt linkib, seda aadressi saab vaadata kĂ€suga mem 0x90000000 (algus aadress mahtus pildi teise 32-bitise sĂ”na); lisaks tuleb seadistada suurus lippudega -s, steki aadress asub aadressil 0x90000000, nĂ€iteks:

    embox>mem 0x90000000
    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275
                      ↑           ↑
              see aadress    see aadress 
                stekist        esimese
                           instruktsiooni

    embox>goto -i 0x9000c27f -s 0x20023200 # Lipp -i on vajalik, et keelata katkestused sĂŒsteemi initsialiseerimise ajal

7: KĂ€ivitame

    embox> servad 20

ja naudime 40-sekundiliste piiride otsingut 🙂

Kui miski lÀheb valesti, siis kirjutage issue meie reposse, vÔi embox-devel@googlegroups.com listi, vÔi kommenteerige siin.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster