Би үйлдлийн систем хөгжүүлэгчдийн нэг
Хэрэв та хайлтын системд "STM32 самбар дээрх OpenCV" гэх мэт зүйлийг бичвэл STM32 самбар эсвэл бусад микроконтроллерууд дээр энэ номын санг ашиглах сонирхолтой цөөнгүй хүмүүсийг олох боломжтой.
Нэрийг нь харахад юу хэрэгтэй байгааг харуулах хэд хэдэн видео байдаг, гэхдээ ихэвчлэн (миний үзсэн бүх видеон дээр) STM32 самбар дээр зөвхөн камераас зөвхөн дүрсийг хүлээн авч, үр дүн нь дэлгэц дээр гарч ирдэг. зураг боловсруулах нь өөрөө ердийн компьютер эсвэл илүү хүчирхэг самбар дээр (жишээлбэл, Raspberry Pi) хийгдсэн.
Яагаад хэцүү байдаг вэ?
Хайлтын асуулгууд түгээмэл болсон нь OpenCV нь хамгийн алдартай компьютерийн харааны номын сан бөгөөд энэ нь илүү олон хөгжүүлэгчид үүнийг мэддэг, микроконтроллер дээр ширээний кодыг ажиллуулах чадвар нь хөгжүүлэлтийн процессыг ихээхэн хялбаршуулдаг гэсэн үг юм. Гэхдээ яагаад энэ асуудлыг шийдэх алдартай бэлэн жор байдаггүй вэ?
Жижиг ороолт дээр OpenCV ашиглах асуудал нь хоёр онцлогтой холбоотой.
- Хэрэв та номын санг хамгийн бага багц модультай ч гэсэн эмхэтгэсэн бол энэ нь маш том код (хэд хэдэн мегабайт заавар) тул ижил STM32F7Discovery-ийн флаш санах ойд (OS-ийг тооцохгүйгээр) багтахгүй болно.
- Номын сан нь өөрөө C++ хэл дээр бичигдсэн байдаг нь
- Эерэг ажиллах хугацаанд дэмжлэг хэрэгтэй (үл хамаарах зүйл гэх мэт)
- LibC/Posix-ийн дэмжлэг бага байдаг бөгөөд энэ нь ихэвчлэн суулгагдсан системд зориулсан үйлдлийн системд байдаг - танд стандарт нэмэх номын сан, стандарт STL загварын номын сан (вектор гэх мэт) хэрэгтэй.
Embox руу шилжүүлж байна
Ердийнх шигээ аливаа программыг үйлдлийн системд шилжүүлэхээс өмнө түүнийг хөгжүүлэгчдийн хүссэн хэлбэрээр бүтээхийг оролдох нь зүйтэй. Манай тохиолдолд үүнтэй холбоотой ямар ч асуудал байхгүй - эх кодыг эндээс олж болно
Сайн мэдээ гэвэл 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 дээр ажиллуулж болно, гэхдээ энэ талаар өөр нийтлэлд хэлэлцэх болно 🙂
Ирмэг илрүүлэгчийн үр дүн ямар форматаар хадгалагдаж байгааг товч тодруулсны дараа бид зураг авах болно.
анхны зураг
үр дүн
STM32F7Discovery дээр ажиллаж байна
32F746GDISCOVERY дээр бид ямар нэгэн байдлаар ашиглаж болох хэд хэдэн техник хангамжийн санах ойн хэсгүүд байдаг.
- 320 киб RAM
- Зургийн хувьд 1МБ флаш
- 8МБ SDRAM
- 16MiB QSPI NAND Flash
- microSD картны үүр
SD картыг зураг хадгалахад ашиглаж болох боловч хамгийн бага жишээ ажиллуулахын тулд энэ нь тийм ч ашигтай биш юм.
Дэлгэц нь 480 × 272 нягтралтай бөгөөд энэ нь фреймбуфер санах ой нь 522 битийн гүнд 240 байт байх болно гэсэн үг юм. Энэ нь RAM-ийн хэмжээнээс их байгаа тул фреймбуфер ба овоо (энэ нь 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
Асуудал нь зургийн хувьд ердөө 1МБ санах ой байгаа явдал юм. Шидэж болно .text
жишээн дээрх зургийг аваад, жишээлбэл, эхлүүлэх үед SD картаас санах ой руу уншаарай, гэхдээ fruits.png нь ойролцоогоор 330KiB жинтэй тул энэ нь асуудлыг шийдэхгүй: ихэнх нь .text
OpenCV кодоос бүрдэнэ.
Ерөнхийдөө ганц л зүйл үлдлээ - кодын нэг хэсгийг QSPI флэш дээр ачаалах (энэ нь санах ойг системийн автобусанд буулгах тусгай горимтой тул процессор энэ өгөгдөлд шууд хандах боломжтой). Энэ тохиолдолд асуудал гарч ирнэ: нэгдүгээрт, QSPI флаш дискний санах ойг төхөөрөмжийг дахин ачаалсны дараа шууд ашиглах боломжгүй (та санах ойн зураглалын горимыг тусад нь эхлүүлэх хэрэгтэй), хоёрдугаарт, та энэ санах ойг "анивчуулж" чадахгүй. танил ачаалагч.
Үүний үр дүнд QSPI дахь бүх кодыг холбож, TFTP-ээр дамжуулан шаардлагатай хоёртын файлыг хүлээн авах өөрөө бичсэн дуудагчаар анивчуулахаар шийдсэн.
үр дүн
Энэ номын санг Embox руу оруулах санаа жил орчмын өмнө гарч ирсэн ч янз бүрийн шалтгааны улмаас дахин дахин хойшилсон. Тэдний нэг нь libstdc++ болон стандарт загварын номын санд зориулсан дэмжлэг юм. Embox дахь C++-ийн дэмжлэгийн асуудал нь энэ нийтлэлийн хамрах хүрээнээс хэтэрсэн тул бид энэ номын сангийн ажиллахад шаардлагатай хэмжээгээр энэ дэмжлэгийг авч чадсан гэдгийг энд л хэлье 🙂
Эцэст нь эдгээр асуудлуудыг даван туулж (наад зах нь OpenCV жишээ ажиллахад хангалттай), жишээ нь ажиллав. Самбар Canny шүүлтүүр ашиглан хил хязгаарыг хайхад 40 урт секунд шаардлагатай. Энэ нь мэдээжийн хэрэг хэтэрхий урт байна (энэ асуудлыг хэрхэн оновчтой болгох талаар бодолтой байгаа бөгөөд амжилтанд хүрсэн тохиолдолд энэ талаар тусдаа нийтлэл бичих боломжтой болно).
Гэсэн хэдий ч завсрын зорилго нь 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/network-г засах хэрэгтэй.
Тохиргооны жишээ:
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