利用opencv進行移動物體檢測

進行運動物體檢測就是將動態的前景從靜態的背景中分離出來。將當前畫面與假設是靜態背景進行比較發現有明顯的變化的區域,就能夠認爲該區域出現移動的物體。在實際狀況中因爲光照陰影等因素干擾比較大,經過像素直接進行比較每每很容易形成誤檢。所以有很多算法被開發出來在進行先後景分離的時候對運動和其餘因素形成的變更進行區分。opencv中提供了多種背景減除的算法,其中基於高斯混合模型(GMM)的cv2.BackgroundSubtractorMOG()cv2.BackgroundSubtractorMOG2()已經基於貝葉斯模型的cv2.bgsegm.createBackgroundSubtractorGMG()最爲經常使用。html

1) GMM法

GMM進行先後景分離最先是在2001年的文章An improved adaptive background mixture model for real-time tracking with shadow detection中提出的。其設計思路爲:python

  1. 在不知道圖像歷史的時候,假設每一個像素點的值都是能夠分解爲一組adaptive Gaussian。adaptive是因爲須要跟隨光照條件的變化而變化。
  2. 像素值的歷史由一組高斯分佈進行建模,包括每一個分佈的權重。
  3. 每次新圖像輸入的時候都會用這一組高斯分佈進行評估,若是像素匹配上其中一個分佈就會認爲這個像素屬於背景,而高斯分佈的均值和方差等參數會用當前像素的值進行更新。
  4. 標記爲前景的像素經過connected component analysis進行分組。
    opencv的cv2.BackgroundSubtractorMOG()的函數就是對次方法的實現。

基於2004年提出的Improved adaptive Gausian mixture model for background subtractio和2006年提出的Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction算法對上述GMM算法進行改良的就是opencv的cv2.BackgroundSubtractorMOG2()的函數。主要的提高是對每一個像素都選擇合適數量的高斯分佈而非原來的所有相同的個數。此外,這個函數還容許是否檢測陰影。android

使用方法(以MOG2爲例)算法

import cv2

cam = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG()
while cam.isOpened():
    ret, frame = cam.read()
    if ret:
        fgmask = fgbg.apply(frame)
        # 經過腐蝕和膨脹過濾一些噪聲
        erode = cv2.erode(fgmask, (21, 21), iterations=1)
        dilate = cv2.dilate(fgmask, (21, 21), iterations=1)
        (_, cnts, _) = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        for c in cnts:
            c_area = cv2.contourArea(c)
            if c_area < 1600 or c_area > 16000:  # 過濾過小或太大的運動物體,這類誤檢機率比較高
                continue
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
        cv2.imshow("origin", frame)
        if cv2.waitKey(1) == ord('q'):
            break
cv2.destroyAllWindows()

2)GMG法

根據2012年的文章Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive Audio Art Installation, opencv開發了相應的函數cv2.bgsegm.createBackgroundSubtractorGMG() (好像在3.2中被放到了contrib中,在以前能夠直接用cv2.createBackgroundSubtractorGMG()進行調用)。這個方法默認使用前120張圖片進行背景的建模,並使用機率前景分割算法找到可能的前景(基於貝葉斯推測)。爲了更好適應不一樣光照變化的影響,新的圖片的權重比舊圖片要高。app

使用方法ide

cam = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (8, 8))
fgbg = cv2.bgsegm.createBackgroundSubtractorGMG(initializationFrames=10)
while cam.isOpened():
    ret, frame = cam.read()
    if ret:
        fgmask = fgbg.apply(frame)
        fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)   # 過濾噪聲
        (_, cnts, _) = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        for c in cnts:
            c_area = cv2.contourArea(c)
            if c_area < 1600 or c_area > 16000:  # 過濾過小或太大的運動物體,這類誤檢機率比較高
                continue
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
        cv2.imshow("origin", frame)
        if cv2.waitKey(1) == ord('q'):
            break
cv2.destroyAllWindows()

參考:

  1. https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html
  2. http://android4arduino.com/computer-vision/motion-detection/
  3. https://www.pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/
  4. https://docs.opencv.org/3.0-beta/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=createbackgroundsubtractormog
相關文章
相關標籤/搜索