目的:
初次接触OpenCV读写文件、操作视频。个人觉得方式很重要,以及细节点注意。对于一些重要关键点写下来。
网址:
http://c.biancheng.net/opencv/
OpenCV是什么?
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,它提供了很多函数,这些函数非常高效地实现了计算机视觉算法(最基本的滤波到高级的物体检测皆有涵盖)。OpenCV 使用 C/C++ 开发,同时也提供了 Python、Java、MATLAB 等其他语言的接口
Mat 类:
Mat 类是存储和操作 OpenCV 中图像的主要数据结构。这个类是在 core 模块中定义的。OpenCV 已经实现了对于这些数据结构自动分配和释放内存的机制。但是,当数据结构共享相同的缓冲存储器时,程序员仍然应该特别注意。
例如,赋值运算符并没有从一个对象(Mat A)到另一个对象(Mat B)复制内存内容;而只是对其引用(相应内容的存储地址)的复制。之后,一个对象(A 或 B)的改变对两个对象都有影响。为了复制一个 Mat 对象的内存内容,应该使用成员函数 Mat::clone()。
重要点:
Mat imread(const String& filename,int flags = IMREAD_COLOR);
flag 指定读取图像的颜色,并在 imgcodecs.hpp 头文件中由如下枚举类型定义和解释:
enum { IMREAD_UNCHANGED = -1, // 8 位,彩色或非彩色
IMREAD_GRAYSCALE = 0, // 8 位,灰度
IMREAD_COLOR = 1, //未改变深度、颜色
IMREAD_ANYDEPTH = 2, //任意深度,未改变颜色
IMREAD_ANYCOLOR = 4, //未改变深度,任意颜色
IMREAD_LOAD_GDAL = 8 // 使用 gdaL 驱动程序
};
注意,在 OpenCV 3.0 版本中,函数 imread 是在 imgcodecs 模块中,而不是像 OpenCV 2.x 在 highgui 模块中。另外,因为一些函数和声明被移入到 OpenCV 3.0 中,所以连接器可能会由于找不到一个或多个声明(符号和/或函数)而得到一些编译错误。
读取输入的图像文件之后,应检查操作是否成功。可使用成员函数 in_image.empty() 来实现这个检查
**
**
imgcodecs 模块中的另一个重要函数是:
bool imwrite(const String& filename,InputArray img,const vector& params=vector())
这个函数将一幅图像(img)保存到一个文件(filename),作为第三个可选参数,一个“属性-值”对的向量指定编解码器的参数(为使用默认值将其设置为空)。编解码器由文件的扩展名决定。 文件名可以使相对地址。
在 OpenCV 中,VideoCapture 类和 VideoWriter 类为视频处理中所涉及的捕获和记录任务提供了一个易用的 C++API。
#include
#include
using namespace std;
using namespace cv;
int main(int, char **)
{
Mat in_frame, out_frame;
const char win1[]=“Grabbing…”, win2[]=“Recording…”;
double fps=30;//每秒的帧数
char file_out[]=“recorded.avi”;
VideoCapture inVid(O) ; //打开默认摄像机
if ( !inVid.isOpened () ) { //检查错误
cout << "Error! Camera not ready...\n";
return -1;
}
//获取输入视频的宽度和高度
int width = (int)inVid.get(CAP_PROP_FRAME_WIDTH);
int height = (int)inVid.get(CAP_PR〇P_FRAME_HEIGHT);
VideoWriter recVid(file out,VideoWriter::fourcc('M','S','V','C'), fps, Size(width, height));
if (!recVid.isOpened()) {
cout << "Error! Video file not opened...\n";
return -1;
}
//为原始视频和最终视频创建两个窗口
namedWindow(win1);
namedWindow(win2);
while (true) {
//从摄像机读取帧(抓取并解码)
inVid >> in frame;
//将帧转换为灰度
cvtColor(in_frame, out_frame, C0L0R_BGR2GRAY);
//将幀写入视频文件(编码并保存)
recVid << out_frame ?
imshow (win1, in_frame);// 在窗口中显示帧
imshow(win2, out_frame); // 在窗口中显示帧
if (waitKey(1000/fps) >= 0)
break;
}
inVid.release(); // 关闭摄像机
return 0;
}
double VideoCapture::get(int propId):
这个函数为一个 VideoCapture 对象返回指定的属性值。在 videoio.hpp 头文件中包含了基于 DC1394(IEEE 1394 数码相机规范)属性的一个完整列表。
static int VideoWriter::fourcc(char c1,char c2,char c3,char c4):
这个函数把四个字符连接起来形成一个 fourcc 码。在示例中,MSVC 代表微软视频(仅在 Windows 上可用)。有效的 fourcc 码列表被发布在 http://www.fourcc.org/codecs.php 上。
FourCC全称Four-Character Codes,代表四字符代码 (four character code), 它是一个32位的标示符,其实就是typedef unsigned int FOURCC;是一种独立标示视频数据流格式的四字符代码。
视频播放软件通过查询 FourCC 代码并且寻找与 FourCC 代码相关联的视频解码器来播放特定的视频流。比如: DIV3 = DivX Low-Motion, DIV4 = DivX Fast-Motion, DIVX = DivX4, FFDS = FFDShow 等。比如wav、avi等RIFF文件的标签头标示,Quake 3的模型文件.md3中也大量存在等于“IDP3”的FOURCC。
bool VideoWriter::isOpened():如果写入视频的对象被成功初始化,这个函数返回 true。例如,使用一个不正确的编解码器会产生一个错误。
注意,在一个系统中有效的 fourcc 码依赖于本地安装的编解码器。为了了解在本地系统中安装的 fourcc 编解码器是否可用,推荐 http://mediaarea.net/en/MediaInfo 上对很多平台都可用的开源工具 MediaInfo。
VideoCapture&VideoCapture::operator>>(Mat&image):
这个函数抓取、解码并返回下一帧。这个方法和布尔函数 VideoCapture::read(OutputArray image)等价。可以使用这个函数而不使用函数 VideoCapture::grab(),然后使用 VideoCapture::retrieve()。
VideoWriter&VideoWriter::operator<<(const Mat&image):
这个函数写入下一帧。这个方法和布尔函数 VideoWriter::write(const Mat&image)等价。
在本示例中,有一个读取/写入循环,可同时地获取并处理窗口事件。waitKey(1000/fps)函数调用负责执行这个任务。在这个示例中,1000/fps 表示返回外部循环之前等待的毫秒数。尽管不精确,但对于录制的视频仍能获取每秒帧数的一个近似度量。
void VideoCapture::release():这个函数释放视频文件或采集设备。尽管在本示例中没有必要显式地包含,但为了说明它的使用,示例中仍包含了这个函数。