OpenCV op STM32F7-Discovery

OpenCV op STM32F7-Discovery Ek is een van die ontwikkelaars van die bedryfstelsel Embos, en in hierdie artikel sal ek praat oor hoe ek daarin geslaag het om OpenCV op die STM32746G-bord te laat loop.

As jy iets soos β€œOpenCV op STM32-bord” in 'n soekenjin tik, kan jy heelwat mense vind wat belangstel om hierdie biblioteek op STM32-borde of ander mikrobeheerders te gebruik.
Daar is verskeie video's wat, te oordeel aan die naam, moet demonstreer wat nodig is, maar gewoonlik (in al die video's wat ek gesien het) op die STM32-bord is slegs die beeld van die kamera ontvang en die resultaat is op die skerm vertoon, en die beeldverwerking self is Γ³f op 'n gewone rekenaar Γ³f op kragtiger borde (byvoorbeeld Raspberry Pi) gedoen.

Waarom is dit moeilik?

Die gewildheid van soeknavrae word verklaar deur die feit dat OpenCV die gewildste rekenaarvisie-biblioteek is, wat beteken dat meer ontwikkelaars daarmee vertroud is, en die vermoΓ« om rekenaar-gereed-kode op 'n mikrobeheerder uit te voer, vergemaklik die ontwikkelingsproses aansienlik. Maar hoekom is daar nog geen gewilde klaargemaakte resepte om hierdie probleem op te los nie?

Die probleem om OpenCV op klein tjalies te gebruik, hou verband met twee kenmerke:

  • As jy die biblioteek saamstel, selfs met 'n minimale stel modules, sal dit eenvoudig nie in die flitsgeheue van dieselfde STM32F7Discovery pas nie (selfs sonder om die bedryfstelsel in ag te neem) as gevolg van 'n baie groot kode (verskeie megagrepe se instruksies)
  • Die biblioteek self is in C++ geskryf, wat beteken
    • Benodig ondersteuning vir positiewe looptyd (uitsonderings, ens.)
    • Min ondersteuning vir LibC/Posix, wat gewoonlik in OS vir ingebedde stelsels gevind word - jy benodig 'n standaard plus-biblioteek en 'n standaard STL-sjabloonbiblioteek (vektor, ens.)

Porteer na Embox

Soos gewoonlik, voordat enige programme na die bedryfstelsel oorgedra word, is dit 'n goeie idee om dit te probeer bou in die vorm waarin die ontwikkelaars dit bedoel het. In ons geval is daar geen probleme hiermee nie - die bronkode kan gevind word op github, is die biblioteek gebou onder GNU/Linux met die gewone cmake.

Die goeie nuus is dat OpenCV gebou kan word as 'n statiese biblioteek uit die boks, wat portering makliker maak. Ons versamel 'n biblioteek met 'n standaard konfigurasie en kyk hoeveel spasie hulle opneem. Elke module word in 'n aparte biblioteek versamel.

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

Soos jy op die laaste reΓ«l kan sien, neem .bss en .data nie veel spasie op nie, maar die kode is meer as 70 MiB. Dit is duidelik dat as dit staties aan 'n spesifieke toepassing gekoppel is, die kode minder sal word.

Kom ons probeer om soveel modules as moontlik uit te gooi sodat 'n minimale voorbeeld saamgestel word (wat byvoorbeeld bloot die OpenCV-weergawe sal uitvoer), so ons kyk cmake .. -LA en skakel alles wat afskakel in die opsies af.

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

Aan die een kant is dit slegs een module van die biblioteek, aan die ander kant is dit sonder samestelleroptimalisering vir kodegrootte (-Os). ~3 MiB kode is nogal baie, maar gee reeds hoop vir sukses.

Begin in die emulator

Dit is baie makliker om op die emulator te ontfout, so maak eers seker dat die biblioteek op qemu werk. As 'n nagebootste platform het ek Integrator / CP gekies, omdat eerstens is dit ook ARM, en tweedens ondersteun Embox grafiese uitset vir hierdie platform.

Embox het 'n meganisme om eksterne biblioteke te bou, deur dit te gebruik, voeg ons OpenCV as 'n module by (deur dieselfde opsies vir die "minimale" bou in die vorm van statiese biblioteke deur te gee), daarna voeg ek 'n eenvoudige toepassing by wat soos volg lyk:

version.cpp:

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

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

    return 0;
}

Ons stel die stelsel bymekaar, voer dit uit - ons kry die verwagte uitset.

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 Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ Π² сборку ΠΈ Ρ‚.ΠΏ.>

