三帧差法:连续三帧,12相减,23相减,结果做与运算。
其中阈值T需要手动调整。
结果得到一个二值图,对二值图做腐蚀,膨胀,在发现轮廓,其中所涉及到得函数有:
cv2.absdiff(img1,img2)#两图相减
cv2.threshold(img,thresh,255,cv2.THRESH_BINARY)#二值化注:此处没有转为1而是255,作用相同
cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))#结构花元素,腐蚀膨胀的kernel
cv2.erode(img,kernel)#腐蚀
cv2.dilate(img,kernel)#膨胀
cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#连通域分析,找轮廓边界
cv2.boundingRect(contour)#轮廓变方框。
import cv2
import numpy as np
def three_frame_differencing(videopath):
cap = cv2.VideoCapture(videopath)
width =int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height =int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
one_frame = np.zeros((height,width),dtype=np.uint8)
two_frame = np.zeros((height,width),dtype=np.uint8)
three_frame = np.zeros((height,width),dtype=np.uint8)
while cap.isOpened():
ret,frame = cap.read()
frame_gray =cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
if not ret:
break
one_frame,two_frame,three_frame = two_frame,three_frame,frame_gray
abs1 = cv2.absdiff(one_frame,two_frame)#相减
_,thresh1 = cv2.threshold(abs1,40,255,cv2.THRESH_BINARY)#二值,大于40的为255,小于0
abs2 =cv2.absdiff(two_frame,three_frame)
_,thresh2 =cv2.threshold(abs2,40,255,cv2.THRESH_BINARY)
binary =cv2.bitwise_and(thresh1,thresh2)#与运算
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
erode = cv2.erode(binary,kernel)#腐蚀
dilate =cv2.dilate(erode,kernel)#膨胀
dilate =cv2.dilate(dilate,kernel)#膨胀
img,contours,hei = cv2.findContours(dilate.copy(),mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_SIMPLE)#寻找轮廓
for contour in contours:
if 100
效果很不好,空洞太大了,准备改用KNN和高斯混合模型试试
涉及代码:
cv2.createBackgroundSubtractorMOG2()
cv2.createBackgroundSubtractorKNN()
高斯混合模型前景提取封装好了直接调用:
fgbg = cv2.createBackgroundSubtractorMOG2()#创建背景剪除
fgmask = fgbg.apply(frame)#获得二值轮廓图
接下了做形态学处理。
cap = cv2.VideoCapture(r"C:\RecordDownload\NVR-THD_ch3_main_20190423120000_20190423120500.dav")
kernel =cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
fgbg =cv2.createBackgroundSubtractorMOG2()
fourcc = cv2.VideoWriter_fourcc(*"XVID")
frame1 = np.zeros((640,480))
out = cv2.VideoWriter("test424.avi",fourcc,10,(640,480))
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
while cap.isOpened():
ret,frame =cap.read()
if not ret:
break
cv2.imshow("1",frame)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
fgmask =fgbg.apply(frame)
mask = cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)
cv2.imshow("2",mask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
_,contours,_ = cv2.findContours(fgmask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
if 100