تبدیل Affine و Perspective در OpenCV

get Perspective Transform

اگر بخواهیم یک تبدیل affine رو یک تصویر انجام بدهیم می توانیم از getPerspectiveTransform استفاده کنیم. به این صورت که مختصات چهار گوشه قسمتی از تصویر که می خواهیم تبدیل رو آن انجام شود را مشخص می کنیم (points_A) و همچنین مشخص می کنیم که می خواهیم این چهار نقطه رو چه نقاطی در تصویر جدید نگاشت شوند(points_B). تابع getPerspectiveTransform یک ماتریس 3*3 بر می گرداند که درواقع اگر هر کدام از چهار نقطه رو تصویر اصلی به فرم [xi, yi, 1] در این ماتریس ضرب شوند حاصل نقاط مورد نظر روی تصویر جدید خواهند بود که به فرم [ti*x’i, ti* y’i, ti] خواهد بود(مختصات تصویر جدید ‘x و ‘y می باشد و ti عدد ثابت است). حال برای اینکه تصویر جدید را ایجاد کنیم از getPerspectiveTransform استفاده می کنیم که به عنوان ورودی عکس اولیه و ماتریس تبدیل و اندازه عکس جدید را می گیرد و عکس جدید را برمی گرداند.

get Affine Transform

 

با استفاده از  getAffineTransform نیز می توان یک تبدیل affine انجام داد با این تفاوت که از سه نقطه استفاده می کنیم. طبق رابطه ی مشخص شده, حاصل getAffineTransform یک ماتریس 2*3 می باشد که اگر هر کدام از سه تقطه اولیه به فرم      [xi, yi, 1] در این ماتریس ضرب شوند حاصل نگاشت این نقاط در تصویر جدید به فرم [x’i, y’i] خواهد بود. با استفاده از warpAffine تصویر جدید به دست می اید که ورودی ان همان طول و عرض تصویر اصلی و تابع تبدیل(M) و تصویر اولیه می باشد.

دستکاری تصاویر (۶) – فیتلرها در Open CV و حذف نویز تصاویر

در قسمت قبلی با کرنل‌ها و نحوه کارکرد آن‌ها و استفاده از آنها برای ایجاد فیلتر روی تصاویر آشنا شدیم؛ حال با اعمال فیلتر روی تصاویر با استفاده از کتابخانه Open CV و توابع مربوطه آشنا می‌شویم.

اعمال فیلتر‌های دو بعدی رو تصویر

با استفاده از Open CV اعمال فیلتر‌های دو بعدی توسط کرنل بر روی تصاویر توسط تابع زیر انجام می‌شود:

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

فیلتر محوی (Blur Filter)

همانطور که در پست قبل دیدیم برای محو کردن تصویر می‌توانیم یک کرنل Moving Average را بر روی تصویر اعمال کنیم. این کرنل یک ماتریس با مجموع جملات ۱ است و هرچه کرنل بزرگ‌تر باشد میزان تاری تصویر بیشتر خواهد شد.

کرنلی که در دفعه قسمت اول برای تاری استفاده شده است یک ماتریس ۳*۳ با عناصر ۱ است که از آنجا که مجموع عناصر ماتریس باید ۱ باشد تقسیم بر ۹ شده است. همچنین برای قسمت دوم از ماتریس بزرگتر ۵*۵ استفاده شده و تقسیم بر ۲۵ شده است.

برای اعمال فیلتر Blur می‌تواند از تابع اختصاصی زیر نیز استفاده کرد:

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

دیگر فیلتر‌های Blur

در Open CV علاوه بر کرنل Box (کرنل Moving Average مورد استفاده تا الان) برای محو کردن تصویر لکرنل‌های گوسین (Gaussian)، مدین (Median) و دوجانبه (Bilateral) نیز پشتیبانی می‌شوند.

فیلتر Gaussian Blur

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

فیلتر Median Blur

این فیلتر متوسط مقدار پیکسل‌هایی که درون کرنل قرار می‌گیرند را به عنوان مقدار نهایی پیکسل قرار می‌دهد.

فیلتر Bilateral Blur

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

 

حذف نویز تصویر

برای حذف نویز تصویر می‌توان از تابع زیر که از روش میانگین گیری استفاده می‌کند کمک گرفت:

پارامتر‌های تابع عبارت‌اند از:

  • src : عکس مورد نظر برای حذف نویز
  • dst : متغیری برای ذخیره کردن عکس خروجی – با دادن none به این پارامتر، خروجی تابع عکس خروجی خواهد بود.
  • h : این پارامتر قدرت فیلتر را برای میزان شدت نور تنظیم می‌کند. هرچه مقدار این پارامتر بزرگتر باشد علاوع بر حذف نویز ممکن است از جزئیات تصویر نیز بکاهد و هرچه کوچکتر باشد جزئیات تصویر را نمی‌کاهد اما ممکن است نویزها را به درستی کاهش ندهد (بازه ۵ تا ۱۰ برای این پارامتر مناسب است).
  • hcolor : همانند h برای مولفه‌های رنگی
  • templateWindowSize : سایز گیره محاسبه کننده وزن‌ها (باید عددی فرد باشد).
  • searchWindowSize : سایز کرنل محاسبه کننده میانگین وزن‌دار برای هر پیکسل (باید عددی فرد باشد).

 

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

  • ()cv2.fastNlMeansDenoising : یا یک تصویر Grayscale کار می‌کند.
  • ()cv2.fastNlMeansDenoisingColored : با یک تصویر رنگی کار می‌کند.
  • ()cv2.fastNlMeansDenoisingMulti : با رشته‌ای از عکس‌های Grayscale که با فاصله زمانی کم گرفته شده‌اند کار می‌کند.
  • ()cv2.fastNlMeansDenoisingColoredMulti : مانند قبلی برای عکس‌های رنگی.

دستکاری تصاویر (۵) – فیلترها و کرنل‌ها

در قسمت قبل با عملیات‌های ریاضی ماتریس‌ها آشنا شدیم. در این قسمت می‌خواهیم به نحوه اعمال فیلتر‌های مختلف روی تصاویر با استفاده از عملیات‌های ریاضی روی ماتریس تصاویر بپردازیم.

برای شروع به چند تعریف نیاز داریم:

تصویر

همانطور که می‌دانید تصویر یک ماتریس است که در هر خانه مقادیر رنگ آن خانه (با توجه به سیستم رنگی مورد استفاده) قرارگرفته اند.

کانولوشن (Convolution)

کانولوشن درواقع یک عملگر ریاضی است که بر روی دو تابع اعمال شده و تابع سومی را به صورت انتگرال حاصلضرب دو تابع که یکی از آنها برعکس شده و روی یکدیگر می‌لغزند تعریف می‌کند.

کراس‌کرولیشن (Cross-correlation)

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

 

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

کرنل

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

 

حال که با تعاریف اولیه مورد نیاز آشنا شدیم به نحوه استفاده و نتیجه آن روی تصاویر می‌پردازیم:

اعمال کرنل روی تصویر

 

در اعمال کرنل روی تصویر نیاز داریم تا با عبور کرنل بر روی تصویر و انجام عملیات کراس‌کرولیشن نتیجه عملیات در خانه‌ای از خانه‌‌های کرنل (که روی تصویر قرار‌گرفته اند) نگاشته شود. برای این‌کار عموما خانه وسط ماتریس کرنل را در نظر می‌گیرند؛ درنتیجه عموم کرنل‌های مورد استفاده ماتریس‌هایی فرد-فرد هستند.

برای عبور کرنل بر روی تصویر می‌توان دو رویه داشت:

  • کانولوشن بدون حاشیه‌گذاری (Valid Padding Convolution)
    عبور کرنل به صورتی که خانه اول ماتریس کرنل (خانه [۰.۰]) بر روی خانه اول ماتریس تصویر بیافتد و کرنل از تصویر خارج نشود.
    این روش باعث از دست رفتن قسمت‌هایی از حاشیه تصویر می‌شود.
نحوه عبور یک ماتریس کرنل بر روی یک ماتریس تصویر و انجام عملیات کراس‌کرولیشن
نحوه عبور کرنل روی ماتریس تصویر و انجام عملیات کراس‌کرولیشن در حالت Valid Padding

 

  • کانولوشن با حاشیه‌گذاری (Same Padding Convolution)
    عبور کرنل به صورتی که خانه مرکز کرنل (خانه‌ای که برای نوشتن مقادیر عملیات در هر مرحله انتخاب شده) بر روی خانه اول ماتریس تصویر بیافتد.
    در این حالت کرنل می‌تواند از تصویر خارج شود که مقادیر خارج از تصویر عموما صفر در نظر گرفته می‌شوند.
نحوه عبور کرنل روی ماتریس تصویر و انجام عملیات کراس‌کرولیشن در حالت Same Padding

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

 

به جز دو روش فوق برای جلوگیری از کوچک شدن تصویر می‌توان از روش‌های تکرار حاشیه تصویر (Edge Value Replication) و یا گسترش آینه‌وار (Mirror Extension) نیز استفاده کرد:

از راست به چپ: گسترش آینه‌وار، تکرار حاشیه تصویر و حاشیه‌گذاری

استفاده از کرنل‌ها

چند مثال از کرنل‌ها با فرض اینکه خانه وسط هر کرنل برای نوشتن مقادیر استفاده شود و همچنین خانه وسط بر روی هر پیکسل قرارگیرد و کرنل در هر مرحله یک پیکسل جابه‌جا شود :

