نقدم لكم في هذا المقال نظام ذكاء صنعي يسمح لنا بمراقبة عملية التباعد الاجتماعي بين الناس بشكل آلي من خلال معالجة الإطارات المتدفقة من الكاميرا .
بحسب الاحصائيات الصادرة عن منظمة الصحة العالمية فأن حصيلة فيروس كورونا اكثر من 6 مليون مصاب , وما يقارب 400 ألف حالة وفاة حيث تأثرت 213 دولة حتى الآن بهذا الفايروس القاتل .
والسبب الأكثر قلقاً ان فايروس كورونا قد ينتقل من شخص الى آخر من خلال المحادثات اذ كان الشخص الغير مصاب قريب جداً من الشخص المصاب . ونظراً لكثافة السكان في بعض المناطق فإن هذا يشكل تحدياً كبيراً في إيقاف انتشار هذا الفايروس .كل هذا فرض علينا نمط معين من الإجراءات لابد من اتباعها بالتالي احد أفضل الوسائل لإيقاف انتشار الفيروس هو التباعد الاجتماعي ” على الأقل حتى يتم ايجاد لقاح لذلك الفايروس “.
ما هي مسافة الأمان – Social distancing ؟
هي من أحد وأهم الإجراءات الواجب اتباعها في أوقات الأوبئة لمنع انتشار الأمراض المعدية , تعني أن الناس يجيب أن يبتعدوا بأجسادهم عن بعضهم البعض للحد من انتشار الامراض المعدية .
المحتويات :
1) مبدأ العام لعمل نموذج الـ Social Distancing .
2) المبدأ الخاص لعمل نموذج الـ Social Distancing .
3) مراحل تطور الخوارزميات المستخدمة في عملية الـ Object Detection .
Sliding Window (a.
R-CNN ( b.
Fast R-CNN ( c.
Faster R-CNN ( d.
Yolov3 ( e.
4) تنصيب الحزم المطلوبة .
5) الكود البرمجي الخاص بمشروع الـSocial Distancing .
6) مقطع يوضح نتيجة تنفيذ النموذج ( حيث تم تصوير هذا المقطع في كلية التربية في جامعة تشرين).
7) الملخص .
أولاً : مبدأ عمل نموذج الـ Social Distancing بشكل عام
1) اكتشاف الأشخاص في كل اطار من اطارات الفيديو باستخدام خوارزمية الـ YOLO فهي عبارة عن شبكة عصبونية التفافية قادرة على اكتشاف أغراض متعددة في الزمن الحقيقي بمرور واحد فقط وهي اختصار لـ ” You Look Only Once ” , في هذا النموذج سنقوم باستخدام الإصدار الثالث من هذه الخوارزمية بواسطة مكتبة Keras .
2) حساب المسافة بين كل شخص مع باقي الأشخاص الآخرين من خلال حساب المسافة بين مركزي مربعي الإطار Bounding box الخاصة بالشخصين المطلوب دراسة وضع التباعد الإجتماعي لهم .
3) تصنيف المسافة المحددة بين كل شخص مع باقي الأشخاص, اذا كانت المسافة قليلة بالتالي هذا الشخص في مرحلة الخطر وقد يتعرض للإصابة بالتالي يتم وضع إطار لونه أحمر حوله, اما اذا كانت المسافة كبيرة بالتالي هذا الشخص في مرحلة أمان ومنه يتم وضع إطار لونه أخضر حوله .
ثانياً : المبدأ الخاص لعمل نموذج ال Social Distancing
1) ليكن لدينا صورة مدخلة اما (ثابتة أو عبارة عن إطار من إطارات الفيديو ) .
2) تطبيق خوارزمية الـ object detection لأكتشاف جميع الأشياء الموجودة في الصورة ( انسان – سيارة – اشارة مرور ) , ثم نأخذ فقط الـ objects الذي يعبر عن المشاة من خلال رقم الـ class الخاص بالإنسان .
3) حساب المسافة بين مركزي الـ bounding box المتعلقة بكل شخصين في الصورة .
4) اختبار هذه المسافة بين كل شخصين , اذا كانت اقل من قيمة معينة ” يتم تحديدها في الكود ” بالتالي الشخصين لا يحققوا القواعد الصحية للتباعد الإجتماعي , أو اذا كانت المسافة أكبر بالتالي الشخصين يحققوا قواعد الصحية للتباعد الإجتماعي .
5) إظهار النتائج .
ثالثاً : مراحل تطور الخوارزميات المستخدمة في عملية الـ Object Detection
Sliding Window (a:
يُقصد بها النوافذ المتحركة , تعتبر الطريقة الأبسط لبناء نموذج يعمل على اكتشاف الكائنات , بحيث مبدأ عملها يعتمد على تقسيم الصورة لعدة مناطق متساوية الحجم وبعد ذلك تصنيف الكائن المكتشف في كل منطقة (انسان – فاكهة -سيارة .. ) , من الممكن ان تكون النوافذ متداخلة فيما بينها وذلك يعتمد على الخطوة stride اذا كانت قليلة جداً من المؤكد سيحدث تداخل أما اذا كانت كبيرة بنسبة معينة لا يحدث تداخل.
خطوات مبدأ عمل الـ Sliding Window برمجياً :
ليكن لدينا صورة ما نقوم بتقسم الصورة الى عدة مناطق متساوية ( على سبيل المثال 10*10 ) من أجل كل منطقة نقوم بما يلي :
1) نطبق شبكة عصبونية التفافية CNN على كل المناطق التي تم تقسيمها لاكتشاف إذا كانت تحوي كائن أم لا .
2) استخراج السماتFeatures المميزة للصورة بوسطة شبكة CNN , على سبيل المثال اذا كان لدينا في الدخل صورة تفاحة وصورة برتقالة والمطلوب القيام بعملية التصنيف لهما , ونعلم ان تفاحة تختلف عن البرتقالة بسمة اللون والطول . مع العلم أن السمات المستخرجة لا نعلمها بل شبكة CNN تقوم بإيجادها .
ملاحظة : خوارزمية Sliding Window بسيطة وفعالة لكنها مكلفة زمنياً والسبب في ذلك وجود عدد من المناطق المطلوب تصنيفها حيث من الممكن أن يكون عدد المناطق كبير جداً .لهذا السبب تم تحسينها .
R-CNN ( b:
هي تحسين لخوارزمية Sliding Window بحيث يتم تجاهل المناطق التي من الممكن أن لا تحوي على كائن, حيث نسمى العملية التي يتم فيها اختيار المناطق التي من الممكن أن تحتوي على كائنب” Region Proposals” اي اقتراحات المنطقة.
تم اقتراح العديد من الخوارزميات “اقتراح المنطقة ” لمعرفة المنطقة الهامة في الصورة” Region of Interest “
ROI ولكن أفضلها هي خوارزمية “Selective Search” . وهذه الخوارزمية تقترح تقريبا 2000 منطقة من الصورة مع العلم ان المناطق المقترحة من قبل الخوارزمية هي ليست عشوائية , بل تتميز كل منطقة مقترحة انها تملك نسبة احتمالية كبيرة لوجود object فيها . يمكن القول أن R-CNN هي عبارة عن شبكة عصبونية قائمة على أساس المنطقة .
الشكل العام لخوارزمية الـ R-CNN
خطوات مبدأ عمل R-CNNبرمجياً :
1) ليكن لدينا صورة ما .
2) نوجد كل المناطق المهمة في الصورة أي”ROI ” باستخدام خوارزمية “Selective Search” .
3) من أجل كل منطقة نقوم بما يلي :
A) تطبق على كل منطقة من المناطق التي تم استخراجها شبكة عصبونية التفافية CNN .
B) استخراج السماتFeatures المميزة للصورة من شبكة CNN .
C) السمات التي تم استخراجها من شبكة CNN يتم ادخالها على شبكة Fully connected تحتوي على خرجين , الخرج الأول هو من اجل توقع مربع التحديد الخاص بكل كائن بحيث يتم استخدام خوارزمية Regression في الخرج , من الممكن ان تكون”Linear Regression ” التوقع الخطي أو” Kalman Filter Regression”بحيث تتوقع المكان القادم بمعلومية المكان الحالي , عملية اختيار خوارزمية التوقع المناسبة تعتمد على “Tracking Detection ” اي تعقب الكائن, أما بالنسبة للخرج الثاني من اجل تصنيف الكائن الموجود في مربع التحديد الذي تم توقعه في الخرج الأول (انسان – قطة – سيارة . . . ) يتم استخدام خوارزمية الـ SVMs في الخرج ,حيث خوارزمية SVMs هي خوارزمية Machine Learning تصنف من الخوارزميات الخاضعة للإشراف مهمتها القيام بعملية “binary classification ” تم تطويرها الى خوارزمية SVMs لكي تقوم بمهمة “Binary Classification ” بالإضافة لمهمة ” Classification Multi ” .
Fast R-CNN ( c:
تعتبر تحسين لخوارزمية الـ R-CNN ,وعملية التحسين تمت على خطوة الـ feature extraction , بدلاً من تمرير كل المناطق المقترحة من قبل خوارزمية selective search كلاً على حدى الى شبكة CNN لإستخراج السمات features الخاصة بكل منطقة . يتم ادخال الصورة بشكل كامل الى شبكة CNN واستخراج السمات features للصورة ككل , بعد ذلك يتم ايجاد المناطق المقترحة . نلاحظ ان ذلك يتم بعملية واحدة أما في خوارزمية R-CNN كُنا نحتاج الى 2000 عملية .
الشكل العام لخوارزمية ال Fast R-CNN :
خطوات مبدأ عمل Fast R-CNNبرمجياً :
1) ليكن لدينا صورة ما .
2) ايجاد كل المناطق المهمة في الصورة أي”ROI ” باستخدام خوارزمية “Selective Search” .
3) ادخال الصورة الى شبكة CNN .
4) استخراج ال features map من كامل الصورة من خلال شبكة الـ
conv5 بحيث خرج هذه الشبكة هي عبارة عن صورة تحتوي على الخصائص ” السمات” الخاصة بالصورة المدخلة ,وعدد الـ Features map في الصورة هو من مرتبات 2n, ولكن في الـ conv5 قيمة n=8 اي ال features المستخرجة من الconv5 هي 256 .
5) القيام بعملية اسقاط لكل منطقة من المناطق التي تم أيجادها بواسطة خوارزمية الـ “selective search “ على الـ features map المناظرة ( اي بمعنى اوضح معرفة موقع كل منطقة مهمة على features map ) .
6) ادخال جميع المناطق الى شبكة SSPnet على شكل صور , كل صورة تعبر عن ROI بعد ذلك نقوم بعملية pooling maxلكل منطقة لتخفيض حجم كل منطقة وجعل ابعادها ثابتة ,نحن نعلم لا يمكن ان يكون دخل شبكة fully conneted متغير لهذا السبب جعلنا ابعاد كل منطقة ثابتة وذلك باستخدام شبكة SSPnet .
ملاحظة : دخل شبكة fully connected عبارة عن vector يحوي السمات features الخاص بكل منطقة بعد حذف السمات features الغير مهمة والحفاظ على السمات features المهمة في هذه المنطقة .
7) شبكة Fully connectedتحتوي على خرجين , الخرج اللأول هو من اجل توقع مربع التحديد الخاص بكل object بحيث يتم استخدام خوارزمية Regression Linear في الخرج, والخرج الثاني من اجل تصنيف الكائن object الموجود في مربع التحديد الذي تم توقعه في الخرج الأول , مع العلم يتم تطبيق تابع softmax على الخرج الثاني .
Faster R-CNN ( d :
هي عبارة عن تحسين لخوارزمية Fast R-CNN و R-CNN , تم الإستغناء عن خوارزمية الـ Selective Search المكلفة زمنياً و المستخدمة في عملية استخراج المناطق المهمة “ROI ” ( حيث عملية استخراج كل منطقة تأخد زمناً معيناً بالتالي من اجل 2000 منطقة سوف يكون زمناً كبيراً) . تستخدم خوارزمية الـ RPN اختصار لـ Region “ Proposal “ Networkوهي عبارة عن شبكة استخراج المناطق حيث تقوم باستخراج كل منطقة بشكل سريع جداً تعتمد على مفهوم الـ Anchors .
ملاحظة : تحدثنا عن مفهوم الـ Anchors بشكل مفصل في المقال الذي عنوانه ” خوارزمية يولو الإصدار الثالث -YOLO v3 ” على مدونة شمرا .
Yolov3 ( e :
تعد خوارزمية YOLO من أهم الخوارزميات المستخدمة في مجال الرؤية الحاسوبية Computer vision .
ملاحظة : تحدثنا ايضاً عن هذه الخوارزمية بشكل مفصل في المقال الذي عنوانه ” خوارزمية يولو الإصدار الثالث -YOLO v3 ” على مدونة شمرا .
رابعاً : تنصيب الحزم المطلوبة
نقوم بتنصيب الحزم التي تساعدنا في بناء النموذج
pip install numpy pip install imutils pip install opencv-python pip install scipy pip install matplolib
خامساً: الكود البرمجي الخاص بمشروع الـSocial Distancing
#import the necessary packages import numpy as np import cv2 import os import matplotlib.pyplot as plt from scipy.spatial import distance as dist import imutils
استيراد المكتبات :
المكتبة cv2 والمقصود بها مكتبة ال OpenCv لرسم حدود مربع الأحاطة Bounding Box على الإطارات .
المكتبة os التي يتم من خلالها التعامل مع الملفات .
المكتبة matplotlib من أجل إظهار الأطارات .
المكتبة scipy تحوي على تابع حساب المسافة الإقليدية .
المكتبة imutils لتغير حجم الأطار .
# base path to YOLO directory MODEL_PATH = "yolo-coco"
ModelPath هو مسار المجلد yolo-coco الذي يحتوي بداخله الملف coco.names والملف yolov3.weights والملف yolov3.cfg.
ملف coco.names هو ملف نصي يحوي على اسماء 80 صف class حيث هذه الأسماء تمثل الكائنات التي تكتشفها خوارزمية YOLO.
# load the COCO class labels our YOLO model was trained on labelsPath = os.path.sep.join([MODEL_PATH, "coco.names"]) LABELS = open(labelsPath).read().strip().split("\n")
فتح الملف لعملية القراءة مع القيام بخطوتي معالجة :
1) حذف الفراغات في بداية ونهاية اسماء الصفوف ان وجدت .. فمثلا اذا لدينا
” person ” نلاحظ ان اسم الصف هذا يحتوي فراغات في بدايته ونهايته . فبعد تطبيق تابع Strip() يصبح ” person” .
2) كل سطر في الملف coco.names يحوي اسم صف class بالتالي لقراءة اسماء الكائنات نقوم بقراءة كل سطر على حدة باستخدام التابع ( split(“\n”.
ينتج لدينا لائحة LABELS يكون الشكل العام لها :
“LABEL[0]=”person
“LABEL[1]=”bicycl
.
.
“LABEL[79]=”toothbrush
# derive the paths to the YOLO weights and model configuration weightsPath = os.path.sep.join([MODEL_PATH, "yolov3.weights"]) configPath = os.path.sep.join([MODEL_PATH, "yolov3.cfg"]) # load our YOLO object detector trained on COCO dataset (80 classes) print("[INFO] loading YOLO from disk...") net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
تابع readNetFromDarknet لتحميل نموذج YOLO v3 الذي تم تدريبه مسبقاً للقيام بعملية اكتشاف الكائنات باستخدام مكتبة ـKeras .
بالنسبة لملف yolov3.weights يحوي على أوزان الشبكة المدربة .
أما ملف yolov3.cfg هو ملف التكوين , يحوي وصف نصي لبنية الشبكة ( تابع التنشيط لشبكة CNN و أبعاد الصورة التي تتعامل معها الشبكة . . .) .
# determine only the *output* layer names that we need from YOLO ln = net.getLayerNames() ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
تحتوي YOLO v3 على ثلاث طبقات خرج هما الطبقات 82 و 94 و 106
التابع getLayerNames يرد قائمة list بأسماء جميع طبقات الموجودة في شبكة YOLO , وشبكة YOLO v3 تحوي على 254 طبقة. بالشكل
( ……..,“conv_0”,”bn_0” ,”relu_0” )
التابع getUnconnectedOutLayers يرد قائمة list بدليل طبقات الخرج, وعند تطبيق هذا التابع على الشبكة YOLO v3 يرد قائمة بثلاث قيم 200 , 227 , 254 ,
هذه القيم تمثل دليل طبقات الخرح .
وبالتالي للحصول طبقات الخرج المقابلة للقيم السابقة نستخدم [ln[ i[0] – 1
وبهذه الطريقة نحصل طبقات الخرج لنموذج YOLO v3.
# initialize minimum probability to filter weak detections along with # the threshold when applying non-maxima suppression MIN_CONF = 0.3 NMS_THRESH = 0.3
MIN_CONF: يعبر عن threshold score والهدف منها حذف الصناديق التي مدى الثقة الخاصة فيها أقل من حد معين .
NMS_THRESH: يعبر عن IOU التي من خلالها يتم تحديد هل الصناديق متداخلة مع بعضها البعض او لا .
ملاحظة : تحدثنا عن مبدأ عمل خوارزمية non-max suppression في المقال الذي عنوانه ” خوارزمية يولو الإصدار الثالث -YOLO v3 ” على مدونة شمرا .
def detect_people(frame, net, ln, personIdx=0): #Block1 # grab the dimensions of the frame and initialize the list of # results (H, W) = frame.shape[:2] results = [] #Block2 # construct a blob from the input frame and then perform a forward # pass of the YOLO object detector, giving us our bounding boxes # and associated probabilities blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),swapRB=True, crop=False) net.setInput(blob) layerOutputs = net.forward(ln) #Block3 # initialize our lists of detected bounding boxes, centroids, and # confidences, respectively boxes = [] centroids = [] confidences = [] #Block4 # loop over each of the layer outputs for output in layerOutputs: # loop over each of the detections for detection in output: # extract the class ID and confidence (i.e., probability) # of the current object detection scores = detection[5:] classID = np.argmax(scores) confidence = scores[classID] #Block5 # filter detections by (1) ensuring that the object # detected was a person and (2) that the minimum # confidence is met if classID == personIdx and confidence > MIN_CONF: # scale the bounding box coordinates back relative to # the size of the image, keeping in mind that YOLO # actually returns the center (x, y)-coordinates of # the bounding box followed by the boxes' width and # height box = detection[0:4] * np.array([W, H, W, H]) (centerX, centerY, width, height) = box.astype("int") #Block6 # use the center (x, y)-coordinates to derive the top # and and left corner of the bounding box x = int(centerX - (width / 2)) y = int(centerY - (height / 2)) # update our list of bounding box coordinates, # centroids, and confidences boxes.append([x, y, int(width), int(height)]) centroids.append((centerX, centerY)) confidences.append(float(confidence)) #Block7 # apply non-maxima suppression to suppress weak, overlapping # bounding boxes idxs = cv2.dnn.NMSBoxes(boxes, confidences, MIN_CONF, NMS_THRESH) #Block8 # ensure at least one detection exists if len(idxs) > 0: # loop over the indexes we are keeping for i in idxs.flatten(): # extract the bounding box coordinates (x, y) = (boxes[i][0], boxes[i][1]) (w, h) = (boxes[i][2], boxes[i][3]) # update our results list to consist of the person # prediction probability, bounding box coordinates, # and the centroid r = (confidences[i], (x, y, x + w, y + h), centroids[i]) results.append(r) # return the list of results return results
التابع detect_people لإ كتشاف الأشخاص في كل إطار من إطارات الفيديو على حدى .
يقبل هذا التابع أربع معاملات :
frame : الاطار من ملف الفيديو أو مباشرة من الكاميرا .
net : نموذج الكشف عن الكائنات YOLO الذي تم تدريبه مسبقاً.
ln : أسماء طبقات طبقات الخرج لنموذج YOLO
personIdx : يمكن لنموذج YOLO اكتشاف أنواع عديدة من الكائنات (مشاة , سيارة , إشارة مرور . . ) ولكن في هذا المشروع سوف نتعامل مع الأشخاص(مشاة) فقط بالتالي من خلال هذا المعامل نمرر دليل صف Class الذي يعبر عن المشاة.
يعيد هذا التابع قائمة results تتضمن النتائج النهائية لتطبيق YOLO على الإطار , و القيم المعادة هي ثقة الكائن واحداثيات مربع الاحاطة والمركز من اجل كل كائن ( مشاة ) مكتشف في الاطار.
Block1
نستخرج أبعاد الاطار
تهيئة القائمة results .
ملاحظة : ثقة الكائن confidence يعبر عن مدى الثقة في كل box ان يغطي الكائن object بأفضل شكل ممكن.
Block2
تطبيق خوارزمية YOLO على الاطار لكن قبل تطبيق هذه الخوارزمية لابد من اجراء معالجة مسبقة للإطار.
التابع blobFromImage لأجراء عملية معالجة مسبقة على الاطار حيث يقبل هذا التابع المعاملات التالية :
المعامل الأول يمثل الأطار .
المعامل الثاني هو scale factor لتحجيم قيم بكسلات الصورة ضمن نطاق [0,1] وهذا يفيد في عملية تسريع معالجة الأطار .
المعامل الثالث لتغيير حجم الإطار الى الأبعاد 416×416 ليتوافق مع نموذج YOLOv3
وذلك لان هذا النموذج يقبل صورة دخل بأبعاد 416×416 بيكسل.
المعامل الرابع swapRB=True لتحويل الصورة من الترتيب RGB الى ترتيب BGR وذلك لان مكتبة OpenCV تتعامل مع صور الملونة بالترتيب BGR.
المعامل الخامس crop=False لإشارة الى عدم اقتصاص الصورة بعد تغير حجمها.
التابع setInput لتطبيق تنسيق blob على الإطار المدخل .
التابع forward يقوم بعملية التنبؤ بجميع الكائنات الموجودة بالإطار (وهو يمثل خرج شبكة YOLO v3).
Block3
نقوم بتهيئة ثلاث قوائم القائمة الأولى boxes ستحوي على احداثيات مربعات الإحاطة (الزاوية اليسرى العليا والزاوية اليمن السفلى ) والقائمة الثانية centroids ستحوي على مركز الكائن وأما القائمة الثالثة confidences ستحوي على مدى الثقة بكل صندوق أنه سيغطي الكائن بأفضل شكل ممكن .
Block4
حلقتي for , الأولى للمرور على طبقات الخرج الثلاثة لشبكة YOLO v3 , والثانية من أجل المرور على جميع التنبؤات لكل طبقة .
القائمة scores تمثل القيم المتنبئ لتصنيف الكائن المكتشف( c1 , c2 , c3 ……… c80)
التابع np.argmax() حيث يرد هذا دليل العنصر الأكبر في القائمة scorce
المتحول confidence يمثل ثقة الكائن .
Block5
تعليمة If من اجل معالجة الكائنات المكتشفة التي هي مشاة فقط وتجاهل الكائنات الأخرى وايضاً من اجل فلترة الاحتماليات (التخلص من الإحتماليات الضعيفة التي تقل عن حد MIN_CONF ).
Box يمثل احداثيات مربع الإحاطة Bounding box( المركز , الطول والعرض ) مطبق عليها Normalization أي مجال قيمها ]0,1[ وبالتالي يجب ضرب هذه الاحداثيات في طول وعرض الإطار للحصول على احداثيات Bounding box الصحيحة على الإطار .
التابع astype() لقصر قيم محددة الى نوع معين من البيانات, حيث نحول قيم احداثيات صندوق الاحاطة الى نوع البيانات Integer .
Block6
نحصل على احداثيات الزاوية العليا اليسرى لصندوق الإحاطة انطلاقا من مركز صندوق الاحاطة وعرضه وطوله بالشكل التالي :
(X = centerX – (width/2
(Y = centerY – (height / 2
حيث (centerX,centerY) تمثل احداثيات مركز مربع الإحاطة .
ملاحظة :خوارزمية YOLO v3 تتنبأ بمركز مربع الإحاطة وطوله وعرضه .
Block7
التابع NMSBoxes() يطبق خوارزمية Non-max Suppression على مربعات الإحاطة التي تم التنبؤ بها بوسطة خوارزمية YOLO v3 بالاعتماد على الوسطاء التالية :
Boxes : قائمة تحتوي على جميع مربعات التحديد (bounding boxes ) للكائنات ( مشاة فقط ) الموجودة في الإطار .
Confidences : قائمة تحتوي على مدى الثقة المقابلة لكل مربع تحديد .
Min_Conf : يعبر عن threshold score والهدف منها حذف الصناديق التي مدى الثقة الخاصة فيها أقل من حد معين .
NMS_THRESH : يعبر IOU التي من خلالها نحدد هل الصناديق متداخلة مع بعضها البعض او لا .
Block8
تعليمة if للتأكد من وجود كائن ( مشاة ) مكتشف على الأقل ففي حال وِجد كائن واحد او أكثر تتم اضافة معلومات هذه الكائنات الى القائمة results .
ملاحظة : المقصود بمعلومات الكائن هنا ( ثقة الكائن – احداثيات مربع الإحاطة – المركز ).
input = "testvideo.mp4" vs = cv2.VideoCapture(input if input else 0) writer = None
input مسار مقطع الفيديو الذي سوف نطبق عليه النموذج .
التابع VideoCapture لقراءة الفيديو من المسار المحدد .
نهيئ كاتب فيديو الخرج بالقيمة None
output = "outputvideo.avi" display = 0
output مسار الملف الذي سنضع فيه فيديو الخرج الناتج عن تطبيق النموذج .
display هذا المتحول في حال كانت قيمته أكبر من الصفر يتم إظهار اطارت الفيديو أثناء تطبيق النموذج.
# define the minimum safe distance (in pixels) that two people can be # from each other MIN_DISTANCE = 100
Min_Distance : تعبر عن قيمة العتبة التي من خلالها نحدد اذا كانت المسافة بين شخصين تحقق قواعد التباعد الصحي او لا .
# loop over the frames from the video stream while True: #Block1 # read the next frame from the file (grabbed, frame) = vs.read() # if the frame was not grabbed, then we have reached the end # of the stream if not grabbed: break #Block2 # resize the frame and then detect people (and only people) in it frame = imutils.resize(frame, width=700) results = detect_people(frame, net, ln,personIdx=LABELS.index("person")) # initialize the set of indexes that violate the minimum social # distance violate = set() #Block3 # ensure there are *at least* two people detections (required in # order to compute our pairwise distance maps) if len(results) >= 2: # extract all centroids from the results and compute the # Euclidean distances between all pairs of the centroids centroids = np.array([r[2] for r in results]) D = dist.cdist(centroids, centroids, metric="euclidean") #Block4 # loop over the upper triangular of the distance matrix for i in range(0, D.shape[0]): for j in range(i + 1, D.shape[1]): # check to see if the distance between any two # centroid pairs is less than the configured number # of pixels if D[i, j] < MIN_DISTANCE: # update our violation set with the indexes of # the centroid pairs violate.add(i) violate.add(j) #Block5 # loop over the results for (i, (prob, bbox, centroid)) in enumerate(results): # extract the bounding box and centroid coordinates, then # initialize the color of the annotation (startX, startY, endX, endY) = bbox (cX, cY) = centroid color = (0, 255, 0) #Block6 # if the index pair exists within the violation set, then # update the color if i in violate: color = (0, 0, 255) # draw (1) a bounding box around the person and (2) the # centroid coordinates of the person, cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2) #Block7 # draw the total number of social distancing violations on the # output frame text = "Social Distancing Violations: {}".format(len(violate)) cv2.putText(frame, text, (10, frame.shape[0] - 25),cv2.FONT_HERSHEY_SIMPLEX, 0.85, (0, 0, 255), 3) #Block8 # check to see if the output frame should be displayed to our # screen if display > 0: # show the output frame plt.imshow( frame) key = cv2.waitKey(1) & 0xFF # if the `q` key was pressed, break from the loop if key == ord("q"): break # if an output video file path has been supplied and the video # writer has not been initialized, do so now if output != "" and writer is None: # initialize our video writer fourcc = cv2.VideoWriter_fourcc(*"MJPG") writer = cv2.VideoWriter(output, fourcc, 25, (frame.shape[1], frame.shape[0]), True) # if the video writer is not None, write the frame to the output # video file if writer is not None: writer.write(frame)
حلقة while من اجل معالجة إطارات الفيديو .
Block1
قراءة اطار من الفيديو .
حيث تابع القراءة يعيد قيمتين :
Frame : يعبر عن الإطار المقروء .
Grabbed : متحول بولياني اذا كانت قيمته True بالتالي تمت قراءة الأطار بنجاح , اما اذا كانت قيمته False عندها لايوجد إطار لقرائته بالتالي نكون قد وصلنا إلى نهاية الفيديو .
تعليمة if في حال وصلنا الى نهاية الفيديو اي لايوجد اطار لقرائته عندها تكون قيمة المتحول grabbed هي False . فيتم كسرالتنفيذ والخروج من الحلقة .
Block2
التابع resize يقوم بتغير ابعاد الإطار .
التابع detect_people يعيد المعلومات حول كل الكائنات المكتشفة ” مشاة ” في الأطار .وتم توضيح الية عمل هذا التابع في الأعلى .
تهيئة المجموعة violate ليتم وضع فيها فيما بعد دليل الكائنات التي انتهكت قواعد التباعد الأجتماعي .
Block3
تعليمة if للتأكد من وجود شخصين على الأقل في الإطار من اجل القيام بحساب المسافة بينهما .
ملاحظة : في حال وجود شخص واحد في الأطار بالتالي هذا الشخص لاداعي لمعالجة حالة التباعد الأجتماعي له ( لأنه ضمنياً يحقق شروط التباعد الصحي فهو الوحيد الموجود في المكان ) .
استخراج جميع النقاط التي تمثل منتصف الكائنات المكتشفة من اجل حساب المسافة الإقليدية بينها.
التابع cdist لحساب المسافة الإقليدية بين كل مركز الكائن مع باقي مراكز الكائنات الأخرى
Block4
حلقتي for تستخدم من اجل مقارنة كل مربع إحاطة مع باقي المربعات الخرى , من خلال حساب المسافة الإقليدية بين احداثيات نقطتي المركز لكل من المربعين , واذ كانت هذه المسافة اقل من قيمة
Min-Distance بالتالي نضيف دليلي هذين المربعين الى مجموعة violate .
Block5
حلقة for للمرور على كل الكائنات ( المشاة ) المكتشفة في الأطار , أي على جميع قيم القائمة result التي يردها التابع detect_people .
ثم نهيئ متحول color افتراضياً بالقيم التي تمثل اللون الأخضر وفق الترتيب BGR .
Block6
تعليمة if لتبديل قيم المتحول color من القيم التي تمثل اللون الأخضر الى القيم التي تمثل اللون الأحمر وفق الترتيب BGR . وذلك من اجل كل كائن ينتهك قواعد التباعد الإجتماعي.
التابع rectangle لرسم مربع احاطة حول الكائن ففي حال كان الكائن لاينتهك قواعد التباعد الأجتماعي يكون لون المربع أخضر والعكس أحمر
ملاحظة : لرسم مستطيل باستخدام مكتبة الـ OpenCV يجب تحديد زاوية المستطيل العليا اليسرى وزاويته السفلى اليمنى
وسطاء التابع rectangle هي :
الوسيط الأول هو الإطار المراد رسم مستطيل عليه .
الوسيط الثاني والثالث هما إحداثيات زاوية المستطيل العليا اليسرى والسفلى اليمنى.
الوسيط الرابع هو لون خط المستطيل .
الوسيط الخامس هو لسماكة خط المستطيل .
Block7
وضع نص على الإطار يعبر عن عدد الأشخاص الذين ينتهكون قواعد التباعد الإجتماعي وهو مساوي لطول المجموعة violat .
لأضافه نص للصورة علينا تحديد :
النص الذي نريد إدراجه , موضع النص بالنسبة للصورة (الزاوية السفلى اليسرى ) ,نوع الخط ,عامل مقياس الخط (الذي يتم ضربه في الحجم الأساسي للخط), اللون , السماكة.
Block8
تعليمة if لإختبار المتحول display , اذا كانت قيمته أكبر من الصفر بالتالي يتم اظهار إطارات الفيديو أثناء معالجة هذه الإطارات .
تعليمة if الثانية لكسر التنفيذ والخروج من حلقة while في حال تم الضغط على الزر “q “.
تعليمة if الثالثة لإختبار المتحول output اذا كان مُسند له مسار الخرج و لم يتم كتابة أي إطار في هذا المسار. فإذا تحقق هذا الشرط نهيئ كاتب الفيديو بمسار ملف الخرج ” الفيديو ” ومعدل اطارات الفيديو المنشأ ( عدد إطارات الفيديو ) .
تعليمة if الرابعة لإختبار اذا كان كاتب الفيديو مهيئ بالتالي كتابة الأطارات على هذا الملف .
سادساً : مقطع يوضح نتيجة تنفيذ النموذج ( حيث تم تصوير هذا المقطع في كلية التربية في جامعة تشرين)
الأشخاص الذين حولهم صندوق أحمر هم في مرحلة الخطر أما الأشخاص الذين حولهم صندوق أخضر هم في مرحلة الأمان .
سابعاً : ملخص
في هذا المقال تعلمنا كيف نحقق كاشف التباعد الإجتماعي باستخدام OpenCv و Deep Learning و Computer Vision بالخطوات التالية :
- استخدام خوارزمية ال YOLO لإكتشاف الأشخاص في الإطارات المتدفقة من الفيديو .
- تحديد مركز كل كائن ( شخص ) مكتشف .
- حساب المسافة بين كل زوجين من المراكز .
- اختبار هذه المسافة اذا كانت تحقق قواعد التباعد الجتماعي أو لا من قيمة معينة يتم تحديدها في الكود .
رابط تحميل المشروع :
ملاحظة : الملف yolov3.weights يبلغ حجمها 237 ميغا بايت لذلك لم نستطع رفعها على موقع github تستطيع تحميله من الموقعهنا
المصدر :
تقديم كلاً من :
محمد كردي
محمد ذويب