本篇文章介绍一下如何使用OpenCV往文件中写入图像或视频。
一、写入图像
程序
下面的例子,创建一个黄色的图像并写入到文件中 。我们先来看一下如何使用OpenCV完成它。
#include <opencv2\highgui\highgui.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char **argv) { Mat img(650, 600, CV_16UC3, Scalar(0, 50000, 50000)); if (img.empty()) { cout << "加载图像失败!" << endl; system("pause"); return -1; } vector<int> compression_params; compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); compression_params.push_back(98); bool bSuccess = imwrite("C:\\Users\\mingceng\\Documents\\TestImage.jpg", img, compression_params); if (!bSuccess) { cout << "保存图像失败!" << endl; } namedWindow("MyWindow", CV_WINDOW_AUTOSIZE); imshow("MyWindow", img); waitKey(0); destroyWindow("MyWindow"); return 0; }
上面的程序和OpenCV读取和显示图片一文“建一个空图像并显示”部分很相似。如果需要本文没有解释到的OpenCV函数的进一步说明,请参考“OpenCV读取和显示图片”一文。
解释
bool imwrite( const string& filename, InputArray img, const vector<int>& params=vector<int>())
这个函数保存"img"变量中的图像到"filename"指定的文件中。保存图像成功,返回true,否则返回false。
它的参数:
- filename - 指定目标文件的路径和名称
- img - 要保存的图像
- params - 这是指定图像格式的int向量
- JPEG 格式 - 首先 push_back CV_IMWRITE_JPEG_QUALITY 然后是一个0-100的数(数越大质量越好)。如果想获取最佳质量的输出,就使用100,但是值越大,写入图像需要的时间越长
- PNG 格式 - 首先puch_back CV_IMWRITE_PNG_COMPRESSION然后是一个0-9的数(值越大压缩越好,也更慢)
图像格式的选择取决于文件的扩展名。只有8 bit或16 bit 无符号单通道或3通道(CV_8UC1, CV_8UC3, CV_8SC1, CV_8SC3, CV_16UC1, CV_16UC3)且是'BGR'通道顺序的图像才可以保存。如果图像的位深或通道顺序不支持使用imwrite函数,可以使用"Mat::convertTo()"或"cvtColor"函数转换图像为支持的格式。
总结
这个程序创建了一个黄色的图像(3个通道,16位深,650高,500宽,(0,50000,50000)分别分配给BGR通道)。因为图像是16位深,每个通道的元素可以使用0-65535的值。我在green和red通道为每个元素使用50000来指定黄色。然后指定压缩技术。上面的例子中,我使用JPEG压缩技术。然后保存图像在"C:\\Users\\mingceng\\Documents\\TestImage.jpg"。最后在窗口中显示该图像,直到用户按下任意键。
二、写入视频
程序
下面的例子,从摄像头捕获一个视频并写入到文件中。我们看一下如何使用OpenCV完成它。
#include <opencv2\highgui\highgui.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char **argv) { VideoCapture cap(0); if (!cap.isOpened()) { cout << "不能打开摄像头设备!" << endl; return -1; } namedWindow("MyVideo", CV_WINDOW_AUTOSIZE); double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); cout << "帧尺寸:" << dWidth << "x" << dHeight << endl; Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight)); VideoWriter oVideoWriter("C:\\Users\\mingceng\\Documents\\MyVideo.avi", CV_FOURCC('D', 'I', 'V', 'X'), 10, frameSize, true); if (!oVideoWriter.isOpened()) { cout << "初始化VideoWriter失败!" << endl; return -1; } while (1) { Mat frame; bool bSuccess = cap.read(frame); if (!bSuccess) { cout << "不能从视频中读取帧!" << endl; break; } oVideoWriter.write(frame); imshow("MyVideo", frame); if (waitKey(10) == 27) { cout << "按下ESC键!" << endl; break; } } return 0; }
解释
Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight))
创建一个给定宽和高的Size对象。这里我转换宽和高为整数,因为它们初始是double值,Size构造函数不接受double值作为它的参数。
VideoWriter::VideoWriter(const string& filename, int fourcc, double fps, Size frameSize, bool isColor=true)
这是VideoWriter类的构造函数。它使用下面的参数初始化对象:
- const string& filename - 指定输出文件的路径和名称
- int fourcc - 指定用于压缩视频的编解码器的四字符代码。你的电脑可能不支持一些编解码器,所以如果保存视频失败,尝试另外的编解码器,下面是一些常见的编解码器:
- CV_FOURCC('D', 'I', 'V', '3') ——DivX MPEG-4
- CV_FOURCC('M', 'P', '4', '2') —— MPEG-4
- CV_FOURCC('D', 'I', 'V', 'X') —— DivX
- CV_FOURCC('P','I','M','1') —— MPEG-1
- CV_FOURCC('I', '2', '6', '3') —— ITU H.263
- CV_FOURCC('M', 'P', 'E', 'G') —— MPEG-1
完整的列表可以在这里找到。
对于windows用户,可以使用CV_FOURCC_PROMPT(-1)弹出一个对话框选择压缩方法和额外的压缩参数。 - double fps - 视频流的帧速率。我在程序里使用10,可以尝试其他值,但应该是编解码器支持的fps,所以使用一个合适的值。
- Size frameSize - 指定视频流每帧的宽和高的Size对象。
- bool isColor - 如果想保存一个彩色视频,这个值为true,否则为false。
if ( !oVideoWriter.isOpened() )
检查VideoWriter对象是否成功初始化。
void write(const Mat& image)
将一个帧写入视频流。帧的尺寸应该和初始化VideoWriter对象时指定的尺寸一样。
其他的OpenCV函数在前面的文章都应经提到了。如果还不熟悉这些OpenCV函数,可以查看OpenCV捕获视频一文。