1 前言
上篇文章介绍了用 C++调用OpenCV接口,打开网络摄像头录制视频,并抓拍截图。本篇我们看一下,Python如何调用OpenCV接口,来做同样的事情。
视频来源 | 视频格式/协议 | 参数 |
网络摄像头 | RTSP | rtsp://admin:123456@192.168.1.104:554/Streaming/Channels/101 |
下边我们用海康IP摄像机做测试,表格中的rtsp地址,是海康摄像机的URL格式,其它品牌(大华、宇视)与之类似。
rtsp://admin:123456@192.168.1.105:554/Streaming/Channels/101
rtsp:表示采用RTSP协议从摄像机取流
admin:摄像机网页登录用户名
123456:摄像机网页登录密码
192.168.1.104:摄像机IP地址
554:RTSP默认端口
输出文件 | 格式 | 文件名称 |
录像文件 | mp4 | output.mp4 |
抓拍图片文件 | bmp | picture_x.bmp |
2 关键接口说明
在测试程序中,主要用到了OpenCV以下接口:
录制视频
VideoWriter:写视频文件类,录制视频文件时使用
测试程序中,用到cv2的VideoWriter函数,调用方式如下:
cv2.VideoWriter(recordFile, fourcc, int(videoFps), (int(videoWidth),int(videoHeight)), True)
参数说明:
filename:保存的录像文件路径及名字,本例中为recordFile
fourcc:指定视频编码器,注意如果想保存mp4格式的录像文件,需要传递的参数格式为*mp4v,如果保存avi格式的录像,则传递*XVID
fps:保存的录像视频帧率
frameSize:录像文件视频分辨率大小,即视频画面的宽和高。特别注意:frameSize的两个参数,一个是视频画面宽videoWidth,一个是视频画面高videoHeight,这2个参数请务必一定要是int类型,不能传递其它类型,比如double或float格式的,否则运行程序时会报错:Opencv -5:Bad argument,如下截图
isColor:表示录像用彩色画面还是黑白画面,默认True,彩色画面
抓拍图片
用到cv2的imwrite函数,调用方式如下:
cv2.imwrite(filename, frame)
参数说明:
filename:保存的抓拍图片文件路径及名字
frame:抓拍的视频帧,其类型为Mat
3 创建测试项目
创建测试项目、配置开发环境,具体可参考这篇文章,过程就不多说了。
Win10+Python3.10+OpenCV4.6.0加载显示图片_来灵的博客-CSDN博客
这次测试项目名称video_recorder,VS2022种创建好的项目截图
将下列代码编辑到video_recorder.py文件里
# !usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
#打开网络摄像头录像
def open_camera_and_record(url):
try:
print("======to open ip camera and record...")
#使用OpenCV自带的VideoCapture()函数定义视频文件对象,网络摄像机本质上可以看作远程网络视频文件
cap = cv2.VideoCapture(url)
# *mp4v是mp4在openCV里的写法
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
#获取视频参数:宽、高、每秒传输帧数
videoWidth = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
videoHeight = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
videoFps = cap.get(cv2.CAP_PROP_FPS)
print('width = %d, height = %d, fps = %d.' % (videoWidth, videoHeight, videoFps))
#定义录制视频对象,录像文件./record/output.mp4
recordFile = './record/output.mp4'
lz = cv2.VideoWriter(recordFile, fourcc, int(videoFps), (int(videoWidth),int(videoHeight)), True)
count = 0
#循环读取每一帧
while(cap.isOpened()):
#第一个返回值result是一个布尔值,表示当前这一帧是否获取正确
result, frame = cap.read()
#读取视频文件结束时,退出播放
if not result:
print('play end...')
break
#在名称为“real video”的窗口中,显示视频
cv2.imshow("real video", frame)
# 写入每一帧
lz.write(frame)
#当按下"q"或“Q”键时,退出录制
key = cv2.waitKey(1)
if key == ord('q') or key == ord('Q'):
break
#按下空格键开始抓拍截图
if 32 == key:
filename = "./picture/picture_%s.bmp" % count
cv2.imwrite(filename, frame)
count += 1
#释放视频文件或摄像头资源
cap.release()
lz.release()
#销毁所有窗口,释放资源
cv2.destroyAllWindows()
print("test end...")
except Exception as e:
#访问异常的错误编号和详细信息
print(str(e))
#若当前目录不存在,则创建;否则不用创建
def make_dir(path):
isExist = os.path.exists(path)
if not isExist:
os.mkdir(path)
print(path + ' ok...')
return True
else:
print(path + ' is already exist...')
return True
if __name__ == '__main__':
#创建录像文件保存目录
make_dir('./record')
#创建抓拍图片保存目录
make_dir('./picture')
#打开网络摄像头播放
url = 'rtsp://admin:123456@192.168.1.104:554/Streaming/Channels/101'
open_camera_and_record(url)
测试项目工程当前目录,新创建2个文件夹:record和picture,分别用于保存录像文件和抓拍图片文件
VS中代码截图
4 效果截图
录像文件
使用VLC打开播放
抓拍图片
打开图片