幀間差分法背景建模
定義
由于場景中的目標(biāo)在運(yùn)動(dòng)夏哭,目標(biāo)的影像在不同圖像幀中的位置不同。該類算法對(duì)時(shí)間上連續(xù)的兩幀圖像進(jìn)行差分運(yùn)算白筹,不同幀對(duì)應(yīng)的像素點(diǎn)相減挖诸,判斷灰度差的絕對(duì)值汁尺,當(dāng)絕對(duì)值超過一定閾值時(shí),即可判斷為運(yùn)動(dòng)目標(biāo)多律,從而實(shí)現(xiàn)目標(biāo)的檢測(cè)功能痴突。
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):算法簡單搂蜓,不易受環(huán)境光線影響
- 缺點(diǎn):
- 不能用于運(yùn)動(dòng)的攝像頭中;
- 無法識(shí)別靜止或運(yùn)動(dòng)速度很慢的目標(biāo)苞也;
- 運(yùn)動(dòng)目標(biāo)表面有大面積灰度值相似區(qū)域的情況下洛勉,在做差分時(shí)圖像會(huì)出現(xiàn)空洞;
混合高斯模型背景建模
基本原理
- 在進(jìn)行前景檢測(cè)前如迟,先對(duì)背景進(jìn)行訓(xùn)練,對(duì)圖像中每個(gè)背景采用一個(gè)混合高斯模型進(jìn)行模擬攻走,每個(gè)背景的混合高斯的個(gè)數(shù)可以自適應(yīng)殷勘。
- 然后在測(cè)試階段,對(duì)新來的像素進(jìn)行GMM匹配昔搂,如果該像素值能夠匹配其中一個(gè)高斯玲销,則認(rèn)為是背景,否則認(rèn)為是前景摘符。
- 由于整個(gè)過程GMM模型在不斷更新學(xué)習(xí)中贤斜,所以對(duì)動(dòng)態(tài)背景有一定的魯棒性。
- 最后通過對(duì)一個(gè)有樹枝搖擺的動(dòng)態(tài)背景進(jìn)行前景檢測(cè)逛裤,取得了較好的效果瘩绒。
在視頻中對(duì)于像素點(diǎn)的變化情況通常是符合高斯分布
背景的實(shí)際分布應(yīng)當(dāng)是多個(gè)高斯分布混合在一起,每個(gè)高斯模型也可以帶有權(quán)重
混合高斯模型學(xué)習(xí)方法
1.首先初始化每個(gè)高斯模型矩陣參數(shù)带族。
2.取視頻中T幀數(shù)據(jù)圖像用來訓(xùn)練高斯混合模型锁荔。來了第一個(gè)像素之后用它來當(dāng)做第一個(gè)高斯分布。
3.當(dāng)后面來的像素值時(shí)蝙砌,與前面已有的高斯的均值比較阳堕,如果該像素點(diǎn)的值與其模型均值差在3倍的方差內(nèi),則屬于該分布择克,并對(duì)其進(jìn)行參數(shù)更新恬总。
4.如果下一次來的像素不滿足當(dāng)前高斯分布,用它來創(chuàng)建一個(gè)新的高斯分布肚邢。
混合高斯模型測(cè)試方法
在測(cè)試階段壹堰,對(duì)新來像素點(diǎn)的值與混合高斯模型中的每一個(gè)均值進(jìn)行比較,如果其差值在2倍的方差之間的話道偷,則認(rèn)為是背景缀旁,否則認(rèn)為是前景。將前景賦值為255勺鸦,背景賦值為0并巍。這樣就形成了一副前景二值圖。
import numpy as np
import cv2
#經(jīng)典的測(cè)試視頻
cap = cv2.VideoCapture('test.avi')
#形態(tài)學(xué)操作需要使用
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
#創(chuàng)建混合高斯模型用于背景建模
fgbg = cv2.createBackgroundSubtractorMOG2()
while(True):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
#形態(tài)學(xué)開運(yùn)算去噪點(diǎn)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
#尋找視頻中的輪廓
im, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
#計(jì)算各輪廓的周長
perimeter = cv2.arcLength(c,True)
if perimeter > 188:
#找到一個(gè)直矩形(不會(huì)旋轉(zhuǎn))
x,y,w,h = cv2.boundingRect(c)
#畫出這個(gè)矩形
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('frame',frame)
cv2.imshow('fgmask', fgmask)
k = cv2.waitKey(150) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()