1、前言
opencv不仅能够处理图像,还能够处理视频
视频是由大量的图像构成的,这些图像是以固定的时间间隔从视频中获取的。这样,就能够使用图像处理的方法对这些图像进行处理,进而达到处理视频的目的。要想处理视频,需要先对视频进行读取、显示、保存等相关操作。为此,opencv提供了videocapture类和 videowiter 类的相关方法。
2、摄像头操作
为了读取并显示摄像头视频,opencv 提供了 videocapture 类的相关方法,这些方法包括摄像头的初始化方法、检验摄像头初始化是否成功的方法、从摄像头中读取帧的方法、关闭摄像头的方法等。
tips :视频是由大量图像构成,这些图像称为帧
videocapture 类:
- index = 0 :表示打开第一个摄像头,对于64位笔记本,打开的就是内置摄像头
- index = 1 :表示打开第二个摄像头,对于64位笔记本,打开的就是连接笔记本的外置摄像头
为了检测摄像头初始化是否成功,opencv提供了isopened()方法,
如果打开摄像头正确的话,接下来就可以读取视频的每一帧了,read()方法
opencv 特别强调,不需要摄像头时,一定要关闭
2.1 读取、显示摄像头视频
实验目的:打开笔记本内置摄像头实时读取并显示视频。当按下空格键时,关笔记本内置摄像头,销毁显示摄像头视频的窗口
代码:
import cv2
capture = cv2.videocapture(0) # 打开笔记本内置摄像头
while (capture.isopened()): # 笔记本内置摄像头被打开后
retval, image = capture.read() # 从摄像头中实时读取视频
cv2.imshow("video", image) # 在窗口中显示读取到的视频
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 32: # 如果按下空格键
break
capture.release() # 关闭笔记本内置摄像头
cv2.destroyallwindows() # 销毁显示摄像头视频的窗口
展示:
2.2 将摄像头视频转为灰度视频
帧就是图像,将每一帧按照数字图像处理的方式处理就可以改变视频的样式
这里展示将视频转为灰度视频的操作
代码:
import cv2
capture = cv2.videocapture(0, cv2.cap_dshow) # 打开笔记本内置摄像头
while (capture.isopened()): # 笔记本内置摄像头被打开后
retval, image = capture.read() # 从摄像头中实时读取视频
# 把彩色视频转换为灰度视频
image_gray = cv2.cvtcolor(image,cv2.color_bgr2gray)
if retval == true: # 读取到摄像头视频后
cv2.imshow("video", image) # 在窗口中显示彩色视频
cv2.imshow("video_gray", image_gray) # 在窗口中显示灰度视频
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 32: # 如果按下空格键
break
capture.release() # 关闭笔记本内置摄像头
cv2.destroyallwindows() # 销毁显示摄像头视频的窗口
展示:
2.3 保存摄像头视频的某一帧图像
代码如下:
import cv2
cap = cv2.videocapture(0, cv2.cap_dshow) # 打开笔记本内置摄像头
while (cap.isopened()): # 笔记本内置摄像头被打开后
ret, frame = cap.read() # 从摄像头中实时读取视频
cv2.imshow("video", frame) # 在窗口中显示视频
k = cv2.waitkey(1) # 图像的刷新时间为1毫秒
if k == 32: # 按下空格键
cap.release() # 关闭笔记本内置摄像头
cv2.destroywindow("video") # 销毁名为video的窗口
cv2.imwrite("d:/copy.png", frame) # 保存按下空格键时摄像头视频中的图像
cv2.imshow('img', frame) # 显示按下空格键时摄像头视频中的图像
cv2.waitkey() # 刷新图像
break
cv2.destroyallwindows() # 销毁显示图像的窗口
效果:
2.4 读取并显示两个摄像头
编写一个程序,在打开笔记本内置摄像头实时读取并显示视频的同时,再打开一个连接笔记本的外置摄像头。当按下空格键时,关闭笔记本内置摄像头和连接笔记本的外置摄像头,销毁显示摄像头视频的窗口。
代码:
import cv2
cap_inner = cv2.videocapture(0, cv2.cap_dshow) # 打开笔记本内置摄像头
cap_outer = cv2.videocapture(1, cv2.cap_dshow) # 打开一个连接笔记本的外置摄像头
while (cap_inner.isopened() & cap_outer.isopened()): # 两个摄像头都被打开后
retval, img_inner = cap_inner.read() # 从笔记本内置摄像头中实时读取视频
ret, img_outer = cap_outer.read() # 从连接笔记本的外置摄像头中实时读取视频
# 在窗口中显示笔记本内置摄像头读取到的视频
cv2.imshow("video_inner", img_inner)
# 在窗口中显示连接笔记本的外置摄像头读取到的视频
cv2.imshow("video_outer", img_outer)
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 32: # 如果按下空格键
break
cap_inner.release() # 关闭笔记本内置摄像头
cap_outer.release() # 关闭连接笔记本的外置摄像头
cv2.destroyallwindows() # 销毁显示摄像头视频的窗口
这里只有一个内置摄像头,所以代码会报错...
3、视频文件操作
videocapture 类及其方法除了能够读取并显示摄像头视频外,还能够读取并显示视频文件。当窗口根据视频文件的时长显示视频文件时,便实现了播放视频文件的效果。
3.1 读取、显示视频文件
代码如下:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
while (video.isopened()): # 视频文件被打开后
retval, image = video.read() # 读取视频文件
# 设置“video”窗口的宽为420,高为300
cv2.namedwindow("video", 0)
cv2.resizewindow("video", 420, 300)
if retval == true: # 读取到视频文件后
cv2.imshow("video", image) # 在窗口中显示读取到的视频文件
else: # 没有读取到视频文件
break
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 27: # 如果按下esc键
break
video.release() # 关闭视频文件
cv2.destroyallwindows() # 销毁显示视频文件的窗口
展示:
调整 waitkeyo方法中的参数值可以控制视频文件的播放速度。例如,当 cv2.waitkey(1)时,视频文件的播放速度非常快;当cv2.waitkcy(50)时,就能够减缓视频文件的播放速度。
3.2 将视频文件转为灰度视频
使用处理图像的相关方法,能够将摄像头视频由彩色视频转换为灰度视频。那么,使用相同的方病也能够将视频文件由彩色视频转换为灰度视频。
代码:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
while (video.isopened()): # 视频文件被打开后
retval, img_color = video.read() # 读取视频文件
# 设置“video”窗口的宽为420,高为300
cv2.namedwindow("gray", 0)
cv2.resizewindow("gray", 420, 300)
if retval == true: # 读取到视频文件后
# 把“公司宣传.avi”由彩色视频转换为灰度视频
img_gray = cv2.cvtcolor(img_color, cv2.color_bgr2gray)
cv2.imshow("gray", img_gray) # 在窗口中显示读取到的视频文件
else: # 没有读取到视频文件
break
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 27: # 如果按下esc键
break
video.release() # 关闭视频文件
cv2.destroyallwindows() # 销毁显示视频文件的窗口
展示:
3.3 视频文件的暂停和播放
编写一个程序,读取并显示 pycharm 当前项目路径下的视频文件。在播放视频文件的过程中,当按下空格键时,暂停播放视频:当再次按下空格键时,继续播放视频;当按下esc键时,关闭视频文件并销毁显示视频文件的窗口
代码如下:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
while (video.isopened()): # 视频文件被打开后
retval, image = video.read() # 读取视频文件
# 设置“video”窗口的宽为420,高为300
cv2.namedwindow("video", 0)
cv2.resizewindow("video", 420, 300)
if retval == true: # 读取到视频文件后
cv2.imshow("video", image) # 在窗口中显示读取到的视频文件
else: # 没有读取到视频文件
break
key = cv2.waitkey(50) # 窗口的图像刷新时间为50毫秒
if key == 32: # 如果按下空格键
cv2.waitkey(0) # 不刷新图像,实现暂停效果
continue # 再按一次空格键,继续播放
if key == 27: # 如果按下esc键
break
video.release() # 关闭视频文件
cv2.destroyallwindows() # 销毁显示视频文件的窗口
展示:
3.4 获取视频文件的属性
在实际应用中,有时需要知道视频文件的属性。videocapture提供了get()方法
其中,propid 的参数如下:
视频是由大量的、连续的图像构成的,把其中的每幅图像称作帧
帧数指的是视频文件中含有的图像总数,帧数越多,视频播放时越流畅
在播放视频的过程中,把每秒显示图像的数量称作帧速率(ips,单位:帧/s)
宽度指的是图像在水平方向上含有的像素总数、帧高度指的是图像在垂直方向上含有的像素总数
代码:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
fps = video.get(cv2.cap_prop_fps) # 获取视频文件的帧速率
frame_count = video.get(cv2.cap_prop_frame_count) # 获取视频文件的帧数
frame_width = int(video.get(cv2.cap_prop_frame_width)) # 获取视频文件的帧宽度
frame_height = int(video.get(cv2.cap_prop_frame_height)) # 获取视频文件的帧高度
# 输出获取到的属性值
print("帧速率:", fps)
print("帧数:", frame_count)
print("帧宽度:", frame_width)
print("帧高度:", frame_height)
控制台展示:
动态视频属性的实验:
代码:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
fps = video.get(cv2.cap_prop_fps) # 获取视频文件的帧速率
frame_num = 1 # 用于记录第几幅图像(即第几帧),初始值为1(即第1幅图像)
while (video.isopened()): # 视频文件被打开后
retval, frame = video.read() # 读取视频文件
# 设置“video”窗口的宽为420,高为300
cv2.namedwindow("video", 0)
cv2.resizewindow("video", 420, 300)
if retval == true: # 读取到视频文件后
# 当前视频播放到第几帧
cv2.puttext(frame, "frame: " + str(frame_num), (0, 100),
cv2.font_hershey_simplex, 2, (0, 0, 255), 5)
# 该帧对应着视频的第几秒
cv2.puttext(frame, "second: " + str(round(frame_num / fps, 2)) + "s",
(0, 200), cv2.font_hershey_simplex, 2, (0, 0, 255), 5)
cv2.imshow("video", frame) # 在窗口中显示读取到的视频文件
else: # 没有读取到视频文件
break
key = cv2.waitkey(50) # 窗口的图像刷新时间为50毫秒
frame_num += 1 #
if key == 27: # 如果按下esc键
break
video.release() # 关闭视频文件
cv2.destroyallwindows() # 销毁显示视频文件的窗口
展示:
73 代表播放到当前视频的第 73 帧
2.92s 代码播放到当前视频的第 2.92秒
4、保存视频操作
这里介绍保存摄像头和视频文件的操作
opencv提供了videowriter类,具体如下
在opencv中,使用cv2.videowriter_fource() 确定视频编码格式,具体如下
例如:在windows中,fource值为cv2.videowriter_fource('x','y','i','d'),帧速率为20,帧大小为640*480。把一段视频保存在当前目录下,关键代码如下:
把视频保存的话,需要使用write()方法,
4.1 保存一段摄像头的视频
代码:
import cv2
capture = cv2.videocapture(0, cv2.cap_dshow) # 打开笔记本内置摄像头
fourcc = cv2.videowriter_fourcc('x', 'v', 'i', 'd') # 确定视频被保存后的编码格式
output = cv2.videowriter("output.avi", fourcc, 20, (640, 480)) # 创建videowriter类对象
while (capture.isopened()): # 笔记本内置摄像头被打开后
retval, frame = capture.read() # 从摄像头中实时读取视频
if retval == true: # 读取到摄像头视频后
output.write(frame) # 在videowriter类对象中写入读取到的帧
cv2.imshow("frame", frame) # 在窗口中显示摄像头视频
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
if key == 27: # 如果按下esc键
break
capture.release() # 关闭笔记本内置摄像头
output.release() # 释放videowriter类对象
cv2.destroyallwindows() # 销毁显示摄像头视频的窗口
展示:
代码可以重复运行,不过每次都会覆盖上一次的视频
4.2 保存10s的摄像头视频
上述的保存视频,是人为控制的,这里提供代码可以录制固定时长的视频
代码:
import cv2
capture = cv2.videocapture(0, cv2.cap_dshow) # 打开笔记本内置摄像头
fourcc = cv2.videowriter_fourcc('x', 'v', 'i', 'd') # 确定视频被保存后的编码格式
fps = 20 # 帧速率
# 创建videowriter类对象
output = cv2.videowriter("ten_seconds.avi", fourcc, fps, (640, 480))
frame_num = 10 * fps # 时长为10秒的摄像头视频含有的帧数
# 笔记本内置摄像头被打开且时长为10秒的摄像头视频含有的帧数大于0
while (capture.isopened() and frame_num > 0):
retval, frame = capture.read() # 从摄像头中实时读取视频
if retval == true: # 读取到摄像头视频后
output.write(frame) # 在videowriter类对象中写入读取到的帧
cv2.imshow("frame", frame) # 在窗口中显示摄像头视频
key = cv2.waitkey(1) # 窗口的图像刷新时间为1毫秒
frame_num -= 1 # 时长为10秒的摄像头视频含有的帧数减少一帧
capture.release() # 关闭笔记本内置摄像头
output.release() # 释放videowriter类对象
cv2.destroyallwindows() # 销毁显示摄像头视频的窗口
展示:
右键可以查看视频的属性:
4.3 读取视频文件并且保存视频文件
读取视频文件,然后将视频保存
代码:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
fps = video.get(cv2.cap_prop_fps) # 获取视频文件的帧速率
# 获取视频文件的帧大小
size = (int(video.get(cv2.cap_prop_frame_width)),
int(video.get(cv2.cap_prop_frame_height)))
fourcc = cv2.videowriter_fourcc('x', 'v', 'i', 'd') # 确定视频被保存后的编码格式
output = cv2.videowriter("copy.avi", fourcc, fps, size) # 创建videowriter类对象
while (video.isopened()): # 视频文件被打开后
retval, frame = video.read() # 读取视频文件
if retval == true: # 读取到视频文件后
output.write(frame) # 在videowriter类对象中写入读取到的帧
else:
break
print("公司宣传.avi已经保存为pycharm当前项目路径下的copy.avi。") # 控制台输出提示信息
video.release() # 关闭视频文件
output.release() # 释放videowriter类对象
4.4 读取视频并保存前10s的视频文件
代码如下:
import cv2
video = cv2.videocapture("公司宣传.avi") # 打开视频文件
fps = video.get(cv2.cap_prop_fps) # 获取视频文件的帧速率
# 获取视频文件的帧大小
size = (int(video.get(cv2.cap_prop_frame_width)),
int(video.get(cv2.cap_prop_frame_height)))
fourcc = cv2.videowriter_fourcc('x', 'v', 'i', 'd') # 确定视频被保存后的编码格式
output = cv2.videowriter("ten_seconds.avi", fourcc, fps, size) # 创建videowriter类对象
frame_num = 10 * fps # 视频文件的前10秒视频含有的帧数
# 视频文件被打开后且视频文件的前10秒视频含有的帧数大于0
while (video.isopened() and frame_num > 0):
retval, frame = video.read() # 读取视频文件
if retval == true: # 读取到视频文件后
output.write(frame) # 在videowriter类对象中写入读取到的帧
frame_num -= 1 # 视频文件的前10秒视频含有的帧数减少一帧
# 控制台输出提示信息
print("公司宣传.avi的前10s视频已经保存为pycharm当前项目路径下的ten_seconds.avi。")
video.release() # 关闭视频文件
output.release() # 释放videowriter类对象
展示:
发表评论