1. Edge detection
Original link: http://blog.sina.com.cn/s/blog_154bd48ae0102weuk.html
General steps of edge detection:
1. Filtering
The algorithm of edge detection is mainly based on the first and second derivatives of the image. But the derivative is usually very sensitive to noise, so we must first use a filter to reduce the noise. The common filtering method is Gaussian filtering.
2. Enhancement
The basis of edge enhancement is to determine the change value of the intensity of each point field of the image. The enhancement algorithm can highlight the points with significant changes in the intensity value of the neighborhood of image gray points. In the specific calculation process, it can be determined by calculating the gradient amplitude.
3. Inspection
In the enhanced image, the gradient value of many points in the field is often large, but in specific occasions, these points are not edge points, so we should choose some way. We usually use the threshold method to detect.
1.1. (CV:: canny) edge detection
Steps of Canny edge detection:
1. Noise elimination (Gaussian filtering)
2. Calculate gradient amplitude and direction (sobel filter)
3. Non maximum suppression (excluding some non edge pixels)
4. Hysteresis threshold
Sobel operator is used to calculate image gradient, so Sobel operator has been called in canny and laplacian.
Sobel operator is a discrete differential operator mainly used for edge detection. It combines Gaussian smoothing and differential derivation to calculate the approximate gradient of image gray function. Using this operator at any point in the image will produce the corresponding gradient vector or normal vector.
Laplace operator is a second-order differential operator in n-dimensional Euclidean space, which is defined as the divergence of gradient.
Except canny operator, all other operators have two directions of x and y
Void canny(InputArray image,OutputArray edges,double threshold1,double threshold2,int apertureSize=3,bool L2gradient=false)
- Image: input image
- edges: output image
- threshold1: the first hysteresis threshold
- threshold2: the second hysteresis threshold
- apertureSize: indicates the aperture size of sobel operator. The default value is 3
- L2gradient: an identifier for calculating the gradient amplitude of an image. The default value is false
1.2. (CV:: Sobel) edge detection
It should be noted that the smaller value of threshold 1 and threshold 2 of this function is used for edge connection, while the larger value is used to control the initial segment of strong edge.
Void Sobel(InputArray image,OutputArray edges,int ddepth,int dx,int dy,int ksize=3,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
- Image: input image
- edges: output image
- ddepth: the depth of the output image
- dx: difference order in x direction
- dy: difference order in y direction
- ksize: the core size of Sobel must be 1 / 3 / 5 / 7
- scale: optional scaling factor when calculating derivative value
- Delta: the optional delta value before the result is stored in the target graph. The default value is 0
- borderType: boundary mode
1.3. (CV:: Laplacian) edge detection
Laplacian(InputArray image,OutputArray edges,int ddepth,int ksize=1,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
- Image: input image
- edges: output image
- ddepth: the depth of the output image
- ksize: the aperture size of the filter used to calculate the second derivative. The size must be positive and odd. The default is 1
- Scale: the optional scale factor used to calculate the Laplace value
- Delta: the optional delta value before the result is stored in the target graph. The default value is 0
- borderType: boundary mode
- Scharr filter
1.4. (CV:: ScHARR) edge detection
Void Scharr(InputArray image,OutputArray edges,int ddepth,int dx,int dy,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
- Image: input image
- edges: output image
- ddepth: the depth of the output image
- dx: difference order in x direction
- dy: difference order in y direction
- scale: optional scaling factor when calculating derivative value
- Delta: the optional delta value before the result is stored in the target graph. The default value is 0
- borderType: boundary mode
Scharr differs from soble by only one parameter, the number of kernels. Scharr only works on kernels of size 3. This function is as fast as sobel function, but the result is more accurate.
//#include"stdafx.h"; #include"opencv2/opencv.hpp" //Spatial variable using namespace cv; using namespace std; void main() { //Display original image Mat image = imread("./image/test3.jpg"); namedWindow("Original drawing"); imshow("Original drawing", image); //Simple usage of canny edge detection Mat result; Canny(image, result, 150, 70); namedWindow("canny Image after edge detection"); imshow("canny Image after edge detection", result); //High order canny usage, turn it into gray image, reduce noise, use canny, and finally take the obtained edge as a mask, copy the original image to the effect image, and get the color edge image Mat grayimage, edge; cvtColor(image, grayimage, COLOR_BGR2GRAY); boxFilter(grayimage, edge, -1, Size(3, 3)); Canny(edge, edge, 150, 70); Mat dst; dst = Scalar::all(123); image.copyTo(dst, edge); namedWindow("canny Image after high-order edge detection"); imshow("canny Image after high-order edge detection", dst); //sobel operator edge detection Mat x_result, y_result; Sobel(image, x_result, 0, 1, 0); Sobel(image, y_result, 0, 0, 1); addWeighted(x_result, 0.5, y_result, 0.5, 0, result); imshow("sobel After edge detection x Image of axis", x_result); imshow("sobel After edge detection y Image of axis", y_result); imshow("sobel Image after edge detection", result); //laplacian edge detection Laplacian(image, result, 0); imshow("laplacian Image after edge detection", result); //scharr filter boxFilter(image, image, -1, Size(3, 3)); Scharr(image, x_result, 0, 1, 0); Scharr(image, x_result, 0, 0, 1); addWeighted(x_result, 0.5, y_result, 0.5, 0, result); imshow("scharr After edge detection x Image of axis", x_result); imshow("scharr After edge detection y Image of axis", y_result); imshow("scharr Image after edge detection", result); waitKey(); }
Execution result:
2. Outline drawing
2.1. (CV:: findcontours) find contours
CV_EXPORTS_W void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point());
- Image: single channel image matrix, which can be gray image, but more commonly used is binary image, which is generally binary image processed by Canny, Laplace and other edge detection operators;
- Contours: contours is defined as "vector < vector > contours", which is a double vector (each element in the vector holds a vector of a set of points composed of continuous points). Each set of points is a contour. As many contours as there are, there are as many elements in the contours;
- Hierarchy: hierarchy is defined as "vector hierarchy",
Definition of Vec4i: typedef VEC < int, 4 > Vec4i; (each element in the vector contains four int variables), so from the definition, hierarchy is a vector
Each element is an array containing four int types. The elements in the vector hierarchy correspond to the elements in the contour vector contour one by one, and the capacity of the vector is the same
The four int variables of each element in the are hierarchy[i][0] ~ hierarchy[i][3], which respectively represent the editing of the next contour, the previous contour, the parent contour and the embedded contour of the current contour I
Number index. If the current contour does not have a corresponding next contour, previous contour, parent contour and embedded contour, the corresponding hierarchy[i] [*] is set to - 1. - Mode: defines the retrieval mode of the contour. The values are as follows:
- RETR_EXTERNAL: only the outermost contour is detected, and the inner contour contained in the outer contour is ignored;
- RETR_LIST: detect all contours, including inner and outer contours, but the detected contours do not establish a hierarchical relationship, are independent of each other, and have no hierarchical relationship, which means that there is no parent contour or embedded contour in this retrieval mode, so the 3rd and 4th components of all elements in the hierarchy vector will be set to - 1, which will be discussed below;
- RETR_CCOMP: detect all contours, but all contours only establish two hierarchical relationships. The periphery is the top layer. If the inner contour in the periphery also contains other contour information, all contours in the inner circumference belong to the top layer;
- RETR_TREE: detect all contours and establish a hierarchical tree structure for all contours. The outer contour contains the inner contour, and the inner contour can continue to contain the embedded contour.
- Method: the approximate method of defining the contour. The values are as follows:
- CHAIN_APPROX_NONE: save all continuous contour points on the object boundary into the contours vector;
- CHAIN_APPROX_SIMPLE: save only the inflection point information of the contour, save all the points at the inflection point of the contour into the contour vector, and save the information on the straight line segment between the inflection point and the inflection point
Interest points are not reserved; - CHAIN_APPROX_TC89_L1: teh chinl chain approximation algorithm is used;
- CHAIN_APPROX_TC89_KCOS: teh chinl chain approximation algorithm is used.
- Offset: Point offset, the offset of all contour information relative to the corresponding Point of the original image, which is equivalent to adding the offset to each detected contour Point, and Point can also
So it's negative!
2.2. (CV:: drawcontours) contour drawing function
void drawContours(InputOutputArray image, InputOutputArrays contours, int contourIdx, const Scalar& color, int thickness = 1, int lineType = 8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point());
- Image: target image, just fill in Mat object.
- Contours: input contours. Each contour is a set of points, which can be represented by a vector of Point type.
- contourIdx: the index number of the contour. Negative values draw all contours.
- Color: outline color.
- Thickness: the thickness of the outline line. The default value is 1. If it is negative, the space inside the profile is filled.
- lineType: the type of line, with a default value of 8. The types that can be removed are as follows:
Type meaning
8 connected Linetype
4 connected Linetype
LINE_AA antialiasing Linetype - Hierarchy: optional hierarchy information, with the default value noArray().
- maxLevel: the maximum level used to draw the outline. It has the default value INT_MAX.
- Offset: the offset of the contour information relative to the corresponding point of the target image, which is equivalent to adding the offset to each contour point, with the default value of Point(). In ROI
This parameter can be used when drawing the outline of the region (region of interest).
#include <iostream> #include <vector> #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace std; using namespace cv; int main() { Mat img = imread("./image/test.jpg"); imshow("Original drawing", img); cvtColor(img, img, COLOR_BGR2GRAY);//Convert to grayscale image //Binarization by Otsu method threshold(img, img, 100, 255, THRESH_OTSU); imshow("Binarization", img); //Extracting contour data from binary image vector<vector<Point> > contour_vec; vector<Vec4i> hierarchy; //1. RETR_EXTERNAL: only the outermost contour is detected, and the inner contour contained in the outer contour is ignored; //2. RETR_LIST: detect all contours findContours(img, contour_vec, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE); cout << "contours number: " << contour_vec.size() << endl; // The previously used for loop is used to draw the outline /*Mat blkImg(binImg.size(), CV_8UC1, Scalar(0)); for(int i = 0; i < contour_vec.size(); i++) { drawContours(blkImg, contour_vec, i, Scalar(255), -1); } */ //Draw a single channel outline image with white background and black outline lines Mat blkImg(img.size(), CV_8UC1, Scalar(255)); drawContours(blkImg, contour_vec, -1, Scalar(0), 2); imshow("Single channel profile", blkImg); //Draw a color outline image with blue-green background color and red outline line Mat colorImg(img.size(), CV_8UC3, Scalar(255, 255, 0)); drawContours(colorImg, contour_vec, -1, Scalar(0, 0, 255), 3); imshow("Color outline", colorImg); waitKey(0); return 0; }
Execution result:
2.3. Examples of image inversion and detection of all contours:
#include <iostream> #include <vector> #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace std; using namespace cv; int main() { Mat img = imread("./image/test17.jpg"); imshow("Original drawing", img); //Image inversion Mat lookUpTable(1, 256, CV_8U); uchar* p = lookUpTable.data; for (int i = 0; i < 256; i++) p[i] = 255 - i; LUT(img, lookUpTable, img);//Image inversion through LUT function cvtColor(img, img, COLOR_BGR2GRAY);//Convert to grayscale image //Binarization by Otsu method threshold(img, img, 100, 255, THRESH_OTSU); imshow("Binarization", img); //Extracting contour data from binary image vector<vector<Point> > contour_vec; vector<Vec4i> hierarchy; findContours(img, contour_vec, hierarchy, RETR_LIST, CHAIN_APPROX_NONE); cout << "contours number: " << contour_vec.size() << endl; // The previously used for loop is used to draw the outline /*Mat blkImg(binImg.size(), CV_8UC1, Scalar(0)); for(int i = 0; i < contour_vec.size(); i++) { drawContours(blkImg, contour_vec, i, Scalar(255), -1); } */ //Draw a single channel outline image with white background and black outline lines Mat blkImg(img.size(), CV_8UC1, Scalar(255)); drawContours(blkImg, contour_vec, -1, Scalar(0), 2); imshow("Single channel profile", blkImg); //Draw a color outline image with blue-green background color and red outline line Mat colorImg(img.size(), CV_8UC3, Scalar(255, 255, 0)); drawContours(colorImg, contour_vec, -1, Scalar(0, 0, 255), 3); imshow("Color outline", colorImg); waitKey(0); return 0; }
Execution result: