[Object Tracking] MeanShift


使用Opencv中均值漂移meanShift跟蹤移動目標

Opencv均值漂移pyrMeanShiftFiltering彩色圖像分割流程剖析

Opencv目標跟蹤—CamShift算法

 


 

MeanShift - cv.MeanShift

Mean Shift均值漂移算法是無參密度估計理論的一種,無參密度估計不需要事先知道對象的任何先驗知識,完全依靠訓練數據進行估計,並且可以用於任意形狀的密度估計,在某一連續點處的密度函數值可由該點鄰域中的若干樣本點估計得出。

Mean shift將特征空間視為先驗概率密度函數,那么輸入就被視為是一組滿足某種概率分布的樣本點,這樣一來,特征空間中數據最密集的地方,對應於概率密度最大的地方,且概率密度的質心就可以被視為是概率密度函數的局部最優值,也就是要求的聚類中心。對於每一個樣本點,計算以它為中心的某個范圍內所有樣本點的均值,作為新的中心(這就是shift既中心的移動),移動直至收斂。這樣每一輪迭代,中心都會向數據更密集的地方移動,直到最后穩定收斂到樣本的“質心”

【以下這個描述容易理解】

可以直觀理解為:在樣本空間中,任選一個點,然后以這個點為圓心,划定一個圓形的區域。在此區域內的所有點以圓心為起點,產生N個向量,然后把這些向量都相加,再以向量的終點為圓心,划定同樣半徑的圓形區域,執行同樣操作,如此迭代,直到收斂。

 

python_opencv_version_demo2

python opencv version demo

Finds an object on a back projection image. C++: int meanShift(InputArray probImage, Rect& window, TermCriteria criteria)
Python: cv2.meanShift(probImage, window, criteria) → retval, window
C: int cvMeanShift(const CvArr
* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp)
Python: cv.MeanShift(prob_image, window, criteria) → comp
Parameters: probImage – Back projection of the object histogram. See calcBackProject()
for details. window – Initial search window. criteria – Stop criteria for the iterative search algorithm.
Returns: Number of iterations CAMSHIFT took to converge.

 

 

以下程序實現了在一個視頻中跟蹤移動目標,大致步驟如下:

 

    • 1. 在視頻播放過程中,通過鼠標框選需要跟蹤的目標target
    • 2. 計算目標圖像target的HSV中H、S分量的直方圖targetHist
    • 3. 用targetHist反向投影計算原圖像中的目標的概率分布
    • 4. 用meanShift通過迭代獲取目標的新的位置window
    • 5. 以新的位置window執行步驟2

 

targetHist反向投影 - 解釋

  • 假設你已經通過下圖得到一個膚色直方圖(Hue-Saturation), 旁邊的直方圖就是 模型直方圖 ( 代表手掌的皮膚色調).你可以通過掩碼操作來抓取手掌所在區域的直方圖:

    T0

    T1

  • 下圖是另一張手掌圖(測試圖像) 以及對應的整張圖像的直方圖:

    T2

    T3

  • 我們要做的就是使用 模型直方圖 (代表手掌的皮膚色調) 來檢測測試圖像中的皮膚區域。以下是檢測的步驟

    1. 對測試圖像中的每個像素 ( p(i,j) ),獲取色調數據並找到該色調( ( h_{i,j}, s_{i,j} ) )在直方圖中的bin的位置。

    2. 查詢 模型直方圖 中對應的bin - ( h_{i,j}, s_{i,j} ) - 並讀取該bin的數值。

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

    4. 通過對測試圖像中的每個像素采用以上步驟, 我們得到了下面的 BackProjection 結果圖:

      ../../../../../_images/Back_Projection_Theory4.jpg
    5. 使用統計學的語言, BackProjection 中儲存的數值代表了測試圖像中該像素屬於皮膚區域的 概率 。比如以上圖為例, 亮起的區域是皮膚區域的概率更大(事實確實如此),而更暗的區域則表示更低的概率(注意手掌內部和邊緣的陰影影響了檢測的精度)。

 

膚色直方圖(Hue-Saturation)的一個簡單的例子:

 


 

meanShfit均值漂移算法 - pyrMeanShiftFiltering

【注意,這里本質是一種 fitering

