OpenCV中直方圖處理函數簡述



轉自 機器人2025

作者Jason Ding

計算直方圖calcHist

直方圖是對數據集合的統計 ,並將統計結果分佈於一系列預定義的bins中。這裏的數據不僅僅指的是灰度值 ,統計數據可能是任何能有效描述圖像的特徵。

假設有一個矩陣包含一張圖像的信息 (灰度值 0-255):

既然已知數字的範圍包含256個值, 我們可以將這個範圍分割成子區域(稱作 bins),如:

然後再統計掉入每一個bin_{i}的像素數目。採用這一方法來統計上面的數字矩陣,我們可以得到下圖( x軸表示 bin, y軸表示各個bin中的像素個數)。

直方圖可以統計的不僅僅是顏色灰度,它可以統計任何圖像特徵(如梯度,方向等等)。

直方圖具體細節

dims: 需要統計的特徵的數目,在上例中,dims = 1因爲我們僅僅統計了灰度值(灰度圖像)

bins: 每個特徵空間子區段的數目,在上例中,bins = 16

range: 每個特徵空間的取值範圍,在上例中,range = [0,255]

OpenCV的直方圖計算

OpenCV提供了一個簡單的計算數組集(通常是圖像或分割後的通道)的直方圖函數calcHist。支持高達32維的直方圖。

1

2

3

4

5

6

7

8

9

10

11

voidcalcHist(

constMat* arrays, // 圖像源數組,同樣深度(CV_8U or CV_32F),同樣大小

intnarrays, // 圖片個數

constint* channels, // 通道

InputArray mask, // 掩碼圖像

OutputArray hist, // 返回的直方圖

intdims, // 直方圖的維數

constint* histSize, // 每一維上直方圖的個數

constfloat** ranges, // 像素值的範圍

booluniform=true,

boolaccumulate=false);

說明:

channels - 用來計算直方圖的channels的數組

mask - 掩碼。如果mask不爲空,那麼它必須是一個8位(CV_8U)的數組,並且它的大小的和arrays[i]的大小相同,值爲1的點將用來計算

dim - 直方圖的維數。必須爲正,並且不大於CV_MAX_DIMS(當前的OpenCV版本中爲32,即最大可以統計32維的直方圖)

histSize - 在每一維上直方圖的個數。簡單把直方圖看作一個一個的豎條的話,就是每一維上豎條的個數

ranges - 用來進行統計的範圍

反投影直方圖

反向投影是一種記錄給定圖像中的像素點如何適應直方圖模型像素分佈的方式。

簡單的講,所謂反向投影就是首先計算某一特徵的直方圖模型,然後使用模型去尋找圖像中存在的該特徵。

1

2

3

4

5

6

7

8

voidcalcBackProject(

constMat* arrays,

intnarrays,

constint* channels,

InputArray hist,

OutputArray backProject,

constfloat** ranges,

doublescale=1booluniform=true);

hist - 輸入直方圖

backProject - 反投影向量,這是一個單通道的向量,和arrays[0]具有相同的大小和深度

下面使用膚色直方圖爲例來解釋反向投影的工作原理:

使用模型直方圖(代表手掌的皮膚色調)來檢測測試圖像中的皮膚區域,

  • 對測試圖像中的每個像素 ( p(i,j) ),獲取色調數據並找到該色調( h(i,j), s(i,j) )在直方圖中的bin的位置

  • 查詢 模型直方圖 中對應的bin( h(i,j), s(i,j) )並讀取該bin的數值

  • 將此數值儲存在新的圖像中(BackProjection)。 你也可以先歸一化 模型直方圖 ,這樣測試圖像的輸出就可以在屏幕顯示了

  • 通過對測試圖像中的每個像素採用以上步驟, 得到 BackProjection 結果圖

  • 使用統計學的語言, BackProjection 中儲存的數值代表了測試圖像中該像素屬於皮膚區域的概率。比如以上圖爲例, 亮起的區域是皮膚區域的概率更大(事實確實如此),而更暗的區域則表示更低的概率

閾值化

閾值是最簡單的圖像分割的方法。

應用舉例:從一副圖像中利用閾值分割出我們需要的物體部分(當然這裏的物體可以是一部分或者整體)。這樣的圖像分割方法是基於圖像中物體與背景之間的灰度差異,而且此分割屬於像素級的分割。

爲了從一副圖像中提取出我們需要的部分,應該用圖像中的每一個像素點的灰度值與選取的閾值進行比較,並作出相應的判斷。(注意:閾值的選取依賴於具體的問題。即:物體在不同的圖像中有可能會有不同的灰度值。)

一旦找到了需要分割的物體的像素點,我們可以對這些像素點設定一些特定的值來表示。(例如:可以將該物體的像素點的灰度值設定爲:‘0’(黑色),其他的像素點的灰度值爲:‘255’(白色);當然像素點的灰度值可以任意,但最好設定的兩種顏色對比度較強,方便觀察結果)。

閾值類型

閾值API

1

2

3

4

5

6

doublethreshold(

InputArray src,

OutputArray dst,

doublethresh,

doublemaxVal,

intthresholdType);

均值漂移(Mean Shift)算法函數

該函數利用了迭代物體搜索算法,它要以一個物體的反射直方圖(back projection)和初始位置作爲輸入。

搜索窗口的重心向反射直方圖的質心(mass center)移動,該過程不斷的重複,直到達到了迭代的次數(criteria.maxCount),或者窗口中心小於一個閾值(criteria.epsilon)。

1

2

3

4

5

intmeanShift(

InputArray probImage, // Back projection of the object histogram

Rect& window, // Initial search window

TermCriteria criteria // Stop criteria for the iterative search algorithm.

);

Camshift算法函數

該函數首先利用meanShift()函數找到物體的中心,然後調整窗口的大小並找到最優的旋轉角度。該函數返回一個rotated rectangle數據結構(包含物體的位置,大小和旋轉角度)。下一次搜索窗口的位置可以通過RotatedRect::boundingRect()得到。

1

2

3

4

5

RotatedRect CamShift(

InputArray probImage, // Back projection of the object histogram

Rect& window, // Initial search window

TermCriteria criteria // Stop criteria for the underlying meanShift()

);

TermCriteria模板類

該類是作爲迭代算法的終止條件使用的,其構造函數需要三個參數:一個是類型,第二個參數爲迭代的最大次數,最後一個是特定的閾值。

1

TermCriteria(inttype, intmaxCount, doubleepsilon);

類型有CV_TERMCRIT_ITER、CV_TERMCRIT_EPS、CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,分別代表着迭代終止條件爲達到最大迭代次數終止,迭代到閾值終止,或者兩者都作爲迭代終止條件。

參考資料

機器學習技法課程,林軒田,臺灣大學

轉載請註明作者Jason Ding及其出處


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章