# Why filter2D rounds certain results?

I have an image and filter:

I applied a few operations on it below. I checked the results for ratioA, and ratioB, and noticed they were the same or very close to the variables with the same names in Matlab. However, the result differs for ratio:

Mat img = imread("lenablur.bmp");
cvtColor(img, img, cv::COLOR_BGR2GRAY);
img.convertTo(img, CV_64F);
cv::Scalar s=255;
divide(img, s, img);

cvtColor(kernel, kernel, cv::COLOR_BGR2GRAY);
kernel.convertTo(kernel, CV_64F);
cv::Scalar kernelsum = cv::sum(kernel);
divide(kernel, kernelsum, kernel);

Mat deconv=img.clone();

Mat ratio; Mat ratioA; Mat ratioB;
filter2D(deconv, ratioA, deconv.depth(), kernel, Point(-1, -1), 0,
BORDER_REFLECT);

divide(img, ratioA, ratioB);

filter2D(ratioB, ratio, ratio.depth(), kernel, Point(-1, -1), 0,
BORDER_REFLECT);
for (int r = 90; r < 93; r++) {
for (int c = 70; c < 75; c++) {
cout << ratio.at<double>(r, c) << " ";
}
cout << endl;
}


the result for ratio is:

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1


The values for ratioA and ratioB were good, and they matched the values I got when using Matlab. However, for ratio the values seemed to be rounded down somehow to int values instead of remaining double. Why did this happen, especially since the values for ratioA and ratioB were not rounded down in OpenCV?

EDIT: observed and img are supposed to be the same, psf and kernel are supposed to be the same. Fixed the typos

edit retag close merge delete

where is deconv coming from ? (you're assuming, that the result of filter2D has the same type)

also, you construct a kernel , but later use a psf . things don't match. please correct.

also: observed ? we can help you, if we can reproduce it, help us with that, please.

( 2018-09-21 12:00:51 -0500 )edit
1

I fixed the typos as mentioned in the EDIT

( 2018-09-21 12:27:48 -0500 )edit

Sort by » oldest newest most voted

no, filter2D() does not round anything. what you observe are errors in your code.

please NEVER write for loops like that with opencv. it's the most dangerous and silly noob ANTIPATTERN there is.

(it's also hard to get the type right (and you got it wrong, it's uchar, not double. an expectation mismatch. you should have checked the type() before applying at(), plain guessing will lead to shooting your own foot))

rather print out your Mat like:

cout << ratio(Range(90,93), Range(70,75)) << endl;


and you won't have to worry about the underlying type ever, again.

but the main problem is here:

filter2D(ratioB, ratio, ratio.depth(), kernel, Point(-1, -1), 0,
^
ratio is an *empty* (uninitialized) Mat, which defaults to type CV_8U


replacing it with :

filter2D(ratioB, ratio, CV_64F, kernel, Point(-1, -1), 0,


(and using a proper cout statement, NOT a for loop) yields the probably correct:

[1.064462175504303, 1.081087461852151, 1.093795521963379, 1.103062688483393, 1.109410216302785;
1.096379468908243, 1.113049809562855, 1.125585710677836, 1.1345460270182, 1.140489215023692;
1.120826367398934, 1.137233223043043, 1.149376122330102, 1.157815148607972, 1.163169752913307]

more

1

that fixed it. Thanks!

( 2018-09-21 13:18:24 -0500 )edit

Official site

GitHub

Wiki

Documentation