Modify findTransformECC to support a mask of pixels to consider

Tests of the mask are also included.

This is useful for registering a non-square image against a non-square
template.

This also needs to relax a sanity check as per
https://github.com/Itseez/opencv/pull/3851
This commit is contained in:
Owen Healy
2015-03-18 21:11:33 -04:00
parent e12a04ac7e
commit 86fb9f8409
4 changed files with 111 additions and 7 deletions

View File

@@ -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,22 +465,22 @@ 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);
subtract(imageWarped, imgMean, imageWarped, imageMask);//zero-mean input
templateZM = Mat::zeros(templateZM.rows, templateZM.cols, templateZM.type());
subtract(templateFloat, tmpMean, templateZM, imageMask);//zero-mean template
const double tmpNorm = std::sqrt(countNonZero(imageMask)*(tmpStd.val[0])*(tmpStd.val[0]));
@@ -496,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);