1. 程式人生 > >Opencv--Canny邊緣檢測器

Opencv--Canny邊緣檢測器

目標

  • 使用OpenCV函式cv :: Canny來實現Canny Edge Detector。

理論

該Canny邊緣檢測是由約翰·F·坎尼在1986年也知道很多的開發最佳的檢測,坎尼演算法旨在滿足三個主要標準:

  • 低錯誤率:意味著只有現有邊緣的良好檢測。
  • 良好的定位:檢測到的邊緣畫素與實際邊緣畫素之間的距離必須最小化。
  • 最小響應:每個邊緣只有一個檢測器響應。

步驟

  • 濾除任何噪音。高斯濾波器用於此目的。可能使用的的高斯核心的示例如下所示:size=5

Canny邊緣檢測器

  • 找到影象的強度梯度。為此,我們遵循類似於Sobel的程式:

應用一對卷積面罩 (在 x 和 y directions:

Canny邊緣檢測器

查詢梯度強度和方向:

Canny邊緣檢測器

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

  • 應用非最大抑制。這將刪除不被認為是邊緣的一部分的畫素。因此,只有細線(候選邊)將保留。
  • 滯後:最後一步。Canny確實使用兩個閾值(上限和下限):
  1. 如果畫素梯度高於上限閾值,則畫素被接受為邊緣
  2. 如果畫素梯度值低於較低閾值,則會被拒絕。
  3. 如果畫素梯度在兩個閾值之間,那麼只有當它連線到高於上限閾值的畫素時才被接受。

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

  • 有關更多詳細資訊,您可以隨時諮詢您最喜愛的Computer Vision書籍。

Code

  • 這個程式是做什麼的?
  1. 要求使用者輸入數值以設定我們的Canny Edge Detector的下限(通過Trackbar)。
  2. 應用Canny Detector並生成一個蒙版(亮線表示黑色背景上的邊緣)。
  3. 應用在原始影象上獲得的蒙版,並將其顯示在視窗中。
  • 程式碼如下:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
Mat src, gray_src, dst;
int t1_value = 50;
int max_value = 255;
const char* OUTPUT_TITLE = "Canny Result";
void Canny_Demo(int, void*);
int main(int argc, char** argv) {
	src = imread("C:/usr/opencv-test/Testpictures/sight.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	cvtColor(src, gray_src, CV_BGR2GRAY);
	createTrackbar("Threshold Value:", OUTPUT_TITLE, &t1_value, max_value, Canny_Demo);
	Canny_Demo(0, 0);

	waitKey(0);
	return 0;
}

void Canny_Demo(int, void*) {
	Mat edge_output;
	blur(gray_src, gray_src, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
	Canny(gray_src, edge_output, t1_value, t1_value * 3, 3, false);//false表用L1,即G(s) = |G(x)|+|G(y)|

	dst.create(src.size(), src.type());
	src.copyTo(dst, edge_output);
	// (edge_output, edge_output);
	imshow(OUTPUT_TITLE, edge_output);
}

說明

請注意以下事項:

  1. 我們建立一個較低的上限閾值3:1(與可變比率)的比率。
  2. 我們設定核心大小為(Sobel操作由Canny函式內部執行)。3
  3. 我們為的下限閾值設定最大值。100
  • 載入源影象:
  • 建立一個相同型別和大小的src(為dst)的矩陣:
  cvtColor(src,src_gray,COLOR_BGR2GRAY);
  • 建立一個視窗來顯示結果:
  • 建立一個跟蹤欄,供使用者輸入Canny檢測器的下限:
createTrackbar("Threshold Value:", OUTPUT_TITLE, &t1_value, max_value, Canny_Demo);

觀察以下內容:

  1. Trackbar要控制的變數是lowThreshold,最大值為max_lowThreshold(我們先前設定為100)
  2. 每次Trackbar註冊一個動作時,將呼叫回撥函式CannyThreshold。
  • 讓我們檢查CannyThreshold函式,一步一步:
  1. 首先,我們用核心大小為3的過濾器模糊影象:    
  1. blur(gray_src, gray_src, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
  2. 然後,我們應用OpenCV函式cv :: Canny
    Canny(gray_src, edge_output, t1_value, t1_value * 3, 3, false);

其中的解釋:

    • detected_edges:源影象,灰度
    • detected_edges:檢測器的輸出(可以與輸入相同)
    • lowThreshold:使用者移動軌跡欄輸入的值
    • highThreshold:在程式中設定為下限閾值的三倍(在Canny的建議之後)
    • kernel_size:我們將它定義為3(要在內部使用的Sobel核心的大小)

結果

  • 在編譯上面的程式碼之後,我們可以執行它作為引數作為影象的路徑。例如,使用以下影象作為輸入:

Canny邊緣檢測器

  • 移動滑塊,嘗試不同的閾值,我們得到以下結果:

Canny邊緣檢測器

  • 注意影象如何與邊緣區域上的黑色背景疊加。