基于OpenCV和Python的文件操作——捕获摄像头的帧,在窗口显示图像,在窗口显示摄像头帧和视频文件的读/写

0 写在前面

这篇博客主要参考资料为《OpenCV 3计算机视觉Python语言实现》(Learning OpenCV 3 Computer Vison with Python)。
因为之前用Faster R-CNN做过一个红绿灯检测的小实践,但是Github提供的demo的输入只是几幅测试图片,而且显示用的matplotlib库,每个窗口必须手动关闭后才能显示下一个窗口,交互体验不好。
为了更好的交互体验和实际测试等需求,应该把输入改为视频流,实时显示检测结果,记录时间戳,保存图像、视频、检测结果等,因此使用到了OpenCV的文件操作等知识。
文件操作包括捕获摄像头的帧,在窗口显示图像,在窗口显示摄像头帧,视频文件的读/写等基本知识,目前只用到了这些,在此记录一下。

1安装OpenCV

我使用的系统为Ubuntu 14.04 LTS,所以这里只介绍在Ubuntu系统安装OpenCV的方法,Windows和OS X请自行查阅资料。
另外编程语言为Python,随人工智能大火的一门语言。

1.1 使用Ubuntu的资源库

以下命令可通过apt这样的包管理器来安装Python及其所依赖的软件包:

$ sudo apt-get install build-essential
$ sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodecdev libavformat-dev libswscale-dev
$ sudo apt-get install python-dev python-numpy libtbb2 libtbb2-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

注:OpenCV的依赖项很多,缺少某些编译项会影响它的部分功能,所以要根据需求提前安装对应的依赖项。

1.2 从源代码构建OpenCV

OenCV目前维护了两个主要版本,分为OpenCV 2.4系列和OpenCV 3系列,请根据需求在https://opencv.org/releases.html下载对应的source版本,然后解压到任意目录下。
本博客使用的OpenCV版本为3.0.0,代码也与之对应,不同版本可能会出现AttributeError: 'module' object has no attribute 'sth.',这是需要查阅文档进行修改。
打开终端,将当前路径切换到OpenCV的解压的目录下,然后运行以下命令:

$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
$ make
$ make install

注:在实际开发中,我们可能会需要不同版本的OpenCV,此时可以将不同版本的OpenCV安装在不同路径下,并在CMakeLists.txt中指定需要的OpenCV路径即可。具体方法请百度。

1.3 运行示例验证是否安装成功

安装结束后,可以在< opencv_folder >/opencv/samples/python文件夹和< opencv_folder >/opencv/samples/python2文件夹下找到OpenCV的Python示例。
打开终端,将当前路径切换到切换到< opencv_folder >/opencv/samples/python下,然后运行以下命令:

$ python camera.py

打开camera.py,内容如下:

#!/usr/bin/python

import cv2.cv as cv
import time

cv.NamedWindow("camera", 1)

capture = cv.CaptureFromCAM(0)

while True:
    img = cv.QueryFrame(capture)
    cv.ShowImage("camera", img)
    if cv.WaitKey(10) == 27:
        break
cv.DestroyAllWindows()

该脚本会显示摄像头捕获的图像,如果是笔记本电脑默认是在带的摄像头,如果是台式机需要安装一个网络摄像头。
如果打开的窗口能实时地显示摄像头捕获的图像,则表明OpenCV安装成功。
当然还有很多脚本可以用做验证,这些脚本也可以当做学习资料。

2 文件操作

2.1 捕获摄像头的帧

VideoCapture类可以获得摄像头的帧流。下面的例子会捕获摄像头10秒的视频信息,并将其写入一个AVI文件中:

#--coding=utf8--
import cv2

cameraCapture = cv2.VideoCapture(0) #请设置摄像头的设备索引(device index)
fps = 30 # an assumption
size = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('MyOutputVedio.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)  # 版本为OpenCV 3

success, frame = cameraCapture.read()
numFramesRemaining = 10 * fps - 1
while success and numFramesRemaining > 0:
    videoWriter.write(frame)
    success, frame = cameraCapture.read()
    numFramesRemaining -= 1
cameraCapture.release()

如何查询摄像头设备的索引见这篇博客,尤其在多摄像的情况下。

2.2 在窗口显示图像

imshow()函数可以实现显示图像,以下代码可以显示一幅图像:

#--coding=utf8--
import cv2
import numpy as np

img = cv2.imread('my-image.png') #这里最好使用图片的绝对路径
cv2.imshow('my image', img)
cv2.waitKey()
cv2.destroyAllWindows()

imshow()函数有两个参数:显示图像帧的名称以及要显示的图像本身。
调用destroyAllWindows()函数可以释放由OpenCV创建的所有窗口。

2.3 在窗口显示摄像头帧

namedWindow()、imshow()和destroyWindows()函数允许指定窗口名来创建、显示和销毁窗口。
任意窗口都可以通过waitKey()函数来获取键盘输入,通过setMouseCallback()函数来获取鼠标输入。
以下代码可以实时显示摄像头帧:

import cv2

clicked = False
def onMouse(event, x, y, flags, param):
    global clicked
    if event == cv2.EVENT_LBUTTONUP:
        clicked == True

cameraCapture = cv2.VideoCapture(0)
cv2.namedWindow('MyWindow')
cv2.setMouseCallback('MyWindow', onMouse)

print 'Showing camera feed. Click window or press any key to stop.'

success, frame = cameraCapture.read()
while success and cv2.waitKey(1) == -1 and not clicked:
    cv2.imshow('MyWindow', frame)
    success, frame = cameraCapture.read()

cv2.destroyAllWindows('MyWindow')
cameraCapture.release()

waitKey()的参数为等待键盘触发的时间,单位为毫秒,其返回值是-1,表示没有键被按下,如果返回27表示按下Esc键。

2.4 视频文件的读/写

VideoCapture类和VideoWriter类支持各种格式的视频文件。
在到达视频文件末尾之前,可以通过VideoCapture类的read()函数来获取新的帧,每一帧是基于BGR格式的图像。
可将一幅图像传递给VideoWriter类的write()函数,该函数会将这幅图像加到VideoWriter类指向的文件中。
以下示例读取AVI文件的帧,并采用YUV颜色编码将其写入另一个帧中:

#--coding=utf8--
import cv2

videoCapture = cv2.VideoCapture('MyInputVideo.avi') #使用绝对路径

fps = videoCapture.get(cv2.CAP_PROP_FPS)
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('MyOutputVedio.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)  # 版本为OpenCV 3.0.0,MyOutputVedio.avi使用绝对路径

success, frame = videoCapture.read()
while success:
    VideoWriter.write(frame)
    success, frame = videoCapture.read()

3 总结

综上,基于OpenCV和Python的文件读写基本介绍完了,实际开发中灵活结合即可。
后续计划基于OpenCV做一个小项目。

阅读更多
换一批

没有更多推荐了,返回首页