Commit dc763e02 authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

updated normalization routine in the matchTemplate to avoid division by zero on…

updated normalization routine in the matchTemplate to avoid division by zero on black images (ticket #798), added test
parent a961cfe1
...@@ -1180,7 +1180,6 @@ namespace cv ...@@ -1180,7 +1180,6 @@ namespace cv
size_t getBlockHistogramSize() const; size_t getBlockHistogramSize() const;
void setSVMDetector(const vector<float>& detector); void setSVMDetector(const vector<float>& detector);
bool checkDetectorSize() const;
static vector<float> getDefaultPeopleDetector(); static vector<float> getDefaultPeopleDetector();
static vector<float> getPeopleDetector_48x96(); static vector<float> getPeopleDetector_48x96();
...@@ -1212,7 +1211,9 @@ namespace cv ...@@ -1212,7 +1211,9 @@ namespace cv
protected: protected:
void computeBlockHistograms(const GpuMat& img); void computeBlockHistograms(const GpuMat& img);
void computeGradient(const GpuMat& img, GpuMat& grad, GpuMat& qangle); void computeGradient(const GpuMat& img, GpuMat& grad, GpuMat& qangle);
double getWinSigma() const; double getWinSigma() const;
bool checkDetectorSize() const;
static int numPartsWithin(int size, int part_size, int stride); static int numPartsWithin(int size, int part_size, int stride);
static Size numPartsWithin(Size size, Size part_size, Size stride); static Size numPartsWithin(Size size, Size part_size, Size stride);
......
...@@ -560,7 +560,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8U( ...@@ -560,7 +560,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8U(
(image_sqsum.ptr(y + h)[x + w] - image_sqsum.ptr(y)[x + w]) - (image_sqsum.ptr(y + h)[x + w] - image_sqsum.ptr(y)[x + w]) -
(image_sqsum.ptr(y + h)[x] - image_sqsum.ptr(y)[x])); (image_sqsum.ptr(y + h)[x] - image_sqsum.ptr(y)[x]));
result.ptr(y)[x] = min(1.f, (ccorr - image_sum_ * templ_sum_scale) * result.ptr(y)[x] = min(1.f, (ccorr - image_sum_ * templ_sum_scale) *
rsqrtf(templ_sqsum_scale * (image_sqsum_ - weight * image_sum_ * image_sum_))); rsqrtf(templ_sqsum_scale * (image_sqsum_ - weight * image_sum_ * image_sum_ + 1.f)));
} }
} }
...@@ -611,7 +611,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC2( ...@@ -611,7 +611,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC2(
(image_sqsum_g.ptr(y + h)[x] - image_sqsum_g.ptr(y)[x])); (image_sqsum_g.ptr(y + h)[x] - image_sqsum_g.ptr(y)[x]));
float ccorr = result.ptr(y)[x]; float ccorr = result.ptr(y)[x];
float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_ float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_
+ image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_)); + image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_ + 1.f));
result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r
- image_sum_g_ * templ_sum_scale_g) * rdenom); - image_sum_g_ * templ_sum_scale_g) * rdenom);
} }
...@@ -680,7 +680,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC3( ...@@ -680,7 +680,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC3(
float ccorr = result.ptr(y)[x]; float ccorr = result.ptr(y)[x];
float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_ float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_
+ image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_ + image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_
+ image_sqsum_b_ - weight * image_sum_b_ * image_sum_b_)); + image_sqsum_b_ - weight * image_sum_b_ * image_sum_b_ + 1.f));
result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r
- image_sum_g_ * templ_sum_scale_g - image_sum_g_ * templ_sum_scale_g
- image_sum_b_ * templ_sum_scale_b) * rdenom); - image_sum_b_ * templ_sum_scale_b) * rdenom);
...@@ -763,7 +763,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC4( ...@@ -763,7 +763,7 @@ __global__ void matchTemplatePreparedKernel_CCOFF_NORMED_8UC4(
float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_ float rdenom = rsqrtf(templ_sqsum_scale * (image_sqsum_r_ - weight * image_sum_r_ * image_sum_r_
+ image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_ + image_sqsum_g_ - weight * image_sum_g_ * image_sum_g_
+ image_sqsum_b_ - weight * image_sum_b_ * image_sum_b_ + image_sqsum_b_ - weight * image_sum_b_ * image_sum_b_
+ image_sqsum_a_ - weight * image_sum_a_ * image_sum_a_)); + image_sqsum_a_ - weight * image_sum_a_ * image_sum_a_ + 1.f));
result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r result.ptr(y)[x] = min(1.f, (ccorr - image_sum_r_ * templ_sum_scale_r
- image_sum_g_ * templ_sum_scale_g - image_sum_g_ * templ_sum_scale_g
- image_sum_b_ * templ_sum_scale_b - image_sum_b_ * templ_sum_scale_b
...@@ -822,7 +822,7 @@ __global__ void normalizeKernel_8U( ...@@ -822,7 +822,7 @@ __global__ void normalizeKernel_8U(
float image_sqsum_ = (float)( float image_sqsum_ = (float)(
(image_sqsum.ptr(y + h)[(x + w) * cn] - image_sqsum.ptr(y)[(x + w) * cn]) - (image_sqsum.ptr(y + h)[(x + w) * cn] - image_sqsum.ptr(y)[(x + w) * cn]) -
(image_sqsum.ptr(y + h)[x * cn] - image_sqsum.ptr(y)[x * cn])); (image_sqsum.ptr(y + h)[x * cn] - image_sqsum.ptr(y)[x * cn]));
result.ptr(y)[x] = min(1.f, result.ptr(y)[x] * rsqrtf(image_sqsum_ * templ_sqsum)); result.ptr(y)[x] = min(1.f, result.ptr(y)[x] * rsqrtf((image_sqsum_ + 1.f) * templ_sqsum));
} }
} }
......
...@@ -124,7 +124,7 @@ struct CV_GpuMatchTemplateTest: CvTest ...@@ -124,7 +124,7 @@ struct CV_GpuMatchTemplateTest: CvTest
F(t = clock();) F(t = clock();)
gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCORR_NORMED); gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCORR_NORMED);
F(cout << "gpu_block: " << clock() - t << endl;) F(cout << "gpu_block: " << clock() - t << endl;)
if (!check(dst_gold, Mat(dst), h * w * 1e-5f)) return; if (!check(dst_gold, Mat(dst), h * w * 1e-4f)) return;
gen(image, n, m, CV_8U, cn); gen(image, n, m, CV_8U, cn);
gen(templ, h, w, CV_8U, cn); gen(templ, h, w, CV_8U, cn);
...@@ -146,7 +146,7 @@ struct CV_GpuMatchTemplateTest: CvTest ...@@ -146,7 +146,7 @@ struct CV_GpuMatchTemplateTest: CvTest
F(t = clock();) F(t = clock();)
gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCOEFF_NORMED); gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCOEFF_NORMED);
F(cout << "gpu_block: " << clock() - t << endl;) F(cout << "gpu_block: " << clock() - t << endl;)
if (!check(dst_gold, Mat(dst), h * w * 1e-6f)) return; if (!check(dst_gold, Mat(dst), h * w * 1e-4f)) return;
gen(image, n, m, CV_32F, cn); gen(image, n, m, CV_32F, cn);
gen(templ, h, w, CV_32F, cn); gen(templ, h, w, CV_32F, cn);
...@@ -207,66 +207,70 @@ struct CV_GpuMatchTemplateTest: CvTest ...@@ -207,66 +207,70 @@ struct CV_GpuMatchTemplateTest: CvTest
return false; return false;
} }
//// Debug check
//for (int i = 0; i < a.rows; ++i)
//{
// for (int j = 0; j < a.cols; ++j)
// {
// float v1 = a.at<float>(i, j);
// float v2 = b.at<float>(i, j);
// if (fabs(v1 - v2) > max_err)
// {
// ts->printf(CvTS::CONSOLE, "%d %d %f %f\n", i, j, v1, v2);
// cin.get();
// }
// }
//}
return true; return true;
} }
} match_template_test;
//void match_template_naive_SQDIFF(const Mat& a, const Mat& b, Mat& c) struct CV_GpuMatchTemplateFindPatternInBlackTest: CvTest
//{ {
// c.create(a.rows - b.rows + 1, a.cols - b.cols + 1, CV_32F); CV_GpuMatchTemplateFindPatternInBlackTest()
// for (int i = 0; i < c.rows; ++i) : CvTest("GPU-MatchTemplateFindPatternInBlackTest", "matchTemplate") {}
// {
// for (int j = 0; j < c.cols; ++j)
// {
// float delta;
// float sum = 0.f;
// for (int y = 0; y < b.rows; ++y)
// {
// const unsigned char* arow = a.ptr(i + y);
// const unsigned char* brow = b.ptr(y);
// for (int x = 0; x < b.cols; ++x)
// {
// delta = (float)(arow[j + x] - brow[x]);
// sum += delta * delta;
// }
// }
// c.at<float>(i, j) = sum;
// }
// }
//}
//void match_template_naive_CCORR(const Mat& a, const Mat& b, Mat& c) void run(int)
//{ {
// c.create(a.rows - b.rows + 1, a.cols - b.cols + 1, CV_32F); try
// for (int i = 0; i < c.rows; ++i) {
// { Mat image = imread(std::string(ts->get_data_path()) + "matchtemplate/black.jpg");
// for (int j = 0; j < c.cols; ++j) if (image.empty())
// { {
// float sum = 0.f; ts->printf(CvTS::CONSOLE, "can't open file '%s'", (std::string(ts->get_data_path())
// for (int y = 0; y < b.rows; ++y) + "matchtemplate/black.jpg").c_str());
// { ts->set_failed_test_info(CvTS::FAIL_INVALID_TEST_DATA);
// const float* arow = a.ptr<float>(i + y); return;
// const float* brow = b.ptr<float>(y); }
// for (int x = 0; x < b.cols; ++x)
// sum += arow[j + x] * brow[x]; Mat pattern = imread(std::string(ts->get_data_path()) + "matchtemplate/cat.jpg");
// } if (pattern.empty())
// c.at<float>(i, j) = sum; {
// } ts->printf(CvTS::CONSOLE, "can't open file '%s'", (std::string(ts->get_data_path())
// } + "matchtemplate/cat.jpg").c_str());
//} ts->set_failed_test_info(CvTS::FAIL_INVALID_TEST_DATA);
} match_template_test; return;
}
gpu::GpuMat d_image(image);
gpu::GpuMat d_pattern(pattern);
gpu::GpuMat d_result;
double maxValue;
Point maxLoc;
Point maxLocGold(284, 12);
gpu::matchTemplate(d_image, d_pattern, d_result, CV_TM_CCOEFF_NORMED);
gpu::minMaxLoc(d_result, NULL, &maxValue, NULL, &maxLoc );
if (maxLoc != maxLocGold)
{
ts->printf(CvTS::CONSOLE, "bad match (CV_TM_CCOEFF_NORMED): %d %d, must be at: %d %d",
maxLoc.x, maxLoc.y, maxLocGold.x, maxLocGold.y);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
gpu::matchTemplate(d_image, d_pattern, d_result, CV_TM_CCORR_NORMED);
gpu::minMaxLoc(d_result, NULL, &maxValue, NULL, &maxLoc );
if (maxLoc != maxLocGold)
{
ts->printf(CvTS::CONSOLE, "bad match (CV_TM_CCORR_NORMED): %d %d, must be at: %d %d",
maxLoc.x, maxLoc.y, maxLocGold.x, maxLocGold.y);
ts->set_failed_test_info(CvTS::FAIL_INVALID_OUTPUT);
return;
}
}
catch (const Exception& e)
{
ts->printf(CvTS::CONSOLE, e.what());
if (!check_and_treat_gpu_exception(e, ts)) throw;
return;
}
}
} match_templet_find_bordered_pattern_test;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment