التعرف على الوجه في بايثون - مع الكود

كتبت بواسطة Shadi Saleh | بتاريخ الأربعاء 22 نيسان 2020

التعرف على  الوجه بعشرة أسطر  - كود بايثون


التعرف التلقائي على الأوجه 

تتناول مقالة سابقة على المدونة بعنوان التعرف على الوجوه باستخدام التعلم العميق  أساسيات التعرف على الوجه ومجالات تطبيقاتها ونموذج لحل هذه المشكلة باستخدام التعلّم العميق Deep Learning.

في هذه المقالة سنقوم بطرح حل سريع وبسيط يعتمد على نموذج مدّرب جاهز لتطبيق هذه التقنية باستخدام لغة البرمجة بايثون بما لا يتجاوز ١٠ أسطر برمجية ودون الحاجة إلى قدرات حاسوبية عالية. 

هذه المقالة موجهّة لغير المتخصصين الراغبين بإضافة ميزة التعرف على الأوجه إلى تطبيق أو موقع إنترنت بأقل جهد ممكن.


 متطلبات العمل

قبل البدء يجب تثبيت المكتبات التالية على بيئة العمل، سنقوم بكتابة التعليمات المناسبة لتثبيت هذه المكتبات على نظام تشغيل أوبنتو لينكس.


OpenCV

وتعتبر من أشهر المكاتب البرمجية في مجال ComputerVision والتعرف على الكائنات, تتميز بسرعتها فهي مكتوبة بلغة c++ وتتوفر واجهات لها في لغات برمجية عديدة مثل بايثون.

تستخدم مكتبة OpenCV التعلم الآلي Machine Learning للبحث عن الأوجه في صور, ولأن الأوجه تحوي ألاف العلامات المميزة يتم اختبارها عند البحث عن الوجه, تعتمد الخوارزمية في OpenCV على تحويل الصورة إلى ألاف الصور الجزئية بحجم بايت واحد, ويتم تحويل مهمة التعرف على الوجه إلى مهمة تصنيف Classification لهذه الصور الجزئية الصغيرة مما يجعل المهمة أسهل من التعرف على كامل الصورة دفعة واحدة.

لتثبيت المكتبة على نظام تشغيل أوبنتو لينكس قم بتنفيذ التعليمات التالي:

sudo apt update
sudo apt install python3-opencv

قد تحتاج إلى تنصيب cmake في حال لم يكن منصب على نظامك، تستطيع تثبيته باستخدام التعليمة التالية:

sudo apt-get -y install cmake 


face_recognition مكتبة


تحوي هذه المكتبة مودل جاهز ومدرّب للتعرف على الأوجه، لتثبيت المودل، قم بتنفيذ التعليمة التالية:

pip install face_recognition

في حال كنت تستخدم python 3 استبدل pip  ب pip3.


التعرف على الأوجه

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

سأقوم باختيار مجموعة من صور فنانين سوريين ووضعهم ضمن مجلد images كالتالي:

abed.jpg ayman.jpg basel.jpg basem.jpg qusai.jpg unknown.jpg

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


أما الصورة الغير معروفة unknown، فهي صورة تجمع كل باسم ياخور وايمن رضا والتي ستقوم الخوارزمية بالتعرف على الأوجه فيها من بين الأوجه ضمن الصور المعروفة known images


ليصبح الكود كمايلي:

import face_recognition

from PIL import Image, ImageDraw

import numpy as np

known_face_names = ["abed","ayman","basel","basem","qusai"]

known_face_encodings=[]

for name in known_face_names:

        image = face_recognition.load_image_file("images/"+name+".jpg")

        encoding = face_recognition.face_encodings(image)[0]

        known_face_encodings.append(encoding)

unknown_image = face_recognition.load_image_file("images/unknown.jpg")

face_locations = face_recognition.face_locations(unknown_image)

face_encodings = face_recognition.face_encodings(unknown_image, face_locations)

pil_image = Image.fromarray(unknown_image)

draw = ImageDraw.Draw(pil_image)

for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):

    matches = face_recognition.compare_faces(known_face_encodings, face_encoding)

    name = "Unknown"

    face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)

    best_match_index = np.argmin(face_distances)

    if matches[best_match_index]:

        name = known_face_names[best_match_index]

    draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255))

    text_width, text_height = draw.textsize(name)

    draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255))

    draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))

pil_image.show()


بالفعل كما وعدت، الكود الخاص بالتعرف على الأوجه لا يتجاوز عشرة أسطر ولكن الجزء الأكبر من الكود يحوي استيراد المكتبات المطلوبة ورسم المربعات التي تحوي على أسماء الاشخاص :)

عند تنفيذ الكود أعلاه سنحصل على الصورة الغير معروفة وقد قامت الخوارزمية برسم مستطيل حول كل وجه معرّف باسم الشخص الذي تعرفت عليه كمايلي:

لاحظ أن الخوارزمية استطاعت التعرف على الأوجه بشكل سليم وقامت بكتابة ayman حول وجه أيمن رضا وbasem حول وجه باسم ياخور، رغم أن الصور المعروفة لكل من أيمن وباسم في مجلد images مختلفة تماما عن الصورة الغير معروفة, وهذا يدل على قوة الخوارزمية ودقتها.


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

رابط المزيد من الأمثلة في المكتبة: https://github.com/ageitgey/face_recognition/tree/master/examples