找邊緣(Canny)

    xiaoxiao2021-03-25  79

    Sobel或Laplace都是基於微分的邊緣檢測算法,只有當雜訊極少,或者先用平滑濾波抑制雜訊後,才能得到理想結果。

    在邊緣檢測中,抑制雜訊和邊緣精確定位很難同時滿足,當我們通過平滑濾波去除噪音的同時,也增加了邊緣定位的不確定性,而提高邊緣檢算子對邊緣敏感度的同時,也增加了對雜訊的敏感度,這邊介紹Canny邊緣檢測算子,Canny在抗雜訊和精確定位間有不錯的效果,OpenCV提供Canny()函式,來進行Canny邊緣檢測,以下為流程,OpenCV已將步驟封裝好,使用時只要呼叫Canny()即可。

    去雜訊:使用5×5的高斯濾波,我們根據下面的高斯函數,以σ=1.3帶入後得到高斯濾波的各個參數。

    記錄梯像素梯度方向和強度:以Sobel運算子計算水平和垂直梯度(Gx、Gy),數學上為兩者平方後相加,得到梯度強度(G),實際上由於運算效率上的考量,OpenCV預設將G設為Gx和Gy的絕對值相加,θ為梯度方向,我們將其分類到0、45、90、135度之一,也就是假設此點我們計算的θ為0~22.5或157.5~180,便將此點θ分類為0。

    非最大抑制:採用梯度找邊緣,邊緣會比較模糊,這方法讓邊緣定位較精確,我們比較每個像素,和他正負梯度方向的像素,要是這個像素的梯度強度最大,就保留此像素的值,否則設為0,也就是假設有某個像素的梯度方向為朝上或下,則和它上面及下面像素比較梯度強度,如果不是最大就設為0。

    判斷邊界:我們依據輸入的上下兩個閾值,通常上下閾值的比例,大約在2:1到3:1之間,由閾值判斷此像素是否為邊緣,分以下三個判斷依據:

    a、要是此像素梯度強度大於上閾值,則此像素為邊緣。

    b、如果此像素梯度強度小於下閾值,此像素不為邊緣。

    c、如果此像素梯度強度介於上下閾值,如果此像素周圍,有像素的梯度強度大於上閾值,則此像素為邊緣,否則不為邊緣。


    OpenCV canny

    void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)

    src:輸入圖,單通道8位元圖。dst:輸出圖,尺寸、型態和輸入圖相同。 threshold1:第一個閾值。threshold2:第二個閾值。apertureSize :Sobel算子的核心大小。L2gradient :梯度大小的算法,預設為false。

    L2gradient分兩種找梯度方式:


    以下示範Canny()的使用,dst2為dst1黑白倒轉,改呈現比較習慣的黑色邊緣:

    #include <cstdio> #include <opencv2/opencv.hpp> using namespace cv; int main(){ Mat src = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE); GaussianBlur(src, src, Size(3,3), 0, 0); Mat dst1, dst2; Canny(src, dst1, 50, 150, 3); threshold(dst1, dst2, 128, 255, THRESH_BINARY_INV); //反轉影像,讓邊緣呈現黑線 imshow("origin", src); imshow("Canny_1", dst1); imshow("Canny_2", dst2); waitKey(0); return 0; }

    转自:http://monkeycoding.com/?p=622

    转载请注明原文地址: https://ju.6miu.com/read-8861.html

    最新回复(0)