帧间差分法(Temporal Difference)就是将视频的前后帧对应的像素点进行差运算得出差值。由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧或三帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值,当绝对值超过一定阈值时,即可判断为运动目标,从而实现目标的检测功能。
1.首先将视频每帧画面转为二值图,然后在每两帧之间进行做差运算,这里使用
cv2.absdiff(前一帧, 后一帧) 当前后帧的同一个像素点的差值不为零,并且差值的绝对值超过设定的阈值时,就可以判断画面发生了移动。
后一帧的对照 = 当前帧.copy()
import cv2
import numpy as np
camera = cv2.VideoCapture(0)
# 判断视频是否打开
if (camera.isOpened()):
print('Open')
else:
print('摄像头未打开')
# 测试用,查看视频size
size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT)))
print('size:' + repr(size))
es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4))
kernel = np.ones((5, 5), np.uint8)
firstframe = None #设置第一个对比模板
while True:
ret, frame = camera.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #灰度化
gray = cv2.GaussianBlur(gray, (21, 21), 0) #模糊处理
if firstframe is None:
firstframe = gray #firstframe取第一张gray
continue
frameDelta = cv2.absdiff(firstframe, gray)
firstframe = gray.copy() #将这帧作为下一帧的对照模板
thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1] #二值化
thresh = cv2.dilate(thresh, None, iterations=2) #腐蚀
cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
#if cv2.contourArea(c) < 1500: # 对于矩形区域,只显示大于给定阈值的轮廓,所以一些微小的变化不会显示。对于光照不变和噪声低的摄像头可不设定轮廓最小尺寸的阈值
#continue
x, y, w, h = cv2.boundingRect(c) #选取画框区域
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) #画框
print(x, y)
cv2.imshow("frame", frame)
cv2.imshow("Thresh", thresh)
cv2.imshow("frame2", frameDelta)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
camera.release()
cv2.destroyAllWindows()
连贯起来整个过程就能分析检测出运动的物体,该方法算法简单,但缺点也多,