摄像头监视脚本
摄像头监视脚本,若检测到摄像头画面有变化,保存这一段视频
一、使用方法
1.运行脚本
默认参数Threshold=3, Period=3, path=./recordings
python cam.py --threshold=30 --period=3 --path=./recordings
2.参数说明
threshold:摄像头捕获到的画面变化量阈值,阈值越小越敏感
period:摄像头捕获周期,单位秒
path:捕获图片保存路径
import cv2
import numpy as np
import time
import argparse
import os
def detect_motion(img1, img2, threshold=25):
"""
检测两帧之间的变化区域
:param img1: 当前帧
:param img2: 上一帧
:param threshold: 像素差异阈值
:return: 变化区域掩码和是否检测到变化
"""
# 转换为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 计算差异
frame_diff = cv2.absdiff(gray1, gray2)
# 应用阈值
_, thresh = cv2.threshold(frame_diff, threshold, 255, cv2.THRESH_BINARY)
# 应用形态学操作去噪
kernel = np.ones((5, 5), np.uint8)
thresh = cv2.dilate(thresh, kernel, iterations=2)
thresh = cv2.erode(thresh, kernel, iterations=1)
# 找到轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 判断是否检测到显著变化
has_motion = False
min_area = 500 # 最小变化区域面积
for contour in contours:
if cv2.contourArea(contour) > min_area:
has_motion = True
break
return thresh, has_motion
def camera_monitor(period=3, video_duration=5):
"""
监视程序入口
:param period: 检查周期(秒)
:param video_duration: 录制视频长度(秒)
"""
print(f'监视器启动!\nParams:\nThreshold={args.threshold}, Period={period}, Save Path={args.path}')
# 构建RTSP URL
rtsp_url = f'rtsp://{args.username}:{args.password}@{args.ip}:{args.port}{args.channel}'
print(f'连接到 RTSP 流: {rtsp_url}')
# 设置RTSP连接
cap = cv2.VideoCapture(rtsp_url)
# 设置RTSP缓冲区大小
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
if not cap.isOpened():
print('错误:无法连接到 RTSP 流')
return
# 获取视频参数
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 20.0
# 读取第一帧
_, last_frame = cap.read()
while True:
ret, current_frame = cap.read()
if not ret:
print('错误:无法读取帧')
break
# 检测变化
motion_mask, has_motion = detect_motion(current_frame, last_frame, args.threshold)
if has_motion:
print("检测到运动!录制视频...")
# 创建视频写入器,修改为MP4格式
timestamp = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime())
video_path = os.path.join(args.path, f'motion_{timestamp}.mp4')
# 使用H.264编码器
if os.name == 'nt': # Windows系统
video_writer = cv2.VideoWriter(
video_path,
cv2.VideoWriter_fourcc(*'H264'),
fps,
(frame_width, frame_height)
)
else: # Linux/Mac系统
video_writer = cv2.VideoWriter(
video_path,
cv2.VideoWriter_fourcc(*'avc1'),
fps,
(frame_width, frame_height)
)
# 记录检测到运动的时间点
start_time = time.time()
# 录制视频片段
while time.time() - start_time < video_duration:
ret, frame = cap.read()
if not ret:
break
# 标记变化区域
motion_mask, _ = detect_motion(frame, last_frame, args.threshold)
contours, _ = cv2.findContours(motion_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 在原图上画出变化区域
frame_marked = frame.copy()
for contour in contours:
if cv2.contourArea(contour) > 500:
cv2.drawContours(frame_marked, [contour], -1, (0, 255, 0), 2)
video_writer.write(frame_marked)
last_frame = frame.copy()
video_writer.release()
print(f'视频保存到: {video_path}')
last_frame = current_frame.copy()
time.sleep(period)
cap.release()
# 参数设置
parser = argparse.ArgumentParser(description='移动侦测摄像机监视器')
parser.add_argument('--threshold', type=int, default=3, help='移动侦测阈值')
parser.add_argument('--period', type=int, default=1, help='监控周期(秒)')
parser.add_argument('--path', type=str, default='./recordings', help='保存录制文件的路径')
# 添加RTSP相关参数
parser.add_argument('--ip', type=str, default='192.168.11.23', help='摄像机的 IP 地址')
parser.add_argument('--port', type=str, default='554', help='RTSP 端口(默认值:554)')
parser.add_argument('--username', type=str, default='admin', help='RTSP 用户名')
parser.add_argument('--password', type=str, default='admin123', help='RTSP 密码')
parser.add_argument('--channel', type=str, default='/cam/realmonitor?channel=1&subtype=1', help='RTSP 通道或流路径')
args = parser.parse_args()
# 确保存储目录存在
if not os.path.exists(args.path):
os.makedirs(args.path)
if __name__ == '__main__':
try:
camera_monitor(period=args.period)
except KeyboardInterrupt:
print("\n用户停止的监控")
finally:
cv2.destroyAllWindows()