میں آپریٹنگ سسٹم کے ڈویلپرز میں سے ایک ہوں۔
اگر آپ سرچ انجن میں "OpenCV on STM32 بورڈ" جیسی کوئی چیز ٹائپ کرتے ہیں، تو آپ کو بہت سے لوگ مل سکتے ہیں جو STM32 بورڈز یا دیگر مائیکرو کنٹرولرز پر اس لائبریری کو استعمال کرنے میں دلچسپی رکھتے ہیں۔
ایسی کئی ویڈیوز ہیں جن کے نام سے اندازہ لگاتے ہوئے یہ ظاہر کرنا چاہیے کہ کیا ضرورت ہے، لیکن عام طور پر (ان تمام ویڈیوز میں جو میں نے دیکھی ہیں) STM32 بورڈ پر، کیمرے سے صرف تصویر موصول ہوئی تھی اور نتیجہ اسکرین پر دکھایا گیا تھا، اور امیج پروسیسنگ بذات خود یا تو باقاعدہ کمپیوٹر پر، یا زیادہ طاقتور بورڈز (مثال کے طور پر، Raspberry Pi) پر کی گئی تھی۔
یہ مشکل کیوں ہے؟
تلاش کے سوالات کی مقبولیت کی وضاحت اس حقیقت سے ہوتی ہے کہ OpenCV کمپیوٹر وژن کی سب سے مشہور لائبریری ہے، جس کا مطلب ہے کہ زیادہ ڈویلپرز اس سے واقف ہیں، اور مائیکرو کنٹرولر پر ڈیسک ٹاپ کے لیے تیار کوڈ کو چلانے کی صلاحیت ترقی کے عمل کو بہت آسان بناتی ہے۔ لیکن اس مسئلے کو حل کرنے کے لئے ابھی تک کوئی مقبول تیار شدہ ترکیبیں کیوں نہیں ہیں؟
چھوٹی شالوں پر اوپن سی وی کے استعمال کا مسئلہ دو خصوصیات سے متعلق ہے:
- اگر آپ ماڈیولز کے کم سے کم سیٹ کے ساتھ بھی لائبریری کو مرتب کرتے ہیں، تو یہ ایک بہت بڑے کوڈ (کئی میگا بائٹس کی ہدایات) کی وجہ سے اسی STM32F7Discovery (یہاں تک کہ OS کو مدنظر رکھے بغیر) کی فلیش میموری میں فٹ نہیں ہو گی۔
- لائبریری خود C++ میں لکھی گئی ہے، جس کا مطلب ہے۔
- مثبت رن ٹائم کے لیے سپورٹ کی ضرورت ہے (استثناء، وغیرہ)
- LibC/Posix کے لیے بہت کم سپورٹ، جو عام طور پر ایمبیڈڈ سسٹمز کے لیے OS میں پایا جاتا ہے - آپ کو ایک معیاری پلس لائبریری اور ایک معیاری STL ٹیمپلیٹ لائبریری (ویکٹر، وغیرہ) کی ضرورت ہے۔
ایمباکس میں پورٹ کرنا
ہمیشہ کی طرح، کسی بھی پروگرام کو آپریٹنگ سسٹم میں پورٹ کرنے سے پہلے، اسے اس شکل میں بنانے کی کوشش کرنا ایک اچھا خیال ہے جس میں ڈویلپرز کا ارادہ تھا۔ ہمارے معاملے میں، اس کے ساتھ کوئی مسئلہ نہیں ہے - ماخذ کوڈ پر پایا جا سکتا ہے
اچھی خبر یہ ہے کہ اوپن سی وی کو باکس سے باہر ایک جامد لائبریری کے طور پر بنایا جا سکتا ہے، جو پورٹنگ کو آسان بناتا ہے۔ ہم ایک معیاری ترتیب کے ساتھ ایک لائبریری جمع کرتے ہیں اور دیکھتے ہیں کہ وہ کتنی جگہ لیتے ہیں۔ ہر ماڈیول کو ایک علیحدہ لائبریری میں جمع کیا جاتا ہے۔
> 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 MiB سے زیادہ ہے۔ یہ واضح ہے کہ اگر یہ کسی مخصوص ایپلیکیشن سے جامد طور پر منسلک ہے، تو کوڈ کم ہو جائے گا۔
آئیے زیادہ سے زیادہ ماڈیولز کو باہر پھینکنے کی کوشش کریں تاکہ ایک کم سے کم مثال جمع ہو جائے (جو، مثال کے طور پر، 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 MiB کوڈ ابھی بھی کافی ہے، لیکن پہلے ہی کامیابی کی امید دیتا ہے۔
ایمولیٹر میں چلائیں۔
ایمولیٹر پر ڈیبگ کرنا بہت آسان ہے، اس لیے پہلے یہ یقینی بنائیں کہ لائبریری qemu پر کام کرتی ہے۔ ایک نقلی پلیٹ فارم کے طور پر، میں نے انٹیگریٹر/CP کا انتخاب کیا، کیونکہ سب سے پہلے، یہ ARM بھی ہے، اور دوسرا، 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 اور ونڈوز انٹرفیس کے ذریعے تصاویر کھینچ سکتے ہیں، جو یقیناً STM32 کی ترتیب میں نہیں ہوں گے۔ درحقیقت، QT کو STM32F7Discovery پر بھی چلایا جا سکتا ہے، لیکن اس پر کسی اور مضمون میں بحث کی جائے گی 🙂
ایک مختصر وضاحت کے بعد جس فارمیٹ میں ایج ڈیٹیکٹر کا نتیجہ محفوظ کیا جاتا ہے، ہمیں ایک تصویر ملتی ہے۔
اصل تصویر
نتیجہ
STM32F7Discovery پر چل رہا ہے۔
32F746GDISCOVERY پر ہارڈویئر میموری کے کئی حصے ہیں جنہیں ہم کسی نہ کسی طریقے سے استعمال کر سکتے ہیں۔
- 320KiB ریم
- تصویر کے لیے 1MiB فلیش
- 8MiB SDRAM
- 16MiB QSPI NAND فلیش
- مائیکرو ایس ڈی کارڈ سلاٹ
تصاویر کو ذخیرہ کرنے کے لیے ایک 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
ان لوگوں کے لیے جو زیادہ واقف نہیں ہیں کہ کون سے حصے کہاں جاتے ہیں، میں وضاحت کروں گا: میں .text
и .rodata
ہدایات اور مستقل (تقریبا الفاظ میں، صرف پڑھنے والا ڈیٹا) موجود ہیں۔ .data
ڈیٹا متغیر ہے، .bss
وہاں "نیلڈ" متغیرات ہیں، جن کے باوجود، ایک جگہ کی ضرورت ہے (یہ سیکشن RAM میں "جائے گا")۔
اچھی خبر یہ ہے کہ .data
/.bss
فٹ ہونا چاہئے، لیکن ساتھ .text
مصیبت یہ ہے کہ تصویر کے لیے صرف 1MiB میموری ہے۔ باہر پھینکا جا سکتا ہے۔ .text
مثال سے تصویر لیں اور اسے پڑھیں، مثال کے طور پر، SD کارڈ سے سٹارٹ اپ میں میموری میں، لیکن fruits.png کا وزن تقریباً 330KiB ہے، اس لیے اس سے مسئلہ حل نہیں ہوگا: زیادہ تر .text
OpenCV کوڈ پر مشتمل ہے۔
مجموعی طور پر، صرف ایک چیز باقی ہے - کوڈ کا ایک حصہ QSPI فلیش پر لوڈ کرنا (اس میں سسٹم بس میں میموری کو میپ کرنے کے لیے آپریشن کا ایک خاص طریقہ ہے، تاکہ پروسیسر اس ڈیٹا تک براہ راست رسائی حاصل کر سکے)۔ اس صورت میں، ایک مسئلہ پیدا ہوتا ہے: سب سے پہلے، QSPI فلیش ڈرائیو کی میموری ڈیوائس کے ریبوٹ ہونے کے فوراً بعد دستیاب نہیں ہوتی ہے (آپ کو میموری میپڈ موڈ کو الگ سے شروع کرنے کی ضرورت ہے)، اور دوسری بات، آپ اس میموری کو "فلیش" نہیں کر سکتے۔ ایک مانوس بوٹ لوڈر۔
نتیجے کے طور پر، QSPI میں تمام کوڈ کو لنک کرنے کا فیصلہ کیا گیا، اور اسے خود تحریر کردہ لوڈر کے ساتھ فلیش کریں جو TFTP کے ذریعے مطلوبہ بائنری حاصل کرے گا۔
نتیجہ
اس لائبریری کو ایمباکس میں پورٹ کرنے کا خیال تقریباً ایک سال قبل سامنے آیا، لیکن بار بار اسے مختلف وجوہات کی بنا پر ملتوی کر دیا گیا۔ ان میں سے ایک libstdc++ اور معیاری ٹیمپلیٹ لائبریری کے لیے سپورٹ ہے۔ Embox میں C++ سپورٹ کا مسئلہ اس مضمون کے دائرہ کار سے باہر ہے، اس لیے یہاں میں صرف اتنا کہوں گا کہ ہم اس لائبریری کے کام کرنے کے لیے صحیح مقدار میں اس سپورٹ کو حاصل کرنے میں کامیاب ہوئے 🙂
آخر میں، ان مسائل پر قابو پا لیا گیا (کم از کم OpenCV مثال کے کام کرنے کے لیے کافی ہے)، اور مثال چل گئی۔ کینی فلٹر کا استعمال کرتے ہوئے بورڈ کو حدود تلاش کرنے میں 40 طویل سیکنڈ لگتے ہیں۔ یہ، یقیناً، بہت طویل ہے (اس معاملے کو بہتر بنانے کے طریقے پر غور کیا جا رہا ہے، کامیابی کی صورت میں اس بارے میں ایک الگ مضمون لکھنا ممکن ہو گا)۔
تاہم، درمیانی مقصد ایک پروٹو ٹائپ بنانا تھا جو بالترتیب STM32 پر OpenCV چلانے کے بنیادی امکان کو ظاہر کرے گا، یہ مقصد حاصل ہو گیا، ہورے!
tl؛ dr: قدم بہ قدم ہدایات
0: ایمباکس کے ذرائع کو ڈاؤن لوڈ کریں، اس طرح:
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: 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 سیکنڈ کی بارڈر سرچ سے لطف اندوز ہوں 🙂
اگر کچھ غلط ہو جاتا ہے تو - اس میں ایک مسئلہ لکھیں۔
ماخذ: www.habr.com