Die volgende stap is om 'n voorbeeld uit te voer, verkieslik een van die standaarde wat deur die ontwikkelaars self aangebied word. op jou webwerf. Ek het gekies grens detector canny.

Die voorbeeld moes effens herskryf word om die prent met die resultaat direk in die raambuffer te vertoon. Ek moes dit doen, want. funksie imshow() kan beelde teken deur die QT-, GTK- en Windows-koppelvlakke, wat natuurlik beslis nie in die konfigurasie vir STM32 sal wees nie. Trouens, QT kan ook op STM32F7Discovery uitgevoer word, maar dit sal in 'n ander artikel bespreek word πŸ™‚

Na 'n kort verduideliking in watter formaat die resultaat van die randdetektor gestoor word, kry ons 'n beeld.

OpenCV op STM32F7-Discovery

oorspronklike prentjie

OpenCV op STM32F7-Discovery

Gevolg

Werk op STM32F7Discovery

Op 32F746GDISCOVERY is daar verskeie hardeware geheue afdelings wat ons op een of ander manier kan gebruik

  1. 320KiB RAM
  2. 1MiB flits vir beeld
  3. 8 MB SDRAM
  4. 16MiB QSPI NAND-flits
  5. microSD-kaartgleuf

'n SD-kaart kan gebruik word om beelde te stoor, maar in die konteks van 'n minimale voorbeeld is dit nie baie nuttig nie.
Die skerm het 'n resolusie van 480Γ—272, wat beteken dat die raambuffergeheue 522 240 grepe op 'n diepte van 32 bisse sal wees, d.w.s. dit is meer as die grootte van RAM, so die raambuffer en die hoop (wat benodig sal word, insluitend vir OpenCV, om data vir beelde en hulpstrukture te stoor) sal in SDRAM geleΓ« wees, alles anders (geheue vir stapels en ander stelselbehoeftes) ) sal na RAM gaan.

As ons die minimum konfigurasie vir STM32F7Discovery neem (gooi die hele netwerk, alle opdragte uit, maak stapels so klein as moontlik, ens.) en voeg OpenCV met voorbeelde daar by, sal die vereiste geheue soos volg wees:

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

Vir diegene wat nie baie vertroud is met watter afdelings waarheen gaan nie, sal ek verduidelik: in .text ΠΈ .rodata instruksies en konstantes (grofweg gesproke, leesalleen-data) lΓͺ in .data die data is veranderlik, .bss daar is "nulle" veranderlikes, wat nietemin 'n plek benodig (hierdie afdeling sal na RAM "gaan").

Die goeie nuus is dat .data/.bss moet pas, maar met .text die probleem is dat daar net 1MiB geheue vir die beeld is. Kan uitgegooi word .text die prent uit die voorbeeld en lees dit, byvoorbeeld, vanaf die SD-kaart in die geheue by opstart, maar fruits.png weeg ongeveer 330KiB, so dit sal nie die probleem oplos nie: meeste .text bestaan ​​uit die OpenCV-kode.

