matchTemplate实现单目标匹配的方法很多在此不赘述,本文主要提供多目标匹配的方法。
首先matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask = noArray() );三个参数Result,反应的是样本与待测目标的相似程度的一个矩阵;
minMaxLoc函数是找出矩阵中最大最小值的大小和位置。
1、 使用matchTemplate得到Result,利用minMaxLoc确定最佳匹配位置,接着利用CoverTarget函数(见下文代码)覆盖掉目标区域得到新的Result重复上述步骤;
2、设置阈值使Result中符合阈值范围的点全部画出来,缺点同个目标被多词框出,解决方法在符合阈值点的领域范围内寻找最佳值。(未实现)。
核心代码:
方法1:
int main()
{
Mat src = imread("1.jpg");
Mat tem = imread("temp.jpg", 0);
Mat gray = Mat::zeros(src.size(), CV_8UC1);
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat resultImage;
int resultImage_cols = gray.cols - tem.cols + 1;
int resultImage_rows = gray.rows - tem.rows + 1;
resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);
matchTemplate(gray, tem, resultImage, 1);
double minValue, maxValue;
Point minLoc, maxLoc;
minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
// 计算第二个最小值
CoverTarget(resultImage, minLoc, maxValue, tem.cols, tem.rows);
minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
// 计算三个最小值
CoverTarget(resultImage, minLoc, maxValue, tem.cols, tem.rows);
minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
imshow("2", src);
waitKey(0);
return 0;
}
void CoverTarget(Mat &result, Point minLoc, int maxVaule, int cols, int rows)
{
// 先将第一个最小值点附近两倍模板宽度和高度的都设置为最大值防止产生干扰
int startX = minLoc.x - cols;
int startY = minLoc.y - rows;
int endX = minLoc.x + cols;
int endY = minLoc.y + rows;
if (startX < 0)
{
startX = 0;
}
if (startY < 0)
{
startY = 0;
}
if (endX > result.cols - 1)
{
endX = result.cols - 1;
}
if (endY > result.rows - 1)
{
endY = result.rows - 1;
}
int y, x;
for (y = startY; y < endY; y++)
{
for (x = startX; x < endX; x++)
{
result.at<float>(y, x) = maxVaule; //覆盖
}
}
}
结果:
完整代码链接:https://download.youkuaiyun.com/download/qq_34902877/11042461
方法2: 法1和法2效果图贴反,抱歉
int main()
{
Mat src = imread("1.jpg");
Mat tem = imread("temp.jpg",0);
Mat gray = Mat::zeros(src.size(), CV_8UC1);
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat resultImage;
int resultImage_cols = gray.cols - tem.cols + 1;
int resultImage_rows = gray.rows - tem.rows + 1;
// int resultImage_cols = gray.cols;
// int resultImage_rows = gray.rows;
resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);
//进行匹配和标准化
/*
参数四:SQDIFF和SQDIFF_NORMED越小数值匹配效果更好,其他方法则反之。
TM_SQDIFF TM_SQDIFF_NORMED TM_CCORR
TM_CCORR_NORMED TM_CCOEFF TM_CCOEFF_NORMED
*/
int matchMethod = 5;//1 3 5
matchTemplate(gray, tem, resultImage, matchMethod);
imshow("效果图片1", resultImage);
// cout << resultImage;
float threshold;
for (int i = 0; i < resultImage.rows; i++)
{
for (int j = 0; j < resultImage.cols; j++)
{
if (matchMethod == 1)
{
threshold = 0.4;
if (resultImage.at<float>(i, j) < threshold)
{
rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
}
}
else if(matchMethod == 3)
{
threshold = 0.8;
if (resultImage.at<float>(i, j) > threshold && resultImage.at<float>(i, j) < 1)
{
rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
}
}
else if (matchMethod == 5)
{
threshold = 0.6;
if (resultImage.at<float>(i, j) > threshold && resultImage.at<float>(i, j) < 1)
{
rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
}
}
}
}
imshow("原始图片", src);
cvWaitKey(0);
return 0;
}
结果:
完整代码链接:https://download.youkuaiyun.com/download/qq_34902877/11042459