OpenCV竟然可以这样学!成神之路终将不远(二)

2 图像入门--视频

2.1 从相机中读取视频

要捕获视频,你需要创建一个 VideoCapture 对象。它的参数可以是设备索引或视频文件的名称。设备索引就是指定哪个摄像头的数字。正常情况下,一个摄像头会被连接。所以我简单地传0(或-1)。你可以通过传递1来选择第二个相机,以此类推。在此之后,你可以逐帧捕获。但是在最后,不要忘记释放俘虏。

代码如下:

import cv2 as cv

capture = cv.VideoCapture(0)
if not capture.isOpened():
    print('cannot open camera')
    exit()

while True:

    # 逐帧捕捉
    ret, frame = capture.read()

    # 如果正确读取帧,ret为True
    if not ret:
        print("Can't receive frame (stream end). Exiting...")
        break
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    # 显示结果帧
    cv.imshow('frame', gray)
    # 这里设的是每3ms读取一帧,按下ESC键退出
    if cv.waitKey(3) & 0xFF == 27:
        break

# 完成所有操作后,释放捕获器
capture.release()
cv.destroyAllWindows()

capture.read() 返回布尔值( True / False )。如果正确读取了帧,它将为True 。因此,你可以通过检查此返回值来检查视频的结尾。

有时,capture可能尚未初始化捕获。在这种情况下,此代码显示错误。你可以通过capture.isOpened()方法检查它是否已初始化。如果是True,那么确定。否则,使用capture.open()打开它。

你还可以使用capture.get(propId) 方法访问该视频的某些功能,其中propId是0到18之间的一个数字。每个数字表示视频的属性(如果适用于该视频),并且可以显示完整的详细信息在这里看到:cv::VideoCapture::get()。其中一些值可以使用capture.set(propId,value) 进行修改。value是你想要的新值。

这里附上propId中0~18这些数字代表的值:

参数 propld 功能
cv2.CAP_PROP_POS_MSEC 0 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳
cv2.CAP_PROP_POS_FRAMES 1 基于0的索引将被解码/捕获下一帧
cv2.CAP_PROP_POS_AVI_RATIO 2 视频文件的相对位置:0 - 视频的开始,1 - 视频的结束
cv2.CAP_PROP_FRAME_WIDTH 3 帧的宽度
cv2.CAP_PROP_FRAME_HEIGHT 4 帧的高度
cv2.CAP_PROP_FPS 5 帧速
cv2.CAP_PROP_FOURCC 6 4个字符表示的视频编码器格式
cv2.CAP_PROP_FRAME_COUNT 7 帧数
cv2.CAP_PROP_FORMAT 8 byretrieve()返回的Mat对象的格式
cv2.CAP_PROP_MODE 9 指示当前捕获模式的后端特定值
cv2.CAP_PROP_BRIGHTNESS 10 图像的亮度(仅适用于相机)
cv2.CAP_PROP_CONTRAST 11 图像对比度(仅适用于相机)
cv2.CAP_PROP_SATURATION 12 图像的饱和度(仅适用于相机)
cv2.CAP_PROP_HUE 13 图像的色相(仅适用于相机)
cv2.CAP_PROP_GAIN 14 图像的增益(仅适用于相机)
cv2.CAP_PROP_EXPOSURE 15 曝光(仅适用于相机)
cv2.CAP_PROP_CONVERT_RGB 16 表示图像是否应转换为RGB的布尔标志
cv2.CAP_PROP_WHITE_BALANCE 17  
cv2.CAP_PROP_RECTIFICATION 18 立体摄像机的整流标志

代码如下:

frame_width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
print(frame_width, frame_height)
 

cv.CAP_PROP_FRAME_WIDTH和cv.CAP_PROP_FRAME_HEIGHT分别可以获取视频的宽度和高度。

如果想要修改宽高,就需要使用capture.set,直接在后面添加自己想要的数值就行了,像这样:

capture.set(cv.CAP_PROP_FRAME_WIDTH, 480)
capture.set(cv.CAP_PROP_FRAME_HEIGHT, 270)

注意:①capture.set只是用来设置摄像头采集图像的宽高的,自己放入的视频并不能通过set函数进行修改,我还一直用它来设置自己的视频,结果半天反应没有,原来这个只能用修改摄像头的;

②如果发现不能修改,可能你放在打开摄像头之前了,需要将它放在打开摄像头之后;

③再有一个就是如果出现错误,请确保使用任何其他相机应用程序(例如Linux中的Cheese)都可以正常使用相机。

2.2 从文件播放视频

它与从相机捕获相同,只是用视频文件名更改摄像机索引。另外,在显示框架时,请使用适当的时间cv.waitKey() 。如果太小,则视频将非常快,而如果太大,则视频将变得很慢(嗯,这就是显示慢动作的方式)。正常情况下25毫秒就可以了,这里涉及到帧率的相关知识,大家可以自行百度去查看。

代码如下:

import cv2 as cv

capture = cv.VideoCapture('03.mp4')
while capture.isOpened():
    ret, frame = capture.read()
    # 如果正确读取帧,ret为True
    if not ret:
        print("不能接收到帧,正在退出中。。。")
        break
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)  # 将每一帧转换为灰度图像
    cv.imshow('frame', gray)
    if cv.waitKey(15) & 0xFF == ord('q'):
        break
capture.release()
cv.destroyAllWindows()

注意:确保安装了正确的 ffmpeg 或 gstreamer 版本。有时,使用视频捕获(Video Capture)是一件令人头疼的事情,主要原因是错误地安装了 ffmpeg / gstreamer。

2.3 保存视频

我们都知道保存图像用cv.imwrite()就可以了,那么视频应该怎么保存呢?

保存视频我们使用的是cv.VideoWriter对象,主要参数有四个:

  • 第一个参数是输出文件名(eg:out.avi)。
  • 第二个参数是fourcc代码段,直接用cv.VideoWriter_fourcc()对象调用,是用于指定视频编解码器的4字节代码,可以在fourcc.org这里找到详细的代码段。
  • 第三个参数是传递帧率的数量,单位fps。
  • 第四个参数是传递帧率的大小。

fourcc代码段详细参数以及使用方法这里就不说了,这里涉及到视频编解码知识,大家可以查找相关资料。

直接上代码:

import cv2 as cv

capture = cv.VideoCapture('03.mp4')
print(capture.get(cv.CAP_PROP_FRAME_WIDTH))  # 960
print(capture.get(cv.CAP_PROP_FRAME_HEIGHT))  # 540
# 定义编解码器并创建VideoWriter对象
fourcc = cv.VideoWriter_fourcc(*'XVID')
save_video = cv.VideoWriter('out.avi', fourcc, 500.0, (960, 540))

while capture.isOpened():
    ret, frame = capture.read()
    if not ret:
        print("不对,我看不见视频啊。。。重新换一个试试?")
        break
    frame = cv.flip(frame, 0)
    # 写翻转的框架
    save_video.write(frame)
    cv.imshow('frame', frame)
    if cv.waitKey(1) & 0xff == 27:
        break

# 完成保存之后释放所有内容
capture.release()
save_video.release()
cv.destroyAllWindows()

注意:相信在这里,大家保存视频会有很多问题,打不开,报各种错误,这里列举了一下:

1. 在 VideoWriter 中指定的尺寸要和 write() 中写进去的一样,不然视频会存储失败的。

2. 仔细看自己的代码while循环里面是否写错了,一般都是这里写错了。

3. 根据自己电脑系统,选择合适的fourcc代码段。

3. 若觉得都没有问题,还是无法打开,将编译环境退出一次或者重启,视频就彻底生成成功并且可以播放了

上一篇:五分钟学会做一个在线抽奖系统,手把手教你抽奖还学不会嘛?


下一篇:c#利用反射给字段属性赋值