【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法 Mean Shift
【youcans 的 OpenCV 例程200篇】176.圖像分割之均值漂移算法
【youcans 的 OpenCV 例程200篇】177.圖像分割之 GraphCuts 圖割法
【youcans 的 OpenCV 例程200篇】178.圖像分割之 GrabCut 圖割法(框選前景)
【youcans 的 OpenCV 例程200篇】179.圖像分割之 GrabCut 圖割法(掩模圖像)
更多內容,請見:
【OpenCV 例程200篇 總目錄-202206更新】
【youcans 的 OpenCV 例程200篇】176.圖像分割之均值漂移算法 (Mean Shift)
5.6 圖像分割之均值漂移算法
均值漂移算法(Mean Shift)是一種基于模式識別的特征空間分析方法,提供了一種目標描述與定位的算法框架。
均值漂移算法的基本思想是,通過反復迭代搜索特征空間中樣本最密集的區域,搜索點沿著樣本點密度增加的方向“漂移”到局部密度極大值點。采用基于核密度估計的爬山算法,自適應調整步長進行迭代搜索,可以收斂到局部極值。
基于 Mean Shift 的目標跟蹤技術采用核概率密度描述目標特征,對于圖像分割通常采用直方圖對目標建模,然后通過相似性度量搜索目標位置,實現目標的匹配與跟蹤。
對于圖像分割,通常將 RGB 圖像映射到 LUV 顏色特征空間,結合位置信息可以構造 5維特征變量 (x,y,l,u,v)。均值漂移算法不僅可以應用于二維圖像處理,也可以用于高維數據處理。可以通過選取不同的核函數,來改變區域當中偏移向量的權重。
均值漂移算法將目標特征與空間信息有效結合,避免使用復雜模型描述目標形狀、外觀和運動,因此對邊緣遮擋、目標旋轉、變形和背景運動不敏感,能夠適應目標的形狀、大小的連續變換,而且計算速度快、抗干擾能力強。
均值漂移算法的缺點是:
(1)缺乏必要的模板更新;
(2)跟蹤過程中由于窗口寬度大小保持不變,當目標尺度變化時,跟蹤就會失敗;
(3)當目標速度較快時,跟蹤效果不好;
(4)直方圖特征在目標顏色特征描述方面略顯匱乏,缺少空間信息;
對于這些缺點,在工程實際中可以進行改進:
(1)引入目標位置變化的預測機制,以減少跟蹤的搜索時間,降低計算量;
(2)將傳統算法中的核函數固定帶寬改為動態變化的帶寬;
(3)使用前一幀的目標跟蹤結果作為目標跟蹤模板。
OpenCV 也提供了函數 cv.meanShift 實現均值漂移算法,該函數只考慮顏色相似性,不考慮像素的位置坐標。
該函數采用目標對象的輸入反投影和初始位置,通過迭代搜索算法,計算反投影圖像窗口中的質心,將搜索窗口中心移向質心,直到達到迭代終止條件。
函數說明:
cv.meanShift(probImage, window, criteria[, ]) → retval, windowcv.meanshift() 函數使用時要先設定目標,需要提供目標的初始窗口位置,計算 HSV 模型中 H (色調)的直方圖。為了減少低亮度的影響,可以使用 cv.inRange() 將低亮度值忽略。
參數說明:
- probImage:對象直方圖的反向投影,參見 calcBackProject
- window:初始的搜索窗口
- criteria:迭代搜索的終止條件
注意事項:
- 如果對反投影進行預濾波并去除噪聲,可以獲得更好的結果。
- 可以通過使用 findContours 檢索連接的組件,丟棄面積較小的輪廓(contourArea),并使用drawContours渲染其余輪廓來實現。
- OpenCV 中的另一個函數 pyrMeanShiftFiltering(),是圖像在色彩層面的平滑濾波,可以中和色彩分布相近的顏色,平滑色彩細節,侵蝕掉面積較小的顏色區域。
例程 11.33: 圖像分割之均值漂移算法
# 11.33 圖像分割之均值漂移算法def meanShiftTracker(src, trackWindow):# meanShift 算法: 在 dst 尋找目標窗口,找到后返回目標窗口位置hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) # BGR-HSV 轉換dst = cv2.calcBackProject([hsv], [0], roiHist, [0, 180], 1) # 計算反向投影term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)_, trackWin = cv2.meanShift(dst, trackWindow, term_crit)x, y, w, h = trackWinimgTrack = src.copy()imgTrack = cv2.rectangle(imgTrack, (x, y), (x + w, y + h), 255, 2)print(x, y, w, h)return imgTrack# if __name__ == '__main__': # 圖像分割之均值漂移算法img = cv2.imread("../images/FigCross1.png", flags=1) # 基準參考圖像imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL) # BGR-HSV 轉換# 設置初始化的窗口位置# print("Select a ROI and then press SPACE or ENTER button!\n")# roi = cv2.selectROI(img, showCrosshair=True, fromCenter=False)# x0, y0, w, h = roi # 矩形裁剪區域 (ymin:ymin+h, xmin:xmin+w) 的位置參數# rect = (x0, y0, w, h) # 邊界框矩形的坐標和尺寸 # rect = (990 311 94 72)(x0, y0, w, h) = (990, 310, 95, 72) # 直接設置矩形窗口的位置參數,也可以鼠標框選 ROItrackWindow = (x0, y0, w, h) # 矩形 ROIprint(x0, y0, w, h)imgROI = np.zeros_like(img) # 創建與 image 相同形狀的黑色圖像imgROI[y0:y0+h, x0:x0+w] = img[y0:y0+h, x0:x0+w].copy()frameROI = imgROI[y0:y0+h, x0:x0+w] # 設置追蹤的區域roiHSV = cv2.cvtColor(frameROI, cv2.COLOR_BGR2HSV) # BGR-HSV 轉換# 取 HSV 在 (0,60,32)~(180,255,255) 之間的部分mask = cv2.inRange(roiHSV, np.array((0., 60., 32.)), np.array((180., 255., 255.)))roiHist = cv2.calcHist([roiHSV], [0], mask, [180], [0, 180]) # 計算直方圖cv2.normalize(roiHist, roiHist, 0, 255, cv2.NORM_MINMAX) # 歸一化# # meanShift 算法: 在 dst 尋找目標窗口,找到后返回目標窗口位置img1 = cv2.imread("../images/FigCross2.png", flags=1) # 讀取彩色圖像(BGR)imgTrack1 = meanShiftTracker(img1, trackWindow)img2 = cv2.imread("../images/FigCross4.png", flags=1) # 讀取彩色圖像(BGR)imgTrack2 = meanShiftTracker(img2, trackWindow)plt.figure(figsize=(10, 6))plt.subplot(231), plt.axis('off'), plt.title("Initial image")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.subplot(234), plt.axis('off'), plt.title("ROI image")plt.imshow(cv2.cvtColor(imgROI, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.subplot(232), plt.axis('off'), plt.title("image 1")plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.subplot(235), plt.axis('off'), plt.title("image track 1")plt.imshow(cv2.cvtColor(imgTrack1, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.subplot(233), plt.axis('off'), plt.title("image 2")plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.subplot(236), plt.axis('off'), plt.title("image track 2")plt.imshow(cv2.cvtColor(imgTrack2, cv2.COLOR_BGR2RGB)) # 顯示 img(RGB)plt.tight_layout()plt.show()程序說明:
均值漂移算法進行圖像分割的效果并不是很好,所以 img2 中的目標并未成功追蹤,這是由于拍攝角度導致目標物體運動后的尺寸發生了變化。不過,如果應用于視頻跟蹤,每次使用上一幀的目標窗口作為追蹤區域,而不是一直使用初始目標窗口,由于目標在相鄰幀的尺寸變化很小,可以解決這個問題。
(本節完)
版權聲明:
OpenCV 例程200篇 總目錄-202205更新
youcans@xupt 原創作品,轉載必須標注原文鏈接:(https://blog.csdn.net/youcans/article/details/124695824)
Copyright 2022 youcans, XUPT
Crated:2022-5-8
歡迎關注 『youcans 的 OpenCV 例程 200 篇』 系列,持續更新中
歡迎關注 『youcans 的 OpenCV學習課』 系列,持續更新中
【youcans 的 OpenCV 例程200篇】176.圖像分割之均值漂移算法
【youcans 的 OpenCV 例程200篇】177.圖像分割之 GraphCuts 圖割法
【youcans 的 OpenCV 例程200篇】178.圖像分割之 GrabCut 圖割法(框選前景)
【youcans 的 OpenCV 例程200篇】179.圖像分割之 GrabCut 圖割法(掩模圖像)
更多內容,請見:
【OpenCV 例程200篇 總目錄-202206更新】
總結
以上是生活随笔為你收集整理的【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法 Mean Shift的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【指纹识别】基于模板匹配算法指纹识别匹配
- 下一篇: 雨天下的南京