網(wǎng)站內(nèi)容管理系統(tǒng)cms免費網(wǎng)站推廣方式
在OpenCV中,模板匹配是一種在較大圖像中查找特定模板圖像位置的技術(shù)。OpenCV提供了多種模板匹配方法,通過cv2.matchTemplate
函數(shù)實現(xiàn),該函數(shù)支持的匹配方式主要有以下6種,下面詳細(xì)介紹每種方法的原理、特點和適用場景。
1. cv2.TM_SQDIFF
(平方差匹配法)
- 原理:計算模板與圖像中每個可能位置的像素值平方差的總和。匹配結(jié)果值越小,表示匹配程度越高。
- 特點:對光照變化比較敏感,因為它直接比較像素值的差異。
- 公式: R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ? I ( x + x ′ , y + y ′ ) ) 2 R(x,y)=\sum _{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,其中 T T T 是模板圖像, I I I 是輸入圖像, R R R 是匹配結(jié)果圖像。
- 適用場景:適用于模板和目標(biāo)圖像的光照條件較為一致的情況。
2. cv2.TM_SQDIFF_NORMED
(歸一化平方差匹配法)
- 原理:是
cv2.TM_SQDIFF
的歸一化版本,將平方差結(jié)果歸一化到 [0, 1] 范圍內(nèi)。匹配結(jié)果值越接近 0,表示匹配程度越高。 - 特點:對光照變化有一定的魯棒性,因為歸一化操作減少了不同圖像之間像素值范圍差異的影響。
- 適用場景:當(dāng)模板和目標(biāo)圖像的光照有一定差異,但差異不是特別大時適用。
3. cv2.TM_CCORR
(相關(guān)性匹配法)
- 原理:計算模板與圖像中每個可能位置的像素值相關(guān)性。匹配結(jié)果值越大,表示匹配程度越高。
- 特點:對光照變化也比較敏感,因為它直接依賴于像素值的相關(guān)性。
- 公式: R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ? I ( x + x ′ , y + y ′ ) ) R(x,y)=\sum _{x',y'} (T(x',y') \cdot I(x + x',y + y')) R(x,y)=∑x′,y′?(T(x′,y′)?I(x+x′,y+y′))
- 適用場景:適用于模板和目標(biāo)圖像的光照條件較為一致,且模板和目標(biāo)之間的亮度模式相似的情況。
4. cv2.TM_CCORR_NORMED
(歸一化相關(guān)性匹配法)
- 原理:是
cv2.TM_CCORR
的歸一化版本,將相關(guān)性結(jié)果歸一化到 [0, 1] 范圍內(nèi)。匹配結(jié)果值越接近 1,表示匹配程度越高。 - 特點:對光照變化有較好的魯棒性,因為歸一化操作消除了不同圖像之間像素值范圍差異的影響。
- 適用場景:在光照條件不穩(wěn)定的情況下,是一種比較常用的匹配方法。
5. cv2.TM_CCOEFF
(相關(guān)系數(shù)匹配法)
- 原理:計算模板與圖像中每個可能位置的像素值相關(guān)系數(shù)。匹配結(jié)果值越大,表示匹配程度越高。相關(guān)系數(shù)衡量的是兩個信號之間的線性相關(guān)性。
- 特點:對光照變化有一定的魯棒性,因為它考慮了模板和圖像的均值。
- 適用場景:適用于模板和目標(biāo)圖像的光照有一定差異,但整體結(jié)構(gòu)相似的情況。
6. cv2.TM_CCOEFF_NORMED
(歸一化相關(guān)系數(shù)匹配法)
- 原理:是
cv2.TM_CCOEFF
的歸一化版本,將相關(guān)系數(shù)結(jié)果歸一化到 [-1, 1] 范圍內(nèi)。匹配結(jié)果值越接近 1,表示匹配程度越高。 - 特點:對光照變化具有較強的魯棒性,是一種比較穩(wěn)定的匹配方法。
- 適用場景:在各種光照條件下都能有較好的表現(xiàn),是最常用的模板匹配方法之一。
代碼示例
import cv2
import numpy as np# 讀取圖像和模板
img = cv2.imread('image.jpg', 0)
template = cv2.imread('template.jpg', 0)
h, w = template.shape[:2]# 定義匹配方法
methods = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']for meth in methods:img2 = img.copy()method = eval(meth)# 執(zhí)行模板匹配res = cv2.matchTemplate(img2, template, method)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)# 根據(jù)不同的匹配方法確定最佳匹配位置if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:top_left = min_locelse:top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 在圖像上繪制矩形框標(biāo)記匹配位置cv2.rectangle(img2, top_left, bottom_right, 255, 2)# 顯示結(jié)果cv2.imshow(meth, img2)cv2.waitKey(0)
cv2.destroyAllWindows()
這個示例代碼展示了如何使用不同的模板匹配方法在圖像中查找模板的位置,并在圖像上繪制矩形框標(biāo)記匹配結(jié)果。你可以根據(jù)實際需求選擇合適的匹配方法。
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;// 定義模板匹配方法名稱和對應(yīng)的枚舉值
const char* method_names[] = { "TM_SQDIFF", "TM_SQDIFF_NORMED", "TM_CCORR","TM_CCORR_NORMED", "TM_CCOEFF", "TM_CCOEFF_NORMED" };
const int methods[] = { TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR,TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED };int main()
{// 讀取圖像和模板Mat img = imread("image.jpg", IMREAD_GRAYSCALE);Mat template_img = imread("template.jpg", IMREAD_GRAYSCALE);if (img.empty() || template_img.empty()){cout << "Could not open or find the image or template" << endl;return -1;}int h = template_img.rows;int w = template_img.cols;// 遍歷不同的匹配方法for (int i = 0; i < 6; i++){Mat img2 = img.clone();Mat result;// 執(zhí)行模板匹配matchTemplate(img2, template_img, result, methods[i]);double minVal, maxVal;Point minLoc, maxLoc;// 查找匹配結(jié)果中的最小值和最大值以及它們的位置minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);Point topLeft;bool isMatch = false;// 根據(jù)不同的匹配方法確定最佳匹配位置,并判斷是否匹配成功if (methods[i] == TM_SQDIFF || methods[i] == TM_SQDIFF_NORMED){topLeft = minLoc;if (methods[i] == TM_SQDIFF_NORMED && minVal < 0.1) // 可調(diào)整閾值{isMatch = true;}}else if (methods[i] == TM_CCORR_NORMED && maxVal > 0.8) // 可調(diào)整閾值{topLeft = maxLoc;isMatch = true;}else if (methods[i] == TM_CCOEFF_NORMED && maxVal > 0.8) // 可調(diào)整閾值{topLeft = maxLoc;isMatch = true;}if (isMatch){Point bottomRight(topLeft.x + w, topLeft.y + h);// 在圖像上繪制矩形框標(biāo)記匹配位置rectangle(img2, topLeft, bottomRight, Scalar(255), 2);}else{cout << "No match found using " << method_names[i] << endl;}// 顯示結(jié)果imshow(method_names[i], img2);}waitKey(0);destroyAllWindows();return 0;
}