基礎(chǔ)
背景去除是在很多視覺(jué)應(yīng)用里的主要預(yù)處理步驟。例如,攝像這樣的場(chǎng)景。一個(gè)固定攝像頭對(duì)顧客進(jìn)行計(jì)數(shù),或者交通攝像頭對(duì)汽車(chē)信息進(jìn)行提取。在所有這些情況下,首先你需要把人或者車(chē)輛單獨(dú)提取出來(lái)。技術(shù)上你需要從靜態(tài)背景里把移動(dòng)的前景提取出來(lái)。
如果你有一個(gè)單獨(dú)的背景的圖像,比如沒(méi)有顧客的房子的圖像,或者沒(méi)有汽車(chē)的路的圖像,這就很簡(jiǎn)單了。值需要在新的圖像里把背景去掉就行了。你得到的就是前景。但是在大多數(shù)情況下,你可能沒(méi)有這種圖像,所以我們需要從我們有的圖像里把背景去掉。當(dāng)車(chē)有影子的時(shí)候這個(gè)情況就很復(fù)雜了。因?yàn)橛白右苍趧?dòng)。簡(jiǎn)單的去除會(huì)把影子也作為前景。
一些算法來(lái)做這個(gè),OpenCV實(shí)現(xiàn)了三個(gè)這樣的算法,很易用,我們一個(gè)個(gè)看一下。
BackgroundSubtractorMOG
這是一個(gè)高斯混合背景/前景分割算法。它使用一個(gè)方法通過(guò)K高斯分布的混合來(lái)給每個(gè)背景像素建模(K=3到5)?;旌系臋?quán)重表示那些顏色留在場(chǎng)景中的時(shí)間規(guī)模。可能的背景顏色是那些留的時(shí)間更長(zhǎng)更靜止的。
寫(xiě)代碼時(shí),我們使用函數(shù)cv2.createBackgroundSubtractorMOG()創(chuàng)建一個(gè)背景對(duì)象.它有一些可選的參數(shù),比如歷史長(zhǎng)度,高斯混合數(shù)量,閾值等。它們?nèi)际悄J(rèn)值,然后在視頻循環(huán)里,使用backgroundsubtractor.apply()方法來(lái)得到背景掩圖
看一個(gè)簡(jiǎn)單例子:
import numpy as np
import cv2cap = cv2.VideoCapture('vtest.avi')
fgbg = cv2.createBackgroundSubtractorMOG()
while(1):
? ? ret, frame = cap.read()? ? fgmask = fgbg.apply(frame)
? ? cv2.imshow('frame',fgmask)
? ? k = cv2.waitKey(30) & 0xff
? ? if k == 27:
? ? ? ? breakcap.release()
cv2.destroyAllWindows()
BackgroundSubtractorMOG2
這也是高斯混合模型的前景/背景分割算法,這個(gè)算法的一個(gè)重要特點(diǎn)是它為每個(gè)像素選擇一個(gè)合適的高斯分布數(shù)。(記住,在上個(gè)例子,我們用了一個(gè)K高斯分布)它提供了更好的由于光照變化因素導(dǎo)致場(chǎng)景變化的適應(yīng)性。
在前面的例子里,我們得創(chuàng)建一個(gè)背景去除對(duì)象,這里,你可以選擇是否檢測(cè)影子。如果detectShadows = True(默認(rèn)的),它會(huì)檢測(cè)并標(biāo)記影子,但是會(huì)減低速度,Shadows會(huì)被標(biāo)記成灰色。
import numpy as np
import cv2cap = cv2.VideoCapture('vtest.avi')
fgbg = cv2.createBackgroundSubtractorMOG2()
while(1):
? ? ret, frame = cap.read()? ? fgmask = fgbg.apply(frame)
? ? cv2.imshow('frame',fgmask)
? ? k = cv2.waitKey(30) & 0xff
? ? if k == 27:
? ? ? ? breakcap.release()
cv2.destroyAllWindows()
BackgroundSubtractorGMG
這個(gè)算法合并了統(tǒng)計(jì)背景圖像判斷和每像素貝葉斯分割。
它使用最開(kāi)始的一些幀(默認(rèn)120)來(lái)對(duì)背景建模。它使用概率前景分割算法通過(guò)貝葉斯推論識(shí)別可能的前景物體。判斷是能適應(yīng)的。最新發(fā)現(xiàn)的權(quán)重更好,以適應(yīng)光線變化。一些形態(tài)學(xué)過(guò)濾運(yùn)算比如開(kāi)和閉被使用來(lái)去掉不需要的噪點(diǎn)。你會(huì)在最開(kāi)始的一些幀里得到一個(gè)黑色窗口
最好是通過(guò)形態(tài)學(xué)的開(kāi)運(yùn)算對(duì)結(jié)果使用,來(lái)移除噪點(diǎn)。
import numpy as np
import cv2cap = cv2.VideoCapture('vtest.avi')
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
fgbg = cv2.createBackgroundSubtractorGMG()while(1):
? ? ret, frame = cap.read()
? ?
? ? fgmask = fgbg.apply(frame)
? ? fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)? ? cv2.imshow('frame',fgmask)
? ? k = cv2.waitKey(30) & 0xff
? ? if k == 27:
? ? ? ? breakcap.release()
cv2.destroyAllWindows()
結(jié)果
原始幀:

BackgroundSubtractorMOG的結(jié)果

BackgroundSubtractorMOG2的結(jié)果
灰色區(qū)域顯示了影子區(qū)域

BackgroundSubtractorGMG的結(jié)果
用形態(tài)學(xué)開(kāi)運(yùn)算去掉了噪點(diǎn)

END