模板匹配是在一幅影象中尋找乙個特定目標的方法之一。這種方法的原理非常簡單,遍歷影象中的每乙個可能的位置,比較各處與模板是否「相似」,當相似度足夠高時,就認為找到了我們的目標。
在 opencv 中,提供了相應的函式完成這個操作。
matchtemplate 函式:在模板和輸入影象之間尋找匹配,獲得匹配結果影象
minmaxloc 函式:在給定的矩陣中尋找最大和最小值,並給出它們的位置
在具體介紹這兩個函式之前呢,我們還要介紹乙個概念,就是如何來評價兩幅影象是否「相似」。
opencv 提供了 6 種計算兩幅影象相似度的方法。
差值平方和匹配 cv_tm_sqdiff
標準化差值平方和匹配 cv_tm_sqdiff_normed
相關匹配 cv_tm_ccorr
標準相關匹配 cv_tm_ccorr_normed
相關匹配 cv_tm_ccoeff
標準相關匹配 cv_tm_ccoeff_normed
下面就分別來介紹。首先,先給出幾個符號:
t(x,y)
用來表示我們的模板。i(x,y)
是我們的目標影象。 r(x,y)
是用來描述相似度的函式。
這類方法利用影象與模板各個畫素差值的平方和來進行匹配,最好匹配為 0。 匹配越差,匹配值越大。
r(x,y)=∑x′,y′(t(x′,y′)−i(x+x′,y+y′))2
這個方法其實和差值平方和演算法是類似的。只不過對影象和模板進行了標準化操作。
r(x,y)=∑x′,y′(t(x′,y′)−i(x+x′,y+y′))2∑x′,y′t(x′,y′)2∑x′,y′i(x+x′,y+y′)2‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√
這種標準化操作可以保證當模板和影象各個畫素的亮度都乘上了同乙個係數時,相關度不發生變化。
也就是說當 i(x,y)
和t(x,y)
變為k×i(x,y)
和k×t(x,y)
時,r(x,y)
不發生變化。
這類方法採用模板和影象的互相關計算作為相似度的度量方法,所以較大的數表示匹配程度較高,0標識最壞的匹配效果。
r(x,y)=∑x′,y′(t(x′,y′)×i(x+x′,y+y′))
這個方法和 標準化差值平方和匹配 類似,都是去除了亮度線性變化對相似度計算的影響。可以保證影象和模板同時變亮或變暗k倍時結果不變。
r(x,y)=∑x′,y′(t(x′,y′)×i(x+x′,y+y′))∑x′,y′t(x′,y′)2∑x′,y′i(x+x′,y+y′)2‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√
這種方法也叫做相關匹配,但是和上面的 cv_tm_ccorr 匹配方法還是有不通過的。簡單的說,這裡是把影象和模板都減去了各自的平均值,使得這兩幅影象都沒有直流分量。
t′(x,y)=t(x,y)−∑x′,y′t(x′,y′)w×hi′(x,y)=i(x,y)−∑x′,y′i(x′,y′)w×hr(x,y)=∑x′,y′(t′(x′,y′)×i′(x+x′,y+y′))
這是 opencv 支援的最複雜的一種相似度演算法。這裡的相關運算就是數理統計學科的相關係數計算方法。具體的說,就是在減去了各自的平均值之外,還要各自除以各自的方差。經過減去平均值和除以方差這麼兩步操作之後,無論是我們的待檢影象還是模板都被標準化了,這樣可以保證影象和模板分別改變光照亮不影響計算結果。計算出的相關係數被限制在了 -1 到 1 之間,1 表示完全相同,-1 表示兩幅影象的亮度正好相反,0 表示兩幅影象之間沒有線性關係。
t′(x,y)=t(x,y)−1w×h∑x′,y′t(x′,y′)∑x′,y′t(x′,y′)2‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√i′(x,y)=i(x,y)−1w×h∑x′,y′i(x′,y′)∑x′,y′i(x′,y′)2‾‾‾‾‾‾‾‾‾‾‾‾‾‾√r(x,y)=∑x′,y′(t′(x′,y′)×i′(x+x′,y+y′))
下面給個例子,我們的測試影象如下:
程式中會用到 opencv 的函式包括:
void matchtemplate( inputarray image, inputarray templ,
outputarray result, int method );
其中 result 是乙個矩陣,返回每乙個點匹配的結果。
void minmaxloc(inputarray src, cv_out double* minval,
cv_out double* maxval=0, cv_out point* minloc=0,
cv_out point* maxloc=0, inputarray mask=noarray());
這個函式可以在乙個矩陣中尋找最大點或最小點,並將位置返回回來。
下面是完整的測試程式。
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main(int argc, char *ar**)
輸出結果是這樣的。
其實上面的**還可以封裝一下。
double match(cv::mat image, cv::mat tepl, cv::point &point, int method)
}
利用這個封裝**,我們可以把所有的匹配方法都實驗一下。並且比較一下計算速度。
int main(int argc, char *ar**)
輸出結果如下:
cv_tm_sqdiff time elapsed: 734 ms
4cv_tm_sqdiff_normed time elapsed: 699 ms
1.43391e-08
cv_tm_ccorr time elapsed: 638 ms
2.78957e+08
cv_tm_ccorr_normed time elapsed: 710 ms
1cv_tm_ccoeff time elapsed: 721 ms
2.30675e+08
cv_tm_ccoeff_normed time elapsed: 759 ms
1
如果我們先將影象都轉換為灰度圖,那麼計算速度會快很多。
cv_tm_sqdiff time elapsed: 249 ms
12cv_tm_sqdiff_normed time elapsed: 246 ms
1.29052e-07
cv_tm_ccorr time elapsed: 208 ms
9.29857e+07
cv_tm_ccorr_normed time elapsed: 242 ms
1cv_tm_ccoeff time elapsed: 246 ms
7.68916e+07
cv_tm_ccoeff_normed time elapsed: 281 ms
1
基本縮短到了 1/3 。所以,如果可以用灰度圖來計算,就不要用彩色圖。
我們還可以去掉模板大小對匹配度的影響:
double match(cv::mat image, cv::mat tepl, cv::point &point, int method)
}
這時的結果如下:
cv_tm_sqdiff time elapsed: 705 ms
0.000609663
cv_tm_sqdiff_normed time elapsed: 682 ms
1.43391e-08
cv_tm_ccorr time elapsed: 615 ms
42517.5
cv_tm_ccorr_normed time elapsed: 698 ms
1cv_tm_ccoeff time elapsed: 703 ms
35158.5
cv_tm_ccoeff_normed time elapsed: 757 ms
1
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
模板匹配,就是在一幅影象中尋找另一幅模板影象最匹配 也就是最相似 的部分的技術。說的有點抽象,下面給個例子說明就很明白了。在上面這幅全明星照中,我們想找出姚明頭像的位置,並把它標記出來,可以做到嗎?可以,這就是模板匹配的要做的事情。其實模板匹配實現的思想也是很簡單很暴力的,就是拿著模板 姚明頭像 在...