چگونه یک نرم افزار تشخیص دهنده لبخند بسازیم

در این آموزش می خواهیم یک مدل تشخیص لبخند را در پایتون توسعه دهیم.

۱- مقدمه

کسب و کار ها به دنبال این هستند تا مهمترین محصول مورد نیاز مردم را به آن ها ارائه دهند: خوشحالی !

چرا؟ خوشحالی شاید چیزی فراتر از یک واکنش شیمیایی باشد. مشتری خوشحال به احتمال زیاد دوباره به فروشگاه مراجعه خواهد کرد و داده های مرتبط با عوامل خوش حال کننده ی مشتری می تواند به مشاغل کمک کند تا بفهمند کدام محصولات بهتر عمل می کنند و میزان ماندگاری بالاتری دارند.

ماشین ها و کامپیوتر ها می توانند نحوه تشخیص خوشحالی افراد را بیاموزند و در این مقاله به شما نشان داده خواهد شد که چگونه یک مدل تشخیص چهره ایجاد کنید که بتواند خوشحالی را تشخیص دهد.

بیایید با اصول اولیه ی کار شروع کنیم. چگونه خوشحالی را ابراز کنیم؟ روی صورت، بیشتر از طریق تغییر حالت چشم و لبخند مان این اتفاق می افتد. ما به طور طبیعی نتیجه می گیریم که وقتی کسی لبخند بر لب دارد خوشحال است. لبخند می تواند شکل های متنوع زیادی داشته باشد، اما شکل آن بیشتر شبیه نوع صاف شده ی ‘U’ است.

🙂

در مراحل بعدی، کد پروژه ارائه شده و توضیح خواهیم داد که برای ساخت مدل تشخصی لبخند چه باید کرد. برای درک مفاهیم الگوریتم، این مقاله را درمورد الگوریتم Viola-Jones بررسی کنید.

تشخیص لبخند

آنچه شما برای ساخت ردیاب شادی نیاز دارید

در این آموزش از Spyder در Anaconda استفاده شده، اما شما می توانید از Jupyter Nb استفاده کنید. پس از داشتن ابزار های لازم، وارد IDE (ویرایشگر کد) شوید.

اگر از spyder استفاده می کنید باید صفحه ای شبیه به این داشته باشید.

قبل از شروع کد نویسی ، حتماً ابزار haar را بارگیری کنید (بخش بعدی)

تشخیص لبخند

۲- ابزار تشخیص چهره ی Haar

همانطور که در مقاله ذکر شده در بالا توضیح داده شده، الگوریتم ویولا-جونز از ویژگی های مشابه Haar برای تشخیص خصوصیات صورت استفاده می کند.

این ابزار مجموعه ای از فیلترها است که یکی پس از دیگری برای شناسایی چهره از طریق ویژگی های آن اعمال می شود.

این فیلترها در پرونده های XML خود در مخزن Haar Cascade GitHub ذخیره می شوند.

– haarcascade_eye.xml
– haarcascade_smile.xml
– haarcascade_frontalface_default.xml

این ها ابزار تشخیص صورت، چشم ها و لبخندها هستند. اگر در تصویر ما چهره ای شاد وجود داشته باشد، باید هر یک از این ویژگی ها را داشته باشیم. کد های هر یک از این لینک ها را دریافت کنید ، آن را در ویرایشگر متن قرار دهید و فایل های خود را با توجه به نام های ذکر شده در بالا ذخیره کنید. هر سه پرونده XML را در همان پوشه قرار دهید که در آن نوت بوک پایتون را شروع می کنید. اکنون که Haas Cascades خود را آماده کردیم وارد محیط مجازی شویم.

تشخیص لبخند 2

الان بالاخره وقت کد نویسیه

۳- وارد کردن OpenCV و بارگذاری ابزارها

import cv2
cascade_face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cascade_eye = cv2.CascadeClassifier('haarcascade_eye.xml') 
cascade_smile = cv2.CascadeClassifier('haarcascade_smile.xml')

تنها کتابخانه مورد نیاز برای دریافت ،OpenCV می باشد. اگرچه این یک ابزار قدرتمند شناسایی اشیا است، اما قدرتمندترین ابزار موجود نیست. کتابخانه های جدید تر و بهتری نیز وجود دارند اما OpenCV هنوز هم ابزار ارزشمندی است و روش خوبی برای درک اصول شناخت شی است. پس از وارد کردن OpenCV (cv2) ، هر یک از ابزار های شناسایی تصویر را که دانلود شده بود فراخوانی کریدم. برای این منظور ، فقط لازم است از تابع OpenCV به نام CascadeClassifier استفاده کنیم.

۴- تعریف تابع تشخیص چهره ، چشم ها و لبخند

def detection(grayscale, img):
    face = cascade_face.detectMultiScale(grayscale, 1.3, 5) 
    for (x_face, y_face, w_face, h_face) in face:
        cv2.rectangle(img, (x_face, y_face), (x_face+w_face, y_face+h_face), (255, 130, 0), 2) 

قبل از اینکه تابع را برای شناسایی تعریف کنید، باید بدانید که قرار است روی یک تصویر اعمال شود ، سپس برای بدست آوردن نتیجه نهایی کنار هم قرار می گیرند.

از آنجا که الگوریتم Viola-Jones با تصاویر در خاکستری کار می کند ، اولین آرگمان این تابع را به عنوان مقیاس خاکستری وارد کردیم.

با این حال همچنین می خواهیم که خروجی نهایی دارای تصویر اصلی رنگی باشد ، بنابراین یک آرگمان دیگر img برای تصویر اصلی وارد می کنم. سپس باید مختصات مستطیل هایی را که چهره را تشخیص می دهند ، بدست آوریم. برای تعریف این مختصات، ۴ حرف را انتخاب کردیم: x ، y ، w ، و h.

x و y مختصات گوشه بالا سمت چپ هستند ، در حالی که w و h به ترتیب عرض و ارتفاع مستطیل ها هستند.

این حرف  ها را در یک صورت متغیر ذخیره کردیم و سپس از یکی دیگر از توابع OpenCV به نام detectMultiScale استفاده کردیم تا در واقع این مختصات را بدست آوریم. بنابراین ما از شی  Cascade_face خود استفاده می کنیم و ۳ آرگومان از روش DetectMultiScale روی آن اعمال می کنیم:

  • مقیاس خاکستری چون تصویر به عنوان سیاه و سفید در حال تجزیه و تحلیل است
  • ضریب مقیاس یک سوم (اندازه تصویر ۱/۳ کاهش می یابد)
  • حداقل تعداد مناطق مجاور پذیرفته شده: ۵ نقطه مجاور.

بعد ، برای رسم مستطیل ها، یک حلقه for ایجاد می کنیم با ۴ حرف x_face ، y_face ، h_face ، w_face در داخل چهره ها. در حلقه for ، ما از تابع مستطیل استفاده کریدم که یکی دیگر از تابع های OpenCV است. این کار در واقع مستطیل را بر روی صورت شما ترسیم می کند و آرگومان های زیر را ارائه می دهد:

آرگومان “img” زیرا می خواهیم مستطیل روی تصویر اصلی رنگی ما کشیده شود.

  • مختصات گوشه بالا سمت چپ: x و y
  • مختصات گوشه پایین سمت راست: w و h
  • رنگ مستطیل: رنگ آبی را انتخاب می کنیم.
  • ضخامت لبه های مستطیل: ضخامت ۲ را انتخاب کردیم (خیلی مهم نیست اما ۲ گزینه خوبی است)

توجه: کد زیر ادامه دارد ( همه را با هم در ادامه قرار داده ایم)

ri_grayscale = grayscale[y_face:y_face+h_face, x_face:x_face     + w_face] 
    ri_color = img[y_face:y_face+h_face, x_face:x_face+w_face]

اکنون که کار چهره تمام شد ، می خواهیم چشم ها را تشخیص دهیم. این تنها بخش مسئله است که کمی مشکل است و درک آن کمی دشوارتر است.

اساساً ، در خطوط بالا ذکر شده است که شما به دنبال چشم در چهره هستید ، بنابراین چهره به “منطقه مورد توجه” ( ROI ) ما تبدیل می شود. از آنجا که الگوریتم با تصاویر در مقیاس خاکستری کار می کند، آرگومان مربوط به مقیاس خاکستری را وارد می کنیم. با این حال ، همچنین می خواهیم تصویر رنگی را نیز دریافت کنم ، بنابراین یک آرگومان دیگر برای تصویر رنگی اضافه می کنیم.

اساساً ، ۲ منطقه مورد توجه وجود دارد: یکی برای تصویر در مقیاس خاکستری و دیگری برای تصویر اصلی رنگی. متعاقباً، مقادیر ri_grays را روی تصویر مقیاس خاکستری با دامنه مختصات مستطیل y: y + h و x: x + w ایجاد می کنیم. سپس روی تصویر رنگی، ri_color را با همان مختصات برای مستطیل ها ایجاد می کنیم.

eye = cascade_eye.detectMultiScale(ri_grayscale, 1.2, 18)

for (x_eye, y_eye, w_eye, h_eye) in eye:
cv2.rectangle(ri_color,(x_eye, y_eye),(x_eye+w_eye, y_eye+h_eye), (0, 180, 60), 2)

برای چشم ها، مرحله اول را با صورت تکرار کردیم و با cascase_eye شیئی به نام چشم ایجاد کردیم و از روش DetectMultiScale برای یافتن ۴ نقطه مورد نظر استفاده کردیم. ضریب مقیاس را به ۱٫۲ و حداقل نقاط مجاور را به ۱۸ تغییر دادیم (برای بدست آوردن نتایج عالی مجبور شدیم این مقادیر را آزمایش کنیم).

سپس یک حلقه for برای چشم ها نیز ایجاد کردیم. می توانید مورد قبلی را کپی پیست کنید ، فقط باید نام های حرف ها را تغییر دهید و رنگ دیگری انتخاب کنید

smile = cascade_smile.detectMultiScale(ri_grayscale, 1.7, 20)
for (x_smile, y_smile, w_smile, h_smile) in smile:
cv2.rectangle(ri_color,(x_smile, y_smile),(x_smile+w_smile, y_smile+h_smile), (255, 0, 130), 2)

return img

سپس دوباره برای لبخند ، همان مراحل تکرار شده برای صورت و چشم را تکرار می کنیم. هنگام استفاده از روش DetectMultiScale ، از ضریب مقیاس ۱٫۷ و حداقل نقاط مجاور به تعداد ۲۰ استفاده کردیم.

(همانطور که قبلاً گفتیم ، برای فهمیدن این کار به آزمایشاتی نیاز است).پس از انجام تمام مراحل ، شما فقط فریم اصلی را بازخوانی می کنید.

۵- نمایش خروجی وب کم

vc = cv2.VideoCapture(0)
while True:
    _, img = vc.read()
    grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    final = detection(grayscale, img) 
    cv2.imshow('Video', final)
    if cv2.waitKey(1) & 0xFF == ord('q'): 
        break 
vc.release() 
cv2.destroyAllWindows() 

با ایجاد یک شی به نام vc شروع کردیم و از کلاس VideoCapture از OpenCV استفاده کردیم. تنها به یک آرگومان نیاز داریم: ۰ یا ۱٫اگر از وب کم داخلی استفاده می کنید ، ۰ اگر خارجی است ۱٫

از آنجا که تابع تشخیص برای یک تصویر واحد کار می کند، اکنون مجبور هستیم نوعی حلقه ایجاد کنیم که به آن امکان اجرای بیش از یک سری عکس را بدهد. بنابراین من یک حلقه while بی نهایت را شروع می کنیم که بعداً با استفاده از یک تابع break آن را می شکنیم. خطوط بعدی ممکن است گیج کننده به نظر برسند ، اما اساساً ، روش خواندن از VideoCapture دارای دو عنصر است:

یکی از آنها آخرین فریمی است که از وب کم ارائه می شود. از آنجا که فقط این را می خواهید، از _ ، img استفاده کنید زیرا روش خواندن ۲ فریم را برمی گرداند و شما فقط این یکی را می خواهید. اکنون باید این روش را از کلاس VideoCapture فراخوانی کنم.

از تابع cvtColor استفاده می کنیم که تصویر رنگی را به مقیاس خاکستری تبدیل می کند، زیرا برای عملکرد شناسایی به یک قاب B&W نیاز دارد. آن را مقیاس خاکستری می نامیم و کلاس cvtColor را می گیرم ، که ۲ آرگومان نیاز دارد:

