OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
反向投影

上一個教程: 直方圖比較
下一個教程: 模板匹配

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

目標

在本教程中,您將學習

理論

什麼是反向投影?

  • 反向投影是一種記錄給定影像的畫素與直方圖模型中畫素分佈匹配程度的方法。
  • 簡單來說:對於反向投影,你計算一個特徵的直方圖模型,然後用它在影像中查詢這個特徵。
  • 應用示例:如果你有一個膚色直方圖(比如,一個色相-飽和度直方圖),那麼你可以用它在影像中查詢膚色區域。

它是如何工作的?

  • 我們以皮膚為例進行解釋。
  • 假設你已經根據下圖獲取了一個膚色直方圖(色相-飽和度)。旁邊的直方圖將作為我們的模型直方圖(我們知道它代表膚色的一個樣本)。你應用了蒙版來只捕獲皮膚區域的直方圖:

  • 現在,讓我們想象你得到另一張手部影像(測試影像),如下圖所示:(及其相應的直方圖):

  • 我們要做的是使用我們的模型直方圖(我們知道它代表膚色)來檢測測試影像中的皮膚區域。以下是步驟:
    1. 對於測試影像中的每個畫素(即 \(p(i,j)\)),收集資料並找到該畫素對應的直方圖bin位置(即 \(( h_{i,j}, s_{i,j} )\))。
    2. 在對應的bin(\(( h_{i,j}, s_{i,j} )\))中查詢模型直方圖,並讀取bin值。
    3. 將此bin值儲存到新影像(反向投影)中。另外,你可能需要先對模型直方圖進行歸一化,以便測試影像的輸出對你可見。
    4. 應用上述步驟,我們得到測試影像的以下反向投影影像:
  1. 從統計學角度看,儲存在反向投影中的值表示測試影像中畫素屬於皮膚區域的機率,這是基於我們使用的模型直方圖。例如,在我們的測試影像中,較亮的區域更有可能是皮膚區域(實際也確實如此),而較暗的區域機率較低(請注意,這些“暗”區域屬於有陰影的表面,這反過來會影響檢測)。

程式碼

  • 此程式的作用是什麼?
    • 載入影像
    • 將原始影像轉換為HSV格式,並僅分離出色相通道用於直方圖(使用OpenCV函式 cv::mixChannels
    • 允許使用者輸入用於直方圖計算的bin數量。
    • 計算直方圖(如果bin改變則更新)和同一影像的反向投影。
    • 在視窗中顯示反向投影和直方圖。

解釋

  • 讀取輸入影像

  • 將其轉換為HSV格式

  • 對於本教程,我們將僅使用色相值來構建我們的一維直方圖(如果你想使用更標準的H-S直方圖,其效果更好,請檢視上面連結中的更高階程式碼)。

  • 如你所見,我們使用函式 cv::mixChannels 從hsv影像中只獲取通道0(色相)。它接受以下引數:
    • &hsv: 要從中複製通道的源陣列
    • 1: 源陣列的數量
    • &hue: 複製通道的目標陣列
    • 1: 目標陣列的數量
    • ch[] = {0,0}: 指示通道如何複製的索引對陣列。在這種情況下,&hsv的色相(0)通道被複制到&hue的0通道(單通道)。
    • 1: 索引對的數量
  • 為使用者建立一個軌跡條以輸入bin值。軌跡條上的任何更改都將呼叫 Hist_and_Backproj 回撥函式。

  • 顯示影像並等待使用者退出程式

  • Hist_and_Backproj 函式: 初始化 cv::calcHist 所需的引數。bin的數量來自軌跡條。

  • 計算直方圖並將其歸一化到 \([0,255]\) 範圍。

  • 透過呼叫函式 cv::calcBackProject 獲取同一影像的反向投影。

  • 所有引數都是已知的(與計算直方圖時使用的相同),我們只添加了backproj矩陣,它將儲存源影像(&hue)的反向投影。
  • 顯示backproj

  • 繪製圖像的一維色相直方圖

結果

以下是使用示例影像(你猜怎麼著?另一隻手)的輸出。你可以調整bin值,你會觀察到它如何影響結果: