100_fps_ir_led_tracking.py

# هذا العمل مرخص بموجب ترخيص MIT.
# حقوق النشر (c) 2013-2023 OpenMV LLC. جميع الحقوق محفوظة.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# يوضح هذا المثال كيفية استخدام التحكم في نافذة القراءة لقراءة جزء صغير من
# مصفوفة بكسلات حساس الكاميرا بسرعة عالية جدًا وتحريك نافذة القراءة هذه.

# تم تصميم واختبار هذا المثال على كاميرا OpenMV Cam H7 Plus باستخدام حساس OV5640.

import csi
import time

EXPOSURE_MICROSECONDS = 1000
TRACKING_THRESHOLDS = [(128, 255)]  # عند خفض التعريض الضوئي فإنك تُعتّم كل شيء.

SEARCHING_RESOLUTION = csi.VGA
SEARCHING_AREA_THRESHOLD = 16
SEARCHING_PIXEL_THRESHOLD = SEARCHING_AREA_THRESHOLD

TRACKING_RESOLUTION = csi.QQVGA
TRACKING_AREA_THRESHOLD = 256
TRACKING_PIXEL_THRESHOLD = TRACKING_AREA_THRESHOLD

TRACKING_EDGE_TOLERANCE = 0.05  # يمكن للكتلة أن تتحرك بنسبة 5% بعيدًا عن المركز.

csi0 = csi.CSI()
csi0.reset()  # إعادة ضبط المستشعر وتهيئته.
csi0.pixformat(csi.GRAYSCALE)  # تعيين صيغة البكسل إلى GRAYSCALE
csi0.framesize(SEARCHING_RESOLUTION)
csi0.snapshot(time=1000)  # انتظر حتى تدخل الإعدادات حيز التنفيذ.
clock = time.clock()  # أنشئ كائن ساعة (clock) لتتبع معدل الإطارات (FPS).

csi0.auto_gain(False)  # أوقفها لأنها ستتذبذب.
csi0.auto_exposure(False, exposure_us=EXPOSURE_MICROSECONDS)
csi0.snapshot(time=1000)

# sensor_w وsensor_h هما عرض/ارتفاع البكسلات الخام لحساس الصورة (x/y تساوي 0 في البداية).
x, y, sensor_w, sensor_h = csi0.ioctl(csi.IOCTL_GET_READOUT_WINDOW)

