【opencv實踐】邊緣檢測


 

邊緣檢測:

一、canny算子

Canny邊緣檢測根據對信噪比與定位乘積進行測度,得到最優化逼近算子,也就是Canny算子。類似與 LoG 邊緣檢測方法,也屬於先平滑后求導數的方法。

二、canny算法描述

1.首先進行高斯平滑濾波;

 

2、然后計算像素點的梯度(利用sobel算子)

3、計算幅值和夾角

4、非極大值抑制(NMS)幅值和夾角,如下圖所示,就是比較梯度方向前后像素梯度的大小。

 

上圖中左右圖:g1、g2、g3、g4都代表像素點,很明顯它們是c的八領域中的4個,左圖中c點是我們需要判斷的點,藍色的直線是它的梯度方向,也就是說c如果是局部極大值,它的梯度幅值M需要大於直線與g1g2和g2g3的交點,dtmp1和dtmp2處的梯度幅值。但是dtmp1和dtmp2不是整像素,而是亞像素,也就是坐標是浮點的,那怎么求它們的梯度幅值呢?線性插值,例如dtmp1在g1、g2之間,g1、g2的幅值都知道,我們只要知道dtmp1在g1、g2之間的比例,就能得到它的梯度幅值,而比例是可以靠夾角計算出來的,夾角又是梯度的方向。

    寫個線性插值的公式:設g1的幅值M(g1),g2的幅值M(g2),則dtmp1可以很得到:

        M(dtmp1)=w*M(g2)+(1-w)*M(g1)  

       其中w=distance(dtmp1,g2)/distance(g1,g2)      

    distance(g1,g2) 表示兩點之間的距離。實際上w是一個比例系數,這個比例系數可以通過梯度方向(幅角的正切和余切)得到。

5、雙閾值選取

  • 將低於閾值的所有值賦零,得到圖像的邊緣陣列 

  • 閾值τ取得太低->假邊緣
  • 閾值τ取得太高->部分輪廊丟失

 Canny算法中減少假邊緣數量的方法是采用雙閾值法。選擇兩個閾值,根據高閾值得到一個邊緣圖像,這樣一個圖像含有很少的假邊緣,但是由於閾值較高,產生的圖像邊緣可能不閉合,為解決這樣一個問題采用了另外一個低閾值。
        在高閾值圖像中把邊緣鏈接成輪廓,當到達輪廓的端點時,該算法會在斷點的8鄰域點中尋找滿足低閾值的點,再根據此點收集新的邊緣,直到整個圖像邊緣閉合。

 三、Canny方法

void Canny(InputArray image,

                OutputArray edges,

                double threshold1,

                double threshold2,

                int apertureSize=3,

                bool L2gradient=false)
參數詳解:
  • 第一個參數,InputArray類型的image,輸入圖像,填Mat類對象即可,且需為單通道8位圖像
  •  第二個參數,OutputArray類型的edges,輸出邊緣圖,和源圖像有一樣的尺寸和類型
  •  第三個參數,double類型的threshold1,第一個滯后性閾值
  •  第四個參數,double類型的threshold2,第二個滯后性閾值
  •  第五個參數,int類型的apertureSize,表示應用Sobel算子的孔徑大小,默認值3
  •  第六個參數,bool類型的L2gradient,一個計算圖像梯度幅值的標識,默認值false
注意:兩個閾值中較小的值用於邊緣連接,較大的值用來控制強邊緣的初始段,推薦高低閾值比為2:1到3:1之間

 四、opencv中的實現

1、圖像灰度化;

2、高斯濾波(blur)

3、計算梯度

4、用雙閾值方法檢測和連接邊緣

 

 

 

 

 

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
using namespace cv;
int main(int argc, char *argv[])
{
    Mat img = imread("lena.jpg", CV_LOAD_IMAGE_COLOR);
    if(img.empty())
       return -1;
    Mat src_gray,src_blur,dst;
    cvtColor(img,src_gray,CV_BGR2GRAY);
    blur(src_gray,src_blur,Size(3,3));
    Canny(src_blur,dst,30,200);
    namedWindow( "lena", CV_WINDOW_AUTOSIZE );
    imshow("lena", img);
    imshow("canny",dst);
    waitKey(0);
    return 0;
}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM