Image Processing13(Canny Edge Detector)

Goal

In this tutorial you will learn how to:

  • Use the OpenCV function cv::Canny() to implement the Canny Edge Detector.
  • 使用OpenCV函数:cv::Canny()来执行Canny边缘检测

Theory

The Canny Edge detector was developed by John F. Canny in 1986. Also known to many as the optimal detector, the Canny algorithm aims to satisfy three main criteria:

  • Low error rate: Meaning a good detection of only existent edges.
  • 低错误率:意味着标识出尽可能的实际边缘,减小噪声产生的误报
  • Good localization: The distance between edge pixels detected and real edge pixels have to be minimized.
  • 高定位性:检测出的边缘像素与实际的边缘像素差距尽可能的小
  • Minimal response: Only one detector response per edge.
  • 最小响应:一个边缘只响应一次

Steps

1.Filter out any noise. The Gaussian filter is used for this purpose. An example of a Gaussian kernel of size=5 that might be used is shown below:

K=1159245424912945121512549129424542

第一步:消除噪声,使用高斯平滑实现这一点。一个大小为5*5的高斯内核如上:

2.Find the intensity gradient of the image. For this, we follow a procedure analogous to Sobel:

第二步:计算图像的梯度。这一步按照Sobel算子的步骤进行计算。

a:Apply a pair of convolution masks (in x and y directions:

a:分别在X方向和Y方向上进行卷积操作:

b:Find the gradient strength and direction with:

Gx=121000+1+2+1

Gy=10+120+210+1

b:计算梯度值和方向:

G=G2x+G2yθ=arctan(GyGx)

The direction is rounded to one of four possible angles (namely 0, 45, 90 or 135)

方向一般是这四种可能。

3.Non-maximum suppression is applied. This removes pixels that are not considered to be part of an edge. Hence, only thin lines (candidate edges) will remain.

3.非极大值抑制。这将消除一些像素,并不认为是边缘的部分。因此,只有一些线条(候选边缘部分)被保留。

4.Hysteresis: The final step. Canny does use two thresholds (upper and lower):

4.之后。最后一步。Canny这里使用了两个阀值。

a.If a pixel gradient is higher than the upper threshold, the pixel is accepted as an edge

a.如果像素的梯度高于upper阀值,则这个像素处是边缘。

b.If a pixel gradient value is below the lower threshold, then it is rejected.

b.如果像素的梯度低于lower阀值。则这个像素不是边缘。

c.If the pixel gradient is between the two thresholds, then it will be accepted only if it is connected to a pixel that is above the upper threshold.

c.如果介于之间,则当这个像素与边缘部分的像素想连接时,其才是边缘。

  1. Canny recommended a upper:lower ratio between 2:1 and 3:1.

  2. Canny 建议上下阀值的比例为2:1和3:1。

For more details, you can always consult your favorite Computer Vision book.

更多的细节,需要不时的查阅你喜欢的计算机视觉书。

Code

  1. What does this program do?
    • Asks the user to enter a numerical value to set the lower threshold for our Canny Edge Detector (by means of a Trackbar).设置lower阀值,通过一个滑动条。
    • Applies the Canny Detector and generates a mask (bright lines representing the edges on a black background).使用Canny边缘检测,并产生一个MASK(明亮的线条代表了边缘部分)
    • Applies the mask obtained on the original image and display it in a window.(使用MASK获得原始图片上的边缘部分,并显示)
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
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); //目标,MASK
    imshow( "src", src );
    imshow( window_name, dst );
}
int main( int argc, char** argv )
{
  CommandLineParser parser( argc, argv, "{@input | lena.jpg | input image}" ); //参数,默认值,帮助信息
  src = imread( parser.get<String>( "@input" ), IMREAD_COLOR ); // Load an image
  if( src.empty() )
  {
    std::cout << "Could not open or find the image!\n" << std::endl;
    std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;
    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;

}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

set(CMAKE_CXX_FLAGS "-std=c++11")
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )


install(TARGETS DisplayImage RUNTIME DESTINATION bin)

Results


猜你喜欢

转载自blog.csdn.net/qq_27806947/article/details/80297496