mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
Add template match with mask.
Signed-off-by: Yan Wang <yan.wang@linux.intel.com>
This commit is contained in:
parent
61991a3330
commit
46ed461e22
@ -3330,9 +3330,11 @@ data type.
|
|||||||
@param result Map of comparison results. It must be single-channel 32-bit floating-point. If image
|
@param result Map of comparison results. It must be single-channel 32-bit floating-point. If image
|
||||||
is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \times (H-h+1)\f$ .
|
is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \times (H-h+1)\f$ .
|
||||||
@param method Parameter specifying the comparison method, see cv::TemplateMatchModes
|
@param method Parameter specifying the comparison method, see cv::TemplateMatchModes
|
||||||
|
@param mask Mask of searched template. It must have the same datatype and size with templ. It is
|
||||||
|
not set by default.
|
||||||
*/
|
*/
|
||||||
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
|
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
|
||||||
OutputArray result, int method );
|
OutputArray result, int method, InputArray mask = noArray() );
|
||||||
|
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
@ -814,12 +814,97 @@ void crossCorr( const Mat& img, const Mat& _templ, Mat& corr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void matchTemplateMask( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
|
||||||
|
{
|
||||||
|
int type = _img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||||
|
CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
|
||||||
|
CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
|
||||||
|
|
||||||
|
Mat img = _img.getMat(), templ = _templ.getMat(), mask = _mask.getMat();
|
||||||
|
int ttype = templ.type(), tdepth = CV_MAT_DEPTH(ttype), tcn = CV_MAT_CN(ttype);
|
||||||
|
int mtype = img.type(), mdepth = CV_MAT_DEPTH(type), mcn = CV_MAT_CN(mtype);
|
||||||
|
|
||||||
|
if (depth == CV_8U)
|
||||||
|
{
|
||||||
|
depth = CV_32F;
|
||||||
|
type = CV_MAKETYPE(CV_32F, cn);
|
||||||
|
img.convertTo(img, type, 1.0 / 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdepth == CV_8U)
|
||||||
|
{
|
||||||
|
tdepth = CV_32F;
|
||||||
|
ttype = CV_MAKETYPE(CV_32F, tcn);
|
||||||
|
templ.convertTo(templ, ttype, 1.0 / 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mdepth == CV_8U)
|
||||||
|
{
|
||||||
|
mdepth = CV_32F;
|
||||||
|
mtype = CV_MAKETYPE(CV_32F, mcn);
|
||||||
|
compare(mask, Scalar::all(0), mask, CMP_NE);
|
||||||
|
mask.convertTo(mask, mtype, 1.0 / 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
|
||||||
|
_result.create(corrSize, CV_32F);
|
||||||
|
Mat result = _result.getMat();
|
||||||
|
|
||||||
|
Mat img2 = img.mul(img);
|
||||||
|
Mat mask2 = mask.mul(mask);
|
||||||
|
Mat mask_templ = templ.mul(mask);
|
||||||
|
Scalar templMean, templSdv;
|
||||||
|
|
||||||
|
double templSum2 = 0;
|
||||||
|
meanStdDev( mask_templ, templMean, templSdv );
|
||||||
|
|
||||||
|
templSum2 = templSdv[0]*templSdv[0] + templSdv[1]*templSdv[1] + templSdv[2]*templSdv[2] + templSdv[3]*templSdv[3];
|
||||||
|
templSum2 += templMean[0]*templMean[0] + templMean[1]*templMean[1] + templMean[2]*templMean[2] + templMean[3]*templMean[3];
|
||||||
|
templSum2 *= ((double)templ.rows * templ.cols);
|
||||||
|
|
||||||
|
if (method == CV_TM_SQDIFF)
|
||||||
|
{
|
||||||
|
Mat mask2_templ = templ.mul(mask2);
|
||||||
|
|
||||||
|
Mat corr(corrSize, CV_32F);
|
||||||
|
crossCorr( img, mask2_templ, corr, corr.size(), corr.type(), Point(0,0), 0, 0 );
|
||||||
|
crossCorr( img2, mask, result, result.size(), result.type(), Point(0,0), 0, 0 );
|
||||||
|
|
||||||
|
result -= corr * 2;
|
||||||
|
result += templSum2;
|
||||||
|
}
|
||||||
|
else if (method == CV_TM_CCORR_NORMED)
|
||||||
|
{
|
||||||
|
if (templSum2 < DBL_EPSILON)
|
||||||
|
{
|
||||||
|
result = Scalar::all(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat corr(corrSize, CV_32F);
|
||||||
|
crossCorr( img2, mask2, corr, corr.size(), corr.type(), Point(0,0), 0, 0 );
|
||||||
|
crossCorr( img, mask_templ, result, result.size(), result.type(), Point(0,0), 0, 0 );
|
||||||
|
|
||||||
|
sqrt(corr, corr);
|
||||||
|
result = result.mul(1/corr);
|
||||||
|
result /= std::sqrt(templSum2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsNotImplemented, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method )
|
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
|
||||||
{
|
{
|
||||||
|
if (!_mask.empty())
|
||||||
|
{
|
||||||
|
cv::matchTemplateMask(_img, _templ, _result, method, _mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int type = _img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
int type = _img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||||
CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
|
CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
|
||||||
CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
|
CV_Assert( (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 );
|
||||||
|
72
samples/cpp/mask_tmpl.cpp
Normal file
72
samples/cpp/mask_tmpl.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
static void help()
|
||||||
|
{
|
||||||
|
cout << "\nThis program demonstrates template match with mask.\n"
|
||||||
|
"Usage:\n"
|
||||||
|
"./mask_tmpl <image_name> <template_name> <mask_name>, Default is ../data/lena_tmpl.jpg\n"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, const char** argv )
|
||||||
|
{
|
||||||
|
const char* filename = argc == 4 ? argv[1] : "../data/lena_tmpl.jpg";
|
||||||
|
const char* tmplname = argc == 4 ? argv[2] : "../data/tmpl.png";
|
||||||
|
const char* maskname = argc == 4 ? argv[3] : "../data/mask.png";
|
||||||
|
|
||||||
|
Mat img = imread(filename);
|
||||||
|
Mat tmpl = imread(tmplname);
|
||||||
|
Mat mask = imread(maskname);
|
||||||
|
Mat res;
|
||||||
|
|
||||||
|
if(img.empty())
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
cout << "can not open " << filename << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmpl.empty())
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
cout << "can not open " << tmplname << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mask.empty())
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
cout << "can not open " << maskname << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//int method = CV_TM_SQDIFF;
|
||||||
|
int method = CV_TM_CCORR_NORMED;
|
||||||
|
matchTemplate(img, tmpl, res, method, mask);
|
||||||
|
|
||||||
|
double minVal, maxVal;
|
||||||
|
Point minLoc, maxLoc;
|
||||||
|
Rect rect;
|
||||||
|
minMaxLoc(res, &minVal, &maxVal, &minLoc, &maxLoc);
|
||||||
|
|
||||||
|
if(method == CV_TM_SQDIFF || method == CV_TM_SQDIFF_NORMED)
|
||||||
|
rect = Rect(minLoc, tmpl.size());
|
||||||
|
else
|
||||||
|
rect = Rect(maxLoc, tmpl.size());
|
||||||
|
|
||||||
|
rectangle(img, rect, Scalar(0, 255, 0), 2);
|
||||||
|
|
||||||
|
imshow("detected template", img);
|
||||||
|
waitKey();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
samples/data/lena_tmpl.jpg
Normal file
BIN
samples/data/lena_tmpl.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
BIN
samples/data/mask.png
Normal file
BIN
samples/data/mask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
BIN
samples/data/tmpl.png
Normal file
BIN
samples/data/tmpl.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
Loading…
Reference in New Issue
Block a user