کرنل تطابق

با توجه به کرنل با جابه‌جا شدن روی تصویر تغییری روی تصویر اعمال نمی‌کند چرا که با قرارگیری روی هر پیکسل تنها مقدار همان پیکسل بدون تغییر روی خودش نوشته می‌شود.

کرنل انتقال به چپ

با توجه به کرنل با جابه‌جا شدن روی تصویرو قرار گیری روی هر پیکسل مقدار پیکسل سمت راستش را جایگزین آن می‌کند. درنتیجه تصویر ۱ پیکسل به سمت چپ میرود.

 

 

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

استفاده از کرنل‌ها برای ایجاد فیلتر روی تصاویر

فیلتر محوی (Blur Filter)

با عبور یک کرنل Moving Average (کرنل تصویر پایین) که کرنلی با مجموع مقادیر ۱ است و مقدار هر خانه را با میانگین مقدار خانه‌های همسایه‌اش جایگذین می‌کند، می‌توان تصویر را محو کرد.

 

این کرنل تغییرات ناگهانی در رنگ تصویر را ملایم‌تر می‌کند. به تصویر زیر که عبور کرنل بالا بر روی یک ماتریس است دقت کنید:

 

همچنین با افزایش سایز کرنل می‌توان میزان تاری تصویر را افزایش داد:

 

فیلتر تیزی (Sharpen Filter)

کرنل زیر را در نظر بگیرید:

می‌توان این کرنل را به صورت زیر باز کرد:

ماتریس سمت راست همان کرنل مربوط به فیلتر محوی (Blur) است که تصویر را بدون جزئیات تولید می‌کند؛ با تفریق این ماتریس از خود تصویر (ماتریس وسط) جزئیات تصویر اصلی حاصل می‌شود؛ حال با اضافه کردن این ماتریس به خود تصویر می‌توان جزئیات تصویر را به آن افزود و تصویری با جزئیات نمایان‌تر شده تولید کرد.

نتیجه حاصل از جدا کردن جزئیات و اضافه کردن آن به عکس را می‌توان به ترتیب در سطر‌های تصویر زیر مشاهده کرد:

درنتیجه فیلتر تیزی (Sharpen Filter) به صورت زیر است:

 

دستکاری تصویر (3) – مثال‌های عملی در OpenCV

تبدیلات همگن (Affine Transform) 

انتقال (Translation) :

برای پیاده سازی این تبدیلات  از cv2.warpAffine استفاده میکینم.

به طور مثال در کد زیر :

پس از خواندن عکس  و دریافت عرض و طول تصویر:

یک نسبت دلخواه برای انتقال طول و عرض تصویر در نظر گرفتیم :

با استفاده از ضرب ماتریس انتقال در مختصات تصویر ،تصویر انتقال پیدا میکند :

از warpAffine برای تبدیل عکس استفاده میکنیم که ورودی های آن به صورت زیر است :

چرخاندن  (Rotations) :

*یادآوری

ماتریس دوران:

 

 

 

دوران در opencv

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

روشی دیگر برای دوران :

ترانهاده ماتریس

ماتریس ترانهاده  با تغییر جای سطر ها با ستون ها باعث چرخش تصویر میشود و فضای سیاه اطراف تصویر ایجاد نمی کند .

flip  تصویر

تصویر را در جهت افق و خط عمود آینه می کند.

پارامتر دوم :

صفر یا false عکس را حول محور x  ها قرینه میکند.

یک یا True عکس را حول محور y ها قرینه میکند.

تغییر اندازه (scaling, resizing) و درون‌یابی (interpolations)

  • fx  و fy  پارامتر های  نام دار هستند میتوان آنها را به تابع پاس نداد.

روش های درون یابی :

  1.  Bilinear Interpolation (درج وابسته به ۴ پیکسل ۴ طرف)
  2.  Bicubic interpolation (درج وابسته به ۴ پیکسل ۴ طرف به علاوه ۴ پیکسل اریب)
  3.  Nearest Neighbor (نزدیکترین همسایه)

استفاده از ماتریس تبدیل

جهت هایی را که میخواهیم  scale شوند را در قطر ماتریس قرار میدهیم.

معایب :

  1. مشکل سیاهی تصویر را دارد.
  2. عکس بعد از اعمال interpolations باید crop شود .

Image Pyramids

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

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

کاربرد: آموزش به هوش مصنوعی برای تشخیص اشیاء

Cropping

Opencv تابع مشخص برای کراپ کردن ندارد.

روش های جایگزین :

یکی از روش های کراپ کردن slicing است که با دادن بازه ی دقیقی از  x ,y (برای ساده تر شدن عکس را بصورت دو بعدی و سیاه سفید تصور میکنیم)همان بازه ی مشخص شده را کراپ می کنیم.

