OpenCV4学习笔记(31)——视频背景、前景提取分离及运动检测
這次要整理的筆記是視頻背景、前景提取及運動檢測,是通過對視頻前面的一系列幀圖像來提取背景模型,從而分離出前景目標和背景,進而對運動的前景目標進行檢測。OpenCV中實現的背景模型提取算法有兩種,一種是基于自適應高斯混合背景建模(MOG2)的幀差法實現的背景提取,另外一種是基于最近鄰KNN算法實現的。這兩種算法相比之下,基于自適應高斯混合背景建模(MOG2)的幀差法所能達到的效果更好,所以使用頻率也比基于最近鄰KNN算法實現的要高,本篇筆記也是基于MOG2來實現的。
自適應高斯混合背景建模(MOG2)的幀差法,這個方法主要有高斯混合模型和幀差法這兩個重要組成部分。下面進行簡要介紹:
混合高斯模型:圖像灰度直方圖反映的是圖像中某個灰度級出現的頻次,也可以認為是圖像灰度概率密度的估計。如果圖像所包含的前景目標區域和背景區域相差比較大,且背景區域和前景目標區域在灰度上有一定的差異,那么該圖像的灰度直方圖呈現雙峰形狀,其中一個峰對應于前景目標,另一個峰對應于背景的中心灰度。那么圖像灰度直方圖的每個峰提取出來都可以作為高斯分布的中心,將圖像分為3 - 5個高斯模型,當一個新的像素點出現后,如果該像素點離任何一個高斯模型的距離都大于其2倍的標準差,則將該像素點歸為前景即運動物體,否則歸為背景。
幀差法:將連續兩幀的圖像數據進行差分,即進行相減操作, 如果其相減后的絕對值大于閾值,則像素點變為255, 否則變為0,通過這種方法來找出視頻中運動的物體。幀差法也分為三幀差法和兩幀差法。
OpenCV中使用createBackgroundSubtractorMOG2(history, 10, false)來創建一個MOG2背景提取器,其參數如下:
第一個參數history:視頻前面一部分用于訓練背景的幀數,默認為500幀,選擇history = 1就變成兩幀差。history越大,背景更新越慢,默認值為500幀。
如果參數learningRate(MOG2背景提取器的apply()中)為默認值,則history被用于計算當前的learningRate,此時history越大,learningRate越小。
第二個參數varThreshold:方差閾值,用于判斷當前像素屬于前景還是背景。
閾值越大,則只有那些差異化越明顯的像素會被歸為前景,運動檢測的靈敏度降低;閾值越小,前景提取越靈敏,但對光照也越敏感,穩定性會降低。
第三個參數 detectShadows :是否保留陰影檢測,默認值為true表示保留陰影檢測;選擇false可提高運行速度,如無特殊要求,建議設為false。
創建MOG2背景提取器后,需要使用apply()方法來應用該背景提取器,其參數為:
第一個參數image:輸入的圖像;
第二個參數fgmask:提取出的前景區域的掩膜,是一個二值圖像,其中白色區域為前景目標,黑色區域為背景;
第三個參數learningRate:學習率,取值范圍為 [0 , 1], 學習率為0時表示背景不更新,為1時表示逐幀更新,學習率越高,背景更新速度越快,默認值為-1,表示算法自動更新學習率(由參數history計算獲得)。
然后使用MOG2背景提取器的getBackgroundImage()方法來獲取圖像的背景圖像,就實現了一幅圖像的背景、前景分離。
如果我們將目標前景區域的二值圖像進行輪廓分析,就能將前景目標的輪廓給尋找出來,然后再獲取該輪廓的外接最小正矩形并繪制出來,這樣就能在一幅圖像中標記出前景目標區域。
如果在視頻中逐幀進行這樣的操作,那么每幀都標記出前景目標,就達到了前景目標跟蹤的效果,那么當前景目標運動時,就能實現對視頻的運動檢測。
下面是代碼演示:
VideoCapture capture;//capture.open("D:\\opencv_c++\\opencv_tutorial\\data\\images\\video.avi");capture.open("D:\\OpenCV\\opencv\\sources\\samples\\data\\vtest.avi");//capture.open(0);if (!capture.isOpened()){return 0;}int fps = capture.get(CAP_PROP_FPS);Mat frame;Ptr<BackgroundSubtractorMOG2> p_MOG2 = createBackgroundSubtractorMOG2(500, 10, false);while (capture.read(frame)){Mat mask, back_image;p_MOG2->apply(frame, mask);p_MOG2->getBackgroundImage(back_image); //獲取背景圖像//消除掩膜毛刺和細微干擾Mat kernel = getStructuringElement(MORPH_RECT, Size(1, 5));morphologyEx(mask, mask, MORPH_OPEN, kernel, Point(-1, -1), 1, 0);vector<vector<Point>> contours;findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);//尋找最大輪廓,并在圖像中標記出來//vector<float> area;//for (int i = 0; i < contours.size(); i++)//{// area.push_back(contourArea(contours[i]));//}//if (area.size() != 0)//{// double minVal, maxVal;// int minIdx[2], maxIdx[2];// minMaxIdx(area, &minVal, &maxVal, minIdx, maxIdx);// Rect rect = boundingRect(contours[maxIdx[1]]);// rectangle(frame, rect, Scalar(0, 0, 255), 2, 8, 0); //繪制最大輪廓的最小外接正矩形//}//檢測視頻中的運動物體for (int t = 0; t < contours.size(); t++){float area = contourArea(contours[t]);if (area < 300){continue;}Rect box = boundingRect(contours[t]);rectangle(frame, box, Scalar(0, 255, 0), 1, 8, 0);}char ch = waitKey(fps);if (ch == 27){break;}imshow("back_image", frame);}capture.release();我們來看一下提取出的背景效果圖:
由于演示視頻開始就有人在走動,所以人的初始位置也被當作了背景的一部分,但是隨著視頻不斷地播放,背景也在不斷地更新,所以這些初始人背景部分也會逐步地變淡,直至消失,就是真正的背景部分了。
下面看一下提取出的前景區域的掩膜圖像:
圖中白色區域就是被提取出的前景目標,也就是在走動的人。
再看一下運動檢測效果:
由于我不知道怎么發小視頻,所以只能用截圖。。。可見圖中,對于運動中的人,都能比較好的用方框標記出來。
MOG2背景提取算法在視頻分析中,是比較常用而且效果還不錯的算法,在對于實時檢測時,雖然也可以對運動物體進行檢測,但是速度就略微有些跟不上,畫面會出現卡頓現象。對于視頻分析,我們通常使用FPS(每秒多少幀的處理能力)來衡量一個算法是否能夠滿足實時處理要求,一般情況下每秒大于5幀基本上可以認為是在進行視頻處理。
好了本次筆記到此結束,謝謝閱讀~
PS:本人的注釋比較雜,既有自己的心得體會也有網上查閱資料時摘抄下的知識內容,所以如有雷同,純屬我向前輩學習的致敬,如果有前輩覺得我的筆記內容侵犯了您的知識產權,請和我聯系,我會將涉及到的博文內容刪除,謝謝!
總結
以上是生活随笔為你收集整理的OpenCV4学习笔记(31)——视频背景、前景提取分离及运动检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 戴尔笔记本一键重装win7系统教程
- 下一篇: NPDP知识推送-第一章新产品开发战略(