آموزش رایگان تشخیص چهره با OpenCV در پایتون
- زمان مطالعه: 7 دقیقه
- اشتراک گذاری این نوشته در:
در این آموزش جذاب، صفر تا صد برنامه تشخیص چهره با استفاده از کتابخانه OpenCV و با یاری از زبان برنامه نویسی پایتون را یاد میگیریم. فرایندِ تشخیص چهره که امروزه در دنیای حقیقی مورد استفاده قرار میگیرد یکی از پرقدرتترین ابزارهای مدرن در حوزه هوش مصنوعی میباشد. به طور مثال، تشخیص هویت تصویری، سیستمهای امنیتی و کاربردهای پزشکی تنها تعدادی از کاربردهای این حوزه هستند و نکته اساسی این حوزه افزایش روزافزون در حوزهها و جنبههای مختلف این سیستم در سراسر جهان است.
کتابخــانه OpenCV
میتوان OpenCV را به عنوان معروفترین کتابخانه در حوزه بینایی ماشین (Computer Vision) معرفی کرد. اصل این کتابخانه برای زبان ++C/C نوشته شده اما با گذشت زمان، اکنون استفاده از آن در زبان برنامهنویسی پایتون نیز مقدور میباشد.
OpenCV برای یافتن چهره اشخاص در تصاویر مختلف، از الگوریتمهای یادگیری ماشین استفاده میکند. به این دلیل که ساختار چهره بسیار پیچیده است و هیچ مثالی وجود ندارد که به وضوح، یافت شدن یا نشدن چهره در یک تصویر را اطلاع دهد. الگوریتمهای بکار گرفته شده قادر هستند تا عملیات پیچیده تشخیص چهره را به هزاران عمل کوچکتر و باینری تقسیم کنند؛ سپس حل هر یک از این اعمال کوچک، بسیار سادهتر میشود. این اعمال کوچک را طبقهبندیها یا Classifiers میگویند.
برای یک شیء مانند چهره، ممکن است شما 6000 یا تعداد بیشتری از طبقهبندیها داشته باشید که هرکدام از آنها برای تشخیص داده شدن باید با قالب یک چهره همخوانی داشتهباشند (که خطاهایی در این همخوانی هم وجود دارد). برای تشخیص چهره، الگوریتم، بررسی تصویر را از بالا سمت چپ شروع کرده و به سمت پایین حرکت میکند و تصویر را در قالب خانههایی کوچک از دادهها برسی میکند. سپس درباره هر قطعه این سوال از خود میپرسد: آيا این تصویرِ یک چهره است؟ و در نهایت اگر خانهای شبیه به چهره بود آن را ثبت میکند. برای درک بهتر این موضوع میتوان یک پازل را در نظر گرفت؛ پازل یک تصویر است که به چندین خانه یا قطعه کوچکتر تقسیم شدهاست، حال اگر شما بخواهید در تصویر اصلی یک چهره را پیدا کنید، باید به ترتیب هر یک از قطعههای کوچک پازل را برسی کرده و در صورت وجود چهره آن را ثبت کنید. اما مشکل اینجاست که الگوریتم باید هر قطعه از تصویر را با 6000 طبقهبندی موجود تطابق دهد و این امر سبب افزایش حجم محاسبات میشود.برای حل این مسئله، OpenCV از Cascades استفاده میکند. حال Cascases چیست؟
به کمک Cascades در OpenCV میتوان مسائل را به ایستگاههای مختلفی تقسیم کرد. برای هر بلوک آزمونی تخمینی و سریع اجرا میشود؛ اگر نتیجه آزمون مثبت باشد، آزمون با جزئیات بیشتری اجرا میشود و … . الگوریتم ممکن است به ۳ تا ۵۰ مورد از این ایستگاهها تقسیم شود. تنها زمانی یک چهره تشخیص داده میشود که تمامی این مراحل با موفقیت طی شوند.
مزیت این روش این است که بخش عظیمی از تصویر پاسخی منفی در مراحل اولیه خواهند داد که در نتیجه الگوریتم زمان خود را برای آزمون تمامی ۶۰۰۰ ویژگی بر روی تصویر تلف نخواهد کرد. به جای زمان بری حدود ساعتها، تشخیص چهره میتواند در لحظه صورت پذیرد.
Cascades در عمل
با وجود این که تئوری تشخیص چهره پیچیده بنظر میرسد اما در عمل بسیار سادهاست. Cascades دارای گروهی از فایلهای XML میباشند که این فایلها دارای دادههای مورد نیاز برای تشخیص اشیاء مختلف نظیر چهره، بدن، توپ و… هستند. کافیست فایل مورد نظر برای تشخیص شیء دلخواهتان را در کد وارد کنید که در نهایت OpenCV آن شیء را درون تصاویر تشخیص میدهد.
نصب OpenCV
توجه داشته باشید که این کتابخانه فقط از نسخه 3.6 به پایین پشتیبانی میکند. برای نصب آن، در Windows دستور زیر را در Command Prompt وارد کنید:
python –m pip install opencv-python
در صورت استفاده از سیستمعامل Linux دستورهای زیر را خط به خط وارد کنید:
sudo apt-get python3-pip python3-opencv
pip install opencv-python
برای اطمینان از نصب کتابخانه، وارد IDLE پیشفرض پایتون شده و دستور زیر را وارد کنید:
import cv2
نوشتن کد تشخیص چهره با OpenCV در پایتون
در گام نخست، لازم است فایل XML مرتبط با تشخیص چهره را از اینجا دانلود کنید. پس از ورود به سایت فایل haarcascade_frontalface_default.xml را میتوانید مشاهده و دانلود نمایید.
در ابتدا باید مقادیر لازم و آدرس دهی های لازم را در کد وارد کنیم:
import cv2
imagePath = "test.jpg"
cascPath = "haarcascade_frontalface_default.xml"
در خط اول پکیج cv2 را وارد میکنیم و در خط دوم آدرس عکس دلخواه خود که در اینجا با نام test و دارای پسوند jpg میباشد را وارد میکنیم و در خط سوم مسیر فایل XML دانلود شده را وارد میکنیم.
توجه نمایید که برای اجرای درست و بدون خطای کدهای برنامه لازم است در سیستم یک دایرکتوری(پوشه) خاص را در نظر بگیریم و کد نویسی را در همان دایرکتوری ذخیره نماییم و همینطور تصاویر برای تشخیص چهره و فایل XML را در دایرکتوری پروژه قرار دهیم. در صورت مواجه با هر گونه ابهام یا مسئله ای به پشتیبانی وب سایت در تلگرام (به آی دی baghbani28) پیام دهید تا در سریعترین زمان فایل موجود برایتان ارسال گردد.
حال کلاس لازم برای تشخیص چهره را با استفاده از بارگذاری فایل XML مربوطه ایجاد میکنیم:
faceCascade = cv2.CascadeClassifier(cascPath)
بارگذاری فایل تصویــر مورد نظر
در ادامه فایل تصویر موردنظر را بارگذاری میکنیم.
در خط اول با استفاده از تابع imread، فایل عکس مورد نظر را بارگذاری کرده و در قالب یک ماتریس 3 بعدی داخل متغییر image قرار میدهیم:
کتابخانه OpenCV فقط قادر به تشخیص اشیاء در تصاویر سیاه سفید میباشد پس در خط دوم تصویر رنگی را به تصویر سیاه و سفید تبدیل میکنیم:
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
عملیات تشخیص چهره
این تابع درواقع بخش کلیدی برنامه ما میباشد که عملیات تشخیص چهره را انجام میدهد:
faces = faceCascade.detectMultiScale(
gray,
scaleFactor = 1.1,
minNeighbors = 5,
minSize = (30, 30)
)
# By KhaneCode
بیاید نگاهی به پارامترهای ورودی بیاندازیم:
1- اولین پارامتر متغییر gray یا همان تصویر سیاه سفید ما میباشد.
2- گاه ممکن است یک چهره در تصویر نزدیکتر از دیگر چهرهها درون تصویر باشد و بزرگتر بنظر برسد؛ scaleFactor معیاری برای متعادل کردن این اختلاف اندازه است.
3- الگوریتم تشخیص چهره از حرکت پنچرهای برای تشخیص استفاده میکند. پارامتر minNeighbors تعیین میکند که در عملیات تشخیص، به چند پنجره نزدیک پنجره اصلی توجه شود. همچنین minSize اندازه آن پنجرهها را تعیین میکند.
لیستی از مشخصات مکانی چهرههای موجود
در نهایت این تابع یک لیست از مشخصات مکانی چهرههای موجود در تصویر را برمیگرداند.
print("Found {0} faces!".format(len(faces)))
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
حال با استفاده از مشخصات مکانی چهرهها نسبت به تصویر اصلی، مستطیلهایی دور آنها رسم میکنیم تا مشخص شود که این تشخیصها درست بودهاند یا خیر. توجه داشته باشید که در اینجا با استفاده از تابع rectangle از کتابخانه OpenCV عملیات رسم را روی تصویر اصلی (رنگی) انجام میدهیم. زیرا در هنگام تبدیل عکس رنگی به سیاه سفید، ابعاد آن تغییری پیدا نمیکند و در نتیجه مشخصات مکانی چهره نیز ثابت میماند.
مشخصات مکانی شامل نقطه عرضی (x) و نقطه طولی (y) که موقعیت را نشان میدهد و اندازه عرض (w) و اندازه طول (h) که ابعاد چهره را نشان میدهد، میباشد.
cv2.imshow("Faces found", image)
cv2.waitKey(0)
در اینجا با استفاده از تابع imshow تصویر نهایی را نمایش میدهیم و با متد waitKey منتظر میمانیم تا کاربر کلیدی را فشار دهد.
نمونهای از نتایج به دست آماده
یکی از تصاویری که در این پروژه مورد بررسی قرارگرفته است را مشاهده میکنید:
همانطور که در تصویر بالا مشاهده میکنید برنامه به درستی کار میکند. علاوهبراین تصویر تصویر دیگری را مورد بررسی قرار دادیم که متوجه وجود خطایی جزیی در برنامه شدیم…
در تصویر بالا دو خطا وجود دارد. برنامه به اشتباه دو بخش از تصویر را به عنوان چهره شناسایی کردهاست. برای حل این مشکل پارامتر scaleFactor را به مقدار 1.35 تغییر میدهیم.
مشاهده میکنید که خطا رفع شده و فقط چهرهها انتخاب شدهاند. اما چه اتفاقی افتاد؟ همانطور که در ابتدای مقاله گفتهشد، ممکن است چهرهها در جایگاههای مختلفی درون تصویر قرار بگیرند که این امر گاهی سبب بروز خطا میشود. همچنین کیفیت تصویر داده شده نیز در دقت تشخیص نقش دارد. این خطا را میتوان با تعیین scaleFactor مناسب حل کرد.
کل کدهای پروژه به صورت یکجــا و کامل:
# importing the module
import cv2
imagePath = "test.jpg"
cascPath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor = 1.35,
minNeighbors = 5,
minSize = (30, 30)
)
print("Found {0} faces!".format(len(faces)))
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow("Faces found", image)
cv2.waitKey(0)
#By KhaneCode
#https://khanecode.ir