mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
Merge pull request #19993 from danielenricocahall:fix-compute-ecc-issue
Fix unsigned int bug in computeECC * address issue with unsigned ints in computeEcc * remove additional logic checking firstOctave * use swap instead of same src/dst * simplify the unsigned check logic
This commit is contained in:
parent
baa22fa808
commit
1b844f8413
@ -323,17 +323,34 @@ double cv::computeECC(InputArray templateImage, InputArray inputImage, InputArra
|
||||
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);
|
||||
|
@ -501,6 +501,18 @@ TEST(Video_ECC_Test_Compute, accuracy)
|
||||
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(); }
|
||||
|
Loading…
Reference in New Issue
Block a user