My opencv Study Notes (18): Uses Sobel variation and Laplace transformation to detect image edges

Source: Internet
Author: User

Both the Sobel transform and the Laplace transform are high-pass filters. What is a Qualcomm filter? Is to retain the image's high-frequency components (the drastic changes), suppress the image's low-frequency components (the slow changes ). The sharp changes in the image often reflect the edge information of the image.

In opencv, it is easy to call the Sobel function:

Mat image = imread ("D:/picture/images/boldt.jpg", 0); If (! Image. data) Return-1; imshow ("source image", image); MAT sobelx; // The parameter is: source image, result image, image depth, X-Direction Order, y-Direction Order, kernel size, scale factor, added value Sobel (image, sobelx, cv_8u, 0.4, 3, 128 ); imshow ("Sobel result in X direction", sobelx); MAT sobely; Sobel (image, sobely, cv_8u, 0.4, 3, 128 ); imshow ("result of Sobel in Y direction", sobely );

Note that here we have made some scale transformations on the Sobel results to better display them.

Note the following:

Because it is for the X direction, sobelx retains a lot of vertical information, so the vertical contour "looks clearer"; y direction is the same.

According to mathematics, the square of the two directions should be added to the square of the open side (2 norm) to obtain the gradient. In fact, to simplify the operation, we directly add their absolute values (1 norm) to obtain the gradient:

// Merge the result mat Sobel; Sobel (image, sobelx, cv_32f,); Sobel (image, sobely, cv_32f,); // calculate 1 norm Sobel = ABS (sobelx) + ABS (sobely); double sobmin, sobmax; minmaxloc (Sobel, & sobmin, & sobmax); // converts the value to 8 bits for scale conversion mat sobelimage; Sobel. convertize (sobelimage, cv_8u,-255. /sobmax, 255); imshow ("result", sobelimage); threshold (sobelimage, sobelimage, 190,255, CV: thresh_binary); imshow ("final result", sobelimage );

Note: The cv_8u type is not used because the calculation result has positive and negative values, but is of the cv_32f type.

 

If you want to accurately calculate the gradient, not only the size, but also the direction, you can do this:

Mat norm, Dir; // calculate L2 norm and carttopolar (sobelx, sobely, Norm, DIR );

The Laplace transformation is to obtain the 2nd-order partial derivative of the X and Y directions, and then add up.

When he acts on the edge of the image (for example, from dark to bright), we can see that the increase in the gray value will inevitably mean from positive curvature (increased intensity) to negative curvature (the intensity reaches the bottleneck). Therefore, the result of Laplace transformation from positive to negative (or vice versa) forms a good indicator of the image edge. Another way to express this fact is that the edge appears at the zero point of the Laplace transformation.

It is easier to calculate the Laplace transformation in opencv:

// Calculate the mat Laplace directly; // Transformation Result * 1 + 128 Laplacian (image, Laplace, cv_32f, 128,); imshow ("directly used result ", laplace); // calculate the value of the Laplace transformation in a small window for (INT I = 0; I <12; I ++) {for (Int J = 0; j <12; j ++) {// because 128 is added to the preceding transform, 128 cout <SETW (5) <static_cast <int> (Laplace. at <float> (I + 135, J + 362)-128 <";}cout <Endl; cout <Endl; cout <Endl;

To better illustrate the role of Laplace transformation, we first define one class:

# If! Defined laplacezc # define laplacezc # include <opencv2/CORE/core. HPP> # include <opencv2/highgui. HPP> # include <opencv2/imgproc. HPP> using namespace CV; Class laplacianzc {PRIVATE: // source image mat IMG; // result of Laplace transformation, 32-bit mat Laplace; // int aperture of the size of the Laplace kernel; public: // constructor laplacianzc (): aperture (3) {}// set the size of the core void setaperture (int A) {aperture = ;} // calculate the Laplace transform mat computelaplacian (const mat & image) {// calculate the Laplace transform lapla Cian (image, Laplace, cv_32f, aperture,); // retained copy IMG = image. clone (); Return Laplace;} // obtain the transformed image mat getlaplacianimage (double scale =-1.0) {double lapmin, lapmax; If (scale <0) {// obtain the maximum and minimum values of the transform minmaxloc (Laplace, & lapmin, & lapmax); Scale = 127/STD: max (-lapmin, lapmax);} mat laplaceimage; laplace. convertize (laplaceimage, cv_8u, scale, 128); Return laplaceimage;} // obtain a 2-value image over zero (MAT getzerocrossings (float Threshold = 1.0) {// Mat _ <float>: const_iterator it = Laplace. begin <float> () + Laplace. step 1 (); // The last element mat _ <float>: const_iterator itend = Laplace. end <float> (); // The first element mat _ <float>: const_iterator itup = Laplace. begin <float> (); // The value 2 of the image is initialized to the white mat binary (Laplace. size (), cv_8u, scalar (255); MAT _ <uchar >:: iterator itout = binary. begin <uchar> () + binary. step 1 (); // make the threshold invalid threshold * =-1.0; For (; it! = Itend; ++ it, ++ itup, ++ itout) {// if the product of adjacent pixels is negative, the symbol here changes if (* It ** (IT-1) <threshold) * itout = 0; else if (* It ** (itup) <threshold) * itout = 0;} return binary ;};# endif

We select a small area for important observation:

First look at the main function:

// Use the laplacianzc class to calculate the laplacianzc Laplacian and Laplacian. setaperture (7); // The transformed result has positive and negative values. Values smaller than 0 are set to 0, and values greater than 255 are set to 255. Mat flap = Laplacian is ineffective. computelaplacian (image); double lpmin, lpmax; // obtain the maximum and minimum values after transformation minmaxloc (flap, & lpmin, & lpmax ); cout <"the range After Laplace transformation is:" <"[" <lpmin <"," <lpmax <"]" <Endl; cout <Endl; Laplace = Laplacian. getlaplacianimage (); imshow ("Laplacian image", Laplace); // print the value of the Laplace transformation in the window for (INT I = 0; I <12; I ++) {for (Int J = 0; j <12; j ++) {cout <SETW (5) <static_cast <int> (flap. at <float> (I + 135, J + 362)/100 <";}cout <Endl; // calculate and display zero point mat zeros = Laplacian. getzerocrossings (lpmax); imshow ("Zero Point", zeros );

The Laplace transformation of each vertex in the printed message is divided by 100 only because the calculation result is too large. If it is displayed normally, it cannot be aligned. But this does not affect zero point (because he only considers positive and negative numbers)

The zero point is:

This is exactly the edge of the tower in that small window!

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.