Saya adalah salah seorang pembangun sistem pengendalian
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
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.
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.
gambar asal
Keputusan
Berjalan pada STM32F7Discovery
Pada 32F746GDISCOVERY terdapat beberapa bahagian memori perkakasan yang boleh kita gunakan satu cara atau yang lain
- 320KiB RAM
- Denyar 1MiB untuk imej
- 8MiB SDRAM
- Denyar NAND 16MiB QSPI
- 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).
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
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
Sumber: www.habr.com