背景分割器BackgroundSubtractor是专门用来视频分析的,会对视频中的每一帧进行“学习”,比较,计算阴影,排除检测图像的阴影区域,按照时间推移的方法提高运动分析的结果。而且BackgroundSubtractor不仅可以用于背景分割,而且还可以提高背景检测的效果。在opencv中有三种分割器:KNN,MOG2,GMG。
通过mog2实现
import numpy as np import cv2 cap=cv2.VideoCapture(1) mog = cv2.createBackgroundSubtractorMOG2() while(1): ret,frame= cap.read() fgmask = mog.apply(frame) cv2.imshow('frame',fgmask) k = cv2.waitKey(30) & 0xff if k == 27: break cap.release() cv2.destroyAllWindows()
通过KNN实现
实现思想:
1.定义1个KNN背景分割器对象 2.定义视频对象 while True: 3.一帧帧读取视频 4.计算前景掩码 5.二值化操作 6.膨胀操作 7.查找轮廓 8.轮廓筛选 9.画出轮廓(在原图像) 10.显示图像帧,
代码实现:
# coding:utf8 import cv2 def detect_video(video): camera = cv2.VideoCapture(video) history = 500 # 训练帧数 bs = cv2.createBackgroundSubtractorKNN(detectShadows=True) # 背景减除器,设置阴影检测 bs.setHistory(history) frames = 0 while True: res, frame = camera.read() if not res: break fg_mask = bs.apply(frame) # 获取 foreground mask if frames < history: frames += 1 continue # 对原始帧进行膨胀去噪 th = cv2.threshold(fg_mask.copy(), 244, 255, cv2.THRESH_BINARY)[1] th = cv2.erode(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)), iterations=2) dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (8, 3)), iterations=2) # 获取所有检测框 image, contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #print(len(contours)) tempjs = 0 for c in contours: # 获取矩形框边界坐标 x, y, w, h = cv2.boundingRect(c) # 计算矩形框的面积 area = cv2.contourArea(c) if 500 < area: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) tempjs = tempjs +1 print(tempjs) cv2.imshow("detection", frame) cv2.imshow("back", dilated) if cv2.waitKey(110) & 0xff == 27: break camera.release() if __name__ == '__main__': #video = 'person.avi' detect_video(1)
#-*- coding:utf-8 -*- import cv2 import numpy as np # 1.常见一个BackgroundSubtractorKNN接口 bs = cv2.createBackgroundSubtractorKNN(detectShadows=True) #2.读取视频 camera = cv2.VideoCapture('traffic.flv') #定义卷积核圆形 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)) while True: ret,frame = camera.read() #3. apply()函数计算了前景掩码 fgmask = bs.apply(frame) #4. 获得前景掩码(含有白色值以及阴影的灰色值),通过设定阈值将非白色(244~255)的所有像素都设为0,而不是1; th = cv2.threshold(fgmask.copy(),244,255,cv2.THRESH_BINARY)[1] #二值化操作 dilated = cv2.dilate(th,kernel,iterations =2) #5.膨胀操作 #cv2.getStructuringElement 构建一个椭圆形的核 #3x3卷积核中有2个1那就设置为1 #6. findContours函数参数说明cv2.RETR_EXTERNAL只检测外轮廓, # cv2.CHAIN_APPROX_SIMPLE只存储水平,垂直,对角直线的起始点。 image,contours,hier = cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #查找轮廓 for c in contours: #从list列表取出每个轮廓 if cv2.contourArea(c) < 1500: #进行轮廓筛选 轮廓面积小于1500 continue (x,y,w,h) = cv2.boundingRect(c) cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow("mog",fgmask) cv2.imshow("thresh",th) cv2.imshow("detection",frame) if cv2.waitKey(100) & 0xff == ord("q"): break camera.release() cv2.destroyAllWindows()