说明
直接使用别人的opencv代码,多是只找出最匹配的轮廓,但是有时候我么需要找出多个,那就需要稍微进行一点点操作,把已经找到的排除在外,接着找。
函数代码
bool cvMatch(cv::Mat &Temp, string Filename,string ownname)
{
if (Temp.empty())return false;
if (Filename.empty())return false;
cv::Mat img1 = imread(Filename);//cv::imread(sPath + "\\car_1.jpg");
cv::Mat img2 = Temp;//cv::imread(sPath + "\\Temp\\car_1_temp.jpg");
//步骤二:创建一个空画布用来绘制匹配结果
cv::Mat dstImg;
dstImg.create(img1.dims, img1.size, img1.type());
//cv::imshow("createImg", dstImg);
//步骤三:匹配,最后一个参数为匹配方式,共有6种,详细请查阅函数介绍
cv::matchTemplate(img1, img2, dstImg, 0);
//步骤四:归一化图像矩阵,可省略
cv::normalize(dstImg, dstImg, 0, 1, 32);
//步骤五:获取最大或最小匹配系数
//首先是从得到的 输出矩阵中得到 最大或最小值(平方差匹配方式是越小越好,所以在这种方式下,找到最小位置)
//找矩阵的最小位置的函数是 minMaxLoc函数
cv::Point minPoint;
cv::Point maxPoint;
double* minVal = 0;
double* maxVal = 0;
dstImg = 1 - dstImg;//翻转灰度
cv::minMaxLoc(dstImg, minVal, maxVal, &minPoint, &maxPoint);
//步骤六:开始正式绘制
cv::rectangle(img1, maxPoint, cv::Point(maxPoint.x + img2.cols, maxPoint.y + img2.rows), cv::Scalar(0, 255, 0), 2, 8);
//选出第二组
cv::Mat Mask = cv::Mat::ones(dstImg.size(), CV_8UC1) * 255;//把已经找出来的区域给屏蔽掉,可以选择操作Mask,也可以直接在原图上操作
for (size_t i = maxPoint.x - img2.cols / 2; i < maxPoint.x + img2.cols && i < Mask.cols; i++)
{
for (size_t j = maxPoint.y - img2.rows / 2; j < maxPoint.y + img2.rows && j < Mask.rows; j++)
{
Mask.at<uchar>(j, i) = 0;
}
}
//正式选出第二组并绘制
minVal = 0; maxVal = 0; minPoint -= minPoint; maxPoint -= maxPoint;
cv::minMaxLoc(dstImg, minVal, maxVal, &minPoint, &maxPoint, Mask);
cv::rectangle(img1, maxPoint, cv::Point(maxPoint.x + img2.cols, maxPoint.y + img2.rows), cv::Scalar(0, 255, 0), 2, 8);
string sPath = "E:\\Pictures\\First\\";
MkDir(sPath + "car");
imwrite(sPath + "car\\" +ownname, img1);
return true;
}
图像结果
模板:
car_1_temp.jpg
图像:
car_1.jpg 中间结果: 1.jpg
使用的mask:
2.jpg
最终结果
car_1.jpg使用其他的图片测试,还勉强有点泛化能力。
网友评论