標籤:opencv 長條圖
計算長條圖calcHist
長條圖是對資料集合的統計 ,並將統計結果分佈於一系列預定義的bins中。這裡的資料不僅僅指的是灰階值 ,統計資料可能是任何能有效描述映像的特徵。
假設有一個矩陣包含一張映像的資訊 (灰階值 0-255):
gray
既然已知數位範圍包含256個值, 我們可以將這個範圍分割成子領域(稱作 bins),如:
bins
然後再統計掉入每一個bin_{i}的像素數目。採用這一方法來統計上面的數字矩陣,我們可以得到( x軸表示 bin, y軸表示各個bin中的像素個數)。
hist1
長條圖可以統計的不僅僅是顏色灰階,它可以統計任何映像特徵(如梯度,方向等等)。
長條圖具體細節
dims: 需要統計的特徵的數目,在上例中,dims = 1因為我們僅僅統計了灰階值(灰階映像)
bins: 每個特徵空間子區段的數目,在上例中,bins = 16
range: 每個特徵空間的取值範圍,在上例中,range = [0,255]
OpenCV的長條圖計算
OpenCV提供了一個簡單的計算數組集(通常是映像或分割後的通道)的長條圖函數calcHist。支援高達32維的長條圖。
void calcHist(const Mat* arrays, // 映像源數組,同樣深度(CV_8U or CV_32F),同樣大小int narrays, // 圖片個數const int* channels, // 通道InputArray mask, // 掩碼映像OutputArray hist, // 返回的長條圖int dims, // 長條圖的維數const int* histSize, // 每一維上長條圖的個數const float** ranges, // 像素值的範圍bool uniform=true, bool accumulate=false );
說明:
channels - 用來計算長條圖的channels的數組
mask - 掩碼。如果mask不為空白,那麼它必須是一個8位(CV_8U)的數組,並且它的大小的和arrays[i]的大小相同,值為1的點將用來計算
dim - 長條圖的維數。必須為正,並且不大於CV_MAX_DIMS(當前的OpenCV版本中為32,即最大可以統計32維的長條圖)
histSize - 在每一維上長條圖的個數。簡單把長條圖看作一個一個的豎條的話,就是每一維上豎條的個數
ranges - 用來進行統計的範圍
反投影長條圖
反向投影是一種記錄給定映像中的像素點如何適應長條圖模型像素分布的方式。
簡單的講,所謂反向投影就是首先計算某一特徵的長條圖模型,然後使用模型去尋找映像中存在的該特徵。
void calcBackProject(const Mat* arrays, int narrays, const int* channels, InputArray hist, OutputArray backProject, const float** ranges, double scale=1, bool uniform=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
- 使用統計學的語言, BackProjection 中儲存的數值代表了測試映像中該像素屬於皮膚地區的機率。比如以為例, 亮起的地區是皮膚地區的機率更大(事實確實如此),而更暗的地區則表示更低的機率
閾值化
閾值是最簡單的映像分割的方法。
應用舉例:從一副映像中利用閾值分割出我們需要的物體部分(當然這裡的物體可以是一部分或者整體)。這樣的映像分割方法是基於映像中物體與背景之間的灰階差異,而且此分割屬於像素級的分割。
為了從一副映像中提取出我們需要的部分,應該用映像中的每一個像素點的灰階值與選取的閾值進行比較,並作出相應的判斷。(注意:閾值的選取依賴於具體的問題。即:物體在不同的映像中有可能會有不同的灰階值。)
一旦找到了需要分割的物體的像素點,我們可以對這些像素點設定一些特定的值來表示。(例如:可以將該物體的像素點的灰階值設定為:‘0’(黑色),其他的像素點的灰階值為:‘255’(白色);當然像素點的灰階值可以任意,但最好設定的兩種顏色對比較強,方便觀察結果)。
Threshold_Example閾值類型
Threshold Type 1
Threshold Type 2
Threshold Type 3
Threshold Type 4
Threshold Type 5閾值API
double threshold(InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType);
均值漂移(Mean Shift)演算法函數
該函數利用了迭代物體搜尋演算法,它要以一個物體的反射長條圖(back projection)和初始位置作為輸入。
搜尋視窗的重心向反射長條圖的質心(mass center)移動,該過程不斷的重複,直到達到了迭代的次數(criteria.maxCount),或者視窗中心小於一個閾值(criteria.epsilon)。
int meanShift(InputArray probImage, // Back projection of the object histogramRect& window, // Initial search windowTermCriteria criteria // Stop criteria for the iterative search algorithm.);
Camshift演算法函數
該函數首先利用meanShift()函數找到物體的中心,然後調整視窗的大小並找到最優的旋轉角度。該函數返回一個rotated rectangle資料結構(包含物體的位置,大小和旋轉角度)。下一次搜尋視窗的位置可以通過RotatedRect::boundingRect()得到。
RotatedRect CamShift(InputArray probImage, // Back projection of the object histogramRect& window, // Initial search windowTermCriteria criteria // Stop criteria for the underlying meanShift());
TermCriteria模板類
該類是作為迭代演算法的終止條件使用的,其建構函式需要三個參數:一個是類型,第二個參數為迭代的最大次數,最後一個是特定的閾值。
TermCriteria(int type, int maxCount, double epsilon);
類型有CV_TERMCRIT_ITER、CV_TERMCRIT_EPS、CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,分別代表著迭代終止條件為達到最大迭代次數終止,迭代到閾值終止,或者兩者都作為迭代終止條件。
參考資料
OpenCV Histograms API文檔
長條圖之calcHist使用
長條圖之calcHist使用(補)
OpenCV 教程 imgproc模組
反向投影
閾值操作
轉載請註明作者Jason Ding及其出處
Github首頁(http://jasonding1354.github.io/)
CSDN部落格(http://blog.csdn.net/jasonding1354)
簡書首頁(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
【電腦視覺】OpenCV中長條圖處理函數簡述