OpenCV Canny邊緣檢測(cè)器

2021-02-19 17:03 更新

目標(biāo)

在本教程中,您將學(xué)習(xí)如何:

  • 使用OpenCV函數(shù)cv :: Canny來實(shí)現(xiàn)Canny Edge Detector。

理論

該Canny邊緣檢測(cè)是由約翰·F·坎尼在1986年也知道很多的開發(fā)最佳的檢測(cè),坎尼算法旨在滿足三個(gè)主要標(biāo)準(zhǔn):

  • 低錯(cuò)誤率:意味著只有現(xiàn)有邊緣的良好檢測(cè)。
  • 良好的定位:檢測(cè)到的邊緣像素與實(shí)際邊緣像素之間的距離必須最小化。
  • 最小響應(yīng):每個(gè)邊緣只有一個(gè)檢測(cè)器響應(yīng)。

步驟

  • 濾除任何噪音。高斯濾波器用于此目的??赡苁褂玫牡母咚箖?nèi)核的示例如下所示:size=5

Canny邊緣檢測(cè)器

  • 找到圖像的強(qiáng)度梯度。為此,我們遵循類似于Sobel的程序:

應(yīng)用一對(duì)卷積面罩 (在 x 和 y directions:

Canny邊緣檢測(cè)器

查找梯度強(qiáng)度和方向:

Canny邊緣檢測(cè)器

方向四舍五入為四個(gè)可能的角度之一(即0,45,90或135)

  • 應(yīng)用非最大抑制。這將刪除不被認(rèn)為是邊緣的一部分的像素。因此,只有細(xì)線(候選邊)將保留。
  • 滯后:最后一步。Canny確實(shí)使用兩個(gè)閾值(上限和下限):
  1. 如果像素梯度高于上限閾值,則像素被接受為邊緣
  2. 如果像素梯度值低于較低閾值,則會(huì)被拒絕。
  3. 如果像素梯度在兩個(gè)閾值之間,那么只有當(dāng)它連接到高于上限閾值的像素時(shí)才被接受。

Canny推薦上限:2:1和3:1之間的較低比例。

  • 有關(guān)更多詳細(xì)信息,您可以隨時(shí)咨詢您最喜愛的Computer Vision書籍。

Code

  • 這個(gè)程序是做什么的?
  1. 要求用戶輸入數(shù)值以設(shè)置我們的Canny Edge Detector的下限(通過Trackbar)。
  2. 應(yīng)用Canny Detector并生成一個(gè)蒙版(亮線表示黑色背景上的邊緣)。
  3. 應(yīng)用在原始圖像上獲得的蒙版,并將其顯示在窗口中。
  • 教程代碼如下所示。您也可以從這里下載

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
Mat src, src_gray;
Mat dst, detected_edges;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*)
{
    blur( src_gray, detected_edges, Size(3,3) );
    Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
    dst = Scalar::all(0);
    src.copyTo( dst, detected_edges);
    imshow( window_name, dst );
}
int main( int, char** argv )
{
  src = imread( argv[1], IMREAD_COLOR ); // Load an image
  if( src.empty() )
    { return -1; }
  dst.create( src.size(), src.type() );
  cvtColor( src, src_gray, COLOR_BGR2GRAY );
  namedWindow( window_name, WINDOW_AUTOSIZE );
  createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
  CannyThreshold(0, 0);
  waitKey(0);
  return 0;
}

說明

  • 創(chuàng)建一些必需的變量:
Mat src, src_gray;
Mat dst, detected_edges;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
const char* window_name = "Edge Map";

請(qǐng)注意以下事項(xiàng):

  1. 我們建立一個(gè)較低的上限閾值3:1(與可變比率)的比率。
  2. 我們?cè)O(shè)置內(nèi)核大小為(Sobel操作由Canny函數(shù)內(nèi)部執(zhí)行)。3
  3. 我們?yōu)榈南孪揲撝翟O(shè)置最大值。100
  • 加載源圖像:
  src = imread( argv[1], IMREAD_COLOR ); // Load an image
  if( src.empty() )
    { return -1; }
  • 創(chuàng)建一個(gè)相同類型和大小的src(為dst)的矩陣:
  dst.create(src.size(),src.type());
  • 將圖像轉(zhuǎn)換為灰度級(jí)(使用函數(shù)cv :: cvtColor):
  cvtColor(src,src_gray,COLOR_BGR2GRAY);
  • 創(chuàng)建一個(gè)窗口來顯示結(jié)果:
  namedWindow(window_name,WINDOW_AUTOSIZE);
  • 創(chuàng)建一個(gè)跟蹤欄,供用戶輸入Canny檢測(cè)器的下限:
  createTrackbar(“Min Threshold:”,window_name,&lowThreshold,max_lowThreshold,CannyThreshold);

觀察以下內(nèi)容:

  1. Trackbar要控制的變量是lowThreshold,最大值為max_lowThreshold(我們先前設(shè)置為100)
  2. 每次Trackbar注冊(cè)一個(gè)動(dòng)作時(shí),將調(diào)用回調(diào)函數(shù)CannyThreshold。
  • 讓我們檢查CannyThreshold函數(shù),一步一步:
  1. 首先,我們用內(nèi)核大小為3的過濾器模糊圖像:    
  1.     blur(src_gray,detected_edges,Size(3,3));
    
  2. 然后,我們應(yīng)用OpenCV函數(shù)cv :: Canny
        Canny(detected_edges,detected_edges,lowThreshold,lowThreshold * ratio,kernel_size);
    

其中的解釋:

    • detected_edges:源圖像,灰度
    • detected_edges:檢測(cè)器的輸出(可以與輸入相同)
    • lowThreshold:用戶移動(dòng)軌跡欄輸入的值
    • highThreshold:在程序中設(shè)置為下限閾值的三倍(在Canny的建議之后)
    • kernel_size:我們將它定義為3(要在內(nèi)部使用的Sobel內(nèi)核的大?。?/li>
  • 我們用零填充dst圖像(意味著圖像是完全黑色的)。
    dst = Scalar :: all(0);
  • 最后,我們將使用函數(shù)cv :: Mat :: copyTo僅映射被識(shí)別為邊緣的圖像的區(qū)域(在黑色背景上)。cv :: Mat :: copy將src映像復(fù)制到dst上。但是,它只會(huì)復(fù)制它們具有非零值的位置中的像素。由于Canny檢測(cè)器的輸出是黑色背景上的邊緣輪廓,因此所得到的dst在所有區(qū)域都將為黑色,但檢測(cè)到的邊緣為黑色。
  •     src.copyTo(dst,detected_edges);
    
  • 我們顯示結(jié)果:
    imshow(window_name,dst);

結(jié)果

  • 在編譯上面的代碼之后,我們可以運(yùn)行它作為參數(shù)作為圖像的路徑。例如,使用以下圖像作為輸入:

Canny邊緣檢測(cè)器

  • 移動(dòng)滑塊,嘗試不同的閾值,我們得到以下結(jié)果:

Canny邊緣檢測(cè)器

  • 注意圖像如何與邊緣區(qū)域上的黑色背景疊加。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)