1 | initial version |
I have found the problem. In adaptiveThreshold gaussianBlur is calculated using image CV_8UC1. That is the problem I think. I think that rounding number add white noise to result image and hence result stability is low.
You can verify with this program. I make a gaussian blur with very big sigma . Gaussian filter is equivalent to a box filter. With a gaussian blur calculated with an image CV_8UC gaussain blur is not at all equivalent to a boxfilter.
With a gaussian blur calculated with an image CV_32FC gaussain blur is now equivalent to a boxfilter.
int main (int argc,char **argv)
{
double minVal, maxVal;
int minIdx[2], maxIdx[2];
bool checkKernel = false;
Mat m,imG,imB;
char tmp[256];
int n=55;
m=imread("T4wsOW8.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat mF(m.rows, m.cols, CV_32FC1);
for (int i = 0; i<m.rows; i++)
{
for (int j = 0; j<m.cols; j++)
mF.at<float>(i, j) = m.at<unsigned char>(i, j);
}
cout << "Image size : Rows = "<<m.rows << "\tcols = " << m.cols << "\t #pixels = "<<m.rows*m.cols<<endl;
for (int blockSize = 3; blockSize < n; blockSize+=2)
{
cout << "\n********\n";
if (checkKernel)
{
Mat g = cv::getGaussianKernel(blockSize, 1000000, CV_64F);
cout << blockSize << "\t" << 1.0 / blockSize << endl;
for (int i = 0; i<g.rows; i++)
{
for (int j = 0; j<g.cols; j++)
cout << g.at<double>(i, j) << "\t";
}
cout << "\n";
}
boxFilter(m, imB, CV_32F, Size(blockSize, blockSize),
Point(-1, -1), true, BORDER_REPLICATE);
cv::GaussianBlur(m, imG, Size(blockSize, blockSize), 1000000.0, 1000000.0, BORDER_REPLICATE);
Mat imDiff;
subtract(imG, imB, imDiff, noArray(), CV_32SC1);
sprintf(tmp, "Diff%d.jpg", blockSize);
String s(tmp);
imwrite(s, imDiff);
Mat a = abs(imDiff);
Scalar x=sum(a);
cout << "For CV_8UC (unsigned char) imageBlocksize = " <<blockSize << "\t" << "Sum( abs(Gaussian filter -boxFilter)) = "<<x[0] << endl;
minMaxIdx(imDiff, &minVal, &maxVal,minIdx,maxIdx);
cout << "Extremum (Gaussian filter -boxFilter) Min = " << minVal << "\tmaxVal = "<<maxVal << endl;
cv::GaussianBlur(mF, imG, Size(blockSize, blockSize), 1000000.0, 1000000.0, BORDER_REPLICATE);
subtract(imG, imB, imDiff, noArray(), CV_32SC1);
a = abs(imDiff);
x = sum(a);
cout << "For CV_32F (float) image " << blockSize << "\t" << "Sum( abs(Gaussian filter -boxFilter)) = " << x[0] << endl;
minMaxIdx(imDiff, &minVal, &maxVal, minIdx, maxIdx);
cout << "Extremum (Gaussian filter -boxFilter) Min = " << minVal << "\tmaxVal = " << maxVal << endl;
}
return 0;
2 | No.2 Revision |
I have found the problem. In adaptiveThreshold gaussianBlur is calculated using image CV_8UC1. That is the problem I think. I think that rounding number add white noise to result image and hence result stability is low.
You can verify with this program. I make a gaussian blur with very big sigma . Gaussian filter is equivalent to a box filter. With a gaussian blur calculated with an image CV_8UC gaussain blur is not at all equivalent to a boxfilter.
With a gaussian blur calculated with an image CV_32FC gaussain blur is now equivalent to a boxfilter.
I think that parameter ADAPTIVE_THRESH_GAUSSIAN_C should be used with caution in adaptiveThreshold
int main (int argc,char **argv)
{
double minVal, maxVal;
int minIdx[2], maxIdx[2];
bool checkKernel = false;
Mat m,imG,imB;
char tmp[256];
int n=55;
m=imread("T4wsOW8.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat mF(m.rows, m.cols, CV_32FC1);
for (int i = 0; i<m.rows; i++)
{
for (int j = 0; j<m.cols; j++)
mF.at<float>(i, j) = m.at<unsigned char>(i, j);
}
cout << "Image size : Rows = "<<m.rows << "\tcols = " << m.cols << "\t #pixels = "<<m.rows*m.cols<<endl;
for (int blockSize = 3; blockSize < n; blockSize+=2)
{
cout << "\n********\n";
if (checkKernel)
{
Mat g = cv::getGaussianKernel(blockSize, 1000000, CV_64F);
cout << blockSize << "\t" << 1.0 / blockSize << endl;
for (int i = 0; i<g.rows; i++)
{
for (int j = 0; j<g.cols; j++)
cout << g.at<double>(i, j) << "\t";
}
cout << "\n";
}
boxFilter(m, imB, CV_32F, Size(blockSize, blockSize),
Point(-1, -1), true, BORDER_REPLICATE);
cv::GaussianBlur(m, imG, Size(blockSize, blockSize), 1000000.0, 1000000.0, BORDER_REPLICATE);
Mat imDiff;
subtract(imG, imB, imDiff, noArray(), CV_32SC1);
sprintf(tmp, "Diff%d.jpg", blockSize);
String s(tmp);
imwrite(s, imDiff);
Mat a = abs(imDiff);
Scalar x=sum(a);
cout << "For CV_8UC (unsigned char) imageBlocksize = " <<blockSize << "\t" << "Sum( abs(Gaussian filter -boxFilter)) = "<<x[0] << endl;
minMaxIdx(imDiff, &minVal, &maxVal,minIdx,maxIdx);
cout << "Extremum (Gaussian filter -boxFilter) Min = " << minVal << "\tmaxVal = "<<maxVal << endl;
cv::GaussianBlur(mF, imG, Size(blockSize, blockSize), 1000000.0, 1000000.0, BORDER_REPLICATE);
subtract(imG, imB, imDiff, noArray(), CV_32SC1);
a = abs(imDiff);
x = sum(a);
cout << "For CV_32F (float) image " << blockSize << "\t" << "Sum( abs(Gaussian filter -boxFilter)) = " << x[0] << endl;
minMaxIdx(imDiff, &minVal, &maxVal, minIdx, maxIdx);
cout << "Extremum (Gaussian filter -boxFilter) Min = " << minVal << "\tmaxVal = " << maxVal << endl;
}
return 0;