STM32F7-Discovery жүйесіндегі OpenCV

STM32F7-Discovery жүйесіндегі OpenCV Мен операциялық жүйені жасаушылардың бірімін Эмбокс, және осы мақалада мен STM32746G тақтасында OpenCV-ді қалай іске қосқаным туралы айтатын боламын.

Іздеу жүйесіне «STM32 тақтасында OpenCV» сияқты нәрсені терсеңіз, STM32 тақталарында немесе басқа микроконтроллерлерде осы кітапхананы пайдалануға қызығушылық танытатын бірнеше адамды таба аласыз.
Аты бойынша не қажет екенін көрсетуі керек бірнеше бейнелер бар, бірақ әдетте (мен көрген барлық бейнелерде) STM32 тақтасында камерадан тек сурет алынды және нәтиже экранда көрсетіледі, және кескінді өңдеудің өзі кәдімгі компьютерде немесе неғұрлым қуатты тақталарда (мысалы, Raspberry Pi) жасалды.

Неге қиын?

Іздеу сұрауларының танымалдылығы OpenCV компьютерлік көрудің ең танымал кітапханасы болуымен түсіндіріледі, яғни онымен көбірек әзірлеушілер таныс, ал микроконтроллерде жұмыс үстеліне дайын кодты іске қосу мүмкіндігі әзірлеу процесін айтарлықтай жеңілдетеді. Бірақ неге әлі күнге дейін бұл мәселені шешуге арналған танымал дайын рецепттер жоқ?

Кішкентай орамалдарда OpenCV қолдану мәселесі екі ерекшелікке байланысты:

  • Егер сіз кітапхананы ең аз модульдер жиынтығымен құрастырсаңыз, ол өте үлкен кодқа (бірнеше мегабайт нұсқаулар) байланысты бірдей STM32F7Discovery флэш-жадына (тіпті ОЖ-ны есепке алмағанда) сыймайды.
  • Кітапхананың өзі C++ тілінде жазылған, яғни
    • Оң орындалу уақытына қолдау қажет (ерекшеліктер, т.б.)
    • Әдетте ендірілген жүйелерге арналған ОЖ-да табылған LibC/Posix үшін аз қолдау – сізге стандартты плюс кітапхана және стандартты STL үлгі кітапханасы (вектор, т.б.) қажет.

Embox-қа тасымалдау

Әдеттегідей, кез келген бағдарламаларды операциялық жүйеге көшірмес бұрын оны әзірлеушілер ойлаған пішінде құруға тырысқан дұрыс. Біздің жағдайда бұл проблема жоқ - бастапқы кодты мына жерден табуға болады гитабе, кітапхана 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 включены в сборку и т.п.>

Келесі қадам - ​​кейбір мысалдарды орындау, жақсырақ әзірлеушілердің өздері ұсынған стандартты үлгілердің бірі. сіздің сайтыңызда. Мен таңдадым шекара детекторы canny.

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

Жиек детекторының нәтижесі қандай пішімде сақталатынын қысқаша түсіндіргеннен кейін біз кескінді аламыз.

STM32F7-Discovery жүйесіндегі OpenCV

түпнұсқа сурет

STM32F7-Discovery жүйесіндегі OpenCV

нәтиже

STM32F7Discovery жүйесінде жұмыс істейді

32F746GDISCOVERY құрылғысында біз қандай да бір жолмен пайдалана алатын бірнеше аппараттық жады бөлімдері бар.

  1. 320 КБ жедел жады
  2. Кескін үшін 1МБ жарқыл
  3. 8МБ SDRAM
  4. 16МБ QSPI NAND Flash
  5. microSD картасы ұясы

SD картасын кескіндерді сақтау үшін пайдалануға болады, бірақ минималды мысалды іске қосу контекстінде бұл өте пайдалы емес.
Дисплейдің рұқсаты 480×272, яғни кадр буферінің жады 522 бит тереңдікте 240 32 байт болады, яғни. бұл RAM өлшемінен үлкен, сондықтан фреймбуфер мен үйме (оның ішінде OpenCV үшін, кескіндер мен көмекші құрылымдар үшін деректерді сақтау үшін қажет) SDRAM-да, қалғанының бәрі (стектерге арналған жады және басқа жүйе қажеттіліктері) орналасады. ) жедел жадқа өтеді.

Егер STM32F7Discovery үшін минималды конфигурацияны алсақ (бүкіл желіні, барлық пәрмендерді шығарып тастаңыз, стектерді мүмкіндігінше кішірейтіңіз және т.б.) және мысалдармен OpenCV қоссаңыз, қажетті жад келесідей болады:

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

Қай бөлімдер қайда баратынын білмейтіндер үшін мен түсіндіремін: in .text и .rodata нұсқаулар мен тұрақтылар (шамамен айтқанда, тек оқуға арналған деректер) жатыр .data деректер өзгермелі, .bss «нөл» айнымалылар бар, олар, дегенмен, орынды қажет етеді (бұл бөлім ЖЖҚ-ға «өтеді».

Жақсы жаңалық сол .data/.bss сәйкес келуі керек, бірақ бірге .text Мәселе мынада, сурет үшін тек 1МБ жады бар. Шығуға болады .text мысалдағы суретті қараңыз және оны, мысалы, іске қосу кезінде SD картасынан жадқа оқыңыз, бірақ fruits.png салмағы шамамен 330 Кб, сондықтан бұл мәселені шешпейді: көпшілігі .text OpenCV кодынан тұрады.

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

Нәтижесінде QSPI-дегі барлық кодты байланыстыру және оны TFTP арқылы қажетті екілік файлды алатын өздігінен жазылған жүктеушімен жыпылықтау туралы шешім қабылданды.

нәтиже

Бұл кітапхананы Embox-қа көшіру идеясы шамамен бір жыл бұрын пайда болды, бірақ ол әртүрлі себептерге байланысты қайта-қайта кейінге қалдырылды. Олардың бірі libstdc++ және стандартты үлгі кітапханасын қолдау болып табылады. Embox-та C++ қолдау мәселесі осы мақаланың аясынан тыс, сондықтан мен бұл кітапхананың жұмыс істеуі үшін біз бұл қолдауға қажетті мөлшерде қол жеткізе алдық деп айта аламын 🙂

Соңында бұл мәселелер еңсерілді (кем дегенде OpenCV мысалының жұмыс істеуі үшін жеткілікті) және мысал орындалды. Тақтаға Canny сүзгісі арқылы шекараларды іздеуге 40 ұзақ секунд қажет. Бұл, әрине, тым ұзақ (бұл мәселені қалай оңтайландыруға болатыны туралы ойлар бар, сәтті болған жағдайда бұл туралы жеке мақала жазуға болады).

STM32F7-Discovery жүйесіндегі OpenCV

Дегенмен, аралық мақсат STM32-де OpenCV іске қосудың іргелі мүмкіндігін көрсететін прототипті жасау болды, сәйкесінше бұл мақсатқа қол жеткізілді, ура!

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: QSPI сайтына qspi.bin сайтына жазылатын ELF бөлімдерінен үзінді

    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.bin.bin файлын QSPI флэш-дискісіне жүктеп алыңыз. Бұл әрекетті орындау үшін хостта 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 секундтық шекараны іздеуден ләззат алыңыз 🙂

Егер бірдеңе дұрыс болмаса - мәселені жазыңыз біздің қойма, немесе тарату тізіміне [электрондық пошта қорғалған], немесе осы жерде түсініктемеде.

Ақпарат көзі: www.habr.com

пікір қалдыру