STM32F7-Discovery-da OpenCV

STM32F7-Discovery-da OpenCV Men operatsion tizimni ishlab chiquvchilardan biriman Embox, va ushbu maqolada men STM32746G platasida OpenCV-ni qanday ishga tushirganim haqida gapiraman.

Agar siz qidiruv tizimiga β€œSTM32 doskasida OpenCV” kabi biror narsani yozsangiz, STM32 platalarida yoki boshqa mikrokontrollerlarda ushbu kutubxonadan foydalanishga qiziqqan bir nechta odamni topishingiz mumkin.
Nomiga ko'ra, nima kerakligini ko'rsatishi kerak bo'lgan bir nechta videolar mavjud, lekin odatda (men ko'rgan barcha videolarda) STM32 platasida faqat kameradan tasvir olingan va natija ekranda ko'rsatilgan, va tasvirni qayta ishlashning o'zi oddiy kompyuterda yoki kuchliroq taxtalarda (masalan, Raspberry Pi) amalga oshirildi.

Nega qiyin?

Qidiruv so'rovlarining mashhurligi OpenCV kompyuterni ko'rishning eng mashhur kutubxonasi ekanligi bilan izohlanadi, ya'ni u bilan ko'proq ishlab chiquvchilar yaxshi tanish va mikrokontrollerda ish stoli uchun tayyor kodni ishga tushirish imkoniyati ishlab chiqish jarayonini sezilarli darajada osonlashtiradi. Lekin nima uchun bu muammoni hal qilish uchun hali ham mashhur tayyor retseptlar yo'q?

Kichkina ro'mollarda OpenCV dan foydalanish muammosi ikkita xususiyat bilan bog'liq:

  • Agar siz kutubxonani minimal modullar to'plami bilan kompilyatsiya qilsangiz, u juda katta kod (bir necha megabayt ko'rsatmalar) tufayli bir xil STM32F7Discovery flesh-xotirasiga (hatto OTni hisobga olmagan holda) mos kelmaydi.
  • Kutubxonaning o'zi C++ tilida yozilgan, ya'ni
    • Ijobiy ish vaqti uchun yordam kerak (istisnolar va boshqalar).
    • Odatda o'rnatilgan tizimlar uchun operatsion tizimda mavjud bo'lgan LibC/Posix uchun juda kam yordam - sizga standart plus kutubxonasi va standart STL shablon kutubxonasi (vektor va boshqalar) kerak.

Embox-ga ko'chirish

Odatdagidek, har qanday dasturni operatsion tizimga o'tkazishdan oldin, uni ishlab chiquvchilar mo'ljallangan shaklda yaratishga harakat qilish yaxshidir. Bizning holatda, bu bilan hech qanday muammo yo'q - manba kodini topish mumkin github, kutubxona odatiy cmake bilan GNU/Linux ostida qurilgan.

Yaxshi xabar shundaki, OpenCV qutidan tashqarida statik kutubxona sifatida yaratilishi mumkin, bu esa portlashni osonlashtiradi. Biz standart konfiguratsiyaga ega kutubxonani yig'amiz va ular qancha joy egallashini ko'ramiz. Har bir modul alohida kutubxonada to'plangan.

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

Oxirgi satrdan ko'rinib turibdiki, .bss va .data ko'p joy egallamaydi, lekin kod 70 MiB dan ortiq. Agar bu ma'lum bir dastur bilan statik ravishda bog'langan bo'lsa, kod kamroq bo'lishi aniq.

Minimal misol yig'ilishi uchun (masalan, OpenCV versiyasini chiqaradi) iloji boricha ko'proq modullarni tashlashga harakat qilaylik, shuning uchun biz ko'rib chiqamiz. cmake .. -LA va variantlarda o'chadigan hamma narsani o'chirib qo'ying.

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

Bir tomondan, bu kutubxonaning faqat bitta moduli, boshqa tomondan, bu kod hajmi uchun kompilyatorni optimallashtirishsiz (-Os). ~3 MiB kod hali ham juda ko'p, ammo muvaffaqiyatga umid qilmoqda.

Emulyatorda ishga tushiring

Emulyatorda disk raskadrovka qilish ancha oson, shuning uchun avval kutubxona qemu da ishlayotganiga ishonch hosil qiling. Emulyatsiya qilingan platforma sifatida men Integrator / CP ni tanladim, chunki birinchidan, bu ham ARM, ikkinchidan, Embox ushbu platforma uchun grafik chiqishni qo'llab-quvvatlaydi.