while True:
    clock.tick()
    img = csi0.snapshot()

    # نحتاج إلى إيجاد جسم بالأشعة تحت الحمراء لتتبعه - من المرجح أن يكون ساطعًا جدًا.
    blobs = img.find_blobs(
        TRACKING_THRESHOLDS,
        area_threshold=SEARCHING_AREA_THRESHOLD,
        pixels_threshold=SEARCHING_PIXEL_THRESHOLD,
    )

    if len(blobs):
        most_dense_blob = max(blobs, key=lambda x: x.density)
        img.draw_rectangle(most_dense_blob.rect)

        def get_mapped_centroid(b):
            # بشكل افتراضي، يتم ضبط نافذة القراءة على كامل مصفوفة بكسلات الحساس مع x/y==0.
            # الدقة التي تراها تُنتج بأخذ البكسلات من نافذة القراءة على
            # الكاميرا. الموقع x/y نسبي إلى مركز الحساس.
            x, y, w, h = csi0.ioctl(csi.IOCTL_GET_READOUT_WINDOW)

            # سيحاول مشغّل الكاميرا التحجيم ليلائم أي دقة تمررها إلى أقصى
            # عرض/ارتفاع يلائم الحساس مع الحفاظ على نسبة الأبعاد.
            ratio = min(w / float(csi0.width()), h / float(csi0.height()))

            # إسناد cx() إلى مركز نافذة العرض ثم التحجيم إلى نافذة القراءة.
            mapped_cx = (b.cx - (csi0.width() / 2.0)) * ratio
            # بما أننا نحافظ على نسبة الأبعاد، فقد يكون هناك إزاحة في x.
            mapped_cx += (w - (csi0.width() * ratio)) / 2.0
            # إضافة إزاحتنا من مركز الحساس
            mapped_cx += x + (sensor_w / 2.0)

            # إسناد cy() إلى مركز نافذة العرض ثم التحجيم إلى نافذة القراءة.
            mapped_cy = (b.cy - (csi0.height() / 2.0)) * ratio
            # بما أننا نحافظ على نسبة الأبعاد، فقد يكون هناك إزاحة في y.
            mapped_cy += (h - (csi0.height() * ratio)) / 2.0
            # إضافة إزاحتنا من مركز الحساس
            mapped_cy += y + (sensor_h / 2.0)

            return (mapped_cx, mapped_cy)  # الموقع X/Y على مصفوفة الحساس.

        def center_on_blob(b, res):
            mapped_cx, mapped_cy = get_mapped_centroid(b)

            # التبديل إلى الدقة (إذا لم تتغير الدقة فلن يفعل هذا شيئًا).
            csi0.framesize(res)

            # بناء نافذة القراءة. x/y هما إزاحتان من المركز.
            x = int(mapped_cx - (sensor_w / 2.0))
            y = int(mapped_cy - (sensor_h / 2.0))
            w = csi0.width()
            h = csi0.height()

            # التركيز على مركز الثقل (centroid).
            csi0.ioctl(csi.IOCTL_SET_READOUT_WINDOW, (x, y, w, h))

            # التحقق مما إذا كنا نصل إلى الحافة.
            new_x, new_y, w, h = csi0.ioctl(csi.IOCTL_GET_READOUT_WINDOW)

            # يمكنك استخدام قيم الخطأ هذه لتشغيل محركات servo لتحريك الكاميرا إذا أردت.
            x_error = x - new_x
            y_error = y - new_y

            if x_error < 0:
                print("-X Limit Reached ", end="")
            if x_error > 0:
                print("+X Limit Reached ", end="")
            if y_error < 0:
                print("-Y Limit Reached ", end="")
            if y_error > 0:
                print("+Y Limit Reached ", end="")

        center_on_blob(most_dense_blob, TRACKING_RESOLUTION)

        # ستقوم هذه الحلقة بتتبع الكتلة بسرعة قراءة أعلى بكثير ودقة أقل.
        while True:
            clock.tick()
            img = csi0.snapshot()

            # إيجاد الكتلة في الصورة ذات الدقة الأقل.
            blobs = img.find_blobs(
                TRACKING_THRESHOLDS,
                area_threshold=TRACKING_AREA_THRESHOLD,
                pixels_threshold=TRACKING_PIXEL_THRESHOLD,
            )

            # إذا فقدنا الكتلة فيجب علينا إيجاد كتلة جديدة.
            if not len(blobs):
                # إعادة ضبط الدقة.
                csi0.framesize(SEARCHING_RESOLUTION)
                csi0.ioctl(csi.IOCTL_SET_READOUT_WINDOW, (sensor_w, sensor_h))
                break

            # تضييق قائمة الكتل وتظليل الكتلة.
            most_dense_blob = max(blobs, key=lambda x: x.density)
            img.draw_rectangle(most_dense_blob.rect)

            print(
                clock.fps(), "BLOB cx:%d, cy:%d" % get_mapped_centroid(most_dense_blob)
            )

            x_diff = most_dense_blob.cx - (csi0.width() / 2.0)
            y_diff = most_dense_blob.cy - (csi0.height() / 2.0)

            w_threshold = (csi0.width() / 2.0) * TRACKING_EDGE_TOLERANCE
            h_threshold = (csi0.height() / 2.0) * TRACKING_EDGE_TOLERANCE

            # إعادة التوسيط على الكتلة إذا بدأت بالخروج عن مجال الرؤية (يكلّف ذلك معدل الإطارات).
            if abs(x_diff) > w_threshold or abs(y_diff) > h_threshold:
                center_on_blob(most_dense_blob, TRACKING_RESOLUTION)

    print(clock.fps())

results matching ""

    No results matching ""