OpenCV STM32F7-Discovery-n

OpenCV STM32F7-Discovery-n Sistema eragilearen garatzaileetako bat naiz Embox, eta artikulu honetan STM32746G plakan OpenCV exekutatzeko nola lortu nuen hitz egingo dut.

Bilatzaile batean "OpenCV on STM32 board" bezalako zerbait idazten baduzu, liburutegi hau STM32 plaketan edo beste mikrokontrolagailuetan erabiltzeko interesa duten jende dezente aurki dezakezu.
Hainbat bideo daude, izenaren arabera, behar dena frogatu beharko luketenak, baina normalean (ikusi ditudan bideo guztietan) STM32 plakan, kameratik irudia bakarrik jasotzen zen eta emaitza pantailan bistaratzen zen, eta irudien tratamendua bera ordenagailu arrunt batean edo plaka indartsuagoetan egiten zen (adibidez, Raspberry Pi).

Zergatik da zaila?

Bilaketa-kontsulten ospea OpenCV ordenagailu bidezko ikusmenaren liburutegirik ezagunena izateak azaltzen du, hau da, garatzaile gehiagok ezagutzen dutela eta mikrokontrolagailu batean mahaigainerako prest dagoen kodea exekutatzeko gaitasunak asko errazten du garapen prozesua. Baina zergatik ez dago oraindik arazo hau konpontzeko prest dauden errezeta ezagunik?

Xal txikietan OpenCV erabiltzearen arazoa bi ezaugarrirekin lotuta dago:

  • Liburutegia konpilatzen baduzu modulu multzo minimo batekin ere, besterik gabe, ez da STM32F7Discovery beraren flash memorian sartuko (nahiz eta sistema eragilea kontuan hartu gabe) kode oso handia delako (hainbat megabyte jarraibide).
  • Liburutegia bera C++-n idatzita dago, hau da
    • Exekuzio-denbora positiboa lortzeko laguntza behar da (salbuespenak, etab.)
    • LibC/Posix-en laguntza gutxi, sistema txertatuetarako sistema eragilean aurkitu ohi dena; liburutegi estandar bat eta STL txantiloi liburutegi estandar bat behar dituzu (bektoreak, etab.)

Embox-era eramatea

Ohi bezala, edozein programa sistema eragilera eraman aurretik, komeni da garatzaileek nahi zuten moduan eraikitzen saiatzea. Gure kasuan, ez dago arazorik honekin - iturburu kodea helbidean aurki daiteke github, liburutegia GNU/Linux-en eraikita dago ohiko cmake-rekin.

Berri ona da OpenCV liburutegi estatiko gisa eraiki daitekeela kaxatik kanpo, eta horrek erraztu egiten du porturatzea. Konfigurazio estandarra duen liburutegi bat biltzen dugu eta zenbat leku hartzen duten ikusten dugu. Modulu bakoitza liburutegi bereizi batean biltzen da.

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

Azken lerroan ikusten denez, .bss eta .data-k ez dute leku handirik hartzen, baina kodea 70 MiB baino gehiagokoa da. Argi dago hau aplikazio zehatz bati estatikoki lotuta badago, kodea txikiagoa izango dela.

Saia gaitezen ahalik eta modulu gehien botatzen, gutxieneko adibide bat muntatzeko (adibidez, OpenCV bertsioa besterik gabe aterako dena), beraz, begiratuko dugu. cmake .. -LA eta itzali aukeretan itzaltzen dena.

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

Alde batetik, hau liburutegiko modulu bakarra da, bestetik, kodearen tamainarako konpiladorearen optimizaziorik gabe (-Os). ~3 MiB kode asko dira oraindik, baina arrakastarako itxaropena ematen du dagoeneko.

Exekutatu emuladorean

Askoz errazagoa da emuladorean araztea, beraz, lehenik eta behin ziurtatu liburutegiak qemu-n funtzionatzen duela. Plataforma emulatu gisa, Integrator / CP aukeratu nuen, zeren lehenik, ARM ere bada, eta, bigarrenik, Embox-ek plataforma honetarako irteera grafikoa onartzen du.

Embox-ek kanpoko liburutegiak eraikitzeko mekanismo bat du, hura erabiliz OpenCV gehitzen dugu modulu gisa (aukera berdinak eraikitzeko "minimoa" liburutegi estatikoen moduan pasatzen), ondoren aplikazio sinple bat gehitzen dut, itxura hau duena:

version.cpp:

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

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

    return 0;
}

Sistema muntatzen dugu, exekutatu - espero den irteera lortzen dugu.

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

Hurrengo urratsa adibideren bat exekutatzen da, hobe garatzaileek beraiek eskaintzen duten estandarren bat. zure webgunean. aukeratzen dut muga-detektagailua canny.

Adibidea apur bat berridatzi behar izan da emaitzarekin irudia zuzenean marko-bufferean bistaratzeko. Hau egin behar nuen, zeren. funtzioa imshow() QT, GTK eta Windows interfazeen bidez irudiak marraz ditzake, eta hori, noski, ez da STM32-ren konfigurazioan egongo. Izan ere, QT STM32F7Discovery-n ere exekutatu daiteke, baina hori beste artikulu batean eztabaidatuko da πŸ™‚

Ertz-detektagailuaren emaitza zein formatutan gordetzen den argitu ondoren, irudi bat lortzen dugu.

OpenCV STM32F7-Discovery-n

jatorrizko irudia

OpenCV STM32F7-Discovery-n

Emaitza

STM32F7Discovery-n exekutatzen

32F746GDISCOVERY-n hainbat hardware-memoria atal daude era batera edo bestera erabil ditzakegun

  1. 320 KiB RAM
  2. 1 MiB flash irudirako
  3. 8 MiB SDRAM
  4. 16 MiB QSPI NAND Flash
  5. microSD txartelaren zirrikitua

SD txartela irudiak gordetzeko erabil daiteke, baina gutxieneko adibide bat exekutatzeko testuinguruan, hau ez da oso erabilgarria.
Pantailak 480Γ—272ko bereizmena du, hau da, framebuffer memoria 522 byte izango da 240 biteko sakoneran, hau da. hau RAM-aren tamaina baino gehiago da, beraz, framebuffer-a eta heap (beharrezkoa izango dena, OpenCV-rako barne, irudien eta egitura laguntzaileen datuak gordetzeko) SDRAM-en kokatuko dira, gainerako guztia (piletarako memoria eta sistemaren behar beste ) RAMera joango da.

STM32F7Discovery-rako gutxieneko konfigurazioa hartzen badugu (sare osoa bota, komando guztiak, pilak ahalik eta txikienak egin, etab.) eta OpenCV gehitzen badugu bertan adibideekin, beharrezkoa den memoria hau izango da:

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

Zein atal nora doazen oso ezagutzen ez dutenentzat, azalduko dut: in .text ΠΈ .rodata argibideak eta konstanteak (gutxi gorabehera, irakurtzeko soilik datuak) daude .data datuak aldagarriak dira, .bss aldagai "nuled" daude, eta, hala ere, leku bat behar dute (atal hau RAMera "joango" da).

Berri ona hori da .data/.bss egokitu beharko luke, baina .text arazoa da irudirako 1MiB memoria baino ez dagoela. Bota daiteke .text adibideko irudia eta irakurri, adibidez, SD txarteletik memoriara abiaraztean, baina fruits.png-ek 330KiB inguru pisatzen du, beraz, honek ez du arazoa konponduko: gehienak .text OpenCV kodeaz osatuta dago.

Oro har, gauza bakarra geratzen da: kodearen zati bat QSPI flash batean kargatzea (memoria sistema-busari mapak egiteko funtzionamendu modu berezi bat du, prozesadoreak datu hauek zuzenean atzitzeko). Kasu honetan, arazo bat sortzen da: lehenik, QSPI flash drive baten memoria ez dago erabilgarri gailua berrabiarazi eta berehala (memoria mapatutako modua bereizita hasi behar duzu), eta, bigarrenik, ezin duzu memoria hau "flash" abiarazle ezagun bat.

Ondorioz, QSPIn kode guztia lotzea erabaki zen, eta TFTP bidez eskatutako bitarra jasoko duen norberak idatzitako kargatzaile batekin flasheatzea.

Emaitza

Liburutegi hau Emboxera eramateko ideia duela urtebete inguru agertu zen, baina behin eta berriz atzeratu zen hainbat arrazoirengatik. Horietako bat libstdc++ eta txantiloi liburutegi estandarra onartzen da. Embox-en C++ euskarriaren arazoa artikulu honen esparrutik kanpo dago, beraz, hemen bakarrik esango dut euskarri hori behar bezala lortzea lortu dugula liburutegi honek funtziona dezan πŸ™‚

Azkenean, arazo hauek gainditu ziren (OpenCV adibidea funtzionatzeko nahikoa behintzat), eta adibidea martxan jarri zen. 40 segundo luze behar ditu taulak Canny iragazkia erabiliz mugak bilatzeko. Hau, noski, luzeegia da (gai hau optimizatzeko gogoetak daude, posible izango da honi buruz aparteko artikulu bat idaztea arrakasta izanez gero).

OpenCV STM32F7-Discovery-n

Hala ere, tarteko helburua STM32n OpenCV exekutatzeko oinarrizko aukera erakutsiko duen prototipo bat sortzea zen, hurrenez hurren, helburu hori lortu zen, aupa!

tl;dr: urratsez urrats argibideak

0: Deskargatu Embbox iturriak, honela:

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

1: Has gaitezen QSPI flash drive bat "flash" egingo duen abio-kargatzailea muntatzen.

    make confload-arm/stm32f7cube

Orain sarea konfiguratu behar duzu, zeren. Irudia TFTP bidez igoko dugu. Taula eta ostalariaren IP helbideak ezartzeko, conf/rootfs/network editatu behar duzu.

Konfigurazio adibidea:

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 - irudia kargatuko den ostalari helbidea, address - Kontseiluaren helbidea.

Horren ostean, abio-kargatzailea biltzen dugu:

    make

2: Abio-kargatzailearen ohiko karga (barkatu hitz-jokoa) taulan - hemen ez dago ezer zehatzik, STM32F7Discovery-rako beste edozein aplikaziotarako bezala egin behar duzu. Ez badakizu nola egin, horri buruz irakur dezakezu Hemen.
3: OpenCVrako konfigurazio batekin irudi bat konpilatzea.

    make confload-platform/opencv/stm32f7discovery
    make

4: QSPI-n idatzi beharreko ELF ataletatik qspi.bin-era idatzi behar da

    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 direktorioan script bat dago hori egiten duena, exekutatu ahal izateko

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

5: Tftp erabiliz, deskargatu qspi.bin.bin QSPI flash drive batera. Ostalarian, horretarako, kopiatu qspi.bin tftp zerbitzariaren erroko karpetara (normalean /srv/tftp/ edo /var/lib/tftpboot/; dagokion zerbitzarirako paketeak eskuragarri daude banaketa ezagunenetan, normalean deitzen direnak). tftpd edo tftp-hpa, batzuetan egin behar duzu systemctl start tftpd.service hasteko).

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

Emboxen (hau da, abio-kargatzailean), hurrengo komandoa exekutatu behar duzu (zerbitzariak 192.168.2.1 helbidea duela suposatzen dugu):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Aginduarekin goto QSPI memoriara "jauzi" egin behar duzu. Kokapen zehatza irudia lotzen denaren arabera aldatuko da, helbide hau ikus dezakezu komandoarekin mem 0x90000000 (hasierako helbidea irudiaren bigarren 32 biteko hitzean sartzen da); pila markatu ere beharko duzu -s, pila helbidea 0x90000000-n dago, adibidez:

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

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

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

7: Abian jartzea

    embox> edges 20

eta gozatu 40 segundoko muga-bilaketaz πŸ™‚

Zerbait gaizki ateratzen bada, idatzi arazo bat gure biltegia, edo posta zerrendara [posta elektroniko bidez babestua], edo hemen iruzkin batean.

Iturria: www.habr.com

Gehitu iruzkin berria