STM32F7-Discovery боюнча OpenCV

STM32F7-Discovery боюнча OpenCV Мен операциялык системаны иштеп чыгуучулардын биримин Embox, жана бул макалада мен STM32746G тактасында OpenCVди кантип иштеткеним жөнүндө сүйлөшөм.

Эгерде сиз издөө системасына "STM32 тактасында OpenCV" сыяктуу нерсени терсеңиз, STM32 такталарында же башка микроконтроллерлерде бул китепкананы колдонууга кызыккан бир топ адамдарды таба аласыз.
Аты боюнча бир нече видеолор бар, алар эмне керек экенин көрсөтүшү керек, бирок адатта (мен көргөн бардык видеолордо) STM32 тактасында камерадан сүрөт гана алынып, натыйжасы экранда көрсөтүлгөн, жана сүрөттү иштетүүнүн өзү кадимки компьютерде, же күчтүүрөөк такталарда (мисалы, Raspberry Pi) жасалган.

Эмне үчүн кыйын?

Издөө сурамдарынын популярдуулугу OpenCV компьютердик көрүүнүн эң популярдуу китепканасы экендиги менен түшүндүрүлөт, бул аны менен көбүрөөк иштеп чыгуучулар жакшы билишет жана микроконтроллерде десктопко даяр кодду иштетүү мүмкүнчүлүгү иштеп чыгуу процессин абдан жөнөкөйлөтөт. Бирок эмне үчүн дагы эле бул көйгөйдү чечүү үчүн популярдуу даяр рецепттер жок?

Кичинекей жоолукчандарга OpenCV колдонуу маселеси эки өзгөчөлүккө байланыштуу:

  • Эгерде сиз китепкананы модулдардын минималдуу топтому менен түзсөңүз, анда ал өтө чоң коддон улам (бир нече мегабайт нускамалар) ошол эле STM32F7Discovery флэш эстутумуна туура келбейт (OSту эсепке албаганда да)
  • Китепкана өзү C++ тилинде жазылган, башкача айтканда
    • Оң иштөө убактысы үчүн колдоо керек (өзгөчө учурлар, ж.б.)
    • LibC/Posix үчүн аз колдоо, адатта орнотулган системалар үчүн OSде табылат - сизге стандарттуу плюс китепкана жана стандарттуу STL шаблон китепканасы (вектор ж.б.) керек.

Embox'ка өтүү

Адаттагыдай эле, кандайдыр бир программаларды операциялык системага көчүрүүдөн мурун, аны иштеп чыгуучулар каалаган формада түзүүгө аракет кылганыңыз жакшы. Биздин учурда, бул боюнча эч кандай көйгөйлөр жок - баштапкы кодун табууга болот github, китепкана GNU/Linux астында кадимки cmake менен курулган.

Жакшы жаңылык, OpenCV статикалык китепкана катары курулса болот, бул портингди жеңилдетет. Биз стандарттуу конфигурациялуу китепкананы чогултуп, алар канча орун ээлей турганын көрөбүз. Ар бир модул өзүнчө китепканада чогултулган.

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

Акыркы саптан көрүнүп тургандай, .bss жана .data көп орун ээлебейт, бирок код 70 МБ ашык. Бул белгилүү бир тиркеме менен статикалык байланышта болсо, код азыраак болуп калаары анык.

Минималдуу мисал чогултулгандай (мисалы, OpenCV версиясын чыгара турган) мүмкүн болушунча көп модулдарды ыргытканга аракет кылалы. cmake .. -LA жана параметрлерде өчүрүлгөн нерселердин баарын өчүрүңүз.

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

Бир жагынан алганда, бул китепкананын бир гана модулу, экинчи жагынан, бул коддун өлчөмү үчүн компиляторду оптималдаштыруусуз (-Os). ~3 МБ код дагы эле көп, бирок ийгиликке үмүт берет.

Эмулятордо иштетиңиз

Эмулятордо мүчүлүштүктөрдү оңдоо бир топ оңой, андыктан адегенде китепкана qemuда иштегенин текшериңиз. Эмуляцияланган платформа катары мен Integrator / CPти тандадым, анткени биринчиден, бул дагы ARM, экинчиден, Embox бул платформа үчүн графикалык чыгарууну колдойт.

Embox тышкы китепканаларды куруу механизмине ээ, аны колдонуу менен биз OpenCVди модул катары кошобуз (статикалык китепканалар түрүндөгү "минималдуу" куруу үчүн бирдей варианттардан өтүп), андан кийин мен төмөнкүдөй жөнөкөй тиркемени кошом:

version.cpp:

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

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

    return 0;
}

Биз системаны чогултабыз, аны иштетебиз - күтүлгөн натыйжаны алабыз.

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

Кийинки кадам - ​​иштеп чыгуучулардын өздөрү сунуштаган стандарттык үлгүлөрдүн бирин иштетүү. сиздин сайтта. Мен тандадым чек ара детектору.

Натыйжасы менен сүрөттү түздөн-түз кадр буферинде көрсөтүү үчүн мисалды бир аз кайра жазуу керек болчу. Мен муну кылышым керек болчу, анткени. функция imshow() QT, GTK жана Windows интерфейстери аркылуу сүрөттөрдү тарта алат, алар, албетте, STM32 конфигурациясында болбойт. Чынында, QT STM32F7Discoveryде да иштетилиши мүмкүн, бирок бул башка макалада талкууланат 🙂

Чет детекторунун натыйжасы кайсы форматта сакталганын кыскача тактоодон кийин биз сүрөт алабыз.

STM32F7-Discovery боюнча OpenCV

оригиналдуу сүрөт

STM32F7-Discovery боюнча OpenCV

жыйынтык

STM32F7Discoveryде иштеп жатат

32F746GDISCOVERYде биз тигил же бул жол менен колдоно турган бир нече аппараттык эстутум бөлүмдөрү бар

  1. 320KiB RAM
  2. Сүрөт үчүн 1МБ флеш
  3. 8МБ SDRAM
  4. 16MiB QSPI NAND Flash
  5. microSD карта уячасы

SD-картаны сүрөттөрдү сактоо үчүн колдонсо болот, бирок минималдуу мисалды иштетүү контекстинде бул абдан пайдалуу эмес.
Дисплей 480×272 резолюцияга ээ, бул фреймбуфердик эстутум 522 бит тереңдикте 240 32 байт болот, б.а. бул оперативдүү эстутумдун көлөмүнөн чоңураак, ошондуктан фреймбуфер жана үймөк (ошондой эле OpenCV үчүн, сүрөттөр жана көмөкчү структуралар үчүн маалыматтарды сактоо үчүн талап кылынат) SDRAMда, калганынын баары (стектер үчүн эс тутум жана башка система муктаждыктары үчүн) жайгашат. ) RAMга барат.

Эгерде биз STM32F7Discovery үчүн минималдуу конфигурацияны алсак (бүт тармакты, бардык буйруктарды чыгарып салыңыз, стектерди мүмкүн болушунча кичирейтиңиз ж.б.) жана ал жерде мисалдар менен OpenCV кошсок, талап кылынган эс тутум төмөнкүдөй болот:

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

Кайсы бөлүмдөр кайда барарын жакшы билбегендер үчүн мен түшүндүрөм: in .text и .rodata инструкциялар жана константалар (болжол менен айтканда, окуу үчүн гана маалыматтар) жатат .data маалыматтар өзгөрмө болуп саналат, .bss "нөл эмес" өзгөрмөлөр бар, бирок алар орунга муктаж (бул бөлүм RAMга "барат").

Жакшы кабар ошол .data/.bss туура келиши керек, бирок менен .text көйгөй сүрөт үчүн эстутум 1MiB гана бар экенинде. Чыгып салса болот .text мисалдагы сүрөттү жана аны окугула, мисалы, SD-картадан ишке киргизүүдө эстутумга, бирок fruits.png 330KiB салмакта, ошондуктан бул көйгөйдү чечпейт: көпчүлүк .text OpenCV кодунан турат.

Жалпысынан алганда, бир гана нерсе калды - коддун бир бөлүгүн QSPI жарыгына жүктөө (анын эстутумду тутумдук шинага түшүрүү үчүн иштөөнүн атайын режими бар, ошондуктан процессор бул маалыматтарга түздөн-түз кире алат). Бул учурда, көйгөй пайда болот: биринчиден, QSPI флэш-дискинин эс тутуму түзмөк кайра жүктөлгөндөн кийин дароо жеткиликтүү болбой калат (сиз эс тутум картасына түшүрүлгөн режимди өзүнчө инициализациялашыңыз керек), экинчиден, бул эстутумду "жарк эттире" албайсыз. тааныш жүктөгүч.

Натыйжада, QSPIдеги бардык кодду байланыштыруу жана аны TFTP аркылуу талап кылынган экиликти ала турган өз алдынча жазылган жүктөгүч менен жаркыруу чечими кабыл алынды.

жыйынтык

Бул китепкананы Embox'ка өткөрүү идеясы бир жыл мурун пайда болгон, бирок ар кандай себептерден улам кайра-кайра кийинкиге калтырылган. Алардын бири libstdc++ жана стандарттык шаблон китепканасын колдоо. Embox'тагы C++ колдоо маселеси бул макаланын алкагына кирбейт, ошондуктан мен бул китепкананын иштеши үчүн бул колдоого керектүү өлчөмдө жетише алдык деп гана айтам 🙂

Акыр-аягы, бул көйгөйлөр чечилди (жок дегенде OpenCV мисалы иштеши үчүн жетиштүү) жана мисал ишке ашты. Кенни чыпкасы аркылуу чек араларды издөө үчүн тактага 40 көп секунд талап кылынат. Бул, албетте, өтө узун (бул маселени кантип оптималдаштыруу боюнча ойлор бар, ийгиликке жеткен учурда бул тууралуу өзүнчө макала жазууга болот).

STM32F7-Discovery боюнча OpenCV

Бирок, ортодогу максат OpenCVди STM32де иштетүүнүн фундаменталдуу мүмкүнчүлүгүн көрсөтө турган прототибин түзүү болчу, тиешелүүлүгүнө жараша бул максатка жетишилди, ураа!

tl;dr: кадам-кадам нускамалар

0: Бул сыяктуу Embox булактарын жүктөп алыңыз:

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

1: Келгиле, QSPI флеш дискин "жарк эттире турган" жүктөгүчтү чогултуудан баштайлы.

    make confload-arm/stm32f7cube

Эми сиз тармакты конфигурациялашыңыз керек, анткени. Сүрөттү TFTP аркылуу жүктөйбүз. Тактаны жана хосттун IP даректерин коюу үчүн conf/rootfs/тармакты түзөтүшүңүз керек.

Конфигурациянын мисалы:

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 - сүрөт жүктөлө турган хосттун дареги, address - коллегиянын дареги.

Андан кийин биз жүктөгүчтү чогултабыз:

    make

2: Жүктөгүчтүн кадимкидей жүктөлүшү (сөз үчүн кечирим сурайм) - бул жерде конкреттүү эч нерсе жок, сиз муну STM32F7Discovery үчүн башка тиркемелердегидей кылышыңыз керек. Эгер муну кантип кылууну билбесеңиз, анда бул тууралуу окуй аласыз бул жерде.
3: OpenCV үчүн конфигурация менен сүрөттү түзүү.

    make confload-platform/opencv/stm32f7discovery
    make

4: ELF бөлүмдөрүнөн үзүндү QSPIге 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

conf каталогунда муну аткарган скрипт бар, андыктан аны иштете аласыз

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

5: tftp колдонуп, QSPI флеш-дискине qspi.bin.bin жүктөп алыңыз. Бул үчүн хостто qspi.bin файлын tftp серверинин түпкү папкасына көчүрүңүз (көбүнчө /srv/tftp/ же /var/lib/tftpboot/; тиешелүү сервер үчүн пакеттер көбүнчө деп аталган көпчүлүк популярдуу дистрибьюцияларда жеткиликтүү. tftpd же tftp-hpa, кээде эмне кылышыңыз керек systemctl start tftpd.service баштоо).

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

Embox'та (б.а. жүктөгүчтө) сиз төмөнкү буйрукту аткарышыңыз керек (серверде 192.168.2.1 дареги бар деп ойлойбуз):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Буйрук менен goto сиз QSPI эс тутумуна "секиришиңиз" керек. Белгилүү жайгашкан жер сүрөттүн кантип байланыштырылышына жараша өзгөрөт, сиз бул даректи буйрук менен көрө аласыз mem 0x90000000 (старт дареги сүрөттүн экинчи 32-бит сөзүнө туура келет); ошондой эле стекти белгилөө керек болот -s, стек дареги 0x90000000, мисалы:

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

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

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

7: Ишке киргизүү

    embox> edges 20

жана 40 секунддук чек ара издөөдөн ырахат алыңыз 🙂

Эгер бир нерсе туура эмес болуп калса - маселени жазыңыз биздин репозиторий, же почта тизмесине [электрондук почта корголгон], же бул жерде комментарийде.

Source: www.habr.com

Комментарий кошуу