Embox-da tashqi kutubxonalarni yaratish mexanizmi mavjud, undan foydalanib, biz OpenCV-ni modul sifatida qo'shamiz (statik kutubxonalar ko'rinishidagi "minimal" qurish uchun bir xil variantlardan o'tib), shundan so'ng men shunday ko'rinadigan oddiy dasturni qo'shamiz:

version.cpp:

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

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

    return 0;
}

Biz tizimni yig'amiz, ishga tushiramiz - kutilgan natijani olamiz.

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

Keyingi qadam, ba'zi bir misolni, yaxshisi ishlab chiquvchilarning o'zlari tomonidan taklif qilingan standartlardan birini ishga tushirishdir. saytingizda. Men tanladim chegara detektori.

Natija bilan tasvirni to'g'ridan-to'g'ri ramka buferida ko'rsatish uchun misolni biroz qayta yozish kerak edi. Men buni qilishim kerak edi, chunki. funktsiyasi imshow() QT, GTK va Windows interfeyslari orqali tasvirlarni chizishi mumkin, bu, albatta, STM32 konfiguratsiyasida bo'lmaydi. Aslida, QT STM32F7Discovery-da ham ishlashi mumkin, ammo bu boshqa maqolada muhokama qilinadi πŸ™‚

Chek detektorining natijasi qaysi formatda saqlanganligini qisqacha aniqlagandan so'ng, biz tasvirni olamiz.

STM32F7-Discovery-da OpenCV

original rasm

STM32F7-Discovery-da OpenCV

natija

STM32F7Discovery tizimida ishlaydi

32F746GDISCOVERY-da biz u yoki bu tarzda foydalanishimiz mumkin bo'lgan bir nechta apparat xotira bo'limlari mavjud.

  1. 320 Kb RAM
  2. Tasvir uchun 1MiB flesh
  3. 8MiB SDRAM
  4. 16MiB QSPI NAND Flash
  5. microSD karta uyasi

Tasvirlarni saqlash uchun SD-kartadan foydalanish mumkin, ammo minimal misolni ishga tushirish kontekstida bu juda foydali emas.
Displey 480 Γ— 272 o'lchamga ega, ya'ni freymbufer xotirasi 522 bit chuqurlikda 240 32 bayt bo'ladi, ya'ni. bu RAM hajmidan kattaroqdir, shuning uchun ramka buferi va yig'ma (bu tasvirlar va yordamchi tuzilmalar uchun ma'lumotlarni saqlash uchun, shu jumladan OpenCV uchun kerak bo'ladi) SDRAMda joylashgan bo'ladi, qolgan hamma narsa (steklar va boshqa tizim ehtiyojlari uchun xotira) ) RAMga o'tadi.

Agar biz STM32F7Discovery uchun minimal konfiguratsiyani olsak (butun tarmoqni, barcha buyruqlarni chiqarib tashlash, steklarni iloji boricha kichikroq qilish va hokazo) va u erda misollar bilan OpenCV qo'shsak, kerakli xotira quyidagicha bo'ladi:

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

Qaysi bo'limlar qayerga borishini juda yaxshi bilmaganlar uchun men tushuntiraman: in .text ΠΈ .rodata ko'rsatmalar va konstantalar (taxminan aytganda, faqat o'qish uchun ma'lumotlar) yotadi .data ma'lumotlar o'zgaruvchan, .bss "nulled" o'zgaruvchilar mavjud, ular shunga qaramay, joy kerak (bu bo'lim RAMga "ketadi").

Yaxshi xabar shu .data/.bss mos kelishi kerak, lekin bilan .text muammo shundaki, tasvir uchun faqat 1MiB xotira mavjud. Chiqib ketish mumkin .text misoldagi rasmni o'qing va uni, masalan, ishga tushirish vaqtida SD-kartadan xotiraga o'qing, lekin fruits.png og'irligi taxminan 330KiB, shuning uchun bu muammoni hal qilmaydi: ko'pchilik .text OpenCV kodidan iborat.

Umuman olganda, faqat bitta narsa qoldi - kodning bir qismini QSPI chirog'iga yuklash (u protsessor ushbu ma'lumotlarga to'g'ridan-to'g'ri kirishi uchun xotirani tizim avtobusiga joylashtirish uchun maxsus ish rejimiga ega). Bunday holda, muammo yuzaga keladi: birinchidan, QSPI flesh-diskining xotirasi qurilma qayta ishga tushirilgandan so'ng darhol mavjud bo'lmaydi (siz xotira xaritasi rejimini alohida ishga tushirishingiz kerak), ikkinchidan, siz ushbu xotirani "flesh" qila olmaysiz. tanish bootloader.

