目录
【day1】8.20号实验记录(初步使用模板匹配)
模板匹配
利用模板匹配可以框定出瓶子,但是却不能分辨哪种瓶子是哪种瓶子。
对同一张图片用不同的模板去进行匹配,选择匹配度最高的作为最终的结果。
而且这种匹配受到模板大小的限制。若是摄像头固定,视角固定,那这个问题可以解决。
单张图的代码
#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include <vector>
#include <algorithm>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>
#define WINDOW_NAME "【程序窗口】"
using namespace cv;
using namespace std;
int main()
{
//改变控制台字体颜色
system("color 02");
Mat srcImage=imread("D:\\opencv_picture_test\\视觉项目\\圆1.png"); //测试图
Mat tempMat = imread("D:\\opencv_picture_test\\视觉项目\\方template.png"); //模板图
//Mat srcImage=imread("D:\\opencv_picture_test\\img.png"); //测试图
//Mat tempMat = imread("D:\\opencv_picture_test\\template.png"); //模板图
cout << tempMat.cols << endl;
cout << tempMat.rows << endl;
Mat refMat;
Mat resultMat;
Mat dispMat;
tempMat.copyTo(refMat);
int match_method = TM_CCOEFF_NORMED;
//采用模板与目标图像像素与各自图像的平均值计算dot product,正值越大匹配度越高,负值越大图像的区别越大,但如果图像没有明显的特征(即图像中的像素值与平均值接近)则返回值越接近0;
matchTemplate(srcImage, refMat, resultMat, match_method);
normalize(resultMat, resultMat, 0, 1, NORM_MINMAX, -1, Mat()); //归一化
double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; //定义最大值最小值以及它们的位置变量
minMaxLoc(resultMat, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); //从结果矩阵中找到匹配度最大以及最小的值并且确定其位置
//对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果
//而其余的方法则是数值越大匹配效果越好
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)
matchLoc = minLoc;
else
matchLoc = maxLoc;
srcImage.copyTo(dispMat);
//circle(dispMat, matchLoc, 5, Scalar(0, 0, 255), 2, 8, 0);
//以最佳匹配点为中心绘制与模板相同大小的框
rectangle(dispMat, matchLoc, Point(matchLoc.x + refMat.cols, matchLoc.y + refMat.rows), Scalar::all(0), 2, 8, 0);
namedWindow("template", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩
imshow("template", refMat);
namedWindow("srcImage", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩
imshow("srcImage", dispMat);
waitKey(0);
return 0;
}
利用多个模板去匹配多张图的代码
写代码过程中遇到的问题
1、要理解好result矩阵的含义
2、match_method 要多试几种
3、不同模板对同一张测试图匹配后得到的result数组中,不需要对其归一化,不然会发现,每个模板的最佳值都是1(使用TM_CCORR_NORMED时),这样就比较不了了。
#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include <vector>
#include <algorithm>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>
#define WINDOW_NAME "【程序窗口】"
using namespace cv;
using namespace std;
void show_text(int nums)
{
if (nums == 0)
{
cout << "方" << endl;
}
else if (nums == 1)
{
cout << "v圆" << endl;
}
else if (nums == 2)
{
cout << "圆" << endl;
}
else if (nums == 3)
{
cout << "小" << endl;
}
else if (nums == 4)
{
cout << "中" << endl;
}
else
{
cout << "无" << endl;
}
}
int main()
{
//改变控制台字体颜色
system("color 02");
//创建模板vector
vector<Mat>tempMat;
//插入模板元素
Mat temp = imread("D:\\opencv_picture_test\\视觉项目\\方template.png");
tempMat.push_back(temp);
temp = imread("D:\\opencv_picture_test\\视觉项目\\v圆template.png");
tempMat.push_back(temp);
temp = imread("D:\\opencv_picture_test\\视觉项目\\圆template.png");
tempMat.push_back(temp);
temp = imread("D:\\opencv_picture_test\\视觉项目\\小template.png");
tempMat.push_back(temp);
temp= imread("D:\\opencv_picture_test\\视觉项目\\中template.png");
tempMat.push_back(temp);
Mat tempMat1 = tempMat[0];
Mat tempMat2 = tempMat[1];
Mat tempMat3 = tempMat[2];
Mat tempMat4 = tempMat[3];
Mat tempMat5 = tempMat[4];
//获取模板数目
int tempMat_Nums = tempMat.size();
//获取测试图像
Mat srcImage=imread("D:\\opencv_picture_test\\视觉项目\\v圆1.png"); //测试图
Mat resultMat;
Mat dispMat;
int match_method = TM_CCORR_NORMED; //经过试错发现此参数较好。
//用每个模板去匹配测试图,并且找出每次结果的最佳匹配值,将值存入vector中
vector<double>goodval;
vector<Point>goodlock;
int matchnum = 0;
Point matchLoc;
for (int i = 0;i < tempMat_Nums;i++)
{
//采用模板与目标图像像素与各自图像的平均值计算dot product,正值越大匹配度越高,负值越大图像的区别越大,但如果图像没有明显的特征(即图像中的像素值与平均值接近)则返回值越接近0;
matchTemplate(srcImage, tempMat[i], resultMat, match_method);
//不归一化,因为不同模板归一化后的最佳值皆为1,无法比较
//normalize(resultMat, resultMat, 0, 1, NORM_MINMAX, -1, Mat()); //归一化
double minVal; double maxVal; Point minLoc; Point maxLoc; //定义最大值最小值以及它们的位置变量
minMaxLoc(resultMat, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); //从结果矩阵中找到匹配度最大以及最小的值并且确定其位置
//对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果
//而其余的方法则是数值越大匹配效果越好
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)
{
goodlock.push_back(minLoc);
goodval.push_back(minVal);
}
else
{
goodlock.push_back(maxLoc);
goodval.push_back(maxVal);
}
cout << i << " "<<maxVal << endl;
}
//找到goodval中最佳的一组
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)
{
auto goodPosition = min_element(goodval.begin(), goodval.end());
matchnum = distance(begin(goodval), goodPosition);
}
else
{
auto goodPosition = max_element(goodval.begin(), goodval.end());
matchnum = distance(begin(goodval), goodPosition);
}
show_text(matchnum);
matchLoc = goodlock[matchnum];
srcImage.copyTo(dispMat);
//circle(dispMat, matchLoc, 5, Scalar(0, 0, 255), 2, 8, 0);
//以最佳匹配点为中心绘制与模板相同大小的框
rectangle(dispMat, matchLoc, Point(matchLoc.x + tempMat[matchnum].cols, matchLoc.y + tempMat[matchnum].rows), Scalar::all(0), 2, 8, 0);
//namedWindow("template", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩
//imshow("template", tempMat);
namedWindow("srcImage", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩
imshow("srcImage", dispMat);
waitKey(0);
return 0;
}