اكتشاف نقاط السمات (Feature Points)

الدرس المرئي 16 - اكتشاف نقاط السمات وتخزينها: https://singtown.com/learn/50021/

مقارنة بين مطابقة القوالب واكتشاف نقاط السمات:
  • تستخدم مطابقة القوالب (find_temolate) خوارزمية ncc، التي لا يمكنها مطابقة الأنماط إلا إذا كانت بنفس الحجم والزاوية تقريبًا مثل صورة القالب. القيود هنا كبيرة نسبيًا. إذا كان النمط المستهدف في مجال الرؤية أكبر أو أصغر قليلًا من صورة القالب، فقد لا تنجح المطابقة.

  • تُعد مطابقة القوالب مناسبة للحالات التي تكون فيها المسافة بين الكاميرا والجسم المستهدف ثابتة ولا تتطلب حركة ديناميكية. على سبيل المثال، فهي مناسبة للكشف عن أجسام محددة على خط التجميع، لكنها غير مناسبة لسيارة تتعقب كرة طائرة متحركة (لأن المسافة بين الكرة المتحركة والكاميرا متغيرة ديناميكيًا، وسيتغير حجم الكرة كما تراه الكاميرا، ولن يكون مطابقًا تمامًا لصورة القالب).

  • للمطابقة متعددة الزوايا ومتعددة الأحجام، يمكنك محاولة حفظ عدة قوالب واستخدام مطابقة القوالب المتعددة.

  • اكتشاف نقاط السمات (find_keypoint): عند بدء تشغيل البرنامج للتو، يستخرج الروتين الصورة الأولى كسمة للجسم المستهدف، ويقوم kpts1 بحفظ سمة الجسم المستهدف. بشكل افتراضي، سيتم مطابقة عدة مقاييس وزوايا من السمة المستهدفة، بدلًا من حفظ حجم وزاوية واحدة فقط للسمة المستهدفة. وهذا أكثر مرونة من مطابقة القوالب، ولا يحتاج إلى حفظ عدة صور قوالب كما في مطابقة القوالب المتعددة.

  • يمكن أيضًا لاكتشاف نقاط السمات حفظ سمات الجسم المستهدف مسبقًا. لم يكن هذا موصى به سابقًا لأن التداخل الناتج عن الإضاءة المحيطة وأسباب أخرى قد يؤدي إلى اختلاف السمات في كل مرة يتم فيها تشغيل البرنامج تحت إضاءة مختلفة، مما يقلل من درجة المطابقة. ومع ذلك، في أحدث إصدار من البرامج الثابتة (firmware)، تمت إضافة إمكانية ضبط التعريض الضوئي وتوازن اللون الأبيض وقيمة الكسب التلقائي. يمكن تحديد قيمة التعريض الضوئي وقيمة توازن اللون الأبيض يدويًا، مما يقلل نسبيًا من تداخل الإضاءة. يمكنك أيضًا تجربة حفظ سمات الجسم المستهدف مسبقًا.


اكتشاف نقاط السمات

هذا الروتين هو 09-feature-Detection-keypoints.py\ يستخدم هذا الروتين خوارزمية FAST/AGAST لاستخراج السمات وتتبع الهدف، ويدعم فقط الصور الرمادية (grayscale).

ملاحظة: سيعتبر هذا الروتين الجسم الذي يظهر خلال العشر ثوانٍ الأولى من تشغيل البرنامج كسمة مستهدفة. يرجى وضع الجسم المستهدف في وسط الكاميرا عند بدء تشغيل البرنامج حتى تظهر نقطة الزاوية المميزة (feature corner point)، مما يثبت أن السمة المستهدفة قد تم التعرف عليها وتسجيلها.

أثناء عملية المطابقة، إذا ظهرت علامة زائد (+) وإطار مستطيل على الشاشة، فهذا يثبت أن المطابقة قد نجحت

# روتين للكشف عن جسم محدد باستخدام نقاط السمات.
# اعرض جسمًا أمام الكاميرا، ثم شغّل هذا السكربت. سيتم استخراج مجموعة من نقاط
# المفصل مرة واحدة، ثم تتبعها في الإطارات التالية. إذا أردت مجموعة جديدة من نقاط المفصل، أعد تشغيل السكربت.
# ملاحظة: راجع الوثائق لضبط find_keypoints وmatch_keypoints.
import csi, time, image
csi0 = csi.CSI()

# إعادة تعيين المستشعر
csi0.reset()

# إعدادات المستشعر
csi0.framesize(csi.VGA)
csi0.window((320, 240))
csi0.pixformat(csi.GRAYSCALE)

csi0.snapshot(time = 2000)
csi0.auto_gain(False)

#رسم نقاط السمات
def draw_keypoints(img, kpts):
    if kpts:
        print(kpts)
        img.draw_keypoints(kpts)
        img = csi0.snapshot()
        time.sleep_ms(1000)

kpts1 = None
#kpts1 يحفظ سمات الجسم المستهدف، ويمكن استيراد السمات من ملف، لكن هذا غير موصى به.
#kpts1 = image.load_descriptor("/desc.orb")
#img = csi0.snapshot()
#draw_keypoints(img, kpts1)

clock = time.clock()

while (True):
    clock.tick()
    img = csi0.snapshot()
    if (kpts1 == None):
        #إذا كان البرنامج قد بدأ التشغيل للتو، استخرج الصورة الأولى كسمة للجسم المستهدف، ويقوم kpts1 بحفظ سمة الجسم المستهدف
        #بشكل افتراضي سيتم مطابقة عدة مقاييس لحجم السمة المستهدفة، وليس فقط الحجم الذي تم حفظ السمة المستهدفة به، وهذا أكثر مرونة من مطابقة القوالب.
        # ملاحظة: بشكل افتراضي، تُرجع find_keypoints نقاط سمات متعددة المقاييس مستخرجة من هرم الصور (image pyramid).
        kpts1 = img.find_keypoints(max_keypoints=150, threshold=10, scale_factor=1.2)
        #image.find_keypoints(roi=Auto, threshold=20, normalized=False, scale_factor=1.5, max_keypoints=100, corner_detector=CORNER_AGAST)
        #roi يمثل منطقة التعرف، وهو صف قيم (tuple) بالشكل (x,y,w,h)، ويكون افتراضيًا مطابقًا لحجم framesize.
        #threshold هي عتبة بين 0 و255، تُستخدم للتحكم في عدد نقاط الزوايا التي يتم اكتشافها. عند استخدام كاشف نقاط السمات الافتراضي AGAST، تكون هذه العتبة حوالي 20. وعند استخدام كاشف FAST، تكون العتبة حوالي 60~80. كلما انخفضت العتبة، زاد عدد نقاط الزوايا التي يتم الحصول عليها.
        #normalized هي قيمة منطقية (boolean)، افتراضيًا False، وتسمح بمطابقة عدة أحجام للسمة المستهدفة (أكثر مرونة من مطابقة القوالب بخوارزمية ncc). إذا تم ضبطها على True، يتم إيقاف النتائج متعددة المقاييس لاكتشاف نقاط السمات، وتتم المطابقة بحجم واحد فقط للسمة المستهدفة (مشابه لمطابقة القوالب)، لكن سرعة الحساب ستكون أسرع قليلًا.
        #scale_factor هو رقم عشري أكبر من 1.0. كلما زادت هذه القيمة، زادت سرعة الاكتشاف، لكن دقة المطابقة تنخفض. عادةً ما تكون القيمة المثلى بين 1.35 و1.5 تقريبًا.
        #max_keypoints هو الحد الأقصى لعدد نقاط السمات التي يمكن استخراجها من جسم واحد. إذا كان عدد نقاط سمات الجسم كبيرًا جدًا مما يتسبب في نفاد ذاكرة RAM، قلّل هذه القيمة.
        #corner_detector هي الخوارزمية المستخدمة في اكتشاف نقاط السمات، والافتراضية هي خوارزمية AGAST. خوارزمية FAST أسرع لكن دقتها أقل.
        draw_keypoints(img, kpts1)
        #رسم السمة المستهدفة في هذه اللحظة
    else:
        #عند المطابقة مع السمة المستهدفة الأولى، يتم ضبط normalized=True افتراضيًا، بحيث تتم المطابقة بحجم واحد فقط للسمة المستهدفة.
        # ملاحظة: عند استخراج نقاط السمات لمطابقة الواصف (descriptor) الأول، نستخدم normalized=True لاستخراج
        # نقاط السمات من المقياس الأول فقط، والتي ستطابق أحد المقاييس في الواصف الأول.
        kpts2 = img.find_keypoints(max_keypoints=150, threshold=10, normalized=True)
        #إذا تم اكتشاف الجسم ذي السمات
        if (kpts2):
            #مطابقة تشابه السمات الموجودة حاليًا مع السمة المستهدفة الأصلية
            match = image.match_descriptor(kpts1, kpts2, threshold=85)
            #image.match_descriptor(descritor0, descriptor1, threshold=70, filter_outliers=False)。تُرجع هذه الدالة كائن kptmatch.
            #عتبة threshold تحدد دقة المطابقة، وتُستخدم لتصفية المطابقات الملتبسة. كلما صغرت هذه القيمة، زادت الدقة. نطاق العتبة من 0 إلى 100، والقيمة الافتراضية 70
            #filter_outliers مغلقة افتراضيًا.

            #match.count هو العدد التقريبي لنقاط السمات المتطابقة بين kpt1 وkpt2.
            #إذا كانت أكبر من 10، فهذا يثبت أن السمتين متشابهتان وأن المطابقة ناجحة.
            if (match.count>10):
                # إذا كان لدينا n مطابقة "جيدة" على الأقل
                # ارسم المستطيل المحيط وعلامة الزائد.
                #ارسم علامة زائد وإطار مستطيل عند مركز السمة المستهدفة المطابَقة.
                img.draw_rectangle(match.rect)
                img.draw_cross((match.cx, match.cy), size=10)

            #match.theta هي زاوية دوران الجسم ذي السمات المطابَق بالنسبة إلى الجسم المستهدف.
            print(kpts2, "matched:%d dt:%d"%(match.count, match.theta))
            #لا يُنصح باستخدام draw_keypoints لرسم نقاط الزوايا المميزة.
            # ملاحظة: قم بإلغاء التعليق إذا أردت رسم نقاط السمات
            #img.draw_keypoints(kpts2, size=KEYPOINTS_SIZE, matched=True)

    # رسم معدل الإطارات (FPS)
    #طباعة معدل الإطارات.
    img.draw_string((0, 0), "FPS:%.2f"%(clock.fps()))

تأثير تشغيل البرنامج:

results matching ""

    No results matching ""