OpenCV á STM32F7-Discovery

OpenCV á STM32F7-Discovery Ég er einn af þróunaraðilum stýrikerfisins Embox, og í þessari grein mun ég tala um hvernig mér tókst að keyra OpenCV á STM32746G borðinu.

Ef þú slærð eitthvað eins og „OpenCV á STM32 borð“ inn í leitarvél geturðu fundið töluvert af fólki sem hefur áhuga á að nota þetta bókasafn á STM32 borðum eða öðrum örstýringum.
Það eru nokkur myndbönd sem, af nafninu að dæma, ættu að sýna hvað þarf, en venjulega (í öllum myndböndum sem ég sá) á STM32 borðinu barst aðeins myndin frá myndavélinni og niðurstaðan birtist á skjánum, og sjálf myndvinnslan fór fram annað hvort á venjulegri tölvu, eða á öflugri töflum (til dæmis Raspberry Pi).

Hvers vegna er það erfitt?

Vinsældir leitarfyrirspurna skýrast af því að OpenCV er vinsælasta tölvusjónasafnið, sem þýðir að fleiri forritarar kannast við það og hæfileikinn til að keyra skrifborðs-tilbúinn kóða á örstýringu einfaldar þróunarferlið til muna. En hvers vegna eru enn engar vinsælar tilbúnar uppskriftir til að leysa þetta vandamál?

Vandamálið við að nota OpenCV á litlum sjölum tengist tveimur eiginleikum:

  • Ef þú setur saman bókasafnið, jafnvel með lágmarks sett af einingum, mun það einfaldlega ekki passa inn í flassminni sama STM32F7Discovery (jafnvel án þess að taka tillit til stýrikerfisins) vegna mjög stórs kóða (nokkrir megabæti af leiðbeiningum)
  • Bókasafnið sjálft er skrifað í C++, sem þýðir
    • Þarftu stuðning fyrir jákvæðan keyrslutíma (undantekningar osfrv.)
    • Lítill stuðningur við LibC/Posix, sem venjulega er að finna í stýrikerfi fyrir innbyggð kerfi - þú þarft staðlað plús bókasafn og staðlað STL sniðmát bókasafn (vektor osfrv.)

Flutningur í Embox

Eins og venjulega, áður en einhver forrit eru flutt yfir í stýrikerfið, er gott að reyna að byggja það í því formi sem forritararnir ætluðu það. Í okkar tilviki eru engin vandamál með þetta - frumkóðann er að finna á github, bókasafnið er byggt undir GNU/Linux með venjulegu cmake.

Góðu fréttirnar eru þær að OpenCV er hægt að byggja upp sem kyrrstætt bókasafn úr kassanum, sem gerir flutning auðveldari. Við söfnum bókasafni með stöðluðum stillingum og sjáum hversu mikið pláss þau taka. Hverri einingu er safnað á sérstakt bókasafn.

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

Eins og þú sérð á síðustu línu taka .bss og .data ekki mikið pláss en kóðinn er meira en 70 MiB. Það er ljóst að ef þetta er statískt tengt tilteknu forriti mun kóðinn minnka.

Við skulum reyna að henda út eins mörgum einingum og mögulegt er svo að lágmarksdæmi sé sett saman (sem til dæmis mun einfaldlega gefa út OpenCV útgáfuna), svo við lítum cmake .. -LA og slökktu á öllu sem slekkur á valkostunum.

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

Annars vegar er þetta aðeins ein eining bókasafnsins, hins vegar er þetta án hagræðingar þýðanda fyrir kóðastærð (-Os). ~3 MiB af kóða er enn frekar mikið, en gefur nú þegar von um árangur.

Keyra í emulator

Það er miklu auðveldara að kemba á keppinautnum, svo fyrst vertu viss um að safnið virki á qemu. Sem líkja eftir vettvangi valdi ég Integrator / CP, vegna þess að í fyrsta lagi er það líka ARM og í öðru lagi styður Embox grafíkúttak fyrir þennan vettvang.

