2016年11月17日 星期四

OPENCV(10)--Canny Edge Detection(Canny邊緣檢測)


    這篇介紹Canny 邊緣檢測原理,即OPENCV提供的Canny演篹法函式庫並實作一範例程式
可用兩個Trackbar 去調整minVal(T1) ,maxVal(T2)閥值,可以清楚看出minVal ,maxVal閥值對Canny 邊緣的變化影響。




原理:
    Canny  邊緣檢測是一種非常流行的邊緣檢測演算法,是 John  F.Canny 在
1986  年提出的。它是一個有很多步驟形成的演算法,我們接下來逐步介紹。

Canny邊緣檢測演算法步驟:

Step 1.雜訊去除
由於邊緣檢測很容易受到雜訊影響,所以第一步是使用 5x5 的高斯濾波器 去除雜訊。

Step 2.計算圖像梯度
    對平滑後的圖像使用 Sobel 運算元計算水平方向和垂直方向的一階導數(Gx  和 Gy),
根據得到的這兩幅梯度圖(Gx  和 Gy)找到邊界的梯度和方向,公式如下:




梯度的方向一般總是與邊界垂直。梯度方向被歸為四類:垂直,水平,和 兩個對角線。

Step 3.非極大值抑制

    在獲得梯度的方向和大小之後,應該對整幅圖像做一個掃描,去除那些非 邊界上的點。
對每一個圖元進行檢查,看這個點的梯度是不是周圍具有相同梯 度方向的點中最大的。
如下圖所示:現在你得到的是一個包含“窄邊界”的二值圖像。


Step 4.滯後閾值
    現在要確定那些邊界才是真正的邊界。 這時我們需要設置兩個閾值: minVal 和 maxVal。
當圖像的灰度梯度高於 maxVal 時被認為是真的邊界, 那些低於 minVal 的邊界會被拋棄。
如果介於兩者之間的話,就要看這個點是 否與某個被確定為真正的邊界點相連,如果是就認為它也是邊界點,如果不是 就拋棄。如下圖:




    A高於閾值 maxVal 所以是真正的邊界點,C 雖然低於 maxVal 但高於 minVal 並且與 A 相連,所以也被認為是真正的邊界點。而 B 就會被拋棄,因 為他不僅低於 maxVal 而且不與真正的邊界點相連。所以選擇合適的 maxVal 和  minVal  對於能否得到好的結果非常重要。
在這一步一些小的雜訊點也會被除去,因為我們假設邊界都是一些長的線段。

原始來源請參考OPENCV官網:
http://docs.opencv.org/3.1.0/da/d22/tutorial_py_canny.html

範例實作:
 
    OpenCV 提供一個函數:cv2.Canny(),就可以完成以上幾個步驟。
這個函數的第一個參數是輸入圖像。第二和第三 個分別是 minVal 和 maxVal閥值。
第三個參數設置用來計算圖像梯度的 Sobel 卷積核的大小,預設值為 3。
最後一個參數是 L2gradient,它可以用來設定 求梯度大小的方程。如果設為  True,
就會使用我們上面提到過的方程,否則使用底下方程式代替,預設值為 False。


<圖一>為灰值化後的原圖




調整兩個Trackbar 的minVal(T1) ,maxVal(T2)閥值,可以清楚看出minVal ,maxVal閥值對
邊緣的變化影響。

<圖二>為Canny效果圖





<完整範例程式>

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

def Change_threhole(x):
 # get current positions of four trackbars
  T1 = cv2.getTrackbarPos('T1','home_canny')
  T2 = cv2.getTrackbarPos('T2','home_canny')
  edges = cv2.Canny(img,T1,T2)
  cv2.imshow('home_canny',edges)
  cv2.imshow('home',img)
  
cv2.namedWindow('home_canny', cv2.WINDOW_NORMAL) #WINDOW_AUTOSIZE 
cv2.namedWindow('home', cv2.WINDOW_NORMAL) #WINDOW_AUTOSIZE   
  
cv2.createTrackbar('T1','home_canny',0,500,Change_threhole)
cv2.createTrackbar('T2','home_canny',0,500,Change_threhole)

img = cv2.imread('home.jpg',0)
edges = cv2.Canny(img,150,300)   ##initial value
cv2.imshow('home_canny',edges)
cv2.imshow('home',img)

k = cv2.waitKey(0) & 0xFF
if k == 27:
 cv2.destroyAllWindows()




歡迎加入FB,AI人工智慧與機器人社團一起討論,
https://www.facebook.com/groups/1852135541678378/2068782386680358/?notif_t=like&notif_id=1477094593187641

加入阿布拉機的3D列印與機器人的FB專頁
https://www.facebook.com/arbu00/


<其他有關OPENCV 文章>
OPENCV(9)--Image Gradients(圖像梯度)
OPENCV(8)--Histogram & Histograms Equalization(長條圖與長條圖均衡化)
OPENCV(7)--2D Convolution ,Image Filtering and Blurring (旋積,濾波與模糊)
OPENCV(6)--Trackbar(軌道桿)
OPENCV(5)--Drawing
OPENCV(4)--Grayscale,Binarization,Threshole(灰階化,二值化,閥值)
OPENCV(3)--Matplotlib pyplot bassic function
OPENCV(2)--Capture Video from Camera
OPENCV(1 )--How to install OPENCV in Python

<參考資料:>OPENCV官網
http://docs.opencv.org/3.1.0/index.html