BackgroundSubtractor
Opencv 有三种背景分割器
K-Nearest:KNN
Mixture of Gaussian(MOG2)
Geometric Multigid(GMG)
借助 BackgroundSubtractor 类,可检测阴影,用阈值排除阴影,从而关注实际特征
createBackgroundSubtractorMOG2
API:
cv2.createBackgroundSubtractorMOG2(
int history = 500,
double varThreshold = 16,
bool detectShadows = true
)
参数解释如下:
- history表示过往帧数,500帧,选择history = 1就变成两帧差
- varThreshold表示像素与模型之间的马氏距离,值越大,只有那些最新的像素会被归到前景,值越小前景对光照越敏感。
- detectShadows 是否保留阴影检测,请选择False这样速度快点。
import cv2
import os
# bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)
bs = cv2.createBackgroundSubtractorMOG2(detectShadows=True)
os.makedirs("frame1", exist_ok=True)
os.makedirs("frame2", exist_ok=True)
os.makedirs("frame3", exist_ok=True)
camera = cv2.VideoCapture('car.mkv')
index = 0
while True:
ret, frame = camera.read()
index += 1
frame_h, frame_w, _ = frame.shape
fgmask = bs.apply(frame)
th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1]
dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)),
iterations=2)
contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
# if cv2.contourArea(c) > frame_w*0.075 * frame_h*0.075:
if cv2.contourArea(c) > 1000:
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), 5)
cv2.imshow("mog", fgmask)
cv2.imwrite("./frame1/{}.jpg".format(index), fgmask)
cv2.imshow("thresh", th)
cv2.imwrite("./frame2/{}.jpg".format(index), th)
cv2.imshow("detection", frame)
cv2.imwrite("./frame3/{}.jpg".format(index), frame)
if cv2.waitKey(30) & 0xff == ord("q"):
break
camera.release()
cv2.destroyAllWindows()
做 gif 的时候只设置了播放一次,重复播放需要刷新
createBackgroundSubtractorKNN
import cv2
import numpy as np
bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)
camera = cv2.VideoCapture('car.mkv')
index = 0
while True:
ret, frame = camera.read()
index += 1
frame_h, frame_w, _ = frame.shape
fgmask = bs.apply(frame)
th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1]
dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)),
iterations=2)
contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
# if cv2.contourArea(c) > frame_w*0.075 * frame_h*0.075:
if cv2.contourArea(c) > 1000:
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 0, 255), 5)
cv2.imshow("mog", fgmask)
cv2.imwrite("./frame1/{}.jpg".format(index), fgmask)
cv2.imshow("thresh", th)
cv2.imwrite("./frame2/{}.jpg".format(index), th)
cv2.imshow("detection", frame)
cv2.imwrite("./frame3/{}.jpg".format(index), frame)
if cv2.waitKey(30) & 0xff == ord("q"):
break
camera.release()
cv2.destroyAllWindows()