meanShfit均值漂移算法是一種通用的聚類算法,它的基本原理是:對於給定的一定數量樣本,任選其中一個樣本,以該樣本為中心點划定一個圓形區域,求取該圓形區域內樣本的質心,即密度最大處的點,再以該點為中心繼續執行上述迭代過程,直至最終收斂。

可以利用均值偏移算法的這個特性,實現彩色圖像分割,Opencv中對應的函數是pyrMeanShiftFiltering。

這個函數嚴格來說並不是圖像的分割,而是圖像在色彩層面的平滑濾波,它可以中和色彩分布相近的顏色,平滑色彩細節,侵蝕掉面積較小的顏色區域,所以在Opencv中它的后綴是濾波“Filter”,而不是分割“segment”。先列一下這個函數,再說一下它“分割”彩色圖像的實現過程。

 

Performs initial step of meanshift segmentation of an image. C++: void pyrMeanShiftFiltering(InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) ) Python: cv2.pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]]) → dst C: void cvPyrMeanShiftFiltering(const CvArr* src, CvArr* dst, double sp, double sr, int max_level=1, CvTermCriteria termcrit=cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,5,1))

第一個參數src,輸入圖像,8位,三通道的彩色圖像,並不要求必須是RGB格式,HSV、YUV等Opencv中的彩色圖像格式均可;

第二個參數dst,輸出圖像,跟輸入src有同樣的大小和數據格式;

第三個參數sp,定義的漂移物理空間半徑大小;

第四個參數sr,定義的漂移色彩空間半徑大小;

第五個參數maxLevel,定義金字塔的最大層數;

第六個參數termcrit,定義的漂移迭代終止條件,可以設置為迭代次數滿足終止,迭代目標與中心點偏差滿足終止,或者兩者的結合;

 

pyrMeanShiftFiltering函數的執行過程是這樣的:

1. 迭代空間構建:

以輸入圖像上src上任一點P0為圓心,建立物理空間上半徑為sp,色彩空間上半徑為sr的球形空間,物理空間上坐標2個—xy,色彩空間上坐標3個—R、G、B(或HSV),構成一個5維的空間球體【其實就是升維的思想】

其中物理空間的范圍x和y是圖像的長和寬,色彩空間的范圍R、G、B分別是0~255。

2. 求取迭代空間的向量並移動迭代空間球體后重新計算向量,直至收斂:

在1中構建的球形空間中,求得所有點相對於中心點的色彩向量之和后,移動迭代空間的中心點到該向量的終點,並再次計算該球形空間中所有點的向量之和,如此迭代,直到在最后一個空間球體中所求得的向量和的終點就是該空間球體的中心點Pn,迭代結束。

3. 更新輸出圖像dst上對應的初始原點P0的色彩值為本輪迭代的終點Pn的色彩值,如此完成一個點的色彩均值漂移。

4. 對輸入圖像src上其他點,依次執行步驟1,、2、3,遍歷完所有點位后,整個均值偏移色彩濾波完成這里忽略對金字塔的討論

【貌似更高級一點,但是三通道也意味着更大的計算量,其實黑白照片能足夠辨別的話,還是采用一通道的好】

 

到這里,meanShift均值偏移算法對彩色圖像的平滑操作就完成了,為了達到分割的目的,需要借助另外一個漫水填充函數的進一步處理來實現,那就是floodFill。

但感覺這個方案不是很好。略。

 


 

CamShift - cv.CamShift

CamShift算法全稱是“Continuously Adaptive Mean-Shift”(連續的自適應MeanShift算法),是對MeanShift算法的改進算法,

可以在跟蹤的過程中隨着目標大小的變化實時調整搜索窗口大小,

對於視頻序列中的每一幀還是采用MeanShift來尋找最優迭代結果,至於如何實現自動調整窗口大小的,可以查到的論述較少,我的理解是通過對MeanShift算法中零階矩的判斷實現的。

 

反向投影,CamShift和MeanShift的運算都是在反向投影圖像上進行的,反向投影的實現過程如下:

計算並生成目標區域的H分量的直方圖,反向投影其實就是把目標圖像上每一個像素點的像素值替換為當前像素值所在bin對應的直方圖bin的數值。

 

Finds an object center, size, and orientation.  C++: RotatedRect CamShift(InputArray probImage, Rect& window, TermCriteria criteria) Python: cv2.CamShift(probImage, window, criteria) → retval, window C: int cvCamShift(const CvArr* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp, CvBox2D* box=NULL )

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM