Implementation of Canny edge detection algorithm

Source: Internet
Author: User
Tags modulus

Image edge information is mainly concentrated in high frequency segment, usually said image sharpening or detection edge, the essence is high-frequency filtering. We know that differential operation is the rate of change of signal, and it has the function of strengthening high frequency component. In the airspace operation, the sharpening of the image is the calculation of the differential. Due to the discrete signal of the digital image, the differential operation becomes the computational difference or gradient. There are many edge detection (gradient) operators in image processing, including common first-order difference, Robert Operator (cross-differential), Sobel operator and so on, which are based on searching for gradient intensity. The Laplace operator (second order differential) is based on over 0 points of detection. The edge image is obtained by calculating the gradient and setting the threshold value.

Canny edge detection operator is a multistage detection algorithm. Presented by John F. Canny in 1986, three criteria for edge detection were proposed:

    1. Low error rate edge detection: the detection algorithm should accurately locate as many edges as possible in the image, minimizing missed and false detections.
    2. Optimal positioning: The detected edge points should be precisely positioned at the center of the edge.
    3. Any edge in the image should be marked only once, and the image noise should not produce a pseudo edge.

Since the canny algorithm has been used as a standard edge detection algorithm, a variety of improved algorithms based on canny algorithm have been developed. Today, the canny algorithm and its various variants are still an excellent edge detection algorithm. And unless the preconditions are right, it's hard to find an edge detection operator that can be significantly better than the canny operator.

About a variety of differential operators, there is a brief introduction of the canny operator, here is not wordy, can be found on the Internet. Directly into the implementation of the canny algorithm. The canny algorithm is divided into several steps.

1. Gaussian Blur.

This step is simple, similar to the log operator (Laplacian of Gaussian) as Gaussian blur, the main role is to remove the noise. Because noise is also concentrated on high-frequency signals, it is easy to be identified as pseudo-edges. Gaussian blur is used to remove noise and reduce the recognition of pseudo-edge. But because the image edge information is also high-frequency signal, Gaussian blur radius selection is very important, too large radius is easy to let some weak edge detection.

Lena original Lena Gaussian blur, Radius 2

2. Calculate the gradient amplitude and direction.

The edges of the image can point in different directions, so the classic canny algorithm uses four gradient operators to calculate the horizontal, vertical, and diagonal gradients separately. However, four gradient operators are not usually used to calculate four directions respectively. Common edge difference operators (such as Rober,prewitt,sobel) calculate differential GX and Gy in both horizontal and vertical directions. This allows you to calculate the gradient mode and direction as follows:

The gradient angle θ ranges from radians-π to π and then approximates it to four directions, representing horizontal, vertical, and two diagonal directions (0°,45°,90°,135°). Can be divided in ±iπ/8 (i=1,3,5,7), the gradient angle of each region to a specific value, representing one of the four directions.

Here I choose the Sobel operator to calculate the gradient. The Sobel algorithm is simple and can be found everywhere, without listing the code. Relative to other edge operators, the edges of the Sobel operator are coarse and bright.

is a gradient-mode diagram of the Sobel operator applied to the Gaussian Blur image L-Channel (HSL) above the radius 2, without any threshold applied.

Sobel operator, no threshold

3. Non-maximum suppression.

Non-maximum suppression is an edge thinning method. The gradient edge is usually more than one pixel wide, but multiple pixels wide. As we said, the edges of the Sobel operator are coarse and bright, and the Sobel results from the above Lena graphs can be seen. So the gradient graph is still very "fuzzy". and guideline 3 requires that the edge has only a precise point width. Non-maximum suppression can help preserve the local maximum gradient and suppress all other gradient values. This means that only the sharpest position in the gradient change is preserved. The algorithm is as follows:

    1. Compare the gradient strength of the current point and the gradient intensity of the positive and negative gradient direction points.
    2. If the gradient strength of the current point is the largest compared to the gradient strength of other points in the same direction, its value is preserved. Otherwise suppressed, which is set to 0. For example, the direction of the current point points directly above the 90° direction, and it needs to be compared with the vertical direction, which is directly above and directly below the pixels.

Note that the direction of the positive or negative is not working, such as the southeast and northwest direction is the same, are considered to be a diagonal direction. In front we approximate the gradient direction to the horizontal, vertical and two diagonal four directions, so each pixel is compared in one of the four directions according to its own direction, deciding whether to retain it. This section of the code is also very simple, listed below. Pmodule,pdirection the previous gradient modulus and gradient direction respectively.

Pmoddrow = pmodule + Width + 1; Pdirdrow = pdirection + width + 1;pstrongdrow = pstrong + width + 1;for (i = 1; i < Hend-1; i++) {pstrongd = Pstrong  Drow;  pmodd = Pmoddrow;  Pdird = Pdirdrow;            for (j = 1; j < Wend-1; J + +) {switch (*pdird) {case 0://x direction Case 4:if (*pmodd > * (pmodd-1) && *pmodd > * (pmodd + 1)) *pstr                Ongd = 255;            Break Case 1://northeast-southwest direction. Notice the data order on Y direction for BMP data Case 5:if (*pmodd > * (pmodd + Width + 1) &A                mp;& *pmodd > * (pmodd-width-1)) *pstrongd = 255;            Break Case 2://Y direction case 6:if (*pmodd > * (pmodd-width) && *pmodd > * (                Pmodd + Width)) *pstrongd = 255;            Break Case 3://NortHwest-southeast direction. Notice the data order on Y direction for BMP data Case 7:if (*pmodd > * (pmodd + Width-1) &A                mp;& *pmodd > * (pmodd-width + 1)) *pstrongd = 255;            Break                Default:assert (0);            Break            } pstrongd++;            pmodd++;    pdird++;    } Pstrongdrow + = Width;    Pmoddrow + = Width; Pdirdrow + = Width;}

The result of non-maximum suppression. The visible edge width has been greatly reduced. However, because there is no threshold applied in this image, there are a lot of points with small gradient modulus values, which is very dark in the figure. Below, the threshold is going to play.

Non-maximum suppression results

4. Double valve value.

The general Edge detection algorithm uses a threshold value to filter out small gradient values caused by noise or color changes, while retaining large gradient values. The canny algorithm applies a double-threshold value, which is a high threshold and a low threshold value to differentiate the edge pixels. If the edge pixel gradient value is greater than the high threshold value, it is considered a strong edge point. If the edge gradient value is less than the high threshold value, it is marked as a weak edge point if it is greater than the low threshold. Points that are less than the lower threshold are suppressed. This one-step algorithm is simple.

5. LAG boundary tracking.

At this point, strong edge points can be thought of as true edges. Weak edge points may be true edges, or may be caused by noise or color changes. To obtain accurate results, the weak edge points caused by the latter should be removed. It is generally considered that the weak edge point and the strong edge point caused by the real edge are connected, but the weak edge point caused by the noise is not. The so-called Lag boundary tracking algorithm examines a weak edge point of 8 connected domain pixels, so long as there is a strong edge point exists, then this weak edge point is considered to be true edge preserved.

This algorithm searches all connected weak edges, and if any point of a connected weak edge is connected to a strong edge point, the weak edge is retained, otherwise the weak edge is suppressed. When searching for a breadth-first or depth-first algorithm, I'm here to achieve the easiest depth-first algorithm. The depth-first algorithm that connects one edge at a time is as follows:

    1. Prepare a stack s, a queue q, set the Unicom indicator variable connected to false. Starting at the first point of the image, enter 2.
    2. If the point is a weak boundary point and is not marked, mark it and put it as the first element in the stack s, and put it into the queue Q that records the connected curve, and enter 3. If the point is not a weak boundary or has been marked, repeat 2 to the next point in the image.
    3. Take an element from stack s and look for its 8-pixel field. If a domain pixel is a weak boundary and is not tagged, put this field pixel tag and join the stack s while adding the queue Q. At the same time find the field corresponding strong boundary graph, if one pixel is strong boundary, indicate this weak boundary curve and strong boundary unicom, set connected to true. Repeat 3 until there are no elements in the stack. If connected is false, remove each element from queue Q, emptying the tag. If connected is true, keep the tag.
    4. Empty queue Q, set connected to false, move to the next point of the image, to 2.
5.    Edge tracking by hysteresis stack<cpoint> s;    Queue<cpoint> Q;    BOOL connected = FALSE;    Long row_idx = Width; for (i = 1; i < Height-1; i++, row_idx + = Width) {for (j = 1; j < Width-1; J + +) {P            WEAKD = Pweak + Row_idx + j;                if (*PWEAKD = = 255) {S.push (CPoint (J, i));                Q.push (CPoint (J, i));        *PWEAKD = 1;                    Label it while (!s.empty ()) {CPoint p = s.top ();                    S.pop ();                    Search Weak edge 8-point Neighborhood PWEAKD = pweak + p.y*width + p.x;                        if (* (pweakd-width-1) = = 255) {CPoint NP = CPoint (p.x-1, p.y-1);                        S.push (NP);                        Q.push (NP);        * (pweakd-width-1) = 1;                  Label it}  if (* (pweakd-width) = = 255) {CPoint NP = CPoint (p.x, p.y-1);                        S.push (NP);                        Q.push (NP);        * (pweakd-width) = 1;                        Label it} if (* (pweakd-width + 1) = = 255) {                        CPoint NP = CPoint (p.x + 1, p.y-1);                        S.push (NP);                        Q.push (NP);        * (pweakd-width + 1) = 1;                        Label it} if (* (pweakd-1) = = 255) {                        CPoint NP = CPoint (p.x-1, P.Y);                        S.push (NP);                        Q.push (NP);        * (pweakd-1) = 1;                        Label it} if (* (PWEAKD + 1) = = 255) {                        CPoint NP = CPoint (p.x + 1, p.y);       S.push (NP);                 Q.push (NP);        * (PWEAKD + 1) = 1;                        Label it} if (* (PWEAKD + Width-1) = = 255) {                        CPoint NP = CPoint (p.x-1, p.y + 1);                        S.push (NP);                        Q.push (NP);        * (PWEAKD + Width-1) = 1;                        Label it} if (* (PWEAKD + Width) = = 255) {                        CPoint NP = CPoint (p.x, p.y + 1);                        S.push (NP);                        Q.push (NP);        * (PWEAKD + Width) = 1;                        Label it} if (* (PWEAKD + Width + 1) = = 255) {                        CPoint NP = CPoint (p.x + 1, p.y + 1);                        S.push (NP);                        Q.push (NP);        * (PWEAKD + Width + 1) = 1;                 Label it}   Search Strong Edge 8-point Neighborhood if (connected = = FALSE) {                        Pstrongd = Pstrong + p.y*width + p.x;                            for (int m =-1, m <= 1; m++) {for (int n =-1; n <= 1; n++)                                {if (* (Pstrongd + m*width + N) = = 255)                                    {connected = TRUE;                                Goto Next; }}}} Next:conti                Nue                    }//No more element in the stack if (connected = = FALSE) { The weak edge is not a connected to any strong edge.                    Suppress it. while (!q.empty ()) {CPoint p = q. Front ();                        Q.pop ();                    Pweak[p.y*width + p.x] = 0; }} else {//clean the queue while (!q                    . empty ()) Q.pop ();                connected = FALSE;    }}}}//Add the connected weak edges (labeled) into strong edge image.    All strong edge pixels is labeled 255, otherwise 0.    for (i = 0; i < len; i++) {if (pweak[i] = = 1) pstrong[i] = 255; }

The following is a gradient model for calculating canny edge detection for Lena graphs and two-valued graphs, a Gaussian radius of 2, a high threshold of 100, and a low threshold of 50.

Canny test gradient canny detection gradient binary graph

As a comparison, the following is the result of the first order difference and the Sobel operator on the original, the threshold value of 100. Because the gradient of the first order difference is relatively small, I enlarge the gradient value of the first order difference to a certain number of times, so that it maintains the same level as the Sobel gradient.

First order differential gradient binary graph with First order differential gradient mode

Sobel gradient Model Sobel gradient binary graph

Obviously, the effect of canny edge detection is very significant. Compared with the normal gradient algorithm, the pseudo-edge caused by noise is greatly suppressed, and the edge thinning is easy to follow. For low-contrast images, the canny algorithm can also have a good effect by adjusting the parameters.

Original canny gradient mode, Gaussian radius 2, low threshold 30, high threshold of canny gradient binary, Gauss radius 2, low threshold 30, high threshold 100

Original canny gradient mode, Gaussian radius 1, low threshold 40, high threshold canny gradient binary graph, Gauss radius 1, low threshold 40, high threshold 80

Implementation of Canny edge detection algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.