1

I am currently trying to translate a Python image detection algorithm in C++ (in order to use it in a smartphone app) using OpenCV. I have similar results to a certain point, where the two algorithms seem to diverge due to the accumulation of small differences in the images: I am applying some transformations to the image, but the number of decimal digits in Python is much larger than in C++ (where I use CV_64FC1 matrices), so I get more and more different results after some iterations...

Do you have any idea on how to overcome this issue?

Thanks in advance :)

EDIT: here is a code that gives a different result in Python and C++

void conv2(const Mat &img, const Mat& kernel, Mat& dest) {
  Mat source = img;
  Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1);
  flip(kernel, kernel, 0);
  filter2D(source, dest, -1, kernel, anchor);
}

void myFunc() {
  Mat im = imread("3.png", IMREAD_GRAYSCALE);
  im.convertTo(im, CV_64F);

  int rows = im.rows;
  int cols = im.cols;
  int sze = 7;

  Mat gauss = getGaussianKernel(sze, 1);
  Mat f = gauss * gauss.t();
  Mat fx, fy;
  Sobel(f, fx, -1, 1, 0);
  Sobel(f, fy, -1, 0, 1);
  Mat Gx, Gy, Gxx, Gyy, Gxy;
  filter2D(im, Gx, -1, fx);
  filter2D(im, Gy, -1, fy);
  pow(Gx, 2, Gxx);
  pow(Gy, 2, Gyy);
  Gxy = Gx.mul(Gy);

  gauss = getGaussianKernel(sze, 38);
  f = gauss * gauss.t();
  conv2(Gxx, f, Gxx);
  conv2(Gyy, f, Gyy);
  conv2(Gxy, f, Gxy);
  Gxy *= 2;

  Mat Gxx_minus_Gyy = Gxx - Gyy;
  Mat Gxy_squared, Gxx_minus_Gyy_squared;
  pow(Gxy, 2, Gxy_squared);
  pow(Gxx_minus_Gyy, 2, Gxx_minus_Gyy_squared);

  Mat denom;
  sqrt(Gxy_squared + Gxx_minus_Gyy_squared, denom);
  // denom += numeric_limits<double>::epsilon();
  Mat sin2theta = Gxy / denom;
  cout.precision(dbl::max_digits10);
  cout << fixed << sum(sin2theta) << endl;
  exit(1);
}

And Python:

def conv2(img, kernel):
    source = img
    kernel = cv2.flip(kernel, 0)
    rows, cols = kernel.shape
    anchor = (int(cols - cols/2 - 1), int(rows - rows/2 - 1))
    return cv2.filter2D(source, -1, kernel, anchor=anchor)


def myFunc():
    im = cv2.imread('3.png', cv2.IMREAD_GRAYSCALE)
    im = np.float64(im)

    rows, cols = im.shape;
    sze = 7

    gauss = cv2.getGaussianKernel(sze, 1);
    f = gauss * gauss.T;
    fx = cv2.Sobel(f, -1, 1, 0)
    fy = cv2.Sobel(f, -1, 0, 1)
    Gx = cv2.filter2D(im, -1, fx)
    Gy = cv2.filter2D(im, -1, fy)
    Gxx = cv2.pow(Gx,2);
    Gyy = cv2.pow(Gy,2);
    Gxy = cv2.multiply(Gx, Gy);

    gauss = cv2.getGaussianKernel(sze, 38);
    f = gauss * gauss.T;
    Gxx = conv2(Gxx, f)
    Gyy = conv2(Gyy, f)
    Gxy = 2*conv2(Gxy, f)
    Gxx_minus_Gyy = Gxx - Gyy
    Gxy_squared = cv2.pow(Gxy, 2)
    Gxx_minus_Gyy_squared = cv2.pow(Gxx_minus_Gyy, 2)
    denom = cv2.sqrt(Gxy_squared + Gxx_minus_Gyy_squared)
    # denom += np.finfo(float).eps;
    sin2theta = Gxy/denom
    print(cv2.sumElems(sin2theta))
    exit()

The call to myFunc() prints the sum of the elements in the "sin2theta" matrix: Python gives 86587.44928456949, and C++ gives 86825.05505451805947814, which starts to make a pretty important difference.

  • Do you really need a precision after the 12th (or something like that) decimal digit? – Miki Nov 04 '17 at 14:19
  • I am not looking for a specific precision, I just think that the difference between the two algorithms results comes from the difference of precision between Python and C++... – Baptiste Amato Nov 04 '17 at 14:42
  • Please show the relevant code, both Python adn C++ – Miki Nov 04 '17 at 14:51
  • For example, `cv2.getGaussianKernel(7, 1)[0, 0]` returns 0.00443304817524 in Python, but returns 0.00443305 in C++. As I use `f = gauss * gaussT` after that, and then apply some Sobel operator on f, I get more and more different results. – Baptiste Amato Nov 04 '17 at 15:12
  • 1
    Are you sure you're seeing the C++ value with the full precision? – Miki Nov 04 '17 at 15:15
  • 1
    Gosh you are so right. For info, I used the following answer: [link](https://stackoverflow.com/questions/554063/how-do-i-print-a-double-value-with-full-precision-using-cout) Ok, now I can check where exactly the divergence comes from, thanks a lot @Miki. – Baptiste Amato Nov 04 '17 at 15:26
  • Well, now I know where does the divergence come from. I have two matrices, Gxx and Gyy, that are the same in Python and C++, at least for the first 10 significative digits. Here is the C++ code: `Mat denom; sqrt(Gxy_squared + Gxx_minus_Gyy_squared, denom); Mat sin2theta = Gxy / denom;` and my Python code: `denom = cv2.sqrt(Gxy_squared + Gxx_minus_Gyy_squared); sin2theta = Gxy/denom;` And here, the "sin2theta" matrix starts to be pretty different between C++ and Python. – Baptiste Amato Nov 04 '17 at 15:43
  • Unless you add a [mcve], it's fairly impossible to answer. I'll reopen the question then – Miki Nov 04 '17 at 16:31
  • You're right, I edited my question and added the code. – Baptiste Amato Nov 04 '17 at 17:00

0 Answers0