OpenCV Sobel Filter - Why Does It Look So Bad, Especially Compared to Gimp?

I am trying to rebuild some preprocessing that I did earlier in Gimp using OpenCV. The first step is a Sobel filter for edge detection. It works fine in Gimp:

enter image description here

Now here is my attempt with OpenCV:

opencv_imgproc.Sobel(/* src = */ scaled, /* dst = */ sobel,
  /* ddepth = */ opencv_core.CV_32F,
  /* dx = */ 1, /* dy = */ 1, /* ksize = */ 5, /* scale = */ 0.25,
  /* delta = */ 0.0, /* borderType = */ opencv_core.BORDER_REPLICATE)

This looks very bad, mostly highlighting points instead of outlines:

enter image description here

So what am I doing wrong, or how does Gimp achieve such a good result and how can I replicate it in OpenCV?

+4
source share
2 answers

Information

, https://www.pexels.com/photo/brown-wooden-flooring-hallway-176162/ ( " " ).

TL; DR

Sobel . . , .

: float- (CV_32F) .

:

// Load example image
std::string path = "C:\\Temp\\SobelTest\\Lobby2\\";
std::string filename = "pexels-photo-176162 scaled down.jpeg";
std::string fqn = path + filename;
cv::Mat img = cv::imread(fqn, CV_LOAD_IMAGE_COLOR); // Value range: 0 - 255

// Convert to float and adapt value range (for simplicity)
img.convertTo(img, CV_32F, 1.f/255); // Value range: 0.0 - 1.0

// Build data for 3x3 vertical Sobel kernel
float sobelKernelHorizontalData[3][3] = 
{
    {-1, 0, 1}, 
    {-2, 0, 2}, 
    {-1, 0, 1}
};
// Calculate normalization divisor/factor
float sobelKernelNormalizationDivisor = 4.f;
float sobelKernelNormalizationFactor = 1.f / sobelKernelNormalizationDivisor;

// Generate cv::Mat for vertical filter kernel
cv::Mat sobelKernelHorizontal = 
    cv::Mat(3,3, CV_32F, sobelKernelHorizontalData); // Value range of filter result (if it is used for filtering): 0 - 4*255 or 0.0 - 4.0
// Apply filter kernel normalization
sobelKernelHorizontal *= sobelKernelNormalizationFactor; // Value range of filter result (if it is used for filtering): 0 - 255 or 0.0 - 1.0

// Generate cv::Mat for horizontal filter kernel
cv::Mat sobelKernelVertical;
cv::transpose(sobelKernelHorizontal, sobelKernelVertical);

// Apply two distinct Sobel filtering steps
cv::Mat imgFilterResultVertical;
cv::Mat imgFilterResultHorizontal;
cv::filter2D(img, imgFilterResultVertical, CV_32F, sobelKernelVertical);
cv::filter2D(img, imgFilterResultHorizontal, CV_32F, sobelKernelHorizontal);

// Build overall filter result by combining the previous results
cv::Mat imgFilterResultMagnitude;
cv::magnitude(imgFilterResultVertical, imgFilterResultHorizontal, imgFilterResultMagnitude);

// Write images to HDD. Important: convert back to uchar, otherwise we get black images
std::string filenameFilterResultVertical = path + "imgFilterResultVertical" + ".jpeg";
std::string filenameFilterResultHorizontal = path + "imgFilterResultHorizontal" + ".jpeg";
std::string filenameFilterResultMagnitude = path + "imgFilterResultMagnitude" + ".jpeg";
cv::Mat imgFilterResultVerticalUchar;
cv::Mat imgFilterResultHorizontalUchar;
cv::Mat imgFilterResultMagnitudeUchar;
imgFilterResultVertical.convertTo(imgFilterResultVerticalUchar, CV_8UC3, 255);
imgFilterResultHorizontal.convertTo(imgFilterResultHorizontalUchar, CV_8UC3, 255);
imgFilterResultMagnitude.convertTo(imgFilterResultMagnitudeUchar, CV_8UC3, 255);

cv::imwrite(filenameFilterResultVertical, imgFilterResultVerticalUchar);
cv::imwrite(filenameFilterResultHorizontal, imgFilterResultHorizontalUchar);
cv::imwrite(filenameFilterResultMagnitude, imgFilterResultMagnitudeUchar);

// Show images
cv::imshow("img", img);
cv::imshow("imgFilterResultVertical", imgFilterResultVertical);
cv::imshow("imgFilterResultHorizontal", imgFilterResultHorizontal);
cv::imshow("imgFilterResultMagnitude", imgFilterResultMagnitude);
cv::waitKey();

, :

 cv::Sobel(img, imgFilterResultVertical, CV_32F, 1, 0, 3, sobelKernelNormalizationFactor);
 cv::Sobel(img, imgFilterResultHorizontal, CV_32F, 0, 1, 3, sobelKernelNormalizationFactor);
 cv::magnitude(imgFilterResultVertical, imgFilterResultHorizontal, imgFilterResultMagnitude);

, , , ()

source imagevertical filter resulthorizontal filter resultcombined filter result (magnitude)

OpenCV

  • ( CV_32F) , . , 4 ( uchar). , , , uchar ( "" ) OpenCV. , , , .
  • 8- (uchar, CV_8UC) 0 255. 32- (CV_32F) 0,0 - 1,0 (, 1,0, , 1.0), 32- , ( , , 1.0 ).

:

f = max(abs(sumNegative), abs(sumPositive))

sumNegative - sumPositive .

: float normalizationDivisor = cv::sum(cv::abs(kernel))(0), .

, . , (B, G, R) "" , . , - "", . .

+6

X, Y, . , 2D (, , , ).

2D- , . , OpenCV , Gimp, Gimp , OpenCV.

, , RGB . RGB , , . .

+1

Source: https://habr.com/ru/post/1659958/


All Articles