بناء خبير الرؤية (OCR) بـ C++ الخالص
في هذه المرحلة، حققنا إنجازاً معمارياً مهماً: قمنا ببناء خط معالجة رؤية حاسوبية (Computer Vision Pipeline) متكامل بـ C++ الخالص، دون الاعتماد على مكتبات ضخمة مثل OpenCV أو Python.
كيف يعمل خط المعالجة (Pipeline)؟
بدلاً من الاعتماد على بيئات جاهزة، بنينا الخطوة تلو الأخرى داخل pz_vision_engine_wrapper.cpp:
- فك التشفير (Decoding): استخدمنا مكتبة
stb_image.hالخفيفة جداً (ملف واحد) لتحويل بايتات الصورة القادمة من Rust إلى مصفوفة بكسلات RGB خام في الذاكرة. - تغيير الحجم (Resizing): برمجنا خوارزمية Bilinear Interpolation يدوية لتغيير ارتفاع الصورة إلى 48 بكسل (المقاس المعياري لنموذج PaddleOCR) مع الحفاظ على نسبة العرض إلى الارتفاع ديناميكياً.
- التطبيع (Normalization): قمنا بتحويل البكسلات من
0-255إلى نطاق-1.0إلى1.0لتتناسب مع أوزان الشبكة العصبية. - التشغيل (Inference): مررنا المصفوفة الجاهزة إلى محرك ONNX Runtime (v1.21).
- فك التشفير النهائي (CTC Decoding): المحرك يُعيد مصفوفة احتمالات (مثلاً
[1, 16, 749]). برمجنا خوارزمية CTC Greedy Decoder لترجمة أعلى الاحتمالات إلى أحرف عربية، مع تجاهل الـ Blank Tokens والتكرارات المتتالية.
لماذا هذا الإنجاز مهم؟
- أداء فائق السرعة (Bare-metal speed): لا يوجد أي overhead قادم من استدعاءات Python أو مكتبات معالجة الصور الضخمة.
- استقلالية تامة (Self-contained): المشروع لا يعتمد إلا على
libonnxruntime.so، مما يجعله جاهزاً للتضمين في أي بيئة دون الحاجة لبيئات افتراضية (Virtual Environments). - كفاءة الذاكرة: نتحكم تماماً بمتى يتم حجز وتحرير الذاكرة عبر
OrtAllocator.
الخطوة التالية
تم تشغيل المحرك بنجاح دون أي انهيار (Crash-free) وأخرج مصفوفة الأبعاد الصحيحة. الخطوة القادمة هي ضبط أرقام الفهارس (Index Mapping) في القاموس، حيث اكتشفنا أن نموذج PaddleOCR يضع الـ Blank Token في نهاية القاموس وليس بدايته.