https://www.cnblogs.com/skyfsm/p/6884253.html 模板匹配的作用在圖像識(shí)別領(lǐng)域作用可大了。那什么是模板匹配,?
模板匹配,,就是在一幅圖像中尋找另一幅模板圖像最匹配(也就是最相似)的部分的技術(shù)。
說的有點(diǎn)抽象,,下面給個(gè)例子說明就很明白了,。
在上面這幅全明星照中,我們想找出姚明頭像的位置,,并把它標(biāo)記出來,,可以做到嗎?
可以,,這就是模板匹配的要做的事情,。
其實(shí)模板匹配實(shí)現(xiàn)的思想也是很簡(jiǎn)單很暴力的,就是拿著模板圖片(姚明頭像)在原圖(全明星照)中從左上至右下依次滑動(dòng),,直到遇到某個(gè)區(qū)域的相似度低于我們?cè)O(shè)定的閾值,那么我們就認(rèn)為該區(qū)域與模板匹配了,,也就是我們找到了姚明的位置,,并把它標(biāo)記出來,。
OpenCV中是通過MtachTemplate函數(shù)完成,。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
Mat img, templ, result;
img = imread("nba.jpg");
templ = imread("76.png");
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create(result_cols, result_rows, CV_32FC1);
matchTemplate(img, templ, result, CV_TM_SQDIFF_NORMED);//這里我們使用的匹配算法是標(biāo)準(zhǔn)平方差匹配 method=CV_TM_SQDIFF_NORMED,,數(shù)值越小匹配度越好
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
double minVal = -1;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
cout << "匹配度:" << minVal << endl;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
cout << "匹配度:" << minVal << endl;
matchLoc = minLoc;
rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0, 255, 0), 2, 8, 0);
imshow("img", img);
waitKey(0);
return 0;
}
結(jié)果看來,大姚的頭像位置確實(shí)被綠框標(biāo)記出來了,!很準(zhǔn),!
我還在程序中特意打印出匹配度的最小值,因?yàn)槲覀冎肋@個(gè)算法是數(shù)值越小匹配度越高,,由輸出的結(jié)果看來這個(gè)數(shù)值還真的很小,,說明匹配度真的相當(dāng)高!
既然我們可以取得匹配度的數(shù)值,,那我們是不是也可以利用該數(shù)值進(jìn)行閾值對(duì)比呢,?比如我想把在閾值范圍之內(nèi)的頭像都標(biāo)記出來,??梢赃@么做:
//閾值判別,小于0.01才認(rèn)為匹配成功,,才將頭像框出來
if (minVal < 0.001)
{
rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0, 255, 0), 2, 8, 0);
}
同理,,如果是數(shù)值越大表明匹配度越大的算法,就使用maxVal來對(duì)比就可以了,。
上面的模板匹配我們使用了標(biāo)準(zhǔn)平方差匹配 CV_TM_SQDIFF_NORMED算法,,看起來效果還不錯(cuò),那還有其他算法嗎,?
問得好,。OpenCV通過函數(shù) matchTemplate 實(shí)現(xiàn)了模板匹配算法??捎玫姆椒ㄓ?個(gè):
通常,,隨著從簡(jiǎn)單的測(cè)量(平方差)到更復(fù)雜的測(cè)量(相關(guān)系數(shù)),我們可獲得越來越準(zhǔn)確的匹配(同時(shí)也意味著越來越大的計(jì)算代價(jià)),。
最好的辦法是對(duì)所有這些設(shè)置多做一些測(cè)試實(shí)驗(yàn),以便為自己的應(yīng)用選擇同時(shí)兼顧速度和精度的最佳方案,。
你想采用哪種算法,只需要將對(duì)應(yīng)的傳進(jìn)函數(shù)matchTemplate里就可以了,。
下面給出利用trackbar顯示出多種模板那匹配算法的代碼,。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat g_srcImage, g_tempalteImage, g_resultImage;
int g_nMatchMethod;
int g_nMaxTrackbarNum = 5;
void on_matching(int, void*)
{
Mat srcImage;
g_srcImage.copyTo(srcImage);
int resultImage_cols = g_srcImage.cols - g_tempalteImage.cols + 1;
int resultImage_rows = g_srcImage.rows - g_tempalteImage.rows + 1;
g_resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);
matchTemplate(g_srcImage, g_tempalteImage, g_resultImage, g_nMatchMethod);
normalize(g_resultImage, g_resultImage, 0, 2, NORM_MINMAX, -1, Mat());
double minValue, maxValue;
Point minLocation, maxLocation, matchLocation;
minMaxLoc(g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation);
if (g_nMatchMethod == TM_SQDIFF || g_nMatchMethod == CV_TM_SQDIFF_NORMED)
{
matchLocation = minLocation;
}
else
{
matchLocation = maxLocation;
}
rectangle(srcImage, matchLocation, Point(matchLocation.x + g_tempalteImage.cols, matchLocation.y + g_tempalteImage.rows), Scalar(0, 0, 255), 2, 8, 0);
rectangle(g_resultImage, matchLocation, Point(matchLocation.x + g_tempalteImage.cols, matchLocation.y + g_tempalteImage.rows), Scalar(0, 0, 255), 2, 8, 0);
imshow("原始圖", srcImage);
imshow("效果圖", g_resultImage);
}
int main()
{
g_srcImage = imread("nba.jpg");
if (!g_srcImage.data)
{
cout << "原始圖讀取失敗" << endl;
return -1;
}
g_tempalteImage = imread("76.png");
if (!g_tempalteImage.data)
{
cout << "模板圖讀取失敗" << endl;
return -1;
}
namedWindow("原始圖", CV_WINDOW_AUTOSIZE);
namedWindow("效果圖", CV_WINDOW_AUTOSIZE);
createTrackbar("方法", "原始圖", &g_nMatchMethod, g_nMaxTrackbarNum, on_matching);
on_matching(0, NULL);
waitKey(0);
return 0;
}
當(dāng)然也會(huì)有一些算法匹配失敗的.
實(shí)驗(yàn)證明,該段程序效果很不錯(cuò),,但注意的是,,模板配在原圖摳出模板圖的形式下準(zhǔn)確率才比較高,不然的話可能準(zhǔn)確度就不太高了,。
那么模板匹配能在哪些項(xiàng)目有應(yīng)用呢,?我說一下我的經(jīng)驗(yàn)。
最近我在參與實(shí)驗(yàn)室的一個(gè)項(xiàng)目,做的是發(fā)票的分類,,分類的方法我首先采用的是模板匹配,,也就是從一類發(fā)票中摳出一些特征區(qū)域,以此作為模板,,自己設(shè)定閾值,,低于閾值就是算是跟該類發(fā)票匹配了,就可以 對(duì)其進(jìn)行分類,。在我的測(cè)試看來,,準(zhǔn)確率還可以,不過也隱藏這一個(gè)比較大的隱患就是,,一旦發(fā)票種類多了,,比如100種,那么檢測(cè)時(shí)間就會(huì)指數(shù)上升,,這是不可取的,。
|