تعلم الآلةرؤية الحاسبمترجم

توقع العمر والجنس باستخدام الشبكات العصبية الترشيحية (CNN) ومكتبة OpenCV

الكاتب: Nagesh Singh Chauhan ترجمة:سعد الشهراني مراجعة: يحيى خوجه

[رابط الموضوع الأصلي هنا]

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

مقدمة

يلعب العمر والجنس، وهما من السمات الأساسية للوجه، دورًا أساسيًا للغاية في التفاعلات الإجتماعية، مما يجعل تقدير العمر والجنس من صورة واحدة للوجه عملية مهمة في التطبيقات الذكية، مثل تصريح الدخول، والتفاعل بين الإنسان والحاسوب، وتطبيق القانون، والتحريات التسويقية والتتبع البصري، الخ.

مثال لحالة استخدام في العالم الحقيقي:


لقد صادفت مؤخرًا Quividi – وهو تطبيق برمجيات الذكاء الاصطناعي – يُستخدم للكشف عن العمر والجنس للمستخدمين الذين يمرون عبر تحليلات الوجه خلال الإنترنت ويبدأ تلقائيًا بتشغيل الإعلانات بناءاً على الجمهور المستهدف.

مثال آخر قد يكون AgeBot – وهو تطبيق أندوريود – يحدد عمرك من صورك باستخدام آلية التعرف على الوجه. يمكنها أن تخمن عمرك وجنسك بالإضافة أيضاً إمكانية العثور على وجوه متعددة في صورة ما وتقدير العمر لكل وجه.

انطلاقاً من حالات الاستخدام المذكورة سابقاً، سوف نقوم ببناء نموذج بسيط للكشف عن العمر والجنس في هذه المقالة المفصلة. لذلك دعونا نبدأ مع حالة الاستخدام لدينا:

حالة الاستخدام – سنقوم ببعض المهام للتعرف على الوجوه، اكتشاف الوجوه وأمور أخرى، سنستخدم CNN (الشبكات العصبية الترشيحية) للتنبؤات المتعلقة بالعمر والجنس من فيديو يوتيوب، لا تحتاج إلى تنزيل الفيديو حيث يمكن الاكتفاء بعنوان الفيديو URL. الجزء المثير للإهتمام هو استخدام CNN للتنبؤات المتعلقة بالعمر والجنس على عناوين URLs للفيديو.

المتطلبات

pip install opencv-python
numpy
pip install pafy
pip install youtube_dl

لمعرفة المزيد : youtube_dl

pafy مكتبة تُستخدم لاسترداد محتوى اليوتيوب وبيانات التعريف الخاصة به (مثل العنوان، التصنيف، عدد مرات المشاهدة، المدة، التقييم، المؤلف، الصورة المصغرة، الكلمات الرئيسية، إلخ). لمعرفة المزيد عن pafy ونسخها إليك الرابط هنا، دعونا نطلع على عينة واحدة كالتالي:

import pafy
url = 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy = pafy.new(url)
print vPafy.title
print vPafy.rating
print vPafy.viewcount
print vPafy.author
print vPafy.length
print vPafy.description

المخرجات

Testing file uploads with Postman (multipart/form-data)
4.87096786499
11478
Valentin Despa
1688
➡️➡️➡️ 📢 Check my online course on Postman. Get it for only $10 (limited supply):
https://www.udemy.com/postman-the-complete-guide/?couponCode=YOUTUBE10

I will show you how to debug an upload script and demonstrate it with a tool that can make requests encoded as "multipart/form-data" so that you can send also a file.

After this, we will go even further and write tests and begin automating the process.

Here is the Git repository containing the files used for this tutorial:
https://github.com/vdespa/postman-testing-file-uploads 

الخطوات

  1. احصل على عنوان URL للفيديو من اليوتيوب.
  2. اكتشاف الوجه باستخدام Haar cascades.
  3. التعرف على الجنس باستخدام الشبكات العصبية الترشيحية CNN .
  4. التعرف على العمر باستخدام الشبكات العصبية الترشيحية CNN .

الخطوة الأولى: احصل على عنوان URL للفيديو من اليوتيوب

احصل على العنوان للفيديو المراد تحليله وحاول الحصول على معلومات الفيديو باستخدام pafy كما هو موضح أعلاه.

الخطوة الثانية: اكتشاف الوجه باستخدام Haar cascades
هذا الجزء الكثير منا على الأقل سمع عنه، يوفر OpenCV/JavaCV طرقًا مباشرة لاستيراد Haar-cascades واستخدامها لاكتشاف الوجوه. لن أشرح هذا الجزء بعمق. يمكنك الرجوع إلى مقالتي السابقة لمعرفة المزيد عن اكتشاف الوجه باستخدام OpenCV بالرابط هنا.

الخطوة الثالثة: التعرف على الجنس باستخدام الشبكات العصبية الترشيحية CNN
يعتبر التعرف على نوع الجنس باستخدام تطبيق OpenCV’s fisherfaces شائعًا للغاية وقد يكون البعض منكم قد جربه أو قرأ عنه أيضًا. لكن في هذا المثال، سأستخدم طريقة مختلفة للتعرف على نوع الجنس. تم تقديم هذه الطريقة من قبل الباحثين، Gil Levi وTal Hassner في العام 2015. وقد استخدمت نماذج CNN المدربة من قبلهما في هذا المثال. سنستخدم حزمة DNN الخاصة بـ OpenCV والتي تعني “الشبكات العصبية العميقة”.

في حزمة DNN، وفر OpenCV فئة تسمى Net والتي يمكن استخدامها لبناء شبكة عصبية. علاوة على ذلك، تدعم هذه الحزم استيراد نماذج الشبكات العصبية من أطر تعلم عميقة معروفة مثل Caffe و Tensorflow و Torch. قام الباحثون الذين ذكرتهم أعلاه بنشر نماذج CNN كنماذج Caffe. لذلك، سوف نستخدم استيراد Caffe Importer هذا النموذج في تطبيقنا.

الخطوة الرابعة: التعرف على العمر باستخدام الشبكات العصبية الترشيحية CNN
يشبه هذا تقريبًا جزء الكشف عن نوع الجنس باستثناء أن ملف prototxt المقابل وملف نموذج Caffe هما “publish_agenet.prototxt” و “age_net.caffemodel”. علاوة على ذلك، تتكون طبقة إخراج CNN (طبقة الاحتمالات) في هذا CNN من 8 قيم للفئات العمرية 8 (“0-2” ، “4-6” ، “8-13” ، “15-20” ، “25-32” “،” 38-43 “،” 48-53 “و” 60”).

لنماذج Caffe ملفان مهمان:

  1. – .prototxt تعريف CNN يكون هنا، يحدد هذا الملف الطبقات في الشبكة العصبية، ومدخلات كل طبقة والمخرجات و وظائفها.
  2. caffemodel يحتوي على معلومات الشبكة العصبية المدربة (نموذج مدرّب).

# قم بتنزيل .prtotxt و .caffemodel من هنا.

# قم بتنزيل haar cascade للكشف عن الوجه من هنا.
لذلك دعونا نبدأ برمجة نموذجنا.

الكود

import cv2
import numpy as np
import pafy

#url of the video to predict Age and gender
url = 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy = pafy.new(url)
play = vPafy.getbest(preftype="mp4")

cap = cv2.VideoCapture(play.url)

cap.set(3, 480) #set width of the frame
cap.set(4, 640) #set height of the frame

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)

age_list = ['(0, 2)', '(4, 6)', '(8, 12)', '(15, 20)', '(25, 32)', '(38, 43)', '(48, 53)', '(60, 100)']

gender_list = ['Male', 'Female']

def load_caffe_models():
 
 age_net = cv2.dnn.readNetFromCaffe('deploy_age.prototxt', 'age_net.caffemodel')

 gender_net = cv2.dnn.readNetFromCaffe('deploy_gender.prototxt', 'gender_net.caffemodel')

 return(age_net, gender_net)
def video_detector(age_net, gender_net):
 font = cv2.FONT_HERSHEY_SIMPLEX

while True:

 ret, image = cap.read()

 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')

 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 faces = face_cascade.detectMultiScale(gray, 1.1, 5)

 if(len(faces)>0):
  print("Found {} faces".format(str(len(faces))))

 for (x, y, w, h )in faces:
  cv2.rectangle(image, (x, y), (x+w, y+h), (255, 255, 0), 2)

 #Get Face
 face_img = image[y:y+h, h:h+w].copy()
 blob = cv2.dnn.blobFromImage(face_img, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)

 #Predict Gender
 gender_net.setInput(blob)
 gender_preds = gender_net.forward()
 gender = gender_list[gender_preds[0].argmax()]
 print("Gender : " + gender)

 #Predict Age
 age_net.setInput(blob)
 age_preds = age_net.forward()
 age = age_list[age_preds[0].argmax()]
 print("Age Range: " + age)

 overlay_text = "%s %s" % (gender, age)
 cv2.putText(image, overlay_text, (x, y), font, 1, (255, 255, 255), 2, cv2.LINE_AA)

 cv2.imshow('frame', image)
 #0xFF is a hexadecimal constant which is 11111111 in binary.
 if cv2.waitKey(1) & 0xFF == ord('q'):
  break

if __name__ == "__main__":
age_net, gender_net = load_caffe_models()

video_detector(age_net, gender_net)

الآن دعونا نفهم الكود

الخطوة 1: استيراد جميع المكتبات المطلوبة.

import cv2
import numpy as np
import pafy

 

الخطوة 2: احصل على عنوان URL لفيديو YouTube وقم بإنشاء كائن “play” يحتوي على أفضل دقة للفيديو بتنسيق webm/mp4.

url = 'https://www.youtube.com/watch?v=c07IsbSNqfI&feature=youtu.be'
vPafy = pafy.new(url)
play = vPafy.getbest(preftype="mp4")

 

الخطوه 3: في كثير من الأحيان، يتعين علينا التقاط بث مباشر من الكاميرا، OpenCV يوفر واجهة بسيطة جداً لهذا. يمكننا التقاط الفيديو من الكاميرا، وتحويله إلى فيديو بتدرج رمادي وعرضه. مجرد مهمة بسيطة للبدء.

لالتقاط مقطع فيديو، تحتاج إلى إنشاء كائن “cap” فيديو. يمكن أن تكون المدخلات إما فهرس الجهاز أو اسم ملف الفيديو. فهرس الجهاز هو مجرد رقم لتحديد الكاميرا. عادةً سيتم توصيل كاميرا واحدة (كما في حالتي). لذلك أنا ببساطة مررت 0 (أو -1). يمكنك تحديد الكاميرا الثانية بتمرير 1 وما إلى ذلك. بعد ذلك، يمكنك التقاط إطار تلو الآخر.

cap = cv2.VideoCapture(0) #if you are using webcam

لكن في حالتي ، فأنا أقرأ عنوان URL للفيديو عبر الإنترنت، لذلك سأقوم بتمرير كائن “play” إلى دالة VideoCapture():

cap = cv2.VideoCapture(play.url)

الخطوة 4: باستخدام set() سأضبط ارتفاع وعرض إطار الفيديو الخاص بنا cap.set (propld, value)، هنا 3 هي propertyId للعرض و 4 مخصصة للارتفاع.

cap.set(3, 480) #set width of the frame
cap.set(4, 640) #set height of the frame

الخطوة 5: إنشاء 3 قوائم منفصلة لتخزين متوسط قيم النموذج (Model_Mean_Values) والعمر والجنس.

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
age_list = ['(0, 2)', '(4, 6)', '(8, 12)', '(15, 20)', '(25, 32)', '(38, 43)', '(48, 53)', '(60, 100)']
gender_list = ['Male', 'Female']

الخطوة 6: لقد حددت دالة لتحميل Caffe model و prototxt لكلا العمر والجنس ، وهذه هي أساسا نماذج CNN المدربة مسبقا والتي سوف تعمل الكشف.

def load_caffe_models():
   age_net = cv2.dnn.readNetFromCaffe('deploy_age.prototxt', 'age_net.caffemodel')
   gender_net = cv2.dnn.readNetFromCaffe('deploy_gender.prototxt', 'gender_net.caffemodel')

الخطوة 7: الآن ، سنقوم بعملية الكشف عن الوجه، والكشف عن العمر، والكشف عن الجنس، لذلك ننشيء دالة video_detector(age_net, gender_net)، داخل الدالة الرئيسية ونمرر age_net و gender_net كمتغيرات لها.

if __name__ == "__main__":
   age_net, gender_net = load_caffe_models()
   video_detector(age_net, gender_net)

الخطوة 8: اقرأ كائن الحد الأقصى الذي تم إنشاؤه من دالة VideoCapture() في الخطوة 3.
تعيد الدالة cap.read() قيمة منطقية (صواب / خطأ). إذا تم قراءة الإطار بشكل صحيح، فسيكون هذا صحيحًا.

#يمكنك التحقق من نهاية الفيديو عن طريق التحقق من قيمة الإرجاع هذه.
#في بعض الأحيان، قد لا يكون هناك تهيئة الالتقاط. في هذه الحالة، يظهر هذا الرمز خطأ.
#يمكنك التحقق مما إذا كان قد تمت تهيئته أم لا بواسطة cap.isOpened(). إذا كان صحيحاً تمت وإلا يتم فتحه باستخدام cap.open().

ret, image = cap.read()

الخطوة 9: تحويل الصورة إلى صورة رمادية لأن كاشف OpenCV يتوقع صور رمادية.

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

الخطوة 10: تحميل النموذج المبني مسبقاً للكشف عن الوجه.

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')

الخطوة 11: حالياً، كيف يمكننا اكتشاف وجه من صورة باستخدام Cascade Classifier؟

حسنًا، مرة أخرى، Cascaded Classifier جعل الأمر من OpenCV أمرًا سهلاً بالنسبة لنا بسبب استخدام الدالة detectMultiScale()، والذي يكتشف ما تحتاجه بالضبط.

detectMultiScale(image, scaleFactor, minNeighbors)

فيما يلي المتغيرات التي يجب تمريرها الى الدالة detectMultiScale()، وظيفتها العامة اكتشاف الكائنات، وفي هذه الحالة، ستكتشف الوجوه نظرًا لأننا استدعينها في Cascade الوجه. إذا وجد وجهًا، فسوف يُرجع قائمة بمواضع الوجه المذكور في النموذج “Rect(x,y,w,h).” ، وإن لم يجد، فسيُرجع “None”.

    • Image :الإدخال الأول هو صورة تدرج الرمادي.
    • scaleFactor: تعوض هذه الوظيفة الإدراك الخاطئ في الحجم الذي يحدث عندما يبدو أن أحد الوجوه أكبر من الآخر لأنه ببساطة أقرب إلى الكاميرا.
    • minNeighbors: خوارزمية الكشف التي تستخدم نافذة متحركة للكشف عن الكائنات، وهي تقوم بذلك عن طريق تحديد عدد الكائنات الموجودة بالقرب من الحالية قبل أن تتمكن من تحديد الوجه الذي تم العثور عليه.
faces = face_cascade.detectMultiScale(gray, 1.1, 5)

الخطوة 12: مرر قائمة الوجوه بتكرار Loop وارسم المستطيلات على الوجوه في الفيديو، أساساً تحدد الوجوه ونقسمها بالشكل والحجم مع رسم المستطيلات.

for (x, y, w, h )in faces:
   cv2.rectangle(image, (x, y), (x+w, y+h), (255, 255, 0), 2)
   # Get Face 
   face_img = image[y:y+h, h:h+w].copy()

الخطوة 13: توفر OpenCV وظيفة لتسهيل المعالجة المسبقة للصورة في تصنيف التعلم العميق blobFromImage() ينفذ الآتي:

      • متوسط الطرح (Mean subtraction)
      • القياس (Scaling)
      • اختيارياً مبادلة قنوات الألوان (optionally channel swapping)

لذلك يقوم blobFromImage بإنشاء blob ثلاثي الأبعاد من الصورة. يتم تغيير حجم الصورة وقصها بشكل اختياري من المركز، وطرح قيم المتوسط، وقيم المقاييس بواسطة scalefactor، ومبادلة القنوات الزرقاء والحمراء.

blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True)
      1. الصورة (Image): هذه هي الصورة المدخله التي نريد نعالجها قبل نقلها عبر شبكتنا العصبية العميقة للتصنيف.
      2. عامل القياس(Scale Factor): بعد إجراء عملية الطرح يعني أنه يمكننا اختيارياً قياس صورنا حسب بعض العوامل. هذه القيمة هي القيمة الافتراضية (1.0 ، أي عدم القياس) ولكن يمكننا توفير قيمة أخرى أيضًا. من المهم أيضًا ملاحظة أن عامل المقياس يجب أن يكون 1/σ لأننا في الواقع نقوم بضرب قنوات الإدخال (بعد الطرح المتوسط) بعامل المقياس
      3. الحجم(size): هنا نوفر الحجم الذي تتوقعه الشبكة العصبية الترشيحية. بالنسبة لمعظم الشبكات العصبية الحديثة ، هذا هو إما 224×224 أو 227×227 أو 299×299.
      4. المتوسط (mean): هذه هي قيم الطرح لدينا. يمكن أن تكون ثلاث نقاط من متوسطات RGB أو يمكن أن تكون قيمة واحدة، في هذه الحالة يتم طرح القيمة المتوفرة من كل قنوات الصورة. إذا كنت تنفذ عملية الطرح الوسطي، فتأكد من توفير الترتيب الثلاثي (R, G, B)، خاصة عند استخدام السلوك الافتراضي لـ swapRB = True.
      5. swapRB: يفترض OpenCV أن الصور بترتيب قناة BGR؛ ومع ذلك، فإن القيمة المتوسطة تفترض أننا نستخدم طلب لحل هذا التناقض، يمكننا تبديل قنوات R و B في الصورة عن طريق تعيين هذه القيمة على True. بشكل افتراضي، ينفذ OpenCV قناة التبادل هذه لنا.
blob = cv2.dnn.blobFromImage(face_img, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)

الخطوة 14: توقع الجنس.

#Predict Gender
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender = gender_list[gender_preds[0].argmax()]

الخطوة 15: توقع العمر.

#Predict Age
age_net.setInput(blob)
age_preds = age_net.forward()
age = age_list[age_preds[0].argmax()]

الخطوة 16: الآن يتعين علينا وضع نص على إطارنا المُخرج باستخدام وحدة putText() من openCV.
تأخذ cv2.putText() المتغيرات التالية:

        • البيانات النصية التي تريد كتابتها
        • موضع إحداثيات المكان الذي تريد وضعه النص فيه (أي بالزاوية السفلية اليسرى حيث تبدأ البيانات)
        • نوع الخط
        • مقياس الخط (يحدد حجم الخط)
        • الأشياء العادية مثل اللون والسماكة و lineType وما إلى ذلك. للحصول على مظهر أفضل، ينصح lineType = cv2.LINE_AA.
overlay_text = "%s %s" % (gender, age)
cv2.putText(image, overlay_text, (x, y), font, 1, (255, 255, 255), 2, cv2.LINE_AA)

الخطوة 17: وأخيرا إظهار الصورة النهائية.

cv2.imshow('frame', image)

في النهاية لدينا:

if cv2.waitKey(1) & 0xFF == ord('q'):
   break

ينتظر برنامجنا بما يصل إلى 1 مللي في ثانية حتى يضغط المستخدم على المفتاح. يأخذ بعد ذلك قيمة المفتاح للقراءة و AND مع 0xFF الذي يزيل أي شيء أعلى من 8 بتات السفلية ويقارن نتيجة ذلك برمز ASCII للحرف q واللتي تعني أن المستخدم قد قرر الخروج عن طريق الضغط على مفتاح q من لوحة المفاتيح.

مخرجات :

Video URL-1: https://www.youtube.com/watch?v=iH1ZJVqJO3Y

Video URL-2: https://www.youtube.com/watch?v=qLNhVC296YI

 

خاتمة

كما رأينا في هذه المقالة ، في بضعة أسطر من التعليمات البرمجية قمنا ببناء نموذج للكشف عن العمر والجنس، من هنا فصاعدًا يمكنك أيضًا دمج اكتشاف المشاعر والكشف عن الأشياء في نفس النموذج وإنشاء تطبيق مكتمل.

نأمل أن تكون هذه المقالة جيدة ومفيدة في سعيكم للتعرف على عمر الشخص وجنسه.

اظهر المزيد

سعد آل سند

مرشح دكتوراه في علم البيانات. مهتم بمعالجة اللغات الطبيعية والذكاء الاصطناعي.

تعليق واحد

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى