Scalar meanTemplate, sdTemplate;
int active_pixels = inputMask.empty() ? templateImage.size().area() : countNonZero(inputMask);
-
+ int type = templateImage.type();
meanStdDev(templateImage, meanTemplate, sdTemplate, inputMask);
Mat templateImage_zeromean = Mat::zeros(templateImage.size(), templateImage.type());
- subtract(templateImage, meanTemplate, templateImage_zeromean, inputMask);
+ Mat templateMat = templateImage.getMat();
+ Mat inputMat = inputImage.getMat();
+
+ /*
+ * For unsigned ints, when the mean is computed and subtracted, any values less than the mean
+ * will be set to 0 (since there are no negatives values). This impacts the norm and dot product, which
+ * ultimately results in an incorrect ECC. To circumvent this problem, if unsigned ints are provided,
+ * we convert them to a signed ints with larger resolution for the subtraction step.
+ */
+ if(type == CV_8U || type == CV_16U) {
+ int newType = type == CV_8U ? CV_16S : CV_32S;
+ Mat templateMatConverted, inputMatConverted;
+ templateMat.convertTo(templateMatConverted, newType);
+ cv::swap(templateMat, templateMatConverted);
+ inputMat.convertTo(inputMatConverted, newType);
+ cv::swap(inputMat, inputMatConverted);
+ }
+ subtract(templateMat, meanTemplate, templateImage_zeromean, inputMask);
double templateImagenorm = std::sqrt(active_pixels*sdTemplate.val[0]*sdTemplate.val[0]);
Scalar meanInput, sdInput;
Mat inputImage_zeromean = Mat::zeros(inputImage.size(), inputImage.type());
meanStdDev(inputImage, meanInput, sdInput, inputMask);
- subtract(inputImage, meanInput, inputImage_zeromean, inputMask);
+ subtract(inputMat, meanInput, inputImage_zeromean, inputMask);
double inputImagenorm = std::sqrt(active_pixels*sdInput.val[0]*sdInput.val[0]);
return templateImage_zeromean.dot(inputImage_zeromean)/(templateImagenorm*inputImagenorm);
EXPECT_NEAR(ecc, -0.5f, 1e-5f);
}
+TEST(Video_ECC_Test_Compute, bug_14657)
+{
+ /*
+ * Simple test case - a 2 x 2 matrix with 10, 10, 10, 6. When the mean (36 / 4 = 9) is subtracted,
+ * it results in 1, 1, 1, 0 for the unsigned int case - compare to 1, 1, 1, -3 in the signed case.
+ * For this reason, when the same matrix was provided as the input and the template, we didn't get 1 as expected.
+ */
+ Mat img = (Mat_<uint8_t>(2, 2) << 10, 10, 10, 6);
+ EXPECT_NEAR(computeECC(img, img), 1.0f, 1e-5f);
+}
+
+
TEST(Video_ECC_Translation, accuracy) { CV_ECC_Test_Translation test; test.safe_run();}
TEST(Video_ECC_Euclidean, accuracy) { CV_ECC_Test_Euclidean test; test.safe_run(); }
TEST(Video_ECC_Affine, accuracy) { CV_ECC_Test_Affine test; test.safe_run(); }