1

I'm new to OpenCV and trying to convert the following MATLAB code to OpenCV using C++:

    [FX,FY]=gradient(mycell{index});

I have tried the following so far but my values are completely different from my MATLAB results

    Mat abs_FXR;
    Mat abs_FYR;
    int scale = 1;
    int delta = 0;

    // Gradient X
    Sobel(myImg, FXR, CV_64F, 1, 0, 3, scale, delta, BORDER_DEFAULT);
    convertScaleAbs( FXR, abs_FXR );
    imshow( window_name2, abs_FXR );

    // Gradient Y
    Sobel(myImg, FYR, CV_64F, 0, 1, 3, scale, delta, BORDER_DEFAULT);
    convertScaleAbs( FYR, abs_FYR );
    imshow( window_name3, abs_FYR );

I also tried using filter2D as per this question, but it still gave different results: Matlab gradient equivalent in opencv

Mat kernelx = (Mat_<float>(1,3)<<-0.5, 0, 0.5);
Mat kernely = (Mat_<float>(3,1)<<-0.5, 0, 0.5);
filter2D(myImg, FXR, -1, kernelx);
filter2D(myImg, FYR, -1, kernely);
imshow( window_name2, FXR );
imshow( window_name3, FYR );

I don't know if this is way off track or if it's just a parameter I need to change. Any help would be appreciated.

UPDATE Here is my expected output from MATLAB:

enter image description hereenter image description here

But here is what I'm getting from OpenCV using Sobel:

enter image description hereenter image description here

And here is my output from OpenCV using the Filter2D method (I have tried increasing the size of my gaussian filter but still get different results compared to MATLAB)

enter image description hereenter image description here

I have also converted my image to double precision using:

eye_rtp.convertTo(eye_rt,CV_64F);
Community
  • 1
  • 1
orikon
  • 293
  • 2
  • 8
  • 18

1 Answers1

2

It is correct that you need to do a central difference computation instead of using the Sobel filter (although Sobel does give a nice derivative) in order to match gradient. BTW, if you have the Image Processing Toolbox, imgradient and imgradientxy have the option of using Sobel to compute the gradient. (Note that the answer in the question you referenced is wrong that Sobel only provides a second derivative, as there are first and second order Sobel operators available).

Regarding the differences you are seeing, you may need to convert myImg to float or double before filter2D. Check the output type of FXL, etc.

Also, double precision is CV_64F and single precision is CV_32F, although this will probably only cause very small differences in this case.

Community
  • 1
  • 1
chappjc
  • 30,359
  • 6
  • 75
  • 132
  • Thanks, they are all of type `cv::Mat`. For conversion, did you mean something like `myImg.convertTo(myImg, CV_64F)`? Unfortunately I end up with something like this: [link](http://imgur.com/T0FjINR) – orikon Apr 09 '14 at 16:28
  • @orikon The type I'm asking about is the elements in the `cv::Mat`. I'm wondering if the elements are integers. For conversion, yes, that's what I meant. – chappjc Apr 09 '14 at 16:39
  • ah I see, they seem to be `unsigned char*` – orikon Apr 09 '14 at 17:20
  • @orikon That's what I figured. I don't know how `filter2D` handles it when `myImg` contains integers, but the computations might end up truncating or worse. Try converting `myImg` to a `CV_32F` and then doing the filtering. – chappjc Apr 09 '14 at 17:21