– قاب (img)

 cv2.COLOR_BGR2GRAY – برای به دست آوردن سایه های مناسب خاکستری ، به طور متوسط آبی-سبز-قرمز.

اکنون من یک متغیر جدید به نام ‘final’ ایجاد کردم و این نتیجه تابع تشخیص می شود. در متغیر “final” ، از تابع تشخیص با آرگومانهای مقیاس خاکستری و img استفاده می کنیم.

تابع imshow یکی دیگر از توابع OpenCV است که به ما امکان می دهد با استفاده از انیمیشن های مستطیل ، محتوای اصلی را که از وب کم آمده است ، مشاهده کنیم. تصاویر پردازش شده را به روشی متحرک نمایش می دهد.

سپس از تابع دیگری برای بستن پنجره استفاده کردیم. شرط if را اعمال کردیم که با هر بار فشار دادن دکمه ‘q’ روی صفحه کلید ، برنامه را خاتمه می دهد. با این کار حلقه while می شکند تا فرآیند پایان یابد.

سرانجام ، از روش انتشار ( release method ) برای خاموش کردن وب کم و عملکرد DestroyAllWindows برای خاتمه دادن به ویندوز استفاده کردیم.

کد کامل خود را در زیر جایگذاری کردیم تا در صورت وجود هرگونه سردرگمی در بخشهای بالا به کد کامل دسترسی داشته باشید.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Aug  7 13:43:51 2019

@author: rohangupta
"""

import cv2

cascade_face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 
cascade_eye = cv2.CascadeClassifier('haarcascade_eye.xml') 
cascade_smile = cv2.CascadeClassifier('haarcascade_smile.xml')

def detection(grayscale, img):
    face = cascade_face.detectMultiScale(grayscale, 1.3, 5)
    for (x_face, y_face, w_face, h_face) in face:
        cv2.rectangle(img, (x_face, y_face), (x_face+w_face, y_face+h_face), (255, 130, 0), 2)
        ri_grayscale = grayscale[y_face:y_face+h_face, x_face:x_face+w_face]
        ri_color = img[y_face:y_face+h_face, x_face:x_face+w_face] 
        eye = cascade_eye.detectMultiScale(ri_grayscale, 1.2, 18) 
        for (x_eye, y_eye, w_eye, h_eye) in eye:
            cv2.rectangle(ri_color,(x_eye, y_eye),(x_eye+w_eye, y_eye+h_eye), (0, 180, 60), 2) 
        smile = cascade_smile.detectMultiScale(ri_grayscale, 1.7, 20)
        for (x_smile, y_smile, w_smile, h_smile) in smile: 
            cv2.rectangle(ri_color,(x_smile, y_smile),(x_smile+w_smile, y_smile+h_smile), (255, 0, 130), 2)
    return img 

vc = cv2.VideoCapture(0) 

while True:
    _, img = vc.read() 
    grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    final = detection(grayscale, img) 
    cv2.imshow('Video', final) 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break 

vc.release() 
cv2.destroyAllWindows() 

۶- جمع بندی

در ابتدا به دلایل زیادی مدل درست کار نمی کرد و چهره ی بدون لبخند را به عنوان لبخند نیز تشخیص می داد. مجبور شدیم با ضریب مقیاس و همچنین حداقل نقاط مجاور کار کنیم تا نتیجه مطلوبی بگیریم.

تشخیص لبخند 3

امیدواریم این آموزش برای شما مفید بوده باشد. اگر شما هم مدلی برای تشخیص لبخند یا احساس توسعه داده اید، نتایج خود را در بخش نظرات با ما به اشتراک بگذارید.

بیشتر بخوانید:

منبع Towards Data Science

درباره‌ی علی قلی زاده

همچنین ببینید

آموزش Keras یادگیری انتقالی با استفاده از مدل های از پیش آموزش دیده

آموزش Keras : یادگیری انتقالی با استفاده از مدل های از پیش آموزش دیده

در آموزش قبلی ، نحوه استفاده از مدل هایی که برای کلاسه بندی تصویر روی …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *