视频分析
最近 AI 因为 ChatGPT 大热,正好找个由头玩一下,家里为了看娃装了个摄像头,一周拍的录像大概 20 多 G,可以拿来练练手。之前都是老婆人肉一个个看的,我这次先筛选出有动静的片段,后续老婆再看
最初的想法,是使用 haarcascades 分类器的,毕竟是老牌分类器,又是 opencv 自带的,公司用了一段时间也还行。但是 full_body 和 frontalface 都试过了,家里光线和环境比较复杂,误报很多。无奈换成了有动静才保留对应视频,这里参考了 利用 OpenCV 过滤监控视频,定期删除静态视频 这个方法比我之前逐帧分析高效太多了,是跳着看的,中间也能利用 GPU,就是不确定是高斯模糊用上了 GPU,还是图像对比 findContours 用上了
最终代码大致如下:
#encoding:utf8
import cv2
import numpy as np
import glob
import os
import shutil
import imutils
main_dir = " 目录 "
video_files = glob.glob(main_dir + '/**/*.mp4', recursive=True)
# 检测视频是否有活动画面
def check_for_movement(video_path):
camera = cv2.VideoCapture(video_path)
total = camera.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
fps = camera.get(cv2.CAP_PROP_FPS) # 帧率
# print(int(total / fps)) # 视频时间
step = (total - 100) / 9 # 间隔时间
# 初始化视频流的第一帧
lastFrame = None
occupied = False
try:
# 遍历视频的每一帧
for i in range(100, int(total), int(step)):
# 获取当前帧并初始化
camera.set(cv2.CAP_PROP_POS_FRAMES, i)
camera.grab() # 解码并返回捕获的视频帧
(grabbed, frame) = camera.read()
# 如果不能抓取到一帧,说明我们到了视频的结尾
if not grabbed:
break
# 调整该帧的大小,转换为灰阶图像并且对其进行高斯模糊
frame = imutils.resize(frame, width=500)
camera_area = frame.shape[0] * frame.shape[1]
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# 如果第一帧是 None,对其进行初始化
if lastFrame is None:
lastFrame = gray
continue
# 计算当前帧和第一帧的不同
frameDelta = cv2.absdiff(lastFrame, gray)
thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]
# 扩展阀值图像填充孔洞,然后找到阀值图像上的轮廓
thresh = cv2.dilate(thresh, None, iterations=2)
(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# 将当前帧置为上一帧
lastFrame = gray
# 遍历轮廓
for c in cnts:
# 如果变化太小,忽略
ca = cv2.contourArea(c)
if ca < 500 or ca > camera_area/2:
continue
occupied = True
break
else:
continue
break
except Exception as e:
print(e)
print("err on:", video_path)
finally:
# 清理摄像机资源
camera.release()
return occupied
def main():
total = len(video_files)
count = 0
for filename in video_files:
count = count + 1
print(count, "/", total, "percent:{:.2%}".format(count/total))
if check_for_movement(filename):
basename = os.path.basename(filename)
shutil.copy(filename, "output/"+basename)
if __name__ == "__main__":
main()
写完后发现,有人写了个 Python 包做这个事情,叫 DVR-Scan,不用自己写代码了。。。回头试试用一下。话说 ChatGPT 3.5 真的比较弱,这个话题反复问也没给到很好的解决方案。。。