修改者:madturtle------對於王先生的版本進行了修改,因為有些地方不對。
模板匹配的工作方式
模板匹配的工作方式跟直方圖的反向投影基本一樣,大致過程是這樣的:通過在輸入影象上滑**像塊對實際的影象塊和輸入影象進行匹配。
假設我們有一張100x100的輸入影象,有一張10x10的模板影象,查詢的過程是這樣的:
(1)從輸入影象的左上角(0,0)開始,切割一塊(0,0)至(10,10)的臨時影象;(改者注:其實每次匹配都是在模板的中心點對應的位置來給畫素賦值,即第一次比較應該是將模板的(temp.width/2,temp.height/2)中心點開始的1/4面積同輸入影象進行比較,匹配得到的結果c儲存到模板中心點所在畫素值中,具體參照《learning opencv》,所以最終用來保留匹配結果的影象大小應該是size = (images->width - patch_size.x + 1,images->height - patch_size.y + 1))
(2)用臨時影象和模板影象進行對比,對比結果記為c;
(3)對比結果c,就是結果影象(0,0)處的畫素值;
(4)切割輸入影象從(0,1)至(10,11)的臨時影象,對比,並記錄到結果影象;
(5)重複(1)~(4)步直到輸入影象的右下角。
大家可以看到,直方圖反向投影對比的是直方圖,而模板匹配對比的是影象的畫素值;模板匹配比直方圖反向投影速度要快一些,但是我個人認為直方圖反向投影的魯棒性會更好。
模板匹配的匹配方式
在opencv和emgucv中支援以下6種對比方式:
cv_tm_sqdiff 平方差匹配法:該方法採用平方差來進行匹配;最好的匹配值為0;匹配越差,匹配值越大。
cv_tm_ccorr 相關匹配法:該方法採用乘法操作;數值越大表明匹配程度越好。
cv_tm_ccoeff 相關係數匹配法:1表示完美的匹配;-1表示最差的匹配。
cv_tm_sqdiff_normed 歸一化平方差匹配法
cv_tm_ccorr_normed 歸一化相關匹配法
cv_tm_ccoeff_normed 歸一化相關係數匹配法
根據我的測試結果來看,上述幾種匹配方式需要的計算時間比較接近(跟《學習opencv》書上說的不同),我們可以選擇乙個能適應場景的匹配方式。
模板匹配的示例**
下面是模板匹配的c#版本**:
//模板匹配顯示結果影象模板匹配和直方圖反向投影生成的結果影象都是32位浮點型單通道影象。如果用c/c++,可以很方便的用opencv中的cvshowimage函式來顯示;如果用.net,因為emgucv中將32位浮點影象轉換成8位位圖的方法有些小問題,我們要自己編寫一段轉換的**,然後再顯示。private void btncalc_click(object sender, eventargs e)
//色彩空間
string colorspace = (string)cmbcolorspace.selecteditem;
iimage imageinput2, imagetemplate2;
if (colorspace == "gray")
else if (colorspace == "hsv")
else
//匹配方式陣列
tm_type tmtypes = new tm_type ;
//輸出影象(匹配結果)
image imageresults = new image[tmtypes.length];
//依次執行每種匹配,並歸一化結果
int i = 0;
double totaltime = 0d; //總共用時
double time; //每種匹配的用時
stopwatch sw = new stopwatch();
txtresult.text += string.format("開始執行匹配(色彩空間:,縮放因子:)/r/n", colorspace, scale);
foreach (tm_type tmtype in tmtypes)
,用時:毫秒,最匹配的點:(,),最匹配的值:/r/n", tmtype, time, bestpoint.x, bestpoint.y, bestvalue);
}
txtresult.text += string.format("匹配結束,共用時:毫秒/r/n", totaltime);
//顯示結果影象
pbresultsqdiff.image = imageconverter.imagesingletobitmap(imageresults[0]);
pbresultsqdiffnormalized.image = imageconverter.imagesingletobitmap(imageresults[1]);
pbresultccorr.image = imageconverter.imagesingletobitmap(imageresults[2]);
pbresultccorrnormalized.image = imageconverter.imagesingletobitmap(imageresults[3]);
pbresultccoeff.image = imageconverter.imagesingletobitmap(imageresults[4]);
pbresultccoeffnormalized.image = imageconverter.imagesingletobitmap(imageresults[5]);
//釋放資源
imageinput.dispose();
imagetemplate.dispose();
imageinput2.dispose();
imagetemplate2.dispose();
foreach (imageimageresult in imageresults)
imageresult.dispose();
}
//找到最匹配的點,以及該點的值
private void findbestmatchpointandvalue(imageimage, tm_type tmtype, out double bestvalue, out point bestpoint)
else
}
////// 將任意浮點型影象轉換成byte影象;
/// 本轉換函式對浮點型影象的具體畫素值沒有要求,自動將值縮放到0~255之間。
///
/// 影象的色彩空間
/// 浮點型影象
/// 返回byte型影象
public static imageimagesingletobyte(imagesource)
where tcolor : struct, icolor
//得到縮放比率和偏移量
double scale = 1.0, shift = 0.0;
scale = (max == min) ? 0.0 : 255.0 / (max - min);
shift = (scale == 0) ? min : -min * scale;
//縮放影象,並浮點影象縮放到256級的灰度
cvinvoke.cvconvertscaleabs(source.ptr, dest.ptr, scale, shift);
return dest;
}
///
/// 將任意浮點型影象轉換成每通道8位的bitmap;
/// 本轉換函式對浮點型影象的具體畫素值沒有要求,自動將值縮放到0~255之間。
///
/// 影象的色彩空間
/// 浮點型影象
/// 返回每通道8位的bitmap
左上是輸入影象,左中是模板影象,右邊是各種匹配方式的結果(相關匹配的結果明顯不正確)
模板匹配和直方圖反向投影的效率
總的來說,模板匹配和直方圖反向投影的效率都不高。在我的機器上,在1136*852大小的輸入影象上匹配104*132的大小的模板影象(都是單通道灰度影象),大約需要700毫秒;而直方圖反向投影大約需要75000毫秒(1.25分鐘)。看來還需要繼續學習,尋找更好的處理方法。
另一方面,通過搜尋opencv的源**,發現opencv基本上沒有使用平行計算。如果學習完之後,還有時間和熱情,我準備嘗試優化下opencv的平行計算;如果.net 4.0正式版推出了,也可以選擇在這一方面做點優化。
OpenCV模板匹配
include include opencv2 opencv.hpp using namespace std using namespace cv int main int argc,char argv load reference image img imread argv 1 always ch...
opencv模板匹配
模板匹配是一種用於在源影象s中尋找定位給定目標影象t 即模板影象 的技術。其原理很簡單,就是通過一些相似度準則來衡量兩個影象塊之間的相似度similarity s,t 2.用途 模板匹配方法常用於一些平面影象處理中,例如印刷中的數字 工業零器件等小尺寸目標影象識別分類。3.方法 模板匹配中,源影象和...
模板匹配opencv
模板匹配,就是在一幅影象中尋找另一幅模板影象最匹配 也就是最相似 的部分的技術。說的有點抽象,下面給個例子說明就很明白了。在上面這幅全明星照中,我們想找出姚明頭像的位置,並把它標記出來,可以做到嗎?可以,這就是模板匹配的要做的事情。其實模板匹配實現的思想也是很簡單很暴力的,就是拿著模板 姚明頭像 在...