آموزش پایتون OpenCV-بینایی رایانه ای با OpenCV در پایتون

آموزش پایتون OpenCV-بینایی رایانه ای با OpenCV در پایتون

OpenCV آموزش - Edureka

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

ما مفاهیم زیر را بررسی می کنیم:

کامپیوتر چیست بینایی؟ رایانه چگونه تصویر را می خواند؟ OpenCV چیست؟ مبانی OpenCV تشخیص تصویر با استفاده از OpenCV آشکارساز حرکت با استفاده از OpenCV

چشم انداز رایانه ای چیست؟

برای ساده سازی پاسخ به این مورد - اجازه دهید سناریویی را در نظر بگیریم.

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

بنابراین ، فکر می کنید ویژگی برچسب خودکار چگونه کار می کند؟ به زبان ساده ، روی بینایی رایانه کار می کند.

بینایی کامپیوتری یک حوزه بین رشته ای است که به نحوه ایجاد رایانه برای درک سطح بالا از تصاویر یا فیلم های دیجیتالی می پردازد.

ایده در اینجا این است که وظایفی را که سیستم های بصری انسان می توانند انجام دهند ، خودکار کند. بنابراین ، یک کامپیوتر باید بتواند اشیایی مانند صورت یک انسان یا چراغ چراغ یا حتی یک مجسمه را تشخیص دهد.

چگونه یک کامپیوتر یک تصویر را می خواند؟

تصویر زیر را در نظر بگیرید:

ما می توانیم بفهمیم این تصویری از خط افق نیویورک است. اما آیا یک کامپیوتر می تواند همه اینها را به تنهایی پیدا کند؟ پاسخ منفی است!

رایانه هر تصویری را در محدوده مقادیر بین 0 تا 255 می خواند.

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

برای هر رنگ اصلی یک ماتریس تشکیل می شود و بعداً این ماتریس ها ترکیب می شوند و مقدار Pixel را برای رنگهای R ، G ، B ارائه می کنند.

هر کدام عنصر ماتریس داده های مربوط به شدت روشنایی پیکسل را ارائه می دهد.

تصویر زیر را در نظر بگیرید:

همانطور که نشان داده شده است ، اندازه تصویر در اینجا می تواند B*A x 3 محاسبه شود.

توجه: برای یک تصویر سیاه و سفید ، فقط یک کانال واحد وجود دارد.

در ادامه این مقاله ، بیایید ببینیم که OpenCV در واقع چیست.

OpenCV چیست؟

< p> OpenCV یک کتابخانه پایتون است که برای حل مشکلات بینایی کامپیوتر طراحی شده است. OpenCV در ابتدا در سال 1999 توسط اینتل توسعه یافت اما بعداً توسط Willow Garage پشتیبانی شد.

OpenCV از طیف گسترده ای از زبان های برنامه نویسی مانند C ++ ، Python ، Java و غیره پشتیبانی می کند. و MacOS.

OpenCV پایتون چیزی نیست جز یک کلاس بسته بندی برای کتابخانه اصلی C ++ که با پایتون استفاده می شود. با استفاده از این ، همه ساختارهای آرایه OpenCV به/از آرایه های NumPy تبدیل می شوند.

این امر ادغام آن با سایر کتابخانه هایی که از NumPy استفاده می کنند را آسان می کند. برایبه عنوان مثال ، کتابخانه هایی مانند SciPy و Matplotlib.

در ادامه این مقاله ، اجازه دهید برخی از عملیات اساسی را که می توانیم با OpenCV انجام دهیم ، بررسی کنیم.

عملیات اساسی با OpenCV؟ < /h1>

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

بارگیری یک تصویر با استفاده از OpenCV:

 وارد کردن cv2
# تصویر رنگی
Img = cv2.imread ("Penguins.jpg" ، 1)
# سیاه و سفید (مقیاس خاکستری)
Img_1 = cv2.imread ("Penguins.jpg" ، 0)) 

همانطور که در قطعه کد بالا مشاهده شد ، اولین نیاز وارد کردن ماژول OpenCV است.

بعداً ما می تواند تصویر را با استفاده از ماژول imread بخواند. 1 در پارامترها نشان می دهد که یک تصویر رنگی است. اگر پارامتر به جای 1 ، 0 باشد ، به این معنی است که تصویر وارد شده یک تصویر سیاه و سفید است. نام تصویر در اینجا "پنگوئن ها" است. کاملاً ساده ، درست است؟

شکل تصویر/وضوح تصویر:

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

 وارد کردن cv2
# سیاه و سفید (مقیاس خاکستری)
Img = cv2.imread ("Penguins.jpg"، 0)
Print (img.shape) 

منظور از شکل تصویر ، شکل آرایه NumPy است. همانطور که در اجرای کد مشاهده می کنید ، ماتریس شامل 768 ردیف و 1024 ستون است.

نمایش تصویر:

نمایش تصویر با استفاده از OpenCV بسیار ساده و سرراست است. به زیر مراجعه کنید.

 وارد کردن cv2
# سیاه و سفید (مقیاس خاکستری)
Img = cv2.imread ("Penguins.jpg"، 0)
cv2.imshow ("پنگوئن ها" ، img)
cv2.waitKey (0)
# cv2.waitKey (2000)
cv2.destroyAllWindows () 

همانطور که مشاهده می کنید ، ابتدا تصویر را با استفاده از imread وارد می کنیم. ما برای نمایش تصاویر به یک خروجی پنجره نیاز داریم ، درست است؟

ما از تابع imshow برای نمایش تصویر با باز کردن یک پنجره استفاده می کنیم. 2 پارامتر برای تابع imshow وجود دارد که نام پنجره و تصویر مورد نظر است.

بعداً منتظر یک رویداد کاربر هستیم. waitKey تا زمانی که کاربر کلیدی را فشار ندهد پنجره را ثابت می کند. پارامتری که به آن منتقل می شود زمان بر حسب میلی ثانیه است.

و در نهایت ، ما از killAllWindows برای بستن پنجره بر اساس پارامتر waitForKey استفاده می کنیم.

تغییر اندازه تصویر:

< p> به طور مشابه ، تغییر اندازه تصویر بسیار آسان است. در اینجا قطعه کد دیگری وجود دارد:

 وارد کردن cv2
# سیاه و سفید (مقیاس خاکستری)
img = cv2.imread ("Penguins.jpg"، 0)
resized_image = cv2.resize (img، (650،500))
cv2.imshow ("پنگوئن ها" ، resized_image)
cv2.waitKey (0)
cv2.destroyAllWindows () 

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

بعداً توجه داشته باشید که شیء تصویر از img به resized_image تغییر می کند ، زیرا شیء تصویر در حال حاضر تغییر کرده است.

بقیه کد برای کد قبلی بسیار ساده است ، درست است؟

من مطمئن هستم که شما کنجکاو هستید که به پنگوئن ها نگاه کنید ، درست است؟ این تصویری است که ما در تمام این مدت به دنبال خروجی آن بودیم!

روش دیگری برای انتقال پارامترها به تابع تغییر اندازه وجود دارد. به پایین مراجعه کنید.

 Resized_image = cv2.resize (img، int (img.shape [1]/2)، int (img.shape [0]/2))) 

در اینجا ، شکل تصویر جدید نصف تصویر اصلی می شود.

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

تشخیص چهره با استفاده از OpenCV

این روش در ابتدا پیچیده به نظر می رسد اما بسیار آسان است. اجازه دهید کل مراحل را با شما در میان بگذارم و شما نیز همان احساس را خواهید داشت.

مرحله 1: با توجه به پیش نیازهای ما ، برای شروع به تصویر نیاز داریم. بعداً ما باید یک طبقه بندی آبشار ایجاد کنیم کهدر نهایت ویژگی های چهره را به ما می دهد.

مرحله 2: این مرحله شامل استفاده از OpenCV است که تصویر و فایل ویژگی ها را می خواند. بنابراین در این مرحله ، آرایه های NumPy در نقاط اصلی داده وجود دارد.

تنها کاری که باید انجام دهیم این است که مقادیر سطر و ستون صورت NumPy ndarray را جستجو کنیم. این آرایه با مختصات مستطیل صورت است.

مرحله 3: این مرحله نهایی شامل نمایش تصویر با کادر صورت مستطیلی است.

تصویر زیر را بررسی کنید ، در اینجا من خلاصه کرده ام 3 مرحله به شکل تصویر برای خوانایی راحت تر:

بسیار ساده ، درست است؟

ابتدا ، یک شی CascadeClassifier برای استخراج ویژگی های صورت ایجاد می کنیم ، همانطور که قبلاً توضیح داده شد. مسیر فایل XML که حاوی ویژگی های چهره است ، پارامتر اینجاست.

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

از چه مختصاتی می پرسید؟ این مختصات مستطیل صورت است. scaleFactor برای کاهش مقدار شکل تا 5٪ تا زمانی که صورت پیدا شود استفاده می شود. بنابراین ، در کل - هر چه مقدار کوچکتر باشد ، دقت بیشتر است.

در نهایت ، صورت روی پنجره چاپ می شود.

افزودن کادر صورت مستطیلی:

< p> این منطق بسیار ساده است - به سادگی استفاده از دستور حلقه for. تصویر زیر را ببینید.

ما تعریف روش ایجاد مستطیل با استفاده از cv2.rectangle با عبور پارامترهایی مانند شیء تصویر ، مقادیر RGB طرح کلی جعبه و عرض مستطیل.

اجازه دهید کل کد را برای تشخیص چهره بررسی کنیم: < /p>

 وارد کردن cv2
# یک CascadeClassifier Object ایجاد کنید
face_cascade = cv2.CascadeClassifier ("haarcascade_frontalface_default.xml")
# خواندن تصویر همانطور که هست
img = cv2.imread ("photo.jpg")
# خواندن تصویر به عنوان تصویر مقیاس خاکستری
gray_img = cv2.cvtColor (img ، cv2.COLOR_BGR2GRAY)
# مختصات تصویر را جستجو کنید
چهره ها = face_cascade.detectMultiScale (gray_img، scaleFactor = 1.05،
                                      حداقل همسایگان = 5)
برای x ، y ، w ، h در صورت:
    img = cv2. rectangle (img، (x، y)، (x+w، y+h)، (0،255،0)، 3)
تغییر اندازه = cv2.resize (img، (int (img.shape [1]/7)، int (img.shape [0]/7)))
cv2.imshow ("خاکستری" ، تغییر اندازه)
cv2.waitKey (0)
cv2.destroyAllWindows () 

در ادامه این مقاله ، بیایید نحوه استفاده از OpenCV برای ضبط ویدئو با وب کم کامپیوتر را بررسی کنیم.

ضبط ویدئو با استفاده از OpenCV

< p> فیلمبرداری با استفاده از OpenCV نیز بسیار ساده است. حلقه زیر ایده بهتری به شما می دهد. آن را بررسی کنید:

تصاویر یکی خوانده می شوند ویدئوها به دلیل پردازش سریع فریم ها ایجاد می شوند که باعث حرکت تک تک تصاویر می شود.

ضبط ویدئو:

تصویر زیر را مشاهده کنید:

< img src = "https://cdn-images-1.medium.com/max/426/1*AElOdTJjCzjfnWIhKwXcYA.png">

ابتدا کتابخانه OpenCV را طبق معمول وارد می کنیم. در مرحله بعد ، روشی به نام VideoCapture داریم که برای ایجاد شی VideoCapture استفاده می شود. این روش برای فعال کردن دوربین روی دستگاه کاربر استفاده می شود. پارامتر این عملکرد نشان می دهد که آیا برنامه باید از دوربین داخلی یا دوربین اضافی استفاده کند. "0" نشان دهنده دوربین داخلی استاین مورد.

و سرانجام ، از روش انتشار برای رهاسازی دوربین در چند میلی ثانیه استفاده می شود.

وقتی جلو می روید و تایپ می کنید و سعی می کنید کد فوق را اجرا کنید ، متوجه می شود که چراغ دوربین برای چند ثانیه روشن می شود و بعداً خاموش می شود. چرا این اتفاق می افتد؟

این اتفاق می افتد زیرا هیچ زمان تأخیری برای عملکرد دوربین وجود ندارد.

با نگاهی به کد بالا ، خط جدیدی به نام time.sleep (3) داریم - این باعث می شود که اسکریپت به مدت 3 ثانیه متوقف شود. توجه داشته باشید که پارامتر منتقل شده زمان در ثانیه است. بنابراین ، وقتی کد اجرا شد ، وب کم به مدت 3 ثانیه روشن می شود.

افزودن پنجره:

افزودن یک پنجره برای نمایش خروجی ویدئو بسیار ساده است و می تواند در مقایسه با روشهای مشابهی که برای تصاویر استفاده می شود. با این حال ، تغییر جزئی وجود دارد. کد زیر را بررسی کنید:

من زیبا هستم مطمئن باشید که می توانید از کد فوق جدا از یک یا دو خط بیشترین معنا را داشته باشید. آرایه قاب. /p>

همانطور که می توانید بررسی کنید ، خروجی را دریافت کردیم به عنوان True و بخشی از آرایه قاب چاپ می شود.

اما برای شروع باید اولین فریم/تصویر ویدیو را بخوانیم ، درست است؟

برای انجام دقیق این کار ، ما ابتدا باید یک شیء فریم ایجاد کنید که تصاویر شیء VideoCapture را بخواند.

< /img>

همانطور که در بالا مشاهده شد ، از روش imshow برای گرفتن اولین فریم ویدئو استفاده می شود.

در تمام این مدت ، ما سعی کرده ایم اولین تصویر/قاب ویدیو را به طور مستقیم ضبط کنیم ضبط ویدئو.

بنابراین چگونه می توان فیلم را به جای اولین تصویر در OpenCV ضبط کرد؟

ضبط مستقیم فیلم:

به منظور ضبط ویدیو ، ما از حلقه while استفاده خواهیم کرد. در حالی که شرایط به گونه ای است که تا زمانی که "check" درست نباشد. اگر چنین است ، Python فریم ها را نمایش می دهد.

در اینجا تصویر قطعه کد آمده است:

ما از تابع cvtColor برای تبدیل هر فریم به تصویر در مقیاس خاکستری استفاده می کنیم ، همانطور که قبلاً توضیح داده شد.

waitKey (1) اطمینان حاصل کنید که یک فریم جدید پس از هر میلی ثانیه فاصله ایجاد می کنید.