Embox er með kerfi til að byggja utanaðkomandi bókasöfn, með því að nota það bætum við OpenCV sem einingu (staðfestum alla sömu valkostina fyrir "lágmarks" byggingu í formi kyrrstæðra bókasöfna), eftir það bæti ég við einföldu forriti sem lítur svona út:

version.cpp:

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

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

    return 0;
}

Við setjum kerfið saman, keyrum það - við fáum væntanlega framleiðslu.

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

Næsta skref er að keyra eitthvert dæmi, helst eitt af þeim stöðluðu sem verktaki sjálfir bjóða upp á. á síðunni þinni. ég valdi landamæraskynjari canny.

Dæmið þurfti að endurskrifa örlítið til að birta myndina með niðurstöðunni beint í ramma biðminni. Ég varð að gera þetta, vegna þess. virka imshow() getur teiknað myndir í gegnum QT, GTK og Windows viðmótin, sem auðvitað verða örugglega ekki í stillingum fyrir STM32. Reyndar er líka hægt að keyra QT á STM32F7Discovery, en það verður fjallað um það í annarri grein 🙂

Eftir stutta útskýringu á hvaða sniði niðurstaða kantskynjarans er geymd fáum við mynd.

OpenCV á STM32F7-Discovery

upprunalega mynd

OpenCV á STM32F7-Discovery

Niðurstaðan

Keyrir á STM32F7Discovery

Á 32F746GDISCOVERY eru nokkrir vélbúnaðarminnishlutar sem við getum notað á einn eða annan hátt

  1. 320KiB vinnsluminni
  2. 1MiB flass fyrir mynd
  3. 8MiB SDRAM
  4. 16MiB QSPI NAND Flash
  5. microSD kortarauf

SD kort er hægt að nota til að geyma myndir, en í samhengi við að keyra lágmarksdæmi er þetta ekki mjög gagnlegt.
Skjárinn er með 480×272 upplausn sem þýðir að framebuffer minni verður 522 bæti á 240 bita dýpi, þ.e. þetta er meira en stærð vinnsluminni, þannig að framebuffer og haugurinn (sem verður krafist, þar á meðal fyrir OpenCV, til að geyma gögn fyrir myndir og aukabyggingar) verða staðsettir í SDRAM, allt annað (minni fyrir stafla og aðrar kerfisþarfir) ) fer í vinnsluminni.

Ef við tökum lágmarksstillingar fyrir STM32F7Discovery (hendum út öllu netinu, öllum skipunum, gerum stafla eins litla og mögulegt er, o.s.frv.) og bætum við OpenCV með dæmum þar, þá verður nauðsynlegt minni sem hér segir:

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

Fyrir þá sem eru ekki mjög kunnugir hvaða hlutar fara hvar, mun ég útskýra: í .text и .rodata leiðbeiningar og fastar (í grófum dráttum, skrifvarið gögn) liggja í .data gögnin eru breytileg, .bss það eru "núllaðar" breytur, sem engu að síður þurfa stað (þessi hluti mun "fara" í vinnsluminni).

Góðu fréttirnar eru þær .data/.bss ætti að passa, en með .text vandamálið er að það er aðeins 1MiB af minni fyrir myndina. Má henda út .text myndina úr dæminu og lestu hana til dæmis af SD-kortinu í minni við ræsingu, en fruits.png vegur um 330KiB, þannig að þetta leysir ekki vandamálið: flestir .text samanstendur af OpenCV kóðanum.

Í stórum dráttum er aðeins eitt eftir - að hlaða hluta af kóðanum á QSPI flass (það er með sérstakan aðgerðarmáta til að kortleggja minni á kerfisrútuna, þannig að örgjörvinn getur nálgast þessi gögn beint). Í þessu tilviki kemur upp vandamál: í fyrsta lagi er minni QSPI glampi drifs ekki tiltækt strax eftir að tækið er endurræst (þú þarft að frumstilla sérstaklega minniskortaða stillingu), og í öðru lagi geturðu ekki „flashað“ þetta minni með kunnuglegt ræsiforrit.

Í kjölfarið var ákveðið að tengja allan kóðann í QSPI, og flakka honum með sjálfskrifaðan hleðslutæki sem mun taka á móti tilskildum binary í gegnum TFTP.

Niðurstaðan

Hugmyndin um að flytja þetta bókasafn yfir á Embox kom upp fyrir um ári síðan, en aftur og aftur var því frestað af ýmsum ástæðum. Einn þeirra er stuðningur við libstdc++ og venjulegt sniðmátasafn. Vandamálið við C++ stuðning í Embox er utan gildissviðs þessarar greinar, svo hér mun ég aðeins segja að okkur tókst að ná þessum stuðningi í réttu magni til að þetta bókasafn virki 🙂

Á endanum tókst að sigrast á þessum vandamálum (að minnsta kosti nóg til að OpenCV dæmið virkaði), og dæmið rann upp. Það tekur 40 langar sekúndur fyrir borðið að leita að mörkum með Canny síunni. Þetta er auðvitað of langt (það eru hugleiðingar um hvernig eigi að hagræða þessu máli, það verður hægt að skrifa sérstaka grein um þetta ef vel tekst til).

OpenCV á STM32F7-Discovery

Hins vegar var millimarkmiðið að búa til frumgerð sem mun sýna þann grundvallarmöguleika að keyra OpenCV á STM32, í sömu röð, þessu markmiði var náð, húrra!

tl;dr: skref fyrir skref leiðbeiningar

0: Sæktu Embbox heimildir, eins og þetta:

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

1: Byrjum á því að setja saman ræsiforrit sem mun „flassa“ QSPI glampi drif.

    make confload-arm/stm32f7cube

Nú þarftu að stilla netið, því. Við munum hlaða upp myndinni í gegnum TFTP. Til að stilla töfluna og hýsingar IP tölurnar þarftu að breyta conf/rootfs/netinu.

Dæmi um stillingar:

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 - hýsingarfang þaðan sem myndin verður hlaðin, address - heimilisfang stjórnar.

Eftir það söfnum við ræsiforritinu:

    make

2: Venjuleg hleðsla á ræsiforritinu (afsakið orðaleikinn) á borðið - það er ekkert sérstakt hér, þú þarft að gera það eins og fyrir öll önnur forrit fyrir STM32F7Discovery. Ef þú veist ekki hvernig á að gera það geturðu lesið um það hér.
3: Að setja saman mynd með stillingu fyrir OpenCV.

    make confload-platform/opencv/stm32f7discovery
    make

4: Útdráttur úr ELF köflum sem á að skrifa til QSPI til 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

Það er handrit í conf möppunni sem gerir þetta, svo þú getur keyrt það

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

5: Notaðu tftp til að hlaða niður qspi.bin.bin á QSPI glampi drif. Til að gera þetta, afritaðu qspi.bin í rótarmöppuna á tftp þjóninum (venjulega /srv/tftp/ eða /var/lib/tftpboot/; pakkar fyrir samsvarandi miðlara eru fáanlegir í vinsælustu dreifingum, venjulega kallaðir tftpd eða tftp-hpa, stundum þarf að gera systemctl start tftpd.service að byrja).

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

Í Embbox (þ.e. í ræsiforritinu) þarftu að framkvæma eftirfarandi skipun (við gerum ráð fyrir að þjónninn hafi heimilisfangið 192.168.2.1):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Með skipun goto þú þarft að "hoppa" inn í QSPI minni. Tiltekin staðsetning er breytileg eftir því hvernig myndin er tengd, þú getur séð þetta heimilisfang með skipuninni mem 0x90000000 (upphafsfangið passar í annað 32-bita orð myndarinnar); þú þarft líka að flagga staflanum -s, heimilisfang stafla er 0x90000000, dæmi:

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

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

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

7: Ræst

    embox> edges 20

og njóttu 40 sekúndna landamæraleitar 🙂

Ef eitthvað fer úrskeiðis - skrifaðu mál inn geymsluna okkar, eða á póstlistann [netvarið], eða í athugasemd hér.

Heimild: www.habr.com

Bæta við athugasemd