提交 78e07d32 编写于 作者: V Vadim Pisarevsky

Merge pull request #3845 from ellbur:findTransformECC-mask

......@@ -278,6 +278,7 @@ order to provide an image similar to templateImage, same type as temlateImage.
criteria.epsilon defines the threshold of the increment in the correlation coefficient between two
iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
Default values are shown in the declaration above.
@param inputMask An optional mask to indicate valid values of inputImage.
The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion
(@cite EP08), that is
......@@ -309,7 +310,8 @@ estimateRigidTransform, findHomography
*/
CV_EXPORTS_W double findTransformECC( InputArray templateImage, InputArray inputImage,
InputOutputArray warpMatrix, int motionType = MOTION_AFFINE,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001));
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001),
InputArray inputMask = noArray());
/** @brief Kalman filter class.
......
......@@ -317,7 +317,8 @@ double cv::findTransformECC(InputArray templateImage,
InputArray inputImage,
InputOutputArray warpMatrix,
int motionType,
TermCriteria criteria)
TermCriteria criteria,
InputArray inputMask)
{
......@@ -397,13 +398,26 @@ double cv::findTransformECC(InputArray templateImage,
Mat templateFloat = Mat(hs, ws, CV_32F);// to store the (smoothed) template
Mat imageFloat = Mat(hd, wd, CV_32F);// to store the (smoothed) input image
Mat imageWarped = Mat(hs, ws, CV_32F);// to store the warped zero-mean input image
Mat allOnes = Mat::ones(hd, wd, CV_8U); //to use it for mask warping
Mat imageMask = Mat(hs, ws, CV_8U); //to store the final mask
Mat inputMaskMat = inputMask.getMat();
//to use it for mask warping
Mat preMask =
inputMaskMat.empty() ? Mat::ones(hd, wd, CV_8U) : inputMaskMat;
//gaussian filtering is optional
src.convertTo(templateFloat, templateFloat.type());
GaussianBlur(templateFloat, templateFloat, Size(5, 5), 0, 0);//is in-place filtering slower?
Mat preMaskFloat = Mat(hd, wd, CV_32F);
preMask.convertTo(preMaskFloat, preMaskFloat.type());
GaussianBlur(preMaskFloat, preMaskFloat, Size(5, 5), 0, 0);//is in-place filtering slower?
// Change threshold.
preMaskFloat *= (0.5/0.95);
// Rounding conversion.
preMaskFloat.convertTo(preMask, preMask.type());
preMask.convertTo(preMaskFloat, preMaskFloat.type());
dst.convertTo(imageFloat, imageFloat.type());
GaussianBlur(imageFloat, imageFloat, Size(5, 5), 0, 0);
......@@ -420,6 +434,8 @@ double cv::findTransformECC(InputArray templateImage,
filter2D(imageFloat, gradientX, -1, dx);
filter2D(imageFloat, gradientY, -1, dx.t());
gradientX = gradientX.mul(preMaskFloat);
gradientY = gradientY.mul(preMaskFloat);
// matrices needed for solving linear equation system for maximizing ECC
Mat jacobian = Mat(hs, ws*numberOfParameters, CV_32F);
......@@ -449,17 +465,16 @@ double cv::findTransformECC(InputArray templateImage,
warpAffine(imageFloat, imageWarped, map, imageWarped.size(), imageFlags);
warpAffine(gradientX, gradientXWarped, map, gradientXWarped.size(), imageFlags);
warpAffine(gradientY, gradientYWarped, map, gradientYWarped.size(), imageFlags);
warpAffine(allOnes, imageMask, map, imageMask.size(), maskFlags);
warpAffine(preMask, imageMask, map, imageMask.size(), maskFlags);
}
else
{
warpPerspective(imageFloat, imageWarped, map, imageWarped.size(), imageFlags);
warpPerspective(gradientX, gradientXWarped, map, gradientXWarped.size(), imageFlags);
warpPerspective(gradientY, gradientYWarped, map, gradientYWarped.size(), imageFlags);
warpPerspective(allOnes, imageMask, map, imageMask.size(), maskFlags);
warpPerspective(preMask, imageMask, map, imageMask.size(), maskFlags);
}
Scalar imgMean, imgStd, tmpMean, tmpStd;
meanStdDev(imageWarped, imgMean, imgStd, imageMask);
meanStdDev(templateFloat, tmpMean, tmpStd, imageMask);
......@@ -497,6 +512,9 @@ double cv::findTransformECC(InputArray templateImage,
// calculate enhanced correlation coefficiont (ECC)->rho
last_rho = rho;
rho = correlation/(imgNorm*tmpNorm);
if (isnan(rho)) {
CV_Error(Error::StsNoConv, "NaN encountered.");
}
// project images into jacobian
project_onto_jacobian_ECC( jacobian, imageWarped, imageProjection);
......
......@@ -394,8 +394,91 @@ void CV_ECC_Test_Homography::run(int from)
ts->set_failed_test_info(cvtest::TS::OK);
}
class CV_ECC_Test_Mask : public CV_ECC_BaseTest
{
public:
CV_ECC_Test_Mask();
protected:
void run(int);
bool testMask(int);
};
CV_ECC_Test_Mask::CV_ECC_Test_Mask(){}
bool CV_ECC_Test_Mask::testMask(int from)
{
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
if (img.empty())
{
ts->printf( ts->LOG, "test image can not be read");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return false;
}
Mat scaledImage;
resize(img, scaledImage, Size(216, 216));
Mat_<float> testImg;
scaledImage.convertTo(testImg, testImg.type());
cv::RNG rng = ts->get_rng();
int progress=0;
for (int k=from; k<ntests; k++){
ts->update_context( this, k, true );
progress = update_progress(progress, k, ntests, 0);
Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
0, 1, (rng.uniform(10.f, 20.f)));
Mat warpedImage;
warpAffine(testImg, warpedImage, translationGround,
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
for (int i=testImg.rows*2/3; i<testImg.rows; i++) {
for (int j=testImg.cols*2/3; j<testImg.cols; j++) {
testImg(i, j) = 0;
mask(i, j) = 0;
}
}
findTransformECC(warpedImage, testImg, mapTranslation, 0,
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask);
if (!isMapCorrect(mapTranslation)){
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
return false;
}
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->printf( ts->LOG, "RMS = %f",
computeRMS(mapTranslation, translationGround));
return false;
}
}
return true;
}
void CV_ECC_Test_Mask::run(int from)
{
if (!testMask(from))
return;
ts->set_failed_test_info(cvtest::TS::OK);
}
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(); }
TEST(Video_ECC_Homography, accuracy) { CV_ECC_Test_Homography test; test.safe_run(); }
TEST(Video_ECC_Mask, accuracy) { CV_ECC_Test_Mask test; test.safe_run(); }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册