若该文为原创文章,未经容许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:http://www.javashuo.com/article/p-wxwjppoc-mo.html
本文章博客地址:http://www.javashuo.com/article/p-qpsdoqzi-ky.html
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么本身研究算法
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)数组
上一篇:《OpenCV开发笔记(五十二):红胖子8分钟带你深刻了解直方图对比匹配(图文并茂+浅显易懂+程序源码)》ide
下一篇:《OpenCV开发笔记(五十四):红胖子8分钟带你深刻了解Haar级联分类器进行人脸检测(图文并茂+浅显易懂+程序源码)》函数
红胖子来也!!!ui
模板匹配识别是传统识别的方式之一,纯靠计算力去进行类似度匹配。.net
实际在使用模板匹配时可能要须要结合其余算法予以辅助,能提升识别的精度。code
模板匹配是在一幅图像中寻找另外一幅图模板图像的技术。视频
模板匹配的原理其实就是将模板在匹配的图像上,从上至下,从左至右按照一个像素点步进去匹配类似度,全部的东西遍历后,获得全部类似度。blog
此处,特别注意,类似度的匹配是有多种方式的,根据不一样的方式去匹配不一样的类似度,主要有如下方式:图片
这类方法是对每一个像素利用平方差来进行匹配,最好匹配为0,匹配越差匹配值则越大。
这类方法是先平方差后再归一化。
这类方法采用模板和图像间的乘法操做,数值越大表示匹配程度越高,0表示最坏的匹配。
这类方法将模板对其均值的相对值与图像对其均值的相关知识进行匹配,1表示彻底匹配,-1表示不匹配,0表示没有任何相关性。
void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask = noArray() );
void minMaxLoc(const SparseMat& a, double* minVal, double* maxVal, int* minIdx = 0, int* maxIdx = 0); void minMaxLoc(InputArray src, double* minVal, double* maxVal = 0, Point* minLoc = 0, Point* maxLoc = 0, InputArray mask = noArray());
OpenCV操做视频,请查看博文:《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储》
OpenCV绘制图形,请查看博文:《OpenCV开发笔记(七):OpenCV基础图形绘制》
void OpenCVManager::testMatchTemplate() { QString fileName1 = "E:/testFile/templ2.jpg"; cv::Mat srcMat = cv::imread(fileName1.toStdString()); cv::String windowName = _windowTitle.toStdString(); cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(700, 900), srcMat.type()); cv::VideoCapture videoCapture; videoCapture.open("E:/testFile/test.avi"); cv::Mat mat; cv::Mat dstMat; int currentIndex = 0; while(true) { // 刷新全图黑色 windowMat = cv::Scalar(0, 0, 0); currentIndex = videoCapture.get(cv::CAP_PROP_POS_FRAMES); videoCapture >> mat; if(!mat.empty()) { dstMat = mat.clone(); // 模板头像 mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat); // 模板 cv::Mat result; // 平方差匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_SQDIFF); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(minIdx.x, minIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(0, 0, 255)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 0, 0.5f, 0xFF0000, "TM_SQDIFF minVal = %f", minVal); } // 归一平方差匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_SQDIFF_NORMED); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(minIdx.x, minIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(0, 255, 0)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 1, 0.5f, 0x00FF00, "TM_SQDIFF_NORMED minVal = %f", minVal); } // 相关匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_CCORR); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(maxIdx.x, maxIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(255, 0, 0)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 2, 0.5f, 0x0000FF, "TM_CCORR maxVal = %f", maxVal); } // 归一相关匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_CCORR_NORMED); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(maxIdx.x, maxIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(255, 255, 0)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 3, 0.5f, 0x00FFFF, "TM_CCORR maxVal = %f", maxVal); } // 系数匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_CCOEFF); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(maxIdx.x, maxIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(255, 0, 255)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 4, 0.5f, 0xFF00FF, "TM_CCOEFF maxVal = %f", maxVal); } // 系数匹配法匹配法 { cv::matchTemplate(dstMat, srcMat, result, cv::TM_CCOEFF_NORMED); // 获取结果中的最大值、最小值的下标和对应值 double minVal, maxVal; cv::Point minIdx, maxIdx; cv::minMaxLoc(result, &minVal, &maxVal, &minIdx, &maxIdx); cv::rectangle(dstMat, cv::Rect(maxIdx.x, maxIdx.y, srcMat.cols, srcMat.rows), cv::Scalar(255, 255, 255)); cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1 + dstMat.rows + 30 * 5, 0.5f, 0xFFFFFF, "TM_CCOEFF_NORMED maxVal = %f", maxVal); } // 视频复制 mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 1 + dstMat.rows), cv::Range(srcMat.cols * 0, srcMat.cols * 0 + dstMat.cols)); cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat); } qDebug() << __FILE__ << __LINE__ << currentIndex; // 更新 cvui::update(); // 显示 cv::imshow(windowName, windowMat); // esc键退出 int key = cv::waitKey(0); switch (key) { case 97: // 'a' 往前一帧 currentIndex--; if(currentIndex < 0) { currentIndex = 0; } videoCapture.set(cv::CAP_PROP_POS_FRAMES, currentIndex); break; case 115: // ‘s’ 日后一帧 break; default: break; } if(key == 27) { break; } } }
对应版本号v1.48.0
上一篇:《OpenCV开发笔记(五十二):红胖子8分钟带你深刻了解直方图对比匹配(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(五十四):红胖子8分钟带你深刻了解Haar级联分类器进行人脸检测(图文并茂+浅显易懂+程序源码)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:http://www.javashuo.com/article/p-wxwjppoc-mo.html
本文章博客地址:http://www.javashuo.com/article/p-qpsdoqzi-ky.html