نکات :

مختصات شروع و پایان حتما  باید اعداد صحیح باشند.

در بازه نویسی به صورت   [ x1 : x2 , y1:y2 ] :

x1 شامل بازه میشود اما x2 نوشته نمیشود .

روش دیگر اسلایس کردن ماتریس  ها به کمک  numpy است.

مثال:

a=np.array([[100,200,400],[1,2,3]])

میخواهیم  عناصر سطر اول [0] و ستون دوم [1]  را انتخاب کنیم.

a [0: , 1:] => array([[200, 400],[ 2, 3]])

 

دستکاری تصویر (1) – ماتریس‌های تبدیل

در جلسات قبل با مفهوم فضاهای رنگی آشنا شدیم و خواندیم که هر عکس رنگی از سه کانال رنگی (R,G,B) تشکیل شده است که هر کدام می توانند از صفر تا 255 مقدار بگیرند .

و اگر ما دستور image.shape  را برای یک عکس رنگی چاپ کنیم خروجی اینچنین خواهد بود

(height,width,3)

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

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

 

که خروجی آن برای هر کانال به صورت زیر خواهد بود:

 

 

تا اینجای کار با مفاهیم اولیه ی open cv  آشنا شدیم اکنون میخواهیم وارد مبحت image manipulations بشیم که لازمه ای این مبحث این هستش که یه دوره ی سریعی روی مباحث جبر خطی که عمدتا در هندسه تحلیلی عنوان شده داشته باشیم .

انواع روش های image manipulations  یا دستکاری تصویر:

  • انتقال های همگن یا غیر همگن ( (Transformations, affine and non affine
  • تبدیلات (Translations)
  • Rotations (دوران)
  • Scaling, re-sizing and interpolations  ( درون یابی یا interpolations به معنای این است که در هنگام تغییر سایز عکس پیکسل هایی که خالی میماند را با چه الگوریتمی میخواهیم پر کنیم.)
  • Image Pyramids

انتقال

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

تبدیلات همگن

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

بدین ترتیب در نتیجه یک تبدیل همگن، تمامی نقاط روی یک خط در ورودی، در خروجی نیز روی یک خط خواهند ماند.

  • انتقال، تجانس، تشابه و چرخش نمونه هایی از تبدیل های همگن هستند.

نکته هر تبدیل خطی همگن هست اما هر تبدیل همگنی خطی نیست.

 

معرفی وکتور

یک بردار یک بعدی است. که دو نوع دارد وکتور ستونی و سطری:

1)وکتور ستونی    2) وکتور سطری

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

نحوه محاسبه نرم اقلیدسی:

اگر دو وکتور به نام های A,B  داشته باشیم نرم اقلیدسی آن برابر است با

ماتریس

ماتریس همان بردار mxn است که در برنامه نویسی نیز همین معنا را دارد و یک عکس سیاه و سفید درواقع یک ماتریس  است که به میزان عرض عکس سطر و ارتفاع آن ستون دارد و هر درایه نمایانگر یک پیکسل است که میتواند ازصفر تا 255 مقدار بگیرد.

عکس رنگی نیز در واقع شامل سه ماتریس است که هر کدام از آنها مقدار یکی از کانالهای رنگی را نگه میدارد.

عملیات های ماتریسی در پایتون

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

جمع یک ماتریس با عدد ثابت

که در آن تک تک خانه های ماتریس با عدد جمع خواهند شد.

ضرب ماتریس در یک عدد ثابت یا scale

که در آن تک تک خانه های ماتریس در عدد ضرب خواهند شد.

 

نرم اقلیدسی در ماتریس ها

که دارای ویژگی های زیر است

  • مقدار آن همواره بزرگتر مساوی صفر است.
  • اگر صفر شود تک تک درایه های ماتریس باید صفر شوند .
  • به ازای هر
  • به ازای هر 

 

برای یاد آوری ضرب ماتریس ها میتوانید اینجا را کلیک کنید.

معرفی چند ماتریس خاص

ماتریس همانی:  یک ماتریس مربعی است کهتمامی درایه های روی قطر اصلی یک و سایر آنها صفر هستند.

ماتریس قطری: یک ماتریس مربعی است که درایه های روی قطر اصلی عدد دارند و سایر آنها صفر هستند.

ماتریس ترا نهاده: ماتریسی است که جای سطر و ستون هایش باهم عوض شده باشند.

ماتریس انتقال: ماتریسی است که برای انتقال بردار ها از طریق ضرب استفاده میشود.

نکاتی درباره ی ضرب ماتریس ها:

  • ضرب ماتریس ها خاصیت جابه جایی ندارد AB!=BA.
  • تنها میتوان ماتریس های مربعی را به توان رساند.