背景差法目标识别python_运动目标检测(4)—背景差分法
背景減法利用圖像序列中的當前幀和事先確定的背景參考模型間的差異比較,來確定運動物體位置,是一種基于統計學原理的運動目標檢測的方法。這種方法的性能取決于背景建模技術,Gloyer等人使用單高斯模型的思路,但常常不能準確地描述背景模型。
1999年Stauffer等人提出了經典的混合高斯背景建模法,這種方法不僅對復雜場景的適應強,而且能通過自動計算的模型參數來對背景模型調整,雖然增加了高斯分布的個數,造成計算量增大,但檢測速度很快,且檢測準確,容易實現。基于混合高斯模型建模的背景減法已是運動檢測的主流方法。OpenCv中有三種三種比較容易使用的方法。
1. BackgroundSubtractorMOG
這是一個以混合高斯模型為基礎的前景/背景分割算法。它是 P.KadewTraKuPong和 R.Bowden 在 2001 年提出的。它使用 K(K=3 或 5)個高斯分布混合對背景像素進行建模。使用這些顏色(在整個視頻中)存在時間的長短作為混合的權重。背景的顏色一般持續的時間最長,而且更加靜止。一個像素怎么會有分布呢?在 x,y 平面上一個像素就是一個像素沒有分布,但是我們現在講的背景建模是基于時間序列的,因此每一個像素點所在的位置在整個時間序列中就會有很多值,從而構成一個分布。
在編寫代碼時,我們需要使用函數cv2.createBackgroundSubtractorMOG()創建一個背景對象。這個函數有些可選參數,比如要進行建模場景的時間長度,高斯混合成分的數量,閾值等。將他們全部設置為默認值。然后在整個視頻中 我們是需要使用 backgroundsubtractor.apply() 就可以得到前景的掩模了。
2. BackgroundSubtractorMOG2
這個也是以高斯混合模型為基礎的背景/前景分割算法。它是以 2004 年和 2006 年 Z.Zivkovic 的兩篇文章為基礎的。這個算法的一個特點是它為每一個像素選擇一個合適數目的高斯分布。(上一個方法中我們使用是 K 高斯分布)。這樣就會對由于亮度等發生變化引起的場景變化產生更好的適應。
和前面一樣我們需要創建一個背景對象。但在這里我們我們可以選擇是否檢測陰影。如果 detectShadows = True(默認值),它就會檢測并將影子標記出來,但是這樣做會降低處理速度。影子會被標記為灰色。
3. BackgroundSubtractorGMG
此算法結合了靜態背景圖像估計和每個像素的貝葉斯分割。這是 2012 年Andrew_B.Godbehere,Akihiro_Matsukawa 和 Ken_Goldberg 在文章中提出的。
它使用前面很少的圖像(默認為前 120 幀)進行背景建模。使用了概率前景估計算法(使用貝葉斯估計鑒定前景)。這是一種自適應的估計,新觀察到的對象比舊的對象具有更高的權重,從而對光照變化產生適應。一些形態學操作如開運算閉運算等被用來除去不需要的噪音。在前幾幀圖像中你會得到一個黑色窗口。
對結果進行形態學開運算對與去除噪聲很有幫助。
4. 三種方法的效果
代碼實現如下:
import numpy as np
import cv2
import imageio
cap = cv2.VideoCapture("E:/opencv_vs/opencv/sources/samples/data/vtest.avi")
fgbg1 = cv2.bgsegm.createBackgroundSubtractorMOG()
fgbg2 = cv2.createBackgroundSubtractorMOG2()
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
fgbg3 = cv2.bgsegm.createBackgroundSubtractorGMG(60) # initializationFrames=120
# 保存gif參數設置
gif1 = 'E:/video/v1.gif'
gif2 = 'E:/video/v2.gif'
gif3 = 'E:/video/v3.gif'
frames1 = []
frames2 = []
frames3 = []
while True:
ret, frame = cap.read()
if not ret:
print('not found')
break
frame = cv2.resize(frame, (400, 400), interpolation=cv2.INTER_CUBIC)
# 前景掩碼
fgmask1 = fgbg1.apply(frame)
fgmask2 = fgbg2.apply(frame)
fgmask3 = fgbg3.apply(frame)
fgmask4 = cv2.morphologyEx(fgmask3, cv2.MORPH_OPEN, kernel, iterations=1) # 形態學開運算
cv2.imshow('frame1', fgmask1)
cv2.imshow('frame2', fgmask2)
cv2.imshow('frame3', fgmask3)
cv2.imshow('frame4', fgmask4)
# 加入幀
frames1.append(fgmask1)
frames2.append(fgmask2)
frames3.append(fgmask4)
# 保存gif
imageio.mimsave(gif1, frames1, 'GIF', duration=0.1)
imageio.mimsave(gif2, frames2, 'GIF', duration=0.1)
imageio.mimsave(gif3, frames3, 'GIF', duration=0.1)
k = cv2.waitKey(100) & 0xff
if k == 27 or k == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
BackgroundSubtractorMOGBackgroundSubtractorMOG2BackgroundSubtractorGMG(噪聲未保存到)BackgroundSubtractorGMG(經形態學運算)
下面是采用BackgroundSubtractorGMG方法處理選取的兩組圖片BackgroundSubtractorGMG原圖1BackgroundSubtractorGMG修圖1BackgroundSubtractorGMG原圖2BackgroundSubtractorGMG修圖2
5. 檢測運動目標
運動目標檢測流程圖
代碼實現如下:
#使用BackgroundSubtractorMOG
import cv2 as cv
import numpy as np
# 設置文件
file_test = "E:/opencv_vs/opencv/sources/samples/data/vtest.avi"
cap = cv.VideoCapture(file_test)
# 設置變量
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (2, 2)) # 定義結構元素
color_m = (255, 0, 0)
# 背景差法
fgbg = cv.bgsegm.createBackgroundSubtractorMOG()
# 視頻文件輸出參數設置
out_fps = 12.0 # 輸出文件的幀率
fourcc = cv.VideoWriter_fourcc('M', 'P', '4', '2')
out = cv.VideoWriter('E:/video/v9.avi', fourcc, out_fps, (500, 500))
while True:
# 讀取一幀
ret, frame = cap.read()
# 如果視頻結束,跳出循環
if not ret:
break
frame = cv.resize(frame, (500, 500), interpolation=cv.INTER_CUBIC)
frame_motion = frame.copy()
# 計算前景掩碼
fgmask = fgbg.apply(frame_motion)
draw1 = cv.threshold(fgmask, 25, 255, cv.THRESH_BINARY)[1] # 二值化
draw1 = cv.dilate(draw1, kernel, iterations=1)
# 查找檢測物體的輪廓,只檢測外輪廓,只需4個點來保存輪廓信息
image_m, contours_m, hierarchy_m = cv.findContours(draw1.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for c in contours_m:
if cv.contourArea(c) < 300:
continue
(x, y, w, h) = cv.boundingRect(c)
cv.rectangle(frame_motion, (x, y), (x + w, y + h), color_m, 2)
cv.imshow("source", frame_motion)
cv.imshow("apply", fgmask)
cv.imshow("draw", draw1)
k = cv.waitKey(200)
if k == ord('q'):
break
out.write(frame_motion) # 保存
out.release()
cap.release()
cv.destroyAllWindows()
運動目標檢測https://www.zhihu.com/video/1016748414142455808
6. 參考資料
[1]opencv官網教程
總結
以上是生活随笔為你收集整理的背景差法目标识别python_运动目标检测(4)—背景差分法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python- re模块(正则表达式)
- 下一篇: websocket python爬虫_p