در این پروژه میخواهیم با آموزش یک سامانه یادگیری ماشین روی از مجموعه تصاویری که از چهرهها، به ازای هر تصویر چهره جدیدی که به سامانه نشان میدهیم. در صورت وجود چهره بین مجموعه آموزشی، آن را بازشناسی نماید.
مقدمه
پردازش چهره برای انسانها کار بسیار سادهای است در یک آزمایش نشان داده شده است که حتی یک نوزاد سه ساله میتواند چهرههای آشنا را تشخیص دهد. ولی اینکه این اطلاعات چگونه در مغز کدگذاری میشوند مشخص نیست و آزمایشهای متعددی برای یافتن کدگذاریهای مغز انجام شده است. برخی از سوالاتی که در این باره مطرح هستند را بیان میکنیم.
آیا تشخیص چهره در مغز انسان یک فرایند اختصاصی است؟
در سال ۱۹۸۶ در این مورد چهار آزمایش انجام شد و دانشمندان به این نتیجه رسیدند که تشخیص چهره مانند بقیهی پردازش تصویرهای دیگر در مغز انجام میشود و مهمترین دلیل آن هم این بود که افرادی که بیماری پروزوپاگنوسیس (Prosopagnosis) دارند، بیماریای که افراد چهرهها را به خوبی تشخیص نمیدهند، در تشخیص تصاویر دیگر نیز مشکل دارند.
ولی در سالهای اخیر دانشمندان آزمایشهایی انجام دادهاند و نتایج متفاوتی گرفتهاند و معتقدند که قسمتی کاملا اختصاصی در مغز برای تشخیص چهره وجود دارد. البته این بحث هنوز هم در بین دانشمندان در جریان است.آیا رنگ در تشخیص چهره برای انسان کاربرد دارد؟
بیشتر الگوریتمها از رنگ برای تشخیص چهره استفاده نمیکنند ولی جالب است که رنگ یکی از ملاکهای بسیار مهم برای تشخیص چهره در انسان است؛ مخصوصا برای عکسهایی که خراب شدهاند و یا کیفیت پایینی دارند.آیا تقارن در پردازش چهره نقش مهمی دارد؟
جواب به این سوال بله است و اثبات شده است که با در نظر گرفتن تقارن صورت مقدار قابل توجهی از ابعاد (در این باره بعداً توضیح داده خواهد شد) کاهش مییابد.
حال به بازشناسی چهره در سیستمها میپردازیم. پردازش چهره در سیستمها به طور کلی از دو مرحله تشکیل میشود.
آموزش: تصویر افراد را به برنامه نشان میدهد.
تشخیص: تصویرهای جدید به سیستم داده میشود و انتظار میرود افرادی را که قبلاً آموزش دیده را بشناسد.
در مرحله آموزش میتوان به سیستم فقط یک فرد را آموزش داد که در این صورت از سیستم به عنوان یک فقط تصویری استفاده شده است و یا یک پایگاه داده از افراد خاص مانند مجرمان به سیستم آموزش داده شود که میتوان از این سیستم در مراکز پلیس استفاده کرد. علاوه بر اینها بازشناسی کاربردهای بسیار زیادی در برنامههایی که ما استفاده میکنیم دارند مثلا فرایند Auto Tagging در بعضی از شبکههای مجازی از بازشناسی چهره استفاده میکند.
برنامههای تشخیص چهره از سه بخش کلی تشکیل شدهاند:
تشخیص چهره(Face Detection)
استخراج الگوها(Feature Extraction)
بازشناسی چهره(Face Recognition)
کارهای مرتبط
پردازش تصویر و بازشناسی چهره الگوریتمهای متعددی دارد که بعضی از آنها را که در مقالات مختلف به آنها اشاره شده بود در زیر میآوریم.
۱-بازشناسی چهره بر اساس ویژگیهای هندسی صورت قابل درکترین روش به نظر میرسد. یکی از اولین روشها نقاط نشانگذاری( محل چشمها، بینی، گوش و ...) شده است که بر این اساس یک بردار ویژگی( فاصلهی بین این نقاط، زاویهی بین این نقاط و ...) ساخته میشود. سپس بین این بردارهای تصویر جدید داده شده و تصویرهای آموزش داده شده فاصله اقلیدسی گرفته میشود. این روش مشکلات زیادی دارد و بعدا به این نتیجه رسیدند که ویژگیهای اجزای منفرد صورت برای تشخیص چهره کار مناسبی نیست.[۱]
۲-روش EigenFace تاثیر زیادی بر الگوریتمهای پردازش تصویر گذاشت این روش در سال 1991 توسط ترک و پنتلند پیشنهاد شد. در این روش هدف این است که دادهها تا حد امکان غیروابسته شوند و به دنبال بردارهای متعامدی میگردد که تا حد امکان این خواسته را برآورده کنند و برای این کار از آنالیز المانهای اصلی یا به اختصار PCA استفاده میکند. اساس این روش بر این باور است که تمامی قسمتهای صورت برای بازشناسی به یک اندازه مهم نیستند و مثلا هنگامی که ما به یک فرد نگاه میکنیم به چشمها، بینی، گونهها و پیشانی بیشتر نگاه میکنیم و اینها در تشخیص چهره افراد مهمتر است.
هنگامی که ما به یک فرد نگاه میکنیم به دنبال قسمتهای که بیشترین تغییرات در آنها رخ میدهد هستیم مثلا فاصلهی بین دهان تا بینی. این الگوریتم ابتدا قسمتهای مهم (دارای بیشترین تغییر) را به دست میآورد و سپس آنها را برای تشخیص چهرهی فرد مقایسه میکند.
مشکل اول این الگوریتم این است که به میزان روشنایی نیز به عنوان یک نکتهی مهم در تشخیص چهره اهمیت میدهد و چهرهی افراد در نورهای متفاوت و یا با زاویههای متفاوت عوض میشود و دوم این که این الگوریتم ویژگیهای کل دادهها را با هم دیگر به دست میآورد و در واقع ممکن است ویژگیهای چهره یک فرد در انتخاب ویژگیها در بقیه دادههای تست تاثیر بگذارد.[۲]
۳-روش FisherFace شباهت زیادی به روش EigenFace دارد فقط کمی پیشرفتهتر شده است. الگوریتم EigenFace به تمام عکسهای تست به طور همزمان نگاه میکند و قسمتهای مهم در تشخیص چهره را پیدا میکند و در واقع به ویژگیهایی که یک فرد مشخص را از بقیه متمایز میسازد نگاه نمیکند.
این الگوریتم ویژگیهای چهرههای افراد را به طور جداگانه به دست میآورد و مانند الگوریتم قبلی یک ویژگی از یک فرد بر ویژگیهای سایر افراد تاثیر نمیگذارد.
البته الگوریتم FisherFace یکی از مشکلات الگوریتم EigenFace را برطرف کرد که آن تاثیر ویژگیهای یک فرد بر بقیه افراد بود ولی تاثیر میزان روشنایی نور در این الگوریتم هنوز وجود دارد.
۴-روش LBPH تلاش کرده است که ایرادات روشهای FisherFace و EigenFace را برطرف کند (تاثیر میزان روشنایی). این الگوریتم به طور یکجا به کل تصویر نگاه نمیکند بلکه به pixelها و مقایسههای آنها با pixelهای کناری خود میپردازد. این الگوریتم تا میزان خوبی تاثیر میزان روشنایی را کم کرده است.
۵-یک الگوریتم تشخیص چهره بر اساس روش Modular PCAاست. الگوریتم پیشنهادی با الگوریتم PCA معمولی مقایسه شده است بهبود نرخ تشخیص برای تصاویر چهره با تغییرات زیادی در جهت روشنایی و بیان صورت. در روش پیشنهادی، تصاویر چهره ها را به کوچکتر زیر تصاویر تقسیم و رویکرد PCA است به هر یک از این زیر تصاویر اعمال می شود. از آنجا که برخی از ویژگی های محلی صورت یک فرد انجام است حتی زمانی که ژست، جهت روشنایی و بیان صورت متفاوت است، ما انتظار داریم که روش ارائه شده قادر به مقابله با این تغییرات است.[۳]
۶-در مقاله ای از Trupti M. Kodinariya با ترکیب الگوریتم PCA با چند الگوریتم دیگر یک روش ترکیبی ارائه شده است. که در دو حالت کار میکند:
تمرین
دستهبندی
حالت تمرین شامل نرمال سازی و استخراج ویژگی از تصاویر با استفاده از الگوریتم PCA, ICA می باشد. سپس ویژگی های استخراج شده, با استفاده از BPNN ها (back propagation neural network) تمرین داده می شوند تا فضای ویژگی ها به کلاسهای متفاوت دسته بندی شوند.[۴]
۷-در مقاله ای از احمد محمودی, روشی با نام EigenFace چند لایه ارائه شده است. در این روش برای محاسبه ی مولفه های اصلی از یک شبکه عصبی خطی استفاده شده است, که علاوه بر کاهش حجم مورد نیاز برای محاسبات, طراحی سخت افزار آن بسیارساده تر خواهد بود. همچنین با توجه به قابلیت های شبکه عصبی در پردازش موازی, سرعت انجام محاسبات افزایش چشم گیری داشته است.
آزمایشها
سه تا از الگوریتمهای بالا توسط کتابخانهی OpenCV پیاده سازی شدهاند که در این پروژه ما از این سه الگوریتم استفاده میکنیم:
EigenFace ,FisherFace, LBPH
که البته پیش از بازشناسی چهره باید آن را تشخیص بدهیم برای این کار باز هم از یک روشی استفاده کردیم که در OpenCV پیادهسازی شده است؛ الگوریتم Cascade یا آبشاری. در این الگوریتمها در مراحل مختلف ویژگیهای متفاوتی به ترتیب بررسی میشود و اگر در یکی از آنها ویژگی مورد نظر برآورده نشود سراغ مرحلهی بعدی نمیرود. به ویژگیهای ذکر شده Haar Features میگویند.
برای پیادهسازی ابتدا نیاز به یک دیتاست برای یادگیری چهرهها داریم برای اینکار از دو دیتاست متفاوت استفاده کردیم.
۱-دیتاست اول، دیتاستی بود که خودمان به وجود آورده بودیم که شامل ۱۰ نفر و از هر نفر تعداد متفاوتی عکس با حالتهای چهرهی متفاوت مانند خندان، ناراحت، متعجب و ... بود (با کیفیتهای متفاوت)
۲-دیتاست دوم دیتاست دانشگاه کمبریج بود که در آن ۴۰ چهره و در کل ۴۰۰ عکس وجود داشت و برای هر عکس حالتهای نور از وسط، با عینک و بدون عینک، شاد، نور از چپ و راست، خواب، چشمک زدن و متعجب وجود داشت(۱۰حالت).
۹ تا از این دیتاها را برای Train در نظر گرفتیم و یکی را برای Test.
نکتهای که در هنگام پیادهسازی با آن مواجه شدیم این بود که EigenFace و FisherFace برای یادگیری و تست به عکسهایی با تعداد پیکسل یکسان نیاز دارند و نمیتوان عکسهای با کیفیت متفاوت و یا ابعاد متفاوت به آنها داد، البته با کمک OpenCV پیادهسازی نسبتا آسانی دارند و فقط کافی است از Face_recognizer مورد نظر استفاده کنیم ولی از آنجایی که دیتاستی که داشتیم شامل عکسهای با سایز یکسان نبود الگوریتم LBPH را توضیح میدهیم که تقریبا شبیه به Modular PCA هم است و خروجی بهتری دارد.
الگوریتم LBPH به این ترتیب عمل میکند که یک آرایه ۳*۳ میسازد و آن را از روی کل عکس عبور میدهد و یک پیکسل را با خانههای مجاورش مقایسه میکند اگر مقدار intensity در آن خانه کمتر یا مساوی با خانه مجاور بود مقدار ۱ را قرار میدهیم و در غیر این صورت مقدار صفر. سپس از این این جدول باینری به دست آمده یک دور ساعتگرد میچرخیم و عدد را تبدیل به مبنای ۱۰ میکنیم.
سپس از این عددهای مبنای ده یک نمودار هیستوگرام میسازیم.
در آخر هر عکس با یک هیستوگرام متناظر میشود. حال هنگامی که تمام دادههای Train را تبدیل به هیستوگرام کرد عکسی که میخواهد توسط آن تست را انجام دهد با هیستوگرامهای قبلی مقایسه میکند و فرد مورد نظر را پیدا میکند.
حال چند مثال از عکسهای train و test شده را میآوریم(دیتاست دانشگاه کمبریج):
خروجی برنامه:
چند مثال از دیتاست شخصی:
خروجی برنامه:
ارزیابی خروجی
برای ارزیابی خروجی از دیتاست دانشگاه استفاده کردیم و هنگامی که برای هر subject با ۹ عکس یادگیری انجام میشد و با ۱ عکس تست انجام میشد نتیجه به صورت زیر بود:
دلیل نسبتا پایین بودن درصد درستی این است که در این دیتاست عکسها کاملا از چهره گرفته شدهاند و بعضی عکسها حاشیهای ندارد، از آنجایی که کد ما ابتدا چهره را پیدا میکند و سپس روی آنها الگوریتم را اجرا میکند در این موارد نمیتواند چهره را به درستی پیدا میکند و عکس را به عنوان یک عکسِ اشتباه در نظر میگیرد. (در واقع میتوان گفت بعضی عکسها زیادی زوم شده هستند)
بهبود نتایج
کلاسیفایر Cascade که در برنامه استفاده کردیم دو پارامتر minNeighbors و ScaleFactor دارد که با تغییر آنها میتوان نتایج را بهبود بخشید. از آنجایی که مشکل اصلی یا گلوگاه کار در پیدا کردن چهره در تصویر بود؛ در تصویر هایی که چهره را پیدا نمیکرد چند ین بار عکس را با حالت های مختلفی از ScaleFactor و minNeighbors بررسی میکند تا بتواند چهره را به درستی تشخیص دهد.(برای اضافه کردن این بهبود باید در کد accuracy را برابر با high قرار دهید زیرا حالت defaul آن برای سرعت بیشتر برابر با low قرار داده شده است).
درصد درستی با اضافه کردن این تغییر مانند جدول زیر شد.
میزان بهبود نتایج با این تغییر به طرز عجیبی بالا بود و به ۱۰۰٪ درست تشخیص دادن در مورد دیتاست موجود رسید.
در این فاز سعی شد با استفاده از دیتاست (LFW (Labeled Face in the Wild و با استفاده از معیارهای precision و recall نتایج را دقیقتر ارزیابی کنیم. به این منظور ابتدا توضیح مختصری دربارهی این معیارها و دیتاست استفاده شده میدهیم.(تمامی مثالهایی که آورده میشود از این دیتاست است)
برای آشنایی با precision و recall ابتدا ماتریسی به نام confusion matrix را معرفی میکنیم.[۵]
TP:True Positive ~ کلسیفایر به درستی در کلاس مثبت قرار داده است
TN:True Negative~ کلسیفایر به درستی در کلاس منفی قرار داده است
FP:False Positive~ کلسیفایر به اشتباه در کلاس مثبت قرار داده است
FN:False Negative~ کلسیفایر به اشتباه در کلاس منفی قرار داده است
البته confusion matrix بالا مخصوص کلسیفایرهای باینری است یعنی در واقع در هنگامی که فقط دو کلاس داشته باشیم؛ در مبحث پردازش تصویر اگر عکسها را به صورت جفت جفت بررسی کنیم که آیا تصویر یک فرد را نشان میدهد( که به آن Face Verification نیز میگویند) کلسیفایر به صورت باینری میشود ولی اگر بخواهیم تشخیص بدهیم عکس فردی که در test داده شده کدام یک از افراد train است( که به آن Face Recognition نیز میگویند) باید از confision matrix برای حالت multi class استفاده کنیم.
همانطور که گفتیم ماتریس بالا مخصوص کلسیفایرهای باینری است پس precision و recall هم که در عکس آورده شده برای حالت باینری است و فرمول حالت کلی آن( multi class) به شکل زیر است.
به استفاده از فرمول بالا میتوان برای هر کلاس مقدار precision و recall را محاسبه کرد سپس با استفاده از یک میانگین وزندار که وزن آن براساس معیار Support تعیین میشود( تعداد افرادی که در آن کلاس داده شده است)، یک مقدار precision و recall کلی برای کلسیفایرمان پیدا میکنیم.
حال توضیح مختصری دربارهی دیتاست میدهیم. دیتاست LFW شامل بیش از ۱۳۰۰۰ عکس است که توسط face detector Viola-Jones از اینترنت جمعآوری شده است. ۱۶۸۰ نفر در این دیتاست دو عکس و یا بیشتر عکس دارند. برای گرفتن دیتاست از دو روش میشد استفاده کرد.
روش اول استفاده از ماژول sklearn.datasets در python بود که دیتا را خودش load میکرد. ولی مشکل اینجا بود که دیتایی که توسط آن load میشد توسط face detector در opencv خوانده نمیشد؛ البته میشد از detector خود sklearn نیز استفاده کرد( sklearn خودش PCA دارد که مشابه EigenFace است) ولی از آنجایی که میخواستیم face detector خودمان در opencv را ارزیابی کنیم از روش دوم استفاده کردیم.
روش دوم دانلود دیتاست از از این لینک است و سپس توسط پایتون براساس کمترین تعداد عکسی که میخواهیم از هر چهره داشته باشیم آنها را جدا میکنیم و بعد با استفاده از هر نسبتی از train و test آنها را دستهبندی میکنیم. برای خواندن دیتاست و جدا کردن train و test برنامه پایتون نوشتیم که میتوان نسبت test به کل داده (به طور پیش فرض ۰.۳ گذاشته شده) و حداقل تعداد عکسها از هر فرد را به آن داد و دیتا را بر این اساس جدا میکند و در دو فولدر جداگانه برای train و test قرار میدهد. (کدهای مربوط به این قسمت در lfw.py زده شده است)
هنگامی که حداقل میزان عکس را برای هر فرد برابر با ۱۰ فرض میکنیم تعداد افراد موجود در دیتاست ۱۵۸ نفر( ۳۰۹۰ عکس در یادگیری و ۱۰۲۳عکس در تست) میشود که در هنگام نمایش دادن با confusion matrix کمی شلوغ و نا مفهوم میشود( البته برای محاسبه مشکلی وجود ندارد و به درستی محاسبه میشود و precision و recall را از روی آن در میآوریم). برای همین یک مثال با حداقل عکس برای هر نفر برابر با ۱۰۰ میزان که تعداد افراد به ۵ تا کاهش مییابد.
برای کشیدن confusion matrix از ماژول sklearn.metrics استفاده میکنیم.
حال به دنبال محاسبهی precision و recall میرویم. تعریف هر کدام از این موارد را در بالا گفتیم. برای محاسبهی آن باز هم از ماژول sklearn.metrics استفاده کردیم و آن را در بالای جدول confusion matrix چاپ میکنیم. باز هم یک مثال برای حالتی که حداقل تعداد عکسها برای هر فرد بیشتر از ۱۰۰ باشد را میاوریم تا هم confusion matrix و هم precision و recall واضح و قابل درک باشند.
حال که به خوبی با این معیارها آشنا شدیم و مثالهایی از خروجی برنامه برای حالتهای ساده را دیدیم، حداقل تعداد عکسها برای هر شخص را برابر ۱۰ قرار میدهیم و precision و recall را محاسبه میکنیم (چون تعداد کلاسها زیاد میشود چاپ کردن confusion matrix خروجی واضحی ندارد).
ابتدا برای حالت "accuracy = "low اجرا میکنیم.
نتیجه:
حال برای حالت "accuracy="high اجرا می کنیم.
نتیجه:
ممکن است در ابتدا به نظر برسد که هیچ پیشرفتی در نتایج حاصل نشده است در صورتی که اینطور نیست. همانطور که میداند بازشناسی چهره از دو بخش کلی تشخیص و شناسایی چهره تشکیل شده است. قسمتی از پروژه را که ما در با این روش بهبود بخشیدیم قسمت تشخیص چهره بود که در این معیارهای precision و recall دیده نمیشود. زیرا در حالت 'accuracy='low خیلی از عکسهای قسمت تست اصلا چهرهشان تشخیص داده نمیشود و برای همین در هیچ کلاسی گذاشته نمیشوند و به طور کلی در معیارهای precision و recall در نظر گرفته نمیشوند چون کلا در confusion matrix نیستند. برای مثال در حالتی که minface=50 است تعداد عکسهایی که برای تست ایجاد میشود برابر با ۴۶۳ عدد است که اگر 'accuracy='low باشد فقط ۳۸۷ عدد از آنها پیشبینی میشوند و بقیه کلا چهره در آنها تشخیص داده نشده و در precision و recall حساب نمیشوند، ولی اگر 'accuracy='high باشد همهی ۴۶۳ عکس پیشبینی میشوند.
برای این که این مسئله مشخصتر شود جدولی از حالتهای مختلف خروجی برنامه مطابق شکل زیر تهیه شده است.
همانطور که میبینید precision و recall تقریبا تغییری نکرده است( بعضی وقتها در هنگام اجرای برنامه accuracy=high بهتر عمل میکند بعضی وقتها accuracy=low معیارهای بالاتری دارد) ولی چیزی که همیشه در accuracy =high بهتر از low است همانطور که در جدول بالا دیده میشود تعداد چهرههای پیشبینی شده است.
برای کار کردن با برنامه حتما باید ابتدا دیتاست را از این لینک دانلود کنید و extract کنید و نام آن را oldlfw قرار دهید و در دایرکتوری پروژه در کنار face.py و lfw.py و config.py بریزید (همگی این ۴تا باید در یک فولدر باشند).
سپس به دو طریق میتوانید مقادیر پیشفرض را تغییر دهید:
۱)با استفاده از پاس دادن آرگومانها از طریق ترمینال (در گیت شرح داده شده)
بطور مثال:'python2 face.py --train 'lfw' --split 0.3 --minface 10 --confm 'OFF' --showimgs 'OFF
۲) با استفاده از تغییر دادن فایل config.py:
هر کدام از مقادیری که به صورت پیشفرض برای برنامه در نظر گرفته شدهاند را میتوانید در این فایل تغییر دهید و سپس برنامه را بدون هیچ آرگومانی اجرا کنید.
python2 face.py
آدرس دسترسی به گیت کد
(قبل از اجرا میتوانید برای کار کردن راحتتر با کد readme.md را بخوانید)
(چندتا عکس نیز از خروجیهای مختلف برنامه نیز در گیت گذاشته شده است)
(ممکن است در بعضی از حالتها به یک warning به این شکل برخورد کنید:
UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.
دلیل آن این است که در حالتهایی که عکسها زیاد شدهاند بعضی از افراد کلا درست تشخیص داده نمیشوند یعنی صورت کسر در فرمول precision و recall صفر میشود که کل کسر را صفر میکند و در نتیجه این اخطار حاصل میشود)
کارهای آینده
الگوریتمهای بهتر و قویتری از EigenFace و FisherFace و LBPH نیز وجود دارند که برای بهبود نتایج میتوان از آنها استفاده کرد برای مثال الگوریتم (HOGs(Histogram of Oriented Gradients و الگوریتم شبکه عصبی.
الگوریتمهای پیشرفتهی تشخیص چهره ترکیبی از OpenCV و یادگیری ماشین هستند که میتوان برای بهبود از آنها استفاده کرد.
مراجع
[1]Brunelli, R., Poggio, T. Face Recognition through Geometrical Features. European Conference on Computer Vision (ECCV) 1992, S. 792–800.
[2]M. Turk and A. Pentland, "Eigenfaces for Recognition", Journal of Cognitive Neuroscience, vol.3, no.1, pp.71-86, 1991, hard copy.
[3]Gottumukkal, Rajkiran and Asari, Vijayan K.. An improved face recognition technique based on modular PCA approach. . In Pattern Recognition Letters, (25) 4: 429-436, Year 2004 .
[4]Trupti M. Kodinariya: Hybrid Approach to Face Recognition System using Principle component and Independent component with score based fusion process. CoRR abs/1401.0395 (2014).
[5] Marina Sokolova, Guy Lapalme: A systematic analysis of performance measures for classification tasks
پیوندهای مفید
[مقاله از شناخت چهره با استفاده از PCA چند لایه و شبکه ی عصبی خطی] http://www.civilica.com/Paper-ACCSI12-ACCSI12_185.htm