图像识别与处理之Opencv——图像数据获取与存储(imread()和imwrite()函数)
来源:互联网 发布:淘宝外卖怎么看在骑手 编辑:程序博客网 时间:2024/06/05 04:12
一、 读写图像文件
将图像文件读入内存,可以使用 imread()函数;
将 Mat 对象以图像文件格式写入内存,可以使用imwrite()函数。
1.1 读图像文件——imread()
imread()函数返回的是 Mat 对象,如果读取文件失败,则会返回一个空矩阵,即 Mat::data 的值是 NULL。执行 imread()之后,需要检查文件是否成功读入,你可以使用 Mat::empty()函数进行检查。
imread()函数的声明如下:
Mat imread(const string& filename, int flags=1)
很明显参数 filename 是被读取或者保存的图像文件名;在 imread()函数中,flag 参数值有三种情况:
- flag>0,该函数返回 3 通道图像,如果磁盘上的图像文件是单通道的灰度图像,则会被强制转为 3 通道;
- flag=0,该函数返回单通道图像,如果磁盘的图像文件是多通道图像,则会被强制转为单通道;
- flag<0,则函数不对图像进行通道转换。
imread()函数支持多种文件格式,且该函数是根据图像文件的内容来确定文件格式,而不是根据文件的扩展名来确定。所指示的文件格式如下:
- Windows 位图文件 - BMP, DIB;
- JPEG 文件 - JPEG, JPG, JPE;
- 便携式网络图片 - PNG;
- 便携式图像格式 - PBM, PGM, PPM;
- Sun rasters - SR, RAS;
- TIFF 文件 - TIFF, TIF;
- OpenEXR HDR 图片 - EXR;
- JPEG 2000 图片- jp2。
你所安装的 OpenCV 并不一定能支持上述所有格式,文件格式的支持需要特定的库,只有在编译 OpenCV 添加了相应的文件格式库,才可支持其格式。
1.2 写图像文件
将图像写入文件,可使用 imwrite()函数,该函数的声明如下:
bool imwrite(const string& filename, InputArray image, const vector<int>& params=vector<int>())
文件的格式由 filename 参数指定的文件扩展名确定。推荐使用 PNG 文件格式。 BMP 格式是无损格式,但是一般不进行压缩,文件尺寸非常大; JPEG 格式的文件娇小,但是 JPEG 是有损压缩,会丢失一些信息。 PNG 是无损压缩格式,推荐使用
imwrite()函数的第三个参数 params 可以指定文件格式的一些细节信息。这个参数里面的数值是跟文件格式相关的:
- JPEG:表示图像的质量,取值范围从 0 到 100。数值越大表示图像质量越高,当然文件也越大。默认值是 95。
- PNG:表示压缩级别,取值范围是从 0 到 9。数值越大表示文件越小,但是压缩花费的时间也越长。默认值是 3。
- PPM, PGM 或 PBM:表示文件是以二进制还是纯文本方式存储,取值为0 或 1。如果取值为 1,则表示以二进制方式存储。默认值是 1。
并不是所有的 Mat 对象都可以存为图像文件,目前支持的格式只有 8U 类型的单通道和 3 通道(颜色顺序为 BGR)矩阵;如果需要要保存 16U 格式图像, 只能使用 PNG、 JPEG 2000 和 TIFF 格式。
如果希望将其他格式的矩阵保存为图像文件,可以先用 Mat::convertTo()函数或者 cvtColor()函数将矩阵转为可以保存的格式。
另外需要注意的是,在保存文件时,如果文件已经存在, imwrite()函数不会进行提醒,将直接覆盖掉以前的文件。
下面例程展示了如何读入一副图像,然后对图像进行 Canny 边缘操作,最后将结果保存到图像文件中。
#include "stdafx.h"#include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/opencv.hpp"using namespace std;using namespace cv;int main(int argc, char* argv[]){ //读入图像,并将之转为单通道图像 Mat im = imread("lena.jpg", 0); //相对路径,即在工程文件夹里 //请一定检查是否成功读图 if (im.empty()) { cout << "Can not load image." << endl; return -1; } //进行 Canny 操作,并将结果存于 result Mat result; Canny(im, result, 50, 150); //保存结果 imwrite("lena-canny.png", result); return 0; }
将
lena.jpg 文件放在当前目录,运行该例程后, lena-canny.png 将会出现在当前目录。 lena-canny.png 图像如下图所示,是 lena.jpg 的边缘提取结果
二、读写视频
介绍 OpenCV 读写视频之前,先介绍一下编解码器(codec)。如果是图像文件,我们可以根据文件扩展名得知图像的格式。但是此经验并不能推广到视频文件中。有些 OpenCV 用户会碰到奇怪的问题,都是 avi 视频文件,有的能用 OpenCV打开,有的不能。
视频的格式主要由压缩算法决定。压缩算法称之为编码器(coder),解压算法称之为解码器(decoder),编解码算法可以统称为编解码器(codec)。视频文件能读或者写,关键看是否有相应的编解码器。编解码器的种类非常多,常用的有 MJPG、 XVID、 DIVX 等,完整的列表请参考 FOURCC 网站 http://www.fourcc.org/codecs.php。因此视频文件的扩展名(如 avi 等)往往只能表示这是一个视频文件。OpenCV 2 中提供了两个类来实现视频的读写。读视频的类是 VideoCapture,写视频的类是 VideoWriter。
2.1 读视频
VideoCapture 既可以从视频文件读取图像,也可以从摄像头读取图像。 可以使用该类的构造函数打开视频文件或者摄像头。如果 VideoCapture 对象已经创建,也可以使用 VideoCapture::open()打开, VideoCapture::open()函数会自动调用VideoCapture::release()函数,先释放已经打开的视频,然后再打开新视频。
如果要读一帧,可以使用 VideoCapture::read()函数。VideoCapture 类重载了>>操作符,实现了读视频帧的功能。 下面的例程演示了使用 VideoCapture 类读视频。
#include <iostream>#include "opencv2/opencv.hpp" using namespace std; using namespace cv; int main(int argc, char** argv) { //打开第一个摄像头 //VideoCapture cap(0); //打开视频文件 VideoCapture cap("video.short.raw.avi"); //检查是否成功打开 if (!cap.isOpened()) { cerr << "Can not open a camera or file." << endl; return -1; } Mat edges; //创建窗口 namedWindow("edges", 1); for (;;) { Mat frame; //从 cap 中读一帧,存到 frame cap >> frame; if (frame.empty())//如果未读到图像 break; cvtColor(frame, edges, CV_BGR2GRAY);//将读到的图像转为灰度图 Canny(edges, edges, 0, 30, 3); //进行边缘提取操作 //显示结果 imshow("edges", edges); //等待 30 秒,如果按键则退出循环 if (waitKey(30) >= 0) break; } //退出时会自动释放 cap 中占用资源 return 0; }
2.2 写视频
使用 OpenCV 创建视频也非常简单,与读视频不同的是,你需要在创建视频时设置一系列参数,包括:文件名,编解码器,帧率,宽度和高度等。编解码器使用四个字符表示,可以是
CV_FOURCC(‘M’,’J’,’P’,’G’)、
CV_FOURCC(‘X’,’V’,’I’,’D’)、
CV_FOURCC(‘D’,’I’,’V’,’X’)等。
如果使用某种编解码器无法创建视频文件,请尝试其他的编解码器。
将图像写入视频可以使用 VideoWriter::write()函数, VideoWriter 类中也重载了<<操作符,使用起来非常方便。另外需要注意:待写入的图像尺寸必须与创建
视频时指定的尺寸一致。下面例程演示了如何写视频文件。本例程将生成一个视频文件,视频的第 0帧上是一个红色的“0”,第 1 帧上是个红色的“1”,以此类推,共 100 帧。
#include "stdafx.h"#include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/opencv.hpp"using namespace std;using namespace cv;int main(int argc, char* argv[]){ //定义视频的宽度和高度 Size s(320, 240); //创建 writer,并指定 FOURCC 及 FPS 等参数 VideoWriter writer = VideoWriter("myvideo.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25, s); //检查是否成功创建 if (writer.isOpened()) { cerr << "Can create video file.\n" << endl; } if (!writer.isOpened()) { cerr << "Can not create video file.\n" << endl; return -1; } //视频帧 Mat frame(s, CV_8UC3); for (int i = 0; i < 100; i++) { frame = Scalar::all(255); //将整数 i 转为 i 字符串类型 char text[128]; snprintf(text, sizeof(text), "%d", i); //将数字绘到画面上 putText(frame, text, Point(s.width / 3, s.height / 3), FONT_HERSHEY_SCRIPT_SIMPLEX, 3, Scalar(0, 0, 255), 3, 8); //将在图像中呈现指定的文本字符串 writer << frame; //将图像写入视频 } //退出程序时会自动关闭视频文件 return 0;}
该程序生成的视频截图:
- 图像识别与处理之Opencv——图像数据获取与存储(imread()和imwrite()函数)
- 图像识别与处理之Opencv——Mat类
- 图像识别与处理之Opencv——常用的OpenCV2函数速查
- 图像识别与处理之Opencv——高斯滤波及GaussianBlur()函数
- OpenCV3图像处理--imread、imwrite、clone
- 图像识别与处理之Opencv——选取图像局部区域
- 图像识别与处理之Opencv——Mat_类与Mat 类的内存管理
- Opencv输出图像函数-imwrite
- opencv读取图像的几个基本函数,imread、namedWindow、imshow、imwrite
- 图像识别与处理之Opencv——像素值的读写
- 图像识别与处理之Opencv——基本数据结构及示例
- Opencv 图像结构分析与形状识别—— drawContours函数用于绘制和填充
- 图像识别与处理之Opencv——Mat表达式的运算(矩阵的一些运算)
- 图像识别与处理之Opencv——霍夫变换编程思路(11月2日暂存)
- 图像处理和图像识别中常用的OpenCV函数
- 图像处理和图像识别中常用的OpenCV函数
- 图像处理和图像识别中常用的OpenCV函数
- 图像处理和图像识别中常用的OpenCV函数
- Machine learning(1)--环境
- .bat脚本基本命令语法
- java (apache POI 组件) 操作 excel 插入批注
- 运行exe报 f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\occcont.cpp 错误解决方法
- Load region LR_IROM1 size(131996 bytes) exceeds limit (131072 bytes)
- 图像识别与处理之Opencv——图像数据获取与存储(imread()和imwrite()函数)
- 提供公共外部逻辑
- Java生成MD5加密字符串
- JNDI 是什么
- flyerinternational优势 擦亮眼进来瞧瞧
- C#取整函数Math.Round、Math.Ceiling和Math.Floor
- Ubuntu 16.04下设置静态IP
- git命令
- 剑指offer---从尾到头打印链表