实现 Sobel 算子

Posted

技术标签:

【中文标题】实现 Sobel 算子【英文标题】:Implementing Sobel Operator 【发布时间】:2018-01-31 15:00:16 【问题描述】:

我正在尝试在水平和垂直方向上实现 sobel 运算符。但不知何故,我得到了反向输出。我附在下面的代码。对于水平遮罩

char mask [3][3]=  -1,-2,-1,0,0,0,1,2,1;

void masking(Mat image)

Mat temImage= image.clone();
for (int i = 1; i < image.rows-1; i++)

    for (int j = 1; j < image.cols-1; j++)
       
        for(int k=0;k<3;k++)
        
            int pixel1 = image.at<Vec3b>(i-1,j-1)[k] * -1;
            int pixel2 = image.at<Vec3b>(i,j-1)[k] * -2;
            int pixel3 = image.at<Vec3b>(i+1,j-1)[k] * -1;

            int pixel4 = image.at<Vec3b>(i-1,j)[k] * 0;
            int pixel5 = image.at<Vec3b>(i,j)[k] * 0;
            int pixel6 = image.at<Vec3b>(i+1,j)[k] * 0;

            int pixel7 = image.at<Vec3b>(i-1,j+1)[k] * 1;
            int pixel8 = image.at<Vec3b>(i,j+1)[k] * 2;
            int pixel9 = image.at<Vec3b>(i+1,j+1)[k] * 1;

            int sum = pixel1 + pixel2 + pixel3 + pixel4 + pixel5 + pixel6 + pixel7 + pixel8 + pixel9;
            if(sum < 0)
            
                sum = 0;
            

            if(sum > 255)
                sum = 255;

            temImage.at<Vec3b>(i,j)[k] = sum;


        
    

//printf("conter = %d",counter);
imshow( "Display", temImage );
imwrite("output1.png",temImage);

我得到的输出为

垂直遮罩在哪里

char mask [3][3]=  -1,0,1,-2,0,2,-1,0,1; 

void masking(Mat image)

Mat temImage= image.clone();
for (int i = 1; i < image.rows-1; i++)

    for (int j = 1; j < image.cols-1; j++)
       
        for(int k=0;k<3;k++)
        
            int pixel1 = image.at<Vec3b>(i-1,j-1)[k] * -1;
            int pixel2 = image.at<Vec3b>(i,j-1)[k] * 0;
            int pixel3 = image.at<Vec3b>(i+1,j-1)[k] * 1;

            int pixel4 = image.at<Vec3b>(i-1,j)[k] * -2;
            int pixel5 = image.at<Vec3b>(i,j)[k] * 0;
            int pixel6 = image.at<Vec3b>(i+1,j)[k] * 2;

            int pixel7 = image.at<Vec3b>(i-1,j+1)[k] * -1;
            int pixel8 = image.at<Vec3b>(i,j+1)[k] * 0;
            int pixel9 = image.at<Vec3b>(i+1,j+1)[k] * 1;

            int sum = pixel1 + pixel2 + pixel3 + pixel4 + pixel5 + pixel6 + pixel7 + pixel8 + pixel9;
            if(sum < 0)
            
                sum = 0;
            

            if(sum > 255)
                sum = 255;

            temImage.at<Vec3b>(i,j)[k] = sum;


        
    

//printf("conter = %d",counter);
imshow( "Display", temImage );
imwrite("output1.png",temImage);

我得到的输出是

下面附上main函数

int main( int argc, char** argv )
Mat input_image = imread("sobel1.jpg",1);
masking(input_image);
waitKey(0);
return 0;

根据指南https://www.tutorialspoint.com/dip/sobel_operator.htm 我应该得到反向输出。任何人都可以在这方面帮助我

原图是

【问题讨论】:

你是正确的教程是错误的:) 在x 你应该看到垂直线,在y 你应该看到水平线。在您的情况下,垂直是y 和水平x,请参阅wikipedia 了解我的意思(符号)。还要检查此tuotrial 以查看输出。 您始终可以使用 opencv sobel operator function 比较结果,其中 xorder=1 表示水平(和 yorder=0),yorder=1(和 xorder=0)表示垂直。 他们颠倒了顺序。看这里。 homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm 或者他们的想法是你会在垂直过滤器中看到垂直线,在水平过滤器中看到水平线。这是不对的。 @Yunnosch 我认为教程中的图像是颠倒的。此外,opencv at 函数采用 (y,x) 坐标,因此代码中的顺序是正确的。该教程似乎以正确的方式解释它,只是图像错误 【参考方案1】:

不,the tutorial 没有错,它谈论的是蒙版而不是渐变。该教程的弱点是它没有提到我们正在使用他们所谓的垂直蒙版来计算水平梯度。

【讨论】:

以上是关于实现 Sobel 算子的主要内容,如果未能解决你的问题,请参考以下文章

实现Sobel算子滤波Robers算子滤波Laplace算子滤波

sobel算子原理与实现

OpenCV入门系列4:图像梯度常用算子——Sobel,Scharr和Laplacian算子

fpga图像处理(sobel算子)

Sobel算子

实现 Sobel 算子