OpenCV pada STM32F7-Discovery

OpenCV pada STM32F7-Discovery Saya adalah salah seorang pembangun sistem pengendalian Embox, dan dalam artikel ini saya akan bercakap tentang bagaimana saya berjaya menjalankan OpenCV pada papan STM32746G.

Jika anda menaip sesuatu seperti "OpenCV pada papan STM32" ke dalam enjin carian, anda boleh menemui beberapa orang yang berminat untuk menggunakan pustaka ini pada papan STM32 atau mikropengawal lain.
Terdapat beberapa video yang, berdasarkan nama, harus menunjukkan apa yang diperlukan, tetapi biasanya (dalam semua video yang saya lihat) pada papan STM32, hanya imej yang diterima daripada kamera dan hasilnya dipaparkan pada skrin, dan pemprosesan imej itu sendiri dilakukan sama ada pada komputer biasa, atau pada papan yang lebih berkuasa (contohnya, Raspberry Pi).

Mengapa sukar?

Populariti pertanyaan carian dijelaskan oleh fakta bahawa OpenCV ialah perpustakaan penglihatan komputer yang paling popular, yang bermaksud bahawa lebih ramai pembangun sudah biasa dengannya, dan keupayaan untuk menjalankan kod sedia desktop pada mikropengawal sangat memudahkan proses pembangunan. Tetapi mengapa masih tiada resipi siap sedia yang popular untuk menyelesaikan masalah ini?

Masalah menggunakan OpenCV pada selendang kecil adalah berkaitan dengan dua ciri:

  • Jika anda menyusun perpustakaan walaupun dengan set modul yang minimum, ia tidak akan masuk ke dalam memori kilat STM32F7Discovery yang sama (walaupun tanpa mengambil kira OS) kerana kod yang sangat besar (beberapa megabait arahan)
  • Perpustakaan itu sendiri ditulis dalam C++, yang bermaksud
    • Perlukan sokongan untuk masa jalan yang positif (pengecualian, dll.)
    • Sedikit sokongan untuk LibC/Posix, yang biasanya terdapat dalam OS untuk sistem terbenam - anda memerlukan perpustakaan tambah standard dan perpustakaan templat STL standard (vektor, dsb.)

Memindahkan ke Embox

Seperti biasa, sebelum mengalihkan sebarang program ke sistem pengendalian, adalah idea yang baik untuk cuba membinanya dalam bentuk yang dituju oleh pembangun. Dalam kes kami, tiada masalah dengan ini - kod sumber boleh didapati di github, perpustakaan dibina di bawah GNU/Linux dengan cmake biasa.

Berita baiknya ialah OpenCV boleh dibina sebagai perpustakaan statik di luar kotak, yang memudahkan pemindahan. Kami mengumpulkan perpustakaan dengan konfigurasi standard dan melihat berapa banyak ruang yang mereka gunakan. Setiap modul dikumpulkan dalam perpustakaan yang berasingan.

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

Seperti yang anda lihat dari baris terakhir, .bss dan .data tidak mengambil banyak ruang, tetapi kodnya melebihi 70 MiB. Adalah jelas bahawa jika ini dikaitkan secara statik kepada aplikasi tertentu, kod akan menjadi kurang.

Mari cuba buang seberapa banyak modul yang mungkin supaya contoh minimum dipasang (yang, sebagai contoh, hanya akan mengeluarkan versi OpenCV), jadi kita lihat cmake .. -LA dan matikan dalam pilihan semua yang dimatikan.

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

Di satu pihak, ini hanya satu modul perpustakaan, sebaliknya, ini tanpa pengoptimuman pengkompil untuk saiz kod (-Os). ~3 MiB kod masih agak banyak, tetapi sudah memberi harapan untuk berjaya.

Jalankan dalam emulator

Adalah lebih mudah untuk nyahpepijat pada emulator, jadi pastikan dahulu perpustakaan berfungsi pada qemu. Sebagai platform yang dicontohi, saya memilih Integrator / CP, kerana pertama, ia juga ARM, dan kedua, Embox menyokong output grafik untuk platform ini.

Embox mempunyai mekanisme untuk membina perpustakaan luaran, menggunakannya kami menambah OpenCV sebagai modul (melepasi semua pilihan yang sama untuk binaan "minimum" dalam bentuk perpustakaan statik), selepas itu saya menambah aplikasi mudah yang kelihatan seperti ini:

version.cpp:

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

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

    return 0;
}

Kami memasang sistem, menjalankannya - kami mendapat output yang diharapkan.

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

Langkah seterusnya ialah menjalankan beberapa contoh, sebaik-baiknya salah satu daripada yang standard yang ditawarkan oleh pembangun sendiri. di tapak anda. saya telah memilih pengesan sempadan cerdik.

Contoh itu perlu ditulis semula sedikit untuk memaparkan imej dengan hasilnya terus dalam penimbal bingkai. Saya terpaksa melakukan ini, kerana. fungsi imshow() boleh melukis imej melalui antara muka QT, GTK dan Windows, yang, sudah tentu, pasti tidak akan berada dalam konfigurasi untuk STM32. Malah, QT juga boleh dijalankan pada STM32F7Discovery, tetapi ini akan dibincangkan dalam artikel lain πŸ™‚

Selepas penjelasan singkat dalam format mana hasil pengesan tepi disimpan, kami mendapat imej.

OpenCV pada STM32F7-Discovery

gambar asal

OpenCV pada STM32F7-Discovery

Keputusan

Berjalan pada STM32F7Discovery

Pada 32F746GDISCOVERY terdapat beberapa bahagian memori perkakasan yang boleh kita gunakan satu cara atau yang lain

  1. 320KiB RAM
  2. Denyar 1MiB untuk imej
  3. 8MiB SDRAM
  4. Denyar NAND 16MiB QSPI
  5. slot kad mikroSD

Kad SD boleh digunakan untuk menyimpan imej, tetapi dalam konteks menjalankan contoh minimum, ini tidak begitu berguna.
Paparan mempunyai resolusi 480 Γ— 272, yang bermaksud bahawa memori framebuffer akan menjadi 522 bait pada kedalaman 240 bit, i.e. ini lebih daripada saiz RAM, jadi framebuffer dan timbunan (yang akan diperlukan, termasuk untuk OpenCV, untuk menyimpan data untuk imej dan struktur tambahan) akan ditempatkan dalam SDRAM, segala-galanya (memori untuk tindanan dan keperluan sistem lain ) akan pergi ke RAM .

Jika kita mengambil konfigurasi minimum untuk STM32F7Discovery (buang seluruh rangkaian, semua arahan, buat susunan sekecil mungkin, dsb.) dan tambah OpenCV dengan contoh di sana, memori yang diperlukan adalah seperti berikut:

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

Bagi mereka yang tidak begitu biasa dengan bahagian mana yang pergi ke mana, saya akan menerangkan: dalam .text ΠΈ .rodata arahan dan pemalar (secara kasarnya, data baca sahaja) terletak .data data boleh berubah, .bss terdapat pembolehubah "nulled", yang, bagaimanapun, memerlukan tempat (bahagian ini akan "pergi" ke RAM).

Berita baiknya ialah .data/.bss sepatutnya sesuai, tetapi dengan .text masalahnya ialah hanya terdapat 1MiB memori untuk imej. Boleh dibuang .text gambar dari contoh dan bacanya, sebagai contoh, dari kad SD ke dalam memori semasa permulaan, tetapi fruits.png mempunyai berat kira-kira 330KiB, jadi ini tidak akan menyelesaikan masalah: kebanyakan .text terdiri daripada kod OpenCV.

Pada umumnya, hanya ada satu perkara yang tinggal - memuatkan sebahagian kod pada denyar QSPI (ia mempunyai mod operasi khas untuk memetakan memori ke bas sistem, supaya pemproses boleh mengakses data ini secara langsung). Dalam kes ini, masalah timbul: pertama, memori pemacu denyar QSPI tidak tersedia serta-merta selepas peranti dibut semula (anda perlu memulakan secara berasingan mod dipetakan memori), dan kedua, anda tidak boleh "mengelapkan" memori ini dengan pemuat but biasa.

Akibatnya, ia telah memutuskan untuk memautkan semua kod dalam QSPI, dan memancarkannya dengan pemuat tulisan sendiri yang akan menerima binari yang diperlukan melalui TFTP.

Keputusan

Idea untuk memindahkan perpustakaan ini ke Embox muncul kira-kira setahun yang lalu, tetapi berulang kali ia ditangguhkan atas pelbagai sebab. Salah satunya ialah sokongan untuk libstdc++ dan perpustakaan templat standard. Masalah sokongan C++ dalam Embox adalah di luar skop artikel ini, jadi di sini saya hanya akan mengatakan bahawa kami berjaya mencapai sokongan ini dalam jumlah yang tepat untuk perpustakaan ini berfungsi πŸ™‚

Akhirnya, masalah ini dapat diatasi (sekurang-kurangnya cukup untuk contoh OpenCV berfungsi), dan contoh itu berjalan. Lembaga mengambil masa selama 40 saat untuk mencari sempadan menggunakan penapis Canny. Ini, sudah tentu, terlalu panjang (terdapat pertimbangan tentang cara mengoptimumkan perkara ini, mungkin untuk menulis artikel berasingan mengenai perkara ini sekiranya berjaya).

OpenCV pada STM32F7-Discovery

Walau bagaimanapun, matlamat perantaraan adalah untuk mencipta prototaip yang akan menunjukkan kemungkinan asas untuk menjalankan OpenCV pada STM32, masing-masing, matlamat ini telah dicapai, hooray!

tl;dr: arahan langkah demi langkah

0: Muat turun sumber Embox, seperti ini:

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

1: Mari kita mulakan dengan memasang pemuat but yang akan "berkelip" pemacu kilat QSPI.

    make confload-arm/stm32f7cube

Sekarang anda perlu mengkonfigurasi rangkaian, kerana. Kami akan memuat naik imej melalui TFTP. Untuk menetapkan alamat IP papan dan hos, anda perlu mengedit conf/rootfs/network.

Contoh konfigurasi:

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 - alamat hos dari mana imej akan dimuatkan, address - alamat lembaga.

Selepas itu, kami mengumpul pemuat but:

    make

2: Pemuatan biasa pemuat but (maaf untuk permainan kata-kata) pada papan - tiada apa-apa yang khusus di sini, anda perlu melakukannya seperti mana-mana aplikasi lain untuk STM32F7Discovery. Jika anda tidak tahu bagaimana untuk melakukannya, anda boleh membaca tentangnya di sini.
3: Menyusun imej dengan konfigurasi untuk OpenCV.

    make confload-platform/opencv/stm32f7discovery
    make

4: Ekstrak daripada bahagian ELF untuk ditulis ke QSPI ke 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

Terdapat skrip dalam direktori conf yang melakukan ini, jadi anda boleh menjalankannya

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

5: Menggunakan tftp, muat turun qspi.bin.bin ke pemacu kilat QSPI. Pada hos, untuk melakukan ini, salin qspi.bin ke folder akar pelayan tftp (biasanya /srv/tftp/ atau /var/lib/tftpboot/; pakej untuk pelayan yang sepadan tersedia dalam kebanyakan pengedaran popular, biasanya dipanggil tftpd atau tftp-hpa, kadangkala anda perlu lakukan systemctl start tftpd.service untuk mula).

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

Pada Embox (iaitu dalam pemuat but), anda perlu melaksanakan arahan berikut (kami menganggap bahawa pelayan mempunyai alamat 192.168.2.1):

    embox> qspi_loader qspi.bin 192.168.2.1

6: Dengan arahan goto anda perlu "melompat" ke dalam memori QSPI. Lokasi tertentu akan berbeza-beza bergantung pada cara imej dipautkan, anda boleh melihat alamat ini dengan arahan mem 0x90000000 (alamat mula sesuai dengan perkataan 32-bit kedua imej); anda juga perlu membenderakan timbunan -s, alamat tindanan adalah pada 0x90000000, contoh:

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

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

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

7: Pelancaran

    embox> edges 20

dan nikmati carian sempadan 40 saat πŸ™‚

Jika ada masalah - tulis isu dalam repositori kami, atau ke senarai mel [e-mel dilindungi], atau dalam ulasan di sini.

Sumber: www.habr.com

Tambah komen