Natijada, QSPI-dagi barcha kodlarni bog'lash va uni TFTP orqali kerakli ikkilik faylni oladigan o'z-o'zidan yozilgan yuklagich bilan o'chirishga qaror qilindi.

natija

Ushbu kutubxonani Embox-ga ko'chirish g'oyasi taxminan bir yil oldin paydo bo'lgan, biroq u turli sabablarga ko'ra qayta-qayta qoldirilgan. Ulardan biri libstdc++ va standart shablon kutubxonasini qo'llab-quvvatlashdir. Embox-da C++-ni qo'llab-quvvatlash muammosi ushbu maqola doirasidan tashqarida, shuning uchun bu erda men shuni aytamanki, biz ushbu kutubxona ishlashi uchun kerakli miqdorda ushbu yordamga erisha oldik πŸ™‚

Oxir-oqibat, bu muammolar bartaraf etildi (hech bo'lmaganda OpenCV misoli ishlashi uchun etarli) va misol ishga tushirildi. Kengashga Canny filtri yordamida chegaralarni qidirish uchun 40 uzoq soniya kerak bo'ladi. Bu, albatta, juda uzoq (bu masalani optimallashtirish bo'yicha fikrlar mavjud, muvaffaqiyatga erishgan taqdirda bu haqda alohida maqola yozish mumkin bo'ladi).

STM32F7-Discovery-da OpenCV

Biroq, oraliq maqsad STM32-da OpenCV-ni ishga tushirishning fundamental imkoniyatlarini ko'rsatadigan prototipni yaratish edi, mos ravishda bu maqsadga erishildi, afsus!

tl; dr: bosqichma-bosqich ko'rsatmalar

0: Embox manbalarini quyidagi kabi yuklab oling:

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

1: QSPI flesh-diskini "chaqnadi" bo'lgan yuklash moslamasini yig'ishdan boshlaylik.

    make confload-arm/stm32f7cube

Endi siz tarmoqni sozlashingiz kerak, chunki. Tasvirni TFTP orqali yuklaymiz. Kengash va xost IP manzillarini o'rnatish uchun siz conf/rootfs/tarmoqni tahrirlashingiz kerak.

Konfiguratsiyaga misol:

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 - rasm yuklanadigan xost manzili, address - kengashning manzili.

Shundan so'ng biz yuklovchini yig'amiz:

    make

2: Doskaga yuklash moslamasining odatiy yuklanishi (so'z uchun uzr) - bu erda aniq hech narsa yo'q, siz buni STM32F7Discovery uchun boshqa har qanday dastur kabi qilishingiz kerak. Agar buni qanday qilishni bilmasangiz, bu haqda o'qishingiz mumkin shu yerda.
3: OpenCV uchun konfiguratsiya bilan tasvirni kompilyatsiya qilish.

    make confload-platform/opencv/stm32f7discovery
    make

4: QSPI ga qspi.bin ga yoziladigan ELF bo'limlaridan ko'chirma

    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 katalogida buni bajaradigan skript mavjud, shuning uchun uni ishga tushirishingiz mumkin

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

5: tftp-dan foydalanib, qspi.bin.bin faylini QSPI flesh-diskiga yuklab oling. Buni amalga oshirish uchun xostda qspi.bin faylini tftp serverining ildiz papkasiga nusxalash (odatda /srv/tftp/ yoki /var/lib/tftpboot/; mos server uchun paketlar odatda deb ataladigan eng mashhur tarqatishlarda mavjud. tftpd yoki tftp-hpa, ba'zan qilish kerak systemctl start tftpd.service boshlamoq).

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

Embox-da (ya'ni yuklash moslamasida) siz quyidagi buyruqni bajarishingiz kerak (biz serverda 192.168.2.1 manzili bor deb taxmin qilamiz):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Buyruq bilan goto QSPI xotirasiga "sakrash" kerak. Muayyan joylashuv tasvirning qanday bog'langanligiga qarab o'zgaradi, siz ushbu manzilni buyruq bilan ko'rishingiz mumkin mem 0x90000000 (boshlang'ich manzil tasvirning ikkinchi 32 bitli so'ziga mos keladi); shuningdek, stekni belgilashingiz kerak bo'ladi -s, stek manzili 0x90000000 da, masalan:

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

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

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

7: ishga tushirish

    embox> edges 20

va 40 soniyalik chegara qidiruvidan rohatlaning πŸ™‚

Agar biror narsa noto'g'ri bo'lsa - muammoni yozing bizning omborimiz, yoki pochta ro'yxatiga [elektron pochta bilan himoyalangan], yoki bu yerda izohda.

Manba: www.habr.com

a Izoh qo'shish