11

I am trying to implement a sobel operator in both horizontal and vertical direction. But somehow I am getting the reverse output. The code I have attached below. For the horizontal mask

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);

}

I am getting the output as

enter image description here

where as for the vertical mask

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);

}

I am getting output as

enter image description here

The main function is attached below

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

}

According the the guide https://www.tutorialspoint.com/dip/sobel_operator.htm I should get reverse output. Can anyone help me in this

The original image is

enter image description here

fireant
  • 14,080
  • 4
  • 39
  • 48
Abhishek
  • 650
  • 1
  • 8
  • 31
  • 2
    You are correct the tutorial is wrong :) in the `x` you should see vertical lines, in `y` you should see the horizontal lines. in your case vertical is the `y` and horizontal `x`, see [wikipedia](https://en.wikipedia.org/wiki/Sobel_operator) to see what I mean (notationwise). Also check this [tuotrial](http://www.meccanismocomplesso.org/en/opencv-python-image-edge-gradient-analysis/) to see the outputs. – api55 Aug 23 '17 at 07:14
  • You can always compare the results using the opencv [sobel operator function](http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html?highlight=sobel#sobel) using xorder=1 for horizontal (and yorder=0) and yorder=1 (and xorder=0) for vertical. – api55 Aug 23 '17 at 07:19
  • They reversed the order. See here. http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm – I.Newton Aug 23 '17 at 07:23
  • Or maybe their idea was you'll see vertical lines in vertical filter and horizontal with the horizontal filter. That's not right. – I.Newton Aug 23 '17 at 07:24
  • @Yunnosch I think the images in the tutorial are inversed. Also, opencv `at` function takes (y,x) coordinates, so the order is correct in the code. The tutorial seems to explain it in the correct way, just the images are wrong – api55 Aug 23 '17 at 07:25
  • You mean they wrongly described as "vertical matrice" the one which highlights the vertical structures in the picture? – Yunnosch Aug 23 '17 at 07:25
  • Lets be careful with the term "inversed". For me it implies that a mostly dark picture gets mostly light (and the other way round). – Yunnosch Aug 23 '17 at 07:27
  • @Yunnosch I meant switched... so the image of the vertical should be the horizontal, and viceversa – api55 Aug 23 '17 at 07:28
  • @Yunnosch that is wrong. the `at` function works with (y,x) coordinates, which is correct in the code. Also the matrices and the OP output is correct for a sobel filter. Changing it will probably give you a wrong answer and even a segmentation error (unless the image is squared like the example). If the OP wants to get the result from the tutorial, just change the kernel used. I think the OP wants to implement the sobel operator and he is confused due to a bad tutorial..... Maybe he should give us some feedback to clarify – api55 Aug 23 '17 at 07:36
  • @api55 (y,x)? Ok, I wasn't aware of that. Thanks for correcting me. It makes my guess of what caues the problem implausible (deleted). I conisder your interpretation plausible now. I just do not "tick" it for proven lack of knowledge on my side. ;-) – Yunnosch Aug 23 '17 at 07:40
  • @Yunnosch Just for the sake of completeness [here is the docs](http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat-at). I think that one is one of the most common source of errors with opencv. A lot of people tend to think it in cartesian coordinates (x,y), but opencv took the matrix convention (i,j) where i is row and j is column. – api55 Aug 23 '17 at 07:46
  • @Abhishek I deleted my answer since you were right, you used the wrong kernel, or better said flipped the kernel.... It was a little confusing the naming of the kernels.... – api55 Aug 24 '17 at 07:18
  • would anyone be so kind to explain what is the role of k in `for(int k=0;k<3;k++)` ? – Cezar Cobuz Jun 15 '18 at 08:59

1 Answers1

1

No, the tutorial is not wrong, it talks about masks and not gradients. The weak point of that tutorial is that it doesn't mention we are calculating horizontal gradients using what they call the vertical mask.

fireant
  • 14,080
  • 4
  • 39
  • 48