OpenCV op STM32F7-Discovery

OpenCV op STM32F7-Discovery Ik bin ien fan 'e ûntwikkelders fan it bestjoeringssysteem Embox, en yn dit artikel sil ik prate oer hoe't ik it slagge om OpenCV út te fieren op it STM32746G-boerd.

As jo ​​soksawat "OpenCV op STM32 board" yn in sykmasine typearje, kinne jo nochal in pear minsken fine dy't ynteressearre binne yn it brûken fan dizze bibleteek op STM32 boards of oare mikrocontrollers.
D'r binne ferskate fideo's dy't, te beoardieljen nei de namme, moatte demonstrearje wat nedich is, mar normaal (yn alle fideo's dy't ik seach) op it STM32-boerd, waard allinich de ôfbylding ûntfongen fan 'e kamera en it resultaat waard werjûn op it skerm, en de ôfbylding ferwurking sels waard dien of op in gewoane kompjûter, of op machtiger boards (Bygelyks, Raspberry Pi).

Wêrom is it dreech?

De populariteit fan sykfragen wurdt ferklearre troch it feit dat OpenCV de populêrste bibleteek foar komputerfisy is, wat betsjut dat mear ûntwikkelders der bekend mei binne, en de mooglikheid om buroblêd-klear koade út te fieren op in mikrocontroller makket it ûntwikkelingsproses sterk simplifies. Mar wêrom binne d'r noch gjin populêre klearmakke resepten foar it oplossen fan dit probleem?

It probleem fan it brûken fan OpenCV op lytse sjaals is relatearre oan twa funksjes:

  • As jo ​​de bibleteek kompilearje sels mei in minimale set fan modules, sil it gewoan net passe yn it flashûnthâld fan deselde STM32F7Discovery (sels sûnder rekken te hâlden mei it OS) fanwege in heul grutte koade (ferskate megabytes oan ynstruksjes)
  • De bibleteek sels is skreaun yn C++, wat betsjut
    • Stipe nedich foar positive runtime (útsûnderings, ensfh.)
    • Lytse stipe foar LibC/Posix, dy't normaal te finen is yn OS foar ynbêde systemen - jo hawwe in standert plus-bibleteek en in standert STL-sjabloanbibleteek nedich (vektor, ensfh.)

Portearje nei Embox

Lykas gewoanlik, foardat jo programma's nei it bestjoeringssysteem portearje, is it in goed idee om it te bouwen yn 'e foarm wêryn't de ûntwikkelders it bedoeld hawwe. Yn ús gefal binne d'r gjin problemen mei dit - de boarnekoade is te finen op github, de bibleteek is boud ûnder GNU/Linux mei de gewoane cmake.

It goede nijs is dat OpenCV kin wurde boud as in statyske bibleteek út 'e doaze, wat porting makliker makket. Wy sammelje in bibleteek mei in standert konfiguraasje en sjogge hoefolle romte se nimme. Elke module wurdt sammele yn in aparte bibleteek.

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

Sa't jo sjen kinne út 'e lêste rigel, nimme .bss en .data net folle romte, mar de koade is mear as 70 MiB. It is dúdlik dat as dit statysk keppele is oan in spesifike applikaasje, de koade minder wurdt.

Litte wy besykje safolle mooglik modules út te smiten sadat in minimaal foarbyld wurdt gearstald (dat bygelyks gewoan de OpenCV-ferzje sil útfiere), dus wy sjogge cmake .. -LA en útsette yn 'e opsjes alles wat útskeakele is.

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

Oan 'e iene kant is dit mar ien module fan' e biblioteek, oan 'e oare kant is dit sûnder kompilatoroptimalisaasje foar koadegrutte (-Os). ~ 3 MiB fan koade is noch hiel wat, mar jout al hope foar sukses.

Run yn 'e emulator

It is folle makliker om te debuggen op 'e emulator, dus soargje derfoar dat de bibleteek wurket op qemu. As emulearre platfoarm keas ik Integrator / CP, om't firstly, it is ek ARM, en twadde, Embox stipet graphics útfier foar dit platfoarm.

Embox hat in meganisme foar it bouwen fan eksterne biblioteken, mei it brûken fan it tafoegjen fan OpenCV as in module (troch alle deselde opsjes foar de "minimale" build yn 'e foarm fan statyske biblioteken), dêrnei foegje ik in ienfâldige applikaasje ta dy't der sa útsjocht:

version.cpp:

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

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

    return 0;
}

Wy sammelje it systeem, rinne it - wy krije de ferwachte útfier.

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

De folgjende stap is om wat foarbyld út te fieren, by foarkar ien fan 'e standert oanbean troch de ûntwikkelders sels. op jo side. ik keas grins detector canny.

It foarbyld moast wat oerskreaun wurde om de ôfbylding mei it resultaat direkt yn 'e framebuffer wer te jaan. Ik moast dit dwaan, om't. funksje imshow() kinne ôfbyldings tekenje fia de QT-, GTK- en Windows-ynterfaces, dy't fansels net yn 'e konfiguraasje foar STM32 sille wêze. Yn feite kin QT ek útfierd wurde op STM32F7Discovery, mar dit sil wurde besprutsen yn in oar artikel 🙂

Nei in koarte opheldering yn hokker opmaak it resultaat fan 'e rânedetektor wurdt opslein, krije wy in ôfbylding.

OpenCV op STM32F7-Discovery

orizjinele foto

OpenCV op STM32F7-Discovery

resultaat

Rint op STM32F7Discovery

Op 32F746GDISCOVERY binne d'r ferskate hardware-ûnthâldseksjes dy't wy op ien of oare manier kinne brûke

  1. 320 KB RAM
  2. 1MiB flash foar ôfbylding
  3. 8 MB SDRAM
  4. 16MiB QSPI NAND Flash
  5. microSD card slot

In SD-kaart kin brûkt wurde om ôfbyldings op te slaan, mar yn 'e kontekst fan it útfieren fan in minimaal foarbyld is dit net heul nuttich.
It display hat in resolúsje fan 480 × 272, wat betsjut dat it framebufferûnthâld 522 bytes sil wêze op in djipte fan 240 bits, d.w.s. dit is mear dan de grutte fan RAM, dus de framebuffer en de heap (dy't nedich is, ynklusyf foar OpenCV, om gegevens foar ôfbyldings en helpstruktueren op te slaan) sille yn SDRAM lizze, al it oare (ûnthâld foar stapels en oare systeembehoeften) ) sil nei RAM gean.

As wy de minimale konfiguraasje foar STM32F7Discovery nimme (it heule netwurk, alle kommando's, meitsje stapels sa lyts mooglik, ensfh.)

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

Foar dyjingen dy't net hiel bekend binne mei hokker seksjes gean wêr, Ik sil útlizze: yn .text и .rodata ynstruksjes en konstanten (rûchwei sprutsen, allinich lêsgegevens) lizze yn .data de gegevens binne feroare, .bss der binne "nulled" fariabelen, dy't, lykwols, nedich in plak (dizze seksje sil "gean" nei RAM).

It goede nijs is dat .data/.bss moat passe, mar mei .text it probleem is dat der mar 1MiB ûnthâld foar de ôfbylding. Kin wurde smiten út .text de foto út it foarbyld en lês it, bygelyks, út de SD kaart yn ûnthâld by opstarten, mar fruits.png waacht oer 330KiB, dus dit sil net oplosse it probleem: meast .text bestiet út de OpenCV-koade.

Troch en grut, der is mar ien ding oerbleaun - it laden fan in part fan de koade op in QSPI flash (it hat in spesjale modus fan wurking foar mapping ûnthâld oan it systeem bus, sadat de prosessor kin tagong ta dizze gegevens direkt). Yn dit gefal ûntstiet in probleem: as earste is it ûnthâld fan in QSPI-flashdrive net direkt beskikber nei't it apparaat opnij is opstarten (jo moatte de ûnthâld-kaartmodus apart inisjalisearje), en twad kinne jo dit ûnthâld net "flashje" mei in bekende bootloader.

As gefolch, it waard besletten om te keppeljen alle koade yn QSPI, en flash it mei in sels-skreaune loader dat sil ûntfange de fereaske binary fia TFTP.

resultaat

It idee om dizze bibleteek nei Embox te portearjen ferskynde sawat in jier lyn, mar it waard hieltyd wer útsteld om ferskate redenen. Ien fan harren is stipe foar libstdc ++ en de standert sjabloanbibleteek. It probleem fan C++-stipe yn Embox is bûten it berik fan dit artikel, dus hjir sil ik allinich sizze dat wy dizze stipe yn it juste bedrach slagge om dizze bibleteek te wurkjen 🙂

Op it lêst waarden dizze problemen oerwûn (op syn minst genôch foar it OpenCV-foarbyld om te wurkjen), en it foarbyld rûn. It duorret 40 lange sekonden foar it boerd om grinzen te sykjen mei it Canny-filter. Dit is fansels te lang (d'r binne ôfwagings oer hoe't jo dizze saak kinne optimalisearje, it sil mooglik wêze om in apart artikel oer dit te skriuwen yn gefal fan sukses).

OpenCV op STM32F7-Discovery

It tuskendoel wie lykwols om in prototype te meitsjen dat de fûnemintele mooglikheid sil sjen litte om OpenCV op STM32 te rinnen, respektivelik, dit doel waard berikt, hoera!

tl;dr: stap foar stap ynstruksjes

0: Download Embbox-boarnen, lykas dit:

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

1: Litte wy begjinne mei it gearstallen fan in bootloader dy't in QSPI flash drive sil "flash".

    make confload-arm/stm32f7cube

No moatte jo it netwurk konfigurearje, om't. Wy sille de ôfbylding uploade fia TFTP. Om it boerd en host IP-adressen yn te stellen, moatte jo de conf/rootfs/netwurk bewurkje.

Foarbyld fan konfiguraasje:

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 - hostadres fan wêrút de ôfbylding sil wurde laden, address - adres fan it bestjoer.

Dêrnei sammelje wy de bootloader:

    make

2: It gewoane laden fan 'e bootloader (sorry foar it wurdpunt) op it boerd - d'r is hjir neat spesifyk, jo moatte it dwaan lykas foar elke oare applikaasje foar STM32F7Discovery. As jo ​​​​net witte hoe't jo it moatte dwaan, kinne jo der oer lêze hjir.
3: In ôfbylding kompilearje mei in konfiguraasje foar OpenCV.

    make confload-platform/opencv/stm32f7discovery
    make

4: Extract út ELF seksjes wurde skreaun nei QSPI to 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

D'r is in skript yn 'e conf-map dat dit docht, dus jo kinne it útfiere

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

5: Mei help fan tftp, download qspi.bin.bin nei in QSPI flash drive. Op de host, om dit te dwaan, kopiearje qspi.bin nei de rootmap fan de tftp-tsjinner (meastentiids /srv/tftp/ of /var/lib/tftpboot/; pakketten foar de korrespondearjende tsjinner binne beskikber yn de meast populêre distribúsjes, meastal neamd tftpd of tftp-hpa, soms moatte jo dwaan systemctl start tftpd.service begjinne).

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

Op Embox (dus yn 'e bootloader), moatte jo it folgjende kommando útfiere (wy geane derfan út dat de tsjinner it adres 192.168.2.1 hat):

    embox> qspi_loader qspi.bin 192.168.2.1

6: mei kommando goto jo moatte "springe" yn QSPI ûnthâld. De spesifike lokaasje sil ferskille ôfhinklik fan hoe't de ôfbylding keppele is, jo kinne dit adres sjen mei it kommando mem 0x90000000 (it startadres past yn it twadde 32-bit wurd fan 'e ôfbylding); jo sille ek moatte flagge de stapel -s, it stackadres is op 0x90000000, foarbyld:

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

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

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

7: opsl

    embox> edges 20

en genietsje fan de 40-twadde grins sykje 🙂

As der wat mis giet - skriuw in probleem yn ús repository, of nei de mailinglist [e-post beskerme], of yn in reaksje hjir.

Boarne: www.habr.com

Add a comment