运动估计


import numpy as np
import cv2 as cv

videoFileName = '运动估计2.mp4'
cap = cv.VideoCapture(videoFileName)
fgbg = cv.createBackgroundSubtractorMOG2() # 创建一个背景提取类的对象
thresh = 200

while True:
ret, frame = cap.read() # 读取视频中每一帧
if not ret: # 没读到当前帧,结束
break

# Foreground Mask(前景掩模)
fgmask = fgbg.apply(frame) # 实时更新当前背景图像 计算出前景对应的掩模图像
_, fgmask = cv.threshold(fgmask, 30, 0xff, cv.THRESH_BINARY) # 使用threshold初步对前景掩模图像过滤
bgImage = fgbg.getBackgroundImage() # 得到的实时更新的背景图像
_, cnts, _ = cv.findContours(fgmask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # 寻找轮廓

count = 0
for c in cnts:
area = cv.contourArea(c)
if area < thresh: # 区域面积小于指定阈值则认为是噪声
continue
count += 1

x, y, w, h = cv.boundingRect(c)
cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0xff, 0), 2)
print('共监测到', count, '个目标', ' ')
cv.imshow('frame', frame)
cv.imshow('Background', bgImage)

key = cv.waitKey(30) # 每一帧间隔30ms
if key == 27: # 按下ESC键退出
break
cap.release()
cv.destroyAllWindows()

feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)
lk_params = dict(winSize=(15, 15),
maxLevel=2,
criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
cap = cv.VideoCapture(videoFileName)

ret, prev = cap.read() # 得到第一帧
prevGray = cv.cvtColor(prev, cv.COLOR_BGR2GRAY) # OpvnCV 只支持灰度图像
p0 = cv.goodFeaturesToTrack(prevGray, mask=None, **feature_params) # 得到好的特征点

while True:
ret, frame = cap.read()
if not ret:
break

gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 转化为灰度
# prevGray 上一帧灰度图像 gray 当前帧灰度图像
# p1 检测到所有光流点的列表 st 每一个特征点计算的执行度
p1, st, err = cv.calcOpticalFlowPyrLK(prevGray, gray, p0, None, **lk_params)

# 选取好的跟踪点
goodPoints = p1[st == 1]
goodPrevPoints = p0[st == 1]
# 在结果图像中迭加画出特征点和计算出来的光流向量
res = frame.copy()
drawColor = (0, 0, 255)
for i, (cur, prev) in enumerate(zip(goodPoints, goodPrevPoints)):
x0, y0 = cur.ravel()
x1, y1 = prev.ravel()
cv.line(res, (x0, y0), (x1, y1), drawColor)
cv.circle(res, (x0, y0), 3, drawColor)
# 更新上一帧
prevGray = gray.copy()
p0 = goodPoints.reshape(-1, 1, 2)

cv.imshow('res', res)
key = cv.waitKey(30)
if key == 27:
break