در اینجا مهم است که توجه داشته باشید که حلقه while کاملاً در حال پخش است تا به تکرار فریم ها و در نهایت نمایش فیلم کمک کند.

ماشه رویداد کاربر نیز در اینجا وجود دارد. هنگامی که کاربر کلید 'q' را فشار می دهد ، پنجره برنامه بسته می شود.

درک OpenCV بسیار آسان است ، درست است؟ من شخصاً دوست دارم که خوانایی آن چقدر خوب است و چگونه یک مبتدی می تواند کار با OpenCV را به سرعت شروع کند.

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

مورد استفاده: تشخیص حرکت با استفاده از OpenCV

بیان مشکل:

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

بنابراین ، اکنون که ما بیانیه مشکل خود را تعریف کرده ایم ، باید منطقی راه حل ایجاد کنیم تا به صورت ساختارمند به مسئله نزدیک شویم.

در نظر بگیرید نمودار زیر:

در ابتدا ، ما ذخیره می کنیم تصویر در یک قاب خاص.

مرحله بعدی شامل تبدیل تصویر به تصویر تار Gaussian است. این کار به منظور اطمینان از محاسبه تفاوت محسوس بین تصویر تار و تصویر واقعی انجام می شود.

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

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

در نهایت ، ما زمان نمایش و خروج شی از قاب را محاسبه می کنیم.

بسیار آسان است ، درست است؟

در اینجا قطعه کد آمده است:

< img src = "https://cdn-images-1.medium.com/max/426/1*tkoLRNbYxGMYGgSHx-eZTA.png">

همین اصل در اینجا نیز رعایت می شود. ابتدا بسته را وارد می کنیم و شیء VideoCapture را ایجاد می کنیم تا از ضبط ویدئو با استفاده از وب کم اطمینان حاصل کنیم.

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

ما باید اولین تصویر/قاب ویدیو را ذخیره کنیم ، درست است؟ ما فقط از عبارت if برای این منظور استفاده می کنیم.

اکنون ، اجازه دهید کمی بیشتر در کد وارد شویم:

ما از تابع absdiff برای محاسبه تفاوت بین اولین فریم رخ داده و همه فریم های دیگر استفاده می کنیم.

تابع آستانه یک مقدار آستانه ارائه می دهد ، به طوری که مقدار اختلاف کمتر از 30 را به سیاه تبدیل می کند. اگر تفاوت بیشتر از 30 باشد ، پیکسل ها را به رنگ سفید تبدیل می کند. THRESH_BINARY برای این منظور استفاده می شود.

بعداً ، از تابع findContours برای تعیین ناحیه کانتور برای تصویر خود استفاده می کنیم. و در این مرحله نیز مرزها را اضافه می کنیم.

عملکرد contourArea ، همانطور که قبلاً توضیح داده شد ، صداها و سایه ها را حذف می کند. برای ساده تر ، فقط آن قسمت را سفید نگه می دارد ، که مساحت آن بیشتر از 1000 پیکسل است ، همانطور که برای آن تعریف کرده ایم.

بعداً ، یک جعبه مستطیلی در اطراف شیء خود در قاب کار ایجاد می کنیم. .

و به دنبال آن این کد ساده وجود دارد:

همانطور که قبلاً بحث شد ، فریم هر 1 میلی ثانیه تغییر می کند و هنگامی که کاربر "q" را وارد می کند ، حلقه شکسته می شود و پنجره بسته می شود.

ما همه موارد اصلی را پوشش داده ایم. جزئیات این وبلاگ آموزش OpenCV Python. موردی که در مورد مورد استفاده ما باقی می ماند این است که ما باید زمانی را که شیء در مقابل دوربین قرار داشت محاسبه کنیم.

محاسبه زمان:

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

هنگامی که شیء در شکل بالا مشخص می شود ، پرچم وضعیت را به 1 تغییر می دهیم. بسیار ساده ، درست است؟

ما قصد داریم فهرستی از وضعیت برای هر فریم اسکن شده تهیه کنید و بعداً تاریخ و زمان را با استفاده از زمان داده در یک لیست در صورت تغییر و مکان ایجاد کنید.

و مقادیر زمان را در یک DataFrame ذخیره می کنیم ، همانطور که در نمودار توضیحی بالا نشان داده شده است. ما با نوشتن DataFrame در یک فایل CSV مطابق شکل به پایان می رسانیم.

رسم نمودار تشخیص حرکت:

آخرین مرحله در مورد استفاده ما برای نمایش نتایج. ما نمودار را نشان می دهیم که حرکت را در 2 محور نشان می دهد. کد زیر را در نظر بگیرید:

برای شروع ، ما DataFrame را از فایل motion_detector.py وارد می کنیم.

مرحله بعدی شامل تبدیل زمان به فرمت رشته قابل خواندن است که قابل تجزیه است.

در نهایت ، مقادیر زمانی DataFrame رسم می شود در مرورگر با استفاده از نمودارهای بوکه.

خروجی:

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

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

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

به دنبال مقالات دیگر این سری باشید که جنبه های مختلف دیگر پایتون و علم داده را توضیح می دهد.

1. آموزش پایتون 2. زبان برنامه نویسی پایتون 3. توابع پایتون 4. مدیریت فایل در پایتون 5. آموزش پایتون Numpy 6. Scikit Learn Machine Learning 7. آموزش پایتان پایتون 8. آموزش Matplotlib 9. آموزش Tkinter 10. آموزش درخواست 11. آموزش PyGame 12. تراشیدن وب با پایتون 13. آموزش PyCharm 14. آموزش یادگیری ماشین 15. الگوریتم رگرسیون خطی از ابتدا در پایتون 16. پایتون برای علم داده 17. پایتون Regex 18. حلقه ها در Python 19. پروژه های پایتون 20. پروژه های یادگیری ماشین 21. آرایه ها در پایتون 22. مجموعه در پایتون 23. چند رشته ای در پایتون 24. سوالات مصاحبه پایتون 25. جاوا در مقابل پایتون 26. چگونه می توان توسعه دهنده پایتون شد؟ 27. توابع پایتون لامبدا 28. Netflix چگونه از پایتون استفاده می کند؟ 29. برنامه نویسی سوکت در پایتون 30 چیست. اتصال پایگاه داده پایتون 31. گلانگ در مقابل پایتون 32. آموزش Python Seaborn 33. فرصتهای شغلی پایتون

در ابتدا در www.edureka.co در 8 فوریه 2019 منتشر شد.

بینایی رایانه ای و یادگیری ماشین در PHP با استفاده از کتابخانه opencv

بینایی رایانه ای و یادگیری ماشین در PHP با استفاده از کتابخانه opencv

سلام به همگی. این مقاله مربوط به سالگرد من است. تقریباً در 7 سال من 10 مقاله (از جمله این مقاله) نوشته ام ، 8 مورد از آنها - فنی. تعداد کل بازدید همه مقالات حدود نیم میلیون است. من مشارکت اصلی را در دو مبحث انجام داده ام: PHP و مدیریت سرور. من دوست دارم در محل اتصال این دو حوزه کار کنم ، اما دامنه علایق من بسیار گسترده تر است. مانند بسیاری از توسعه دهندگان ، من اغلب از نتایج کار شخص دیگری (مقالات در رسانه ، کد در github و غیره) استفاده می کنم ، بنابراین همیشه خوشحالم که نتایج خود را در پاسخ با جامعه به اشتراک بگذارم. نوشتن مقاله نه تنها بازگشت بدهی به جامعه است ، بلکه به شما امکان می دهد افراد همفکر خود را بیابید ، نظرات خود را از متخصصان در زمینه ای محدود دریافت کنید و دانش خود را در زمینه مورد بررسی بیشتر عمیق کنید. در واقع این مقاله درباره یکی از این لحظات است. در آن من آنچه را که تقریباً تمام وقت آزاد خود را در شش ماه گذشته انجام می دادم شرح می دهم. به جز آن لحظاتی که برنامه های تلویزیونی را تماشا می کردم یا بازی می کردم.

در حال حاضر ، "یادگیری ماشین" بسیار سریع در حال توسعه است ، قبلاً مقالات زیادی از جمله مقاله های متوسط ​​و تقریباً همه توسعه دهندگان را نوشته است. دوست دارند از آن در وظایف کاری و پروژه های خانگی خود استفاده کنند ، اما از کجا شروع کنیم و از چه چیزی استفاده کنیم همیشه قابل درک نیست. اکثر مقالات برای مبتدیان مجموعه ای از ادبیات را ارائه می دهند ، که در مورد خواندن آنها زندگی کافی وجود ندارد ، دوره های "ارزان" و غیره. به طور مرتب مقالات جدیدی ظاهر می شود که در آنها رویکردهای جدید برای حل یک مشکل خاص شرح داده شده است. در github می توانید پیاده سازی روشی را که در مقالات توضیح داده شده است بیابید. به عنوان زبانهای برنامه نویسی بیشتر از موارد زیر استفاده می شود: c /c ++ ، python 2/3 ، lua و matlab و به عنوان چارچوب: caffe ، tensorflow ، torch. تقسیم بندی زیاد در زبان ها و چارچوب های برنامه نویسی روش پیدا کردن آنچه شما نیاز دارید و ادغام آن در پروژه را بسیار پیچیده می کند.

برای کاهش این همه آشفتگی در opencv یک ماژول dnn اضافه شده است که به شما امکان می دهد از مدل آموزش داده شده در چارچوب های اساسی استفاده کنید. من به شما نشان می دهم که چگونه می توان از این ماژول از php استفاده کرد.

