تصویر و ماتریس در OpenCV – ایجاد ماتریس ها

در مطلب آشنایی با مفاهیم ابتدایی در OpenCV – ساختار Mat تا اندازه ای مفهوم و کاربرد ماتریس ها در پردازش تصویر (Image Processong)، بینایی ماشین (Computer Vision) و OpenCV را توضیح دادیم. در این مطلب و چندین مطلب بعدی زمان را صرف کار بر روی ایجاد ماتریس ها و پیمایش آنها می کنیم.

ایجاد ماتریس ها بدون اندازه و نوع

زمانی که در دستور ;int var را می نویسید در واقع به کامپایلر سی پلاس پلاس اعلام می کنید که نیاز به ایجاد یک متغیر از نوع int و بدون مقدار دارید. کامپایلر نیز بخشی از فضای آدرس حافظه (مثلا ۴بیت برای عدد صحیح) را برای متغیر var ایجاد می کند. در OpenCV نیز می توانیم یک شی یا نمونه اولیه و بدون مقدار را توسط مثال زیر ایجاد کنیم.

در مثال بالا imageMatrix یک متغیر از نوع کلاس Mat است. در واقع با دستور بالا ماتریسی بدون اندازه (عرض – ارتفاع) و بدون نوع ایجاد کرده ایم. در مطلب قبلی در مورد انواع داده در OpenCV صحبت کردیم و در ادامه همین مطلب توضیح داده ایم که چگونه ماتریس هایی با ابعاد و تعیین نوع درایه های آن، ایجاد کنیم.

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

ایجاد ماتریس ها با اندازه و نوع

در مطلب قبلی در مورد انواع داده (Data Type) موجود در OpenCV صحبت کردیم و توضیح دادیم که بر اساس داده های تصویر، درایه های تصویر دارای یک نوع هستند. به طور مثال اگر تصویر خاکستری (تک کانالی) ۸ بیتی داشته باشیم، نوع درایه های تصویر CV_8U (یا CV_8UC1) خواهد بود.

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

به طور مثال می خواهیم ماتریس (یا به عبارت دیگر تصویری) با ابعاد ۳۰۰ در ۳۰۰ ایجاد کنیم که درایه های به ترتیب از نوع ۸ بیتی تک کانالی (CV_8U یا CV_8UC1) و به صورت ۸ بیتی سه کانالی (CV_8UC3) باشند. در خطوط ۱۰ و ۱۱ دو دستور به صورت کامنت شده وجود دارند. برای آزمایش برنامه لطفا هر بار یکی از دو خط را از حالت کامنت خارج و برنامه را اجرا کنید.

در خط ۱۰ یک ماتریس از نوع CV_8U (معادل CV_8UC1) ایجاد کردیم که به معنی تصویر خاکستری (Grayscale) تک کانالی است. در خط ۱۱ ک ماتریس از نوع CV_8UC3 ایجاد کردیم که به معنی تصویر رنگی (Color Image) سه کانالی است.

برای امتحان کردن برنامه لطفا ابعاد ماتریس را از ۳۰۰ به ماتریس ۳ در ۳ کاهش دهید و سپس توسط متد cout محتوای ماتریس ۳ در ۳ را یکبار برای نوع CV_8U (یا CV_8UC1) و یکبار برای نوع CV_8UC3 امتحان کنید. همانطور که در خروجی خواهید دید، در خروجی مربوط به تصویر رنگی RGB سه کانالی (نوع CV_8UC3)، به ازای هر پیکسل از تصویر یک بردار سه تایی از اعداد وجود دارد که به صورت معکوس معنی BGR را می دهند.

ایجاد یک ماتریس ها از رو ابعاد ماتریس دیگر

در فرم سوم از تابع سازنده کلاس Mat، آرگومان اول یک شی از کلاس Size است. این کلاس ابعاد یک تصویر را در خود نگه می دارد. اگر مطالب پیشین را به یاد داشته باشید، توضیح دادیم که متد ()size از کلاس Mat اندازه تصویر را به صورت جفت (width, height) برگشت می دهد. در واقع با توجه به فرم زیر از تابع سازنده کلاس Mat می توانیم توسط تعیین ابعاد از طریق کلاس Size، یک ماتریس تعریف کنیم.

در قطعه کد زیر ابتدا در خط ۱۰ یک تصویر را خوانده ایم، پس قاعدتا یک ماتریس تعریف شده است که در خط ۱۱ ابعاد این ماتریس را نشان داده ایم. در خط ۱۳ یک ماتریس از روی ابعاد و نوع ماتریس قبلی، یعنی ماتریس firstImage ایجاد کرده ایم. در شکل زیر می بینید که ابعاد متغیر secondImgae با ابعاد firstImage یکی است. در خط ۱۶ یک متغیر از نوع کلاس Size برای نگهداری ابعاد ایجاد کرده ایم و سپس درون تابع سازنده به صورت دستی نوع درایه های ماتریس را تعیین کرده ایم.

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

ایجاد یک ماتریس ها توسط کلاس Scalar

در فرم پنجم و ششم از تابع سازنده کلاس Mat، آرگومان آخر یک شی از کلاس Scalar است. هدف از تابع Scalar تعیین مقادیر پیکسل در درایه های ماتریس است. اگر می خواهیم تصویر رنگی سه کانالی ۸ بیتی داشته باشیم، پس در فرم های زیر باید نوع را CV_8UC3 و آرگومان Scalar را به صورت سه تایی (b, g, r) تعیین کنیم. توجه کنید در OpenCV سیستم RGB به صورت معکوس، یعنی BGR در نظر گرفته می شود.

قطعه کد زیر مثالی را نشان می دهد. در ایجاد grayscaleImage چون از نوع تک کانالی ۸ بیتی (CV_8U) است، پس تنها یک مقدار را تابع سازنده کلاس Scalar ارسال کررده ایم. در ایجاد colorImage ابتدا ابعاد را توسط کلاس Size تعیین کردیم و سپس ترکیب رنگ ها را توسط کلاس Scalar تعیین کردیم و در نهایت آنها را به تابع سازنده ارسال کرده ایم.