OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
模板匹配

上一個教程: 反向投影
下一個教程: 在影像中查詢輪廓

原始作者Ana Huamán
相容性OpenCV >= 3.0

目標

在本教程中,您將學習如何

  • 使用OpenCV函式 matchTemplate() 搜尋影像塊與輸入影像之間的匹配項
  • 使用OpenCV函式 minMaxLoc() 查詢給定陣列中的最大值和最小值(及其位置)。

理論

什麼是模板匹配?

模板匹配是一種在影像中查詢與模板影像(塊)匹配(相似)區域的技術。

雖然影像塊必須是矩形,但可能並非所有矩形都相關。在這種情況下,可以使用掩膜來隔離影像塊中應用於查詢匹配的部分。

它是如何工作的?

  • 我們需要兩個主要組成部分

    1. 源影像 (I): 我們期望在其中找到模板影像匹配項的影像
    2. 模板影像 (T): 將與源影像進行比較的影像塊

    我們的目標是檢測最高的匹配區域

  • 為了識別匹配區域,我們必須透過滑動來將模板影像與源影像進行比較
  • 透過滑動,我們指的是一次移動影像塊一個畫素(從左到右,從上到下)。在每個位置,都會計算一個度量,以表示該位置的匹配程度是“好”還是“壞”(或影像塊與源影像特定區域的相似程度)。
  • 對於 TI 上方的每個位置,您將度量儲存結果矩陣 R 中。R 中的每個位置 \((x,y)\) 都包含匹配度量

上圖是使用度量 TM_CCORR_NORMED 滑動影像塊的結果 R。最亮的位置表示最高的匹配。如您所見,紅色圓圈標記的位置可能是值最高的位置,因此該位置(由該點作為角點以及寬度和高度等於影像塊影像形成的矩形)被視為匹配。

  • 實際上,我們使用函式 minMaxLoc()R 矩陣中定位最高值(或最低值,取決於匹配方法的型別)

掩膜如何工作?

  • 如果匹配需要掩膜,則需要三個元件
    1. 源影像 (I): 我們期望在其中找到模板影像匹配項的影像
    2. 模板影像 (T): 將與源影像進行比較的影像塊
    3. 掩膜影像 (M): 掩膜,一個掩蓋模板的灰度影像
  • 目前只有兩種匹配方法接受掩膜:TM_SQDIFF 和 TM_CCORR_NORMED(有關OpenCV中所有可用匹配方法的解釋,請參見下文)。
  • 掩膜必須與模板具有相同的尺寸
  • 掩膜應具有CV_8U或CV_32F深度,並且與模板影像具有相同的通道數。在CV_8U情況下,掩膜值被視為二進位制,即零和非零。在CV_32F情況下,值應在[0..1]範圍內,模板畫素將乘以相應的掩膜畫素值。由於樣本中的輸入影像為CV_8UC3型別,因此掩膜也以彩色影像讀取。

OpenCV中有哪些可用的匹配方法?

好問題。OpenCV在函式 matchTemplate() 中實現了模板匹配。可用的方法有6種

  1. 方法=TM_SQDIFF

    \[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\]

  2. 方法=TM_SQDIFF_NORMED

    \[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\]

  3. 方法=TM_CCORR

    \[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\]

  4. 方法=TM_CCORR_NORMED

    \[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\]

  5. 方法=TM_CCOEFF

    \[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\]

    其中

    \[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\]

  6. 方法=TM_CCOEFF_NORMED

    \[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\]

程式碼

  • 此程式的作用是什麼?
    • 載入輸入影像、影像塊(模板)以及可選的掩膜
    • 使用OpenCV函式 matchTemplate() 執行模板匹配過程,使用前面描述的6種匹配方法中的任何一種。使用者可以透過在軌跡條中選擇來選擇方法。如果提供了掩膜,它將僅用於支援掩膜的方法
    • 標準化匹配過程的輸出
    • 定位匹配機率較高的位置
    • 在最高匹配區域周圍繪製一個矩形

解釋

  • 宣告一些全域性變數,例如影像、模板和結果矩陣,以及匹配方法和視窗名稱

  • 載入源影像、模板,以及可選地,如果匹配方法支援,則載入掩膜

  • 建立軌跡條以輸入要使用的匹配方法。檢測到更改時,將呼叫回撥函式。

  • 讓我們看看回調函式。首先,它複製了源影像

  • 執行模板匹配操作。引數自然是輸入影像 I、模板 T、結果 R 和匹配方法(由軌跡條給出),以及可選的掩膜影像 M

  • 我們標準化結果

  • 我們使用 minMaxLoc() 定位結果矩陣 R 中的最小值和最大值。

  • 對於前兩種方法(TM_SQDIFF 和 MT_SQDIFF_NORMED),最佳匹配是最低值。對於所有其他方法,值越高表示匹配越好。因此,我們將相應的值儲存在 matchLoc 變數中

  • 顯示源影像和結果矩陣。在可能出現最高匹配的區域周圍繪製一個矩形

結果

  1. 使用如下輸入影像測試我們的程式

和模板影像

  1. 生成以下結果矩陣(第一行是標準方法SQDIFF、CCORR和CCOEFF,第二行是其歸一化版本)。在第一列中,越暗表示匹配越好,對於其他兩列,位置越亮表示匹配越高。

  1. 右側的匹配項如下所示(右側男子的臉部周圍有黑色矩形)。請注意,CCORR和CCDEFF給出了錯誤的最佳匹配,但其歸一化版本是正確的,這可能是由於我們只考慮“最高匹配”而不是其他可能的較高匹配。