تشخیص اشیا توسط رنگ در تصویر با OpenCV

در مطلب های پیشین در مورد فضای رنگ و چگونگی تبدیل از یک فضای رنگ به فضای رنگ دیگر صحبت کرده ایم. توسط متد ()cvtColor می توانیم یک فضای رنگ را به فضای رنگ دیگر تبدیل کنیم. در این مطلب می خواهیم با متدهای ()inRange و ()bitwise_and و کاربرد آنها در ایجاد ماسک های تصویر (Image Mask) و تشخیص رنگ ها در تصویرها و فریم های ویدیوها آشنا شویم.

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

گام ۱ – تبدیل فضای رنگ از BGR به HSV توسط متد ()cvtColor و تعیین پارامتر cv2.COLOR_BGR2HSV

گام ۲ – تعیین حد بالا و حد پایین رنگ برای تشخیص اشیا در همین بازه

گام ۳ – استفاده از تابع ()inRange و حد های پایین و بالای رنگ در این متد برای ایجاد ماسک تصویر

گام ۴ – استفاده از ماسک تصویر به همراه تصویر اصلی درون متد ()bitwise_and

ماسک تصویر

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

گام ۱ در ایجاد ماسک تصویر : تبدیل فضای رنگ BGR به HSV و ایجاد یک ماتریس جدید که در کدهای زیر آنرا hsv نامیده ایم. در واقع hsv همان تصویر اصلی است ولی فضای رنگ آن از BGR به HSV تبدیل شده است.

گام ۲ در ایجاد ماسک تصویر: استفاده از متد ()inRange برای ایجاد ماسک تصویر. در کدهای زیر می بینید که دو حد یا بازه پایین و بالا تعیین شده اند و سپس این دوبازه به عنوان آرگومان های دوم و سوم به متد ()inRange فرستاد شده اند و آرگومان اول متد ()inRange نیز همان متغیر hsv است. در کدهای زیر ابتدا دو آرایه NumPy به نام های lower_red و upper_red ایجاد کرده ایم که هر کدام به ترتیب حد پایین وحد بالا رنگ قرمز قابل استفاده در OpenCV را در خود نگه می دارند.

ماسک تصویر اساسا یک ناحیه (Region) مشخص از تصویر است که به دنبال قوانین خاص ایجاد می شود. در اینجا ما یک ماسک ایجاد می کنیم که شامل یک یا چندین شی با رنگ آبی است. این ناحیه آبی رنگ تنها شامل رنگی های درون تصویر hsv می شود که میان بازه [110,50,50] تا بازه [130, 255, 255] قرار داشته باشند. این دو بازه در OpenCV مربوط به حدهای پایین و بالای رنگ آبی در فضای رنگ HSV هستند.

گام نهایی تشخیص رنگ

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

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

کد کامل برنامه

همچنین قطعه کد زیر ابتدا فریم های دوربین سیستم شما را به صورت بلادرنگ خوانده و همان چیزی که در بالا توضیح دادیم را این بار به ازای فریم های ویدیویی انجام می دهد. توجه کنید در کدهای زیر، متغیر frame همان مفهوم تصویر اصلی (متغیر image) خوانده شده توسط متد ()imread در کد بالا را دارد.

جمع بندی

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

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

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

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

۱ – حد پایین و حد بالای رنگ قرمز

۲ – حد پایین و حد بالای رنگ سبز

 

۳ – حد پایین و حد بالای رنگ آبی

دانلود سورس برنامه های این مطلب –

مطالعه و منبع