جرمی هوارد (خالق دوره عملی رایگان "یادگیری ماشین برای برنامه نویسان") معتقد است که اکنون بین یادگیری ماشین و یادگیری یک آستانه بزرگ وجود دارد. هوارد می گوید برای شروع یادگیری ماشینی یک سال تجربه برنامه نویسی کافی است. من کاملاً با او موافقم و امیدوارم مقاله من به کاهش آستانه ورود به opencv برای توسعه دهندگان php که با یادگیری ماشین آشنایی کمی دارند و هنوز مطمئن نیستند که آیا اصلاً می خواهند این کار را انجام دهند یا خیر ، کمک کند. سعی کنید تمام نقاطی را که برای آنها ساعت ها و روزها صرف کرده ام توصیف کنید ، بنابراین لازم نیست بیش از یک دقیقه برای این کار وقت بگذارید.

لوگوی پروژه php-opencv

من در حال نوشتن بودمیک ماژول php-opencv توسط خودم با استفاده از SWIG و زمان زیادی را صرف آن کردم ، اما من به چیزی نرسیدم. همه چیز از این جهت پیچیده بود که من c /c ++ نمی دانستم و برنامه های افزودنی برای php 7 ننوشته بودم. متأسفانه اکثر مطالب موجود در اینترنت برای برنامه های افزودنی php در php 5 نوشته شده است ، بنابراین مجبور شدم اطلاعات را جمع آوری کنم کمی ، و مشکلات را به تنهایی حل کنم.

سپس من کتابخانه php-opencv را در فضای github پیدا کردم ، این یک ماژول برای php7 است که به روش های opencv تماس می گیرد. چندین شب طول کشید تا نمونه ها را گردآوری ، نصب و اجرا کنم. من سعی کردم ویژگی های مختلف این ماژول را امتحان کنم ، اما برخی از روشها را نداشتم ، خودم آنها را اضافه کردم ، یک درخواست pull ایجاد کردم و نویسنده کتابخانه قبول کرد. بعداً ، ویژگی های بیشتری اضافه کردم.

نحوه بارگذاری تصویر به این شکل است:

$ image = cv \ imread ("images/face.jpg") ؛ < p> برای مقایسه ، در پایتون به این شکل است:

image = cv2.imread ("images/face.jpg")

هنگام خواندن یک تصویر با php (همچنین مانند c ++) ، اطلاعات در شی Mat (ماتریس) ذخیره می شوند. در php ، آنالوگ آن یک آرایه چند بعدی است ، اما بر خلاف یک آرایه چند بعدی ، این شی اجازه می دهد تا دستکاری های سریع مختلفی انجام شود ، به عنوان مثال ، تقسیم همه عناصر بر یک عدد. در پایتون ، هنگامی که تصویر بارگیری می شود ، شیء numpy بازگردانده می شود.

مراقب باشید ، میراث! این اتفاق افتاد به طوری که imread (در php ، c ++ و pyton) تصویر را نه در قالب RGB ، بلکه در BGR بارگذاری می کند. بنابراین ، در مثالهای opencv ، اغلب می توانید روش تبدیل BGR -> RGB و بالعکس را مشاهده کنید.

تشخیص چهره

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

$ src = imread ("images /aces.jpg") $ خاکستری = cvtColor ($ src ، COLOR_BGR2GRAY) ؛ $ faceClassifier = جدید CascadeClassifier ()؛ $ faceClassifier-> load (‘models/lbpcascades/lbpcascade_frontalface.xml’) ؛ $ faceClassifier-> deteMultiScale ($ خاکستری ، $ چهره) ؛

کد نمونه کامل

نتیجه:

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

$ faceRecognizer = LBPHFaceRecognizer :: create ()؛ $ faceRecognizer-> قطار ($ myFaces، $ myLabels = [1،1،1،1])؛ //4 صورت من $ faceRecognizer-> بروز رسانی ($ angelinaFaces ، $ angelinaLabels = [2،2،2،2]) ؛ //4 چهره آنجلینا $ label = $ faceRecognizer-> پیش بینی ($ faceImage ، $ اطمینان)؛ //دریافت برچسب (1 یا 2) و اطمینان

کد نمونه کامل

مجموعه داده ها:

نتیجه:

وقتی کار با LBPHFaceRecognizer را شروع کردم ، توانایی ذخیره /بارگذاری /به روزرسانی مدل نهایی را نداشت. در واقع اولین درخواست کشش من این روشها را اضافه کرد: نوشتن /خواندن /بروزرسانی. < /p>

علائم چهره/نقاط دیدنی

وقتی شروع به آشنایی با opencv کردم ، اغلب با عکس هایی از افراد برخورد می کردم ، جایی که نقاط چشم ، بینی ، لب ها و غیره را مشخص می کرد. می خواستم این آزمایش را خودم تکرار کنم ، اما در نسخه opencv برای پایتون اجرا نشد. یک شب طول کشید تا پشتیبانی FacemarkLBF را به php اضافه کنم و یک بولت بک دوم ارسال کنم. همه به سادگی کار می کنند ، ما پیش مدل را بارگذاری می کنیم ، آرایه ای از چهره ها را تغذیه می کنیم ، برای هر فرد آرایه ای از امتیاز دریافت می کنیم.

$ facemark = FacemarkLBF :: create ()؛ $ facemark-> loadModel (‘models/opencv-facemark-lbf/lbfmodel.yaml’) ؛ $ facemark-> fit ($ image، $ face، $ landmarks)؛

کد نمونه کامل

نتیجه:

همانطور که از مثال مشاهده می شود ، آرایش یک زامبی می تواند یافتن نقاط روی صورت را مشکل کند. نقاط همچنین می توانند در یافتن چهره تداخل ایجاد کنند. روشنایی نیز بر آن تأثیر می گذارد. در این مورد ، اجسام خارجی در دهان (توت فرنگی ، سیگار و غیره) ممکن است تداخلی نداشته باشند. مقاله Deep Learning ، اکنون در OpenCV. بدون تردید ، تصمیم گرفتم امکان استفاده از مدلهای از پیش آموزش دیده را که در اینترنت زیاد است ، به php-opencv اضافه کنم. بارگیری مدل های کافه چندان دشوار نبود ، اگرچه بعداً زمان زیادی را صرف کردم تا نحوه کار با ماتریس های چند بعدی را یاد بگیرم و با مدلهای caffe /torch /tensorflow بدون استفاده از opencv کار کنم. < /p>

تشخیص چهره با استفاده از ماژول dnn

بنابراین ، opencv به شما امکان می دهد مدل های از پیش آموزش دیده را در Caffe با استفاده از عملکرد readNetFromCaffe بارگذاری کنید. این دو پارامتر را می طلبد - مسیرهای .prototxt و .caffemodel. در فایل نمونه اولیه توضیحات مدل ، و در مدل کافه-وزنهای محاسبه شده در طول آموزش مدل وجود دارد. در اینجا نمونه ای از شروع یک فایل اولیه است:

ورودی: "داده" شکل ورودی { کم نور: 1 کم نور: 3 کم نور: 300 کم نور: 300 }

این قطعه فایل توضیح می دهد که انتظار می رود یک ماتریس 4 بعدی 1x3x300x300 ورودی را وارد کند. در توضیح مدلها ، معمولاً آنچه در این قالب انتظار می رود بیان شده است ، اما در بیشتر موارد به این معنی است که انتظار می رود تصویر RGB (3 کانال) با اندازه 300x300 وارد شود. با بارگیری یک تصویر RGB با ابعاد 300x300 با عملکرد imread ، ما ماتریسی از 300x300x3 دریافت می کنیم. برای آوردن ماتریس 300x300x3 به فرم 1x3x300x300 در opencv یک تابع blobFromImage وجود دارد. پس از آن ، ما فقط می توانیم با استفاده از روش setInput blob را روی ورودی شبکه اعمال کرده و متد forward را فراخوانی کنیم ، که نتیجه نهایی را به ما باز می گرداند.

$ src = imread ("images /aces.jpg" )؛ $ net = \ CV \ DNN \ readNetFromCaffe ("models/ssd/res10_300x300_ssd_deploy.prototxt" ، "models/ssd/res10_300x300_ssd_iter_140000.caffemodel") ؛ $ blob = \ CV \ DNN \ blobFromImage ($ src، $ scalefactor = 1.0، $ size = new size (300، 300)، $ mean = new Scalar (104، 177، 123)، $ swapRB = true، $ crop = غلط) ؛ $ net-> setInput ($ blob، “”)؛ $ result = $ net-> forward ()؛

در این حالت ، نتیجه یک ماتریس 1x1x200x7 است ، یعنی 200 آرایه از هر 7 عنصر. در یک عکس با چهار چهره ، این شبکه 200 نامزد پیدا کرد. هر کدام شبیه [، $ اعتماد ، $ startX ، $ startY ، $ endX ، $ endY] هستند. عنصر $ اطمینان مسئول "اطمینان" است ، یعنی پس از آن احتمال پیش بینیخوب است ، به عنوان مثال 0.75. عناصر زیر مختص مختصات مستطیل با صورت هستند. در این مثال ، تنها 3 نفر با اطمینان بیش از 50 found و 197 نامزد باقی مانده اطمینان کمتر از 15 found پیدا کردند.

حجم مدل 10 مگابایت است ، کد نمونه کامل

نتیجه:

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

بهبود کیفیت تصاویر با استفاده از شبکه عصبی

A مدتها پیش در مورد کتابخانه waifu2x شنیدم ، که به شما امکان می دهد نویز را حذف کرده و اندازه آیکون ها /عکس ها را افزایش دهید. خود کتابخانه به زبان lua نوشته شده است ، و در زیر کاپوت از چندین مدل (برای افزایش آیکون ها ، حذف نویز عکس و غیره) آموزش داده شده در مشعل استفاده می شود. نویسنده کتابخانه این مدلها را به کافه صادر کرد و به من کمک کرد تا از opencv استفاده کنم. در نتیجه ، نمونه ای برای افزایش وضوح آیکون ها در php نوشته شد. حجم مدل 2 مگابایت است ، کد کامل مثال.

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

طبقه بندی تصویر

The MobileNet شبکه عصبی ، آموزش داده شده بر روی مجموعه داده ImageNet ، به شما امکان می دهد یک تصویر را طبقه بندی کنید. در کل ، می تواند 1000 کلاس را تعیین کند ، که به نظر من کافی نیست. حجم مدل 16 مگابایت است ، کد کامل نمونه.

نتیجه: 87٪ - گربه مصری ، 4٪ - گربه تابی ، گربه بزرگ ، 2٪ - گربه ببر

API تشخیص شی Tensorflow

شبکه MobileNet SSD (آشکارساز چند شات تک شات) ، آموزش داده شده در Tensorflow بر روی مجموعه داده COCO ، نه تنها می تواند یک تصویر را طبقه بندی کند ، بلکه مناطق را نیز برمی گرداند ، اگرچه فقط می تواند 182 کلاس را تشخیص دهد. حجم مدل 19 مگابایت است ، کد کامل مثال.

اصلی < /img> نتیجه

برجسته سازی نحو و تکمیل کد

من به همراه مخزن نمونه ، فایل phpdoc.php را نیز اضافه کردم. با تشکر از آن ، Phpstorm نحو توابع ، کلاسها و روشهای آنها را برجسته می کند و همچنین با تکمیل کد کار می کند. این فایل نیازی به درج کد شما ندارد (در غیر این صورت خطایی رخ می دهد) ، کافی است آن را در پروژه خود قرار دهید. شخصاً ، زندگی را برای من آسان می کند. این فایل بیشتر توابع opencv را توصیف می کند ، اما نه همه آنها ، بنابراین درخواست های pull خوش آمدید.

نصب

ماژول dnn فقط در نسخه 3.4 در opencv ظاهر شد (قبل از آن در opencv-contribute). در اوبونتو 18.04 آخرین نسخه opencv 3.2 است. ساخت opencv از منابع حدود نیم ساعت طول می کشد ، بنابراین من بسته را تحت اوبونتو 18.04 گردآوری کردم (همچنین برای 17.10 ، حجم 25 مگابایت کار می کند) ، و همچنین بسته های php-opencv را برای php 7.2 (اوبونتو 18.04) و php 7.1 (اوبونتو 17.10) گردآوری کردم. (حجم 100 کیلوبایت) ppa ثبت شده: php-opencv ، اما هنوز به پر کردن تسلط ندارد و چیزی بهتر از بارگذاری بسته ها در github پیدا نکرده است. من همچنین یک درخواست برای ایجاد یک حساب کاربری در pecl ایجاد کردم ، اما پس از چند ماه من هنوزپاسخی دریافت نکرد بنابراین در حال حاضر نصب تحت اوبونتو 18.04 به این شکل است:

به روز رسانی مناسب && apt install -y wget && \ wget https://raw.githubusercontent.com/php-opencv/php-opencv-packages/master/opencv_3.4_amd64.deb && dpkg -i opencv_3.4_amd64.deb && rm opencv_3.4_amd64.deb && \ wget https://raw.githubusercontent.com/php-opencv/php-opencv-packages/master/php-opencv_7.2-3.4_amd64.deb && dpkg -i php-opencv_7.2–3.4_amd64.deb && rm php -opencv_7.2–3.4_amd64.deb && \ echo “extension = opencv.so”> /etc/php/7.2/cli/conf.d/opencv.ini

نصب این گزینه حدود 1 دقیقه به طول می انجامد. همه گزینه های نصب در اوبونتو. من همچنین یک تصویر داکر 168 مگابایتی را گردآوری کردم.

نمونه هایی با استفاده از

بارگیری: opencv-samples.git && cd php-opencv-example

در حال اجرا:

php dete_face_by_dnn_ssd.php

PS

مشترک شوید ، بنابراین برای اینکه مقاله های بعدی من را از دست ندهید ، یک هاسکی بگذارید تا به من انگیزه دهد تا آنها را بنویسم و ​​در نظرات س questionsالات بنویسم ، گزینه هایی را برای آزمایش/مقاله جدید ارائه دهید.

منابع:

php- نمونه های opencv-همه نمونه های مقاله php-opencv/php-opencv-چنگال من با پشتیبانی از ماژول dnn hihozhou /php-opencv-مخزن اصلی ، بدون پشتیبانی از ماژول dnn (من pulrequest را ایجاد کردم ، اما هنوز پذیرفته نشده است). https://habr.com/post/358902/- نسخه روسی