Canny Edge Detection

  • مدرس: علی بیگدلی
  • تاریخ انتشار: Sep 05, 2020

مقدمه

تشخیص لبه یک مشکل اساسی در پردازش تصویر است. Opencv عملکرد Canny () را ارائه می دهد که به تشخیص لبه های تصویر کمک می کند. Canny edge detection یک الگوریتم چند مرحله ای است که می تواند لبه ها را تشخیص دهد. این الگوریتم شامل چهار مرحله است -

  1. Noise Reduction
  2. Gradient Computation
  3. Non-Max Suppression
  4. Hysteresis Thresholding


اجازه دهید این مراحل را با جزئیات بیشتری مشاهده کنیم.


1.Noise Reduction

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

2. Gradient Computation

لبه ها با تغییر شدت پیکسل ها مطابقت دارند. برای تشخیص آن ، ساده ترین راه استفاده از فیلترهایی است که این تغییر شدت را در هر دو جهت برجسته می کنند: افقی (x) و عمودی (y)
بنابراین در این مرحله ، اولین عملگر مشتق 2-D مانند اپراتور Sobel در جهت افقی و همچنین عمودی بر روی تصویر صاف شده اعمال می شود. این به شما کمک می کند تا مشتق اول در جهت افقی (G_x) و جهت عمودی (G_y) برای برجسته سازی مناطق تصویر با مشتقات فضایی اول زیاد باشد.

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

3. Non-Max Suppression
پس از انجام مراحل محاسبه شیب ، ضخامت لبه یکنواخت نیست. برخی از لبه ها ضخیم هستند در حالی که برخی دیگر نازک هستند و همچنین پیکسل های ناخواسته ای وجود دارد که ممکن است تصاویر نباشد. بنابراین برای غلبه بر این مسئله از سرکوب غیر حداکثر استفاده می شود.
در این مرحله ، برای هر پیکسل ، بررسی می شود که آیا در همسایگی خود در جهت شیب حداکثر محلی باشد.

همانطور که در تصویر می بینیم ، نقطه A در لبه است و نقاط B و C در جهت گرادیان قرار دارند. از آنجا که جهت گرادیان همیشه عمود بر لبه است ، بنابراین نقطه A با نقاط B و C بررسی می شود اگر حداکثر محلی را تشکیل دهد ، برای مرحله بعدی در نظر گرفته می شود ، در غیر این صورت ، یعنی مقدار پیکسل صفر می شود ، سرکوب می شود.
با کلمات ساده ، فرض کنید من (m ، n) یک تصویر است -
اگر I (m، n) بزرگتر از دو همسایه آن در امتداد شیب تتا (m، n) باشد ، پس I (m، n) را بدون تغییر نگه دارید ، در غیر این صورت ، آن را روی 0 تنظیم کنید.

4. Hysteresis Thresholding
این مرحله برای شناسایی پیکسلهایی استفاده می شود که همه به لبه ها کمک می کنند ، واقعاً لبه هستند و نیستند.
برای این کار باید دو آستانه T1 (آستانه بالا) و T2 (آستانه پایین) داشته باشیم.
هر لبه با شیب شدت بیش از آستانه بالا مطمئناً لبه است.
هر لبه زیر minVal مطمئناً بدون لبه است ، بنابراین دور ریخته می شود.
آن هایی که بین این دو آستانه قرار می گیرند ، براساس اتصال لبه ها یا غیر لبه ها طبقه بندی می شوند. یعنی اگر به پیکسل های "Sure-edge" متصل باشند ، به عنوان بخشی از لبه ها در نظر گرفته می شوند. در غیر این صورت ، کنار گذاشته می شوند.

مثال فوق را در نظر بگیرید تا آن را به روشنی درک کنیم.
Edge A بالای آستانه بالا (T1) است. بنابراین به عنوان "لبه معتبر" در نظر گرفته می شود.
اگرچه لبه C زیر آستانه High است ، اما به لبه A متصل است. بنابراین این نیز به عنوان یک لبه معتبر در نظر گرفته می شود و ما آن منحنی کامل را بدست می آوریم.
اگرچه Edge B بالاتر از آستانه پایین است و در همان منطقه لبه C قرار دارد ، اما به هیچ "لبه مطمئنی" متصل نیست ، بنابراین کنار گذاشته می شود.
بنابراین بسیار مهم است که ما باید Low Threshold و High Threshold را بر این اساس انتخاب کنیم تا نتیجه صحیح بدست آوریم.

 

چند نکته مهم
تأثیر عملگر Canny با سه پارامتر تعیین می شود:

  1. عرض هسته گوسی که در مرحله صاف سازی استفاده می شود ،
  2.  آستانه فوقانی
  3. آستانه های پایین تر مورد استفاده توسط ردیاب.

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

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

 

OpenCV تمام موارد بالا را در یک تابع ، cv2.Canny () قرار می دهد. خواهیم دید که چگونه از آن استفاده کنیم.

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('Sample.jpg',0)
edges = cv2.Canny(img,100,200)

plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()

خروجی قطعه کد بالا:

 

ثبت دیدگاه
نام *
ایمیل*
دیدگاه *
captcha
0دیدگاه