Oor die algemeen is daar net een ding oor - laai 'n deel van die kode op 'n QSPI-flits (dit het 'n spesiale werkingsmodus om geheue na die stelselbus te karteer, sodat die verwerker direk toegang tot hierdie data kan kry). In hierdie geval ontstaan ​​'n probleem: eerstens, die geheue van 'n QSPI-flitsaandrywer is nie onmiddellik beskikbaar nadat die toestel herlaai is nie (jy moet die geheue-gekarteermodus afsonderlik inisialiseer), en tweedens kan jy nie hierdie geheue "flash" met 'n bekende selflaaiprogram.

As gevolg hiervan is besluit om al die kode in QSPI te koppel, en dit te flits met 'n selfgeskrewe laaier wat die vereiste binΓͺre via TFTP sal ontvang.

Gevolg

Die idee om hierdie biblioteek na Embox oor te dra het sowat 'n jaar gelede verskyn, maar dit is oor en oor uitgestel weens verskeie redes. Een daarvan is ondersteuning vir libstdc++ en die standaard sjabloonbiblioteek. Die probleem van C++-ondersteuning in Embox is buite die bestek van hierdie artikel, so hier sal ek net sΓͺ dat ons daarin geslaag het om hierdie ondersteuning in die regte hoeveelheid te bereik sodat hierdie biblioteek kan werk πŸ™‚

Op die ou end is hierdie probleme oorkom (ten minste genoeg vir die OpenCV-voorbeeld om te werk), en die voorbeeld het gehardloop. Dit neem 40 lang sekondes vir die bord om na grense te soek met die Canny-filter. Dit is natuurlik te lank (daar is oorwegings oor hoe om hierdie saak te optimaliseer, dit sal moontlik wees om 'n aparte artikel hieroor te skryf in geval van sukses).

OpenCV op STM32F7-Discovery

Die tussendoel was egter om 'n prototipe te skep wat die fundamentele moontlikheid sal wys om OpenCV onderskeidelik op STM32 te laat loop, hierdie doelwit is bereik, hoera!

tl;dr: stap vir stap instruksies

0: Laai Embbox-bronne af, soos hierdie:

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

1: Kom ons begin deur 'n selflaaiprogram saam te stel wat 'n QSPI-flitsskyf sal "flash".

    make confload-arm/stm32f7cube

Nou moet jy die netwerk instel, want. Ons sal die prent via TFTP oplaai. Om die bord en gasheer IP-adresse op te stel, moet jy die conf/rootfs/netwerk wysig.

Konfigurasie voorbeeld:

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 - gasheeradres van waar die prent gelaai sal word, address - adres van die raad.

Daarna versamel ons die selflaaiprogram:

    make

2: Die gewone laai van die selflaaiprogram (jammer vir die woordspeling) op die bord - daar is niks spesifiek hier nie, jy moet dit doen soos vir enige ander toepassing vir STM32F7Discovery. As jy nie weet hoe om dit te doen nie, kan jy daaroor lees hier.
3: Stel 'n prent saam met 'n konfigurasie vir OpenCV.

    make confload-platform/opencv/stm32f7discovery
    make

4: Uittreksel uit ELF-afdelings wat na QSPI na qspi.bin geskryf moet word

    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

Daar is 'n script in die conf-gids wat dit doen, sodat jy dit kan laat loop

    ./conf/qspi_objcopy.sh # НуТный Π±ΠΈΠ½Π°Ρ€Π½ΠΈΠΊ -- build/base/bin/qspi.bin

5: Gebruik tftp, laai qspi.bin.bin af na 'n QSPI-flitsskyf. Op die gasheer, om dit te doen, kopieer qspi.bin na die wortelgids van die tftp-bediener (gewoonlik /srv/tftp/ of /var/lib/tftpboot/; pakkette vir die ooreenstemmende bediener is beskikbaar in die meeste gewilde verspreidings, gewoonlik genoem tftpd of tftp-hpa, soms moet jy doen systemctl start tftpd.service om te begin).

    # Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ для tftpd
    sudo cp build/base/bin/qspi.bin /srv/tftp
    # Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ для tftp-hpa
    sudo cp build/base/bin/qspi.bin /var/lib/tftpboot

Op Embbox (d.w.s. in die selflaaiprogram), moet jy die volgende opdrag uitvoer (ons neem aan dat die bediener die adres 192.168.2.1 het):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Met bevel goto jy moet "spring" in QSPI geheue. Die spesifieke ligging sal wissel na gelang van hoe die beeld gekoppel is, jy kan hierdie adres met die opdrag sien mem 0x90000000 (die beginadres pas in die tweede 32-bis woord van die beeld); jy sal ook die stapel moet vlag -s, die stapeladres is by 0x90000000, byvoorbeeld:

    embox>mem 0x90000000
    0x90000000:     0x20023200  0x9000c27f  0x9000c275  0x9000c275
                      ↑           ↑
              это адрСс    это  адрСс 
                стэка        ΠΏΠ΅Ρ€Π²ΠΎΠΉ
                           инструкции

    embox>goto -i 0x9000c27f -s 0x20023200 # Π€Π»Π°Π³ -i Π½ΡƒΠΆΠ΅Π½ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡ€Π΅Ρ‚ΠΈΡ‚ΡŒ прСрывания Π²ΠΎ врСмя ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ систСмы

    < Начиная ΠΎΡ‚ΡΡŽΠ΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π²ΠΎΠ΄ Π½Π΅ Π·Π°Π³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊΠ°, Π° ΠΎΠ±Ρ€Π°Π·Π° с OpenCV >

7: Begin

    embox> edges 20

en geniet die grenssoektog van 40 sekondes πŸ™‚

As iets verkeerd loop - skryf 'n uitgawe in ons bewaarplek, of na die poslys [e-pos beskerm], of in 'n opmerking hier.

Bron: will.com

Voeg 'n opmerking