hand_landmarks_single_hand.py
# هذا العمل مرخص بموجب ترخيص MIT.
# حقوق النشر (c) 2013-2025 لشركة OpenMV LLC. جميع الحقوق محفوظة.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# يوضح هذا المثال نموذج MediaPipe Hand Landmarks Detection من Google لاكتشاف معالم يد واحدة.
#
# ملاحظة: يتطلب هذا المثال كاميرا OpenMV مزودة بوحدة NPU مثل AE3 أو N6 للعمل في الوقت الفعلي.
import csi
import time
import ml
from ml.preprocessing import Normalization
from ml.postprocessing.mediapipe import BlazePalm
from ml.postprocessing.mediapipe import HandLandmarks
# تهيئة المستشعر.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
# يتطلب BlazePalm صورة مربعة للحصول على أفضل النتائج.
# يعمل HandLandmarks مع الصور غير المربعة الناتجة عن اقتصاصات BlazePalm.
csi0.window((400, 400))
# تحميل نموذج اكتشاف راحة اليد المدمج
palm_detection = ml.Model("/rom/palm_detection_full_192.tflite", postprocess=BlazePalm(threshold=0.4))
print(palm_detection)
# تحميل نموذج معالم اليد المدمج
hand_landmarks = ml.Model("/rom/hand_landmarks_full_224.tflite", postprocess=HandLandmarks(threshold=0.4))
print(hand_landmarks)
# خطوط الاتصال بين مفاصل اليد لرسم هيكل اليد.
hand_lines = ((0, 1), (1, 2), (2, 3), (3, 4), (0, 5), (5, 6), (6, 7), (7, 8),
(5, 9), (9, 10), (10, 11), (11, 12), (9, 13), (13, 14), (14, 15), (15, 16),
(13, 17), (17, 18), (18, 19), (19, 20), (0, 17))
# متغيرات التتبع.
n = None
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
if n is None:
# palms عبارة عن قائمة من الصفوف (tuples) بالشكل ((x, y, w, h), score, keypoints)
for r, score, keypoints in palm_detection.predict([img]):
# rect هو (x, y, w, h) - قم بتكبيره 3 أضعاف لنموذج معالم اليد
wider_rect = (r[0] - r[2], r[1] - r[3], r[2] * 3, r[3] * 3)
# التعامل فقط مع منطقة الاهتمام (ROI) الخاصة براحة اليد المكتشفة
n = Normalization(roi=wider_rect)
else:
# hands عبارة عن قائمة من الصفوف (tuples) بالشكل ((x, y, w, h), score, keypoints)
# الفهرس 0 (إن وُجد) هو اليد اليسرى
# الفهرس 1 (إن وُجد) هو اليد اليمنى
hands = hand_landmarks.predict([n(img)])
# لم يتم اكتشاف أي يد، أعد تهيئة المتتبع.
if not hands:
n = None
continue
# رسم مربعات إحاطة حول الأيدي المكتشفة والنقاط الرئيسية.
for i, detections in enumerate(hands):
for r, score, keypoints in detections:
ml.utils.draw_predictions(img, [r], ("right",) if i else ("left",), ((0, 0, 255),), format=None)
# keypoints: مصفوفة ndarray بحجم (21, 3) لمفاصل اليد (x, y, z)
# تتبع الفهارس اصطلاح MediaPipe:
# 0: الرسغ
# الإبهام: 1 cmc، 2 mcp، 3 ip، 4 tip
# السبابة: 5 mcp، 6 pip، 7 dip، 8 tip
# الوسطى: 9 mcp، 10 pip، 11 dip، 12 tip
# البنصر: 13 mcp، 14 pip، 15 dip، 16 tip
# الخنصر: 17 mcp، 18 pip، 19 dip، 20 tip
# (cmc=القاعدة، mcp=المفصل، pip=الوسط، dip=البعيد، ip=مفصل الإبهام، tip=طرف الإصبع)
ml.utils.draw_skeleton(img, keypoints, hand_lines, kp_color=(255, 0, 0), line_color=(0, 255, 0))
# توسيط new_wider_rect على اليد لأغراض التتبع
new_wider_rect = (r[0] + (r[2] // 2) - (wider_rect[2] // 2),
r[1] + (r[3] // 2) - (wider_rect[3] // 2),
wider_rect[2],
wider_rect[3])
# التعامل فقط مع منطقة الاهتمام (ROI) الخاصة باليد المكتشفة
n = Normalization(roi=new_wider_rect)
print(clock.fps(), "fps")