本篇文章介绍一下如何使用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)弹出一个对话框选择压缩方法和额外的压缩参数。OpenCV写入图像或视频-程序旅途

  • double fps - 视频流的帧速率。我在程序里使用10,可以尝试其他值,但应该是编解码器支持的fps,所以使用一个合适的值。
  • Size frameSize - 指定视频流每帧的宽和高的Size对象。
  • bool isColor - 如果想保存一个彩色视频,这个值为true,否则为false。
 if ( !oVideoWriter.isOpened() )

检查VideoWriter对象是否成功初始化。

void write(const Mat& image)

将一个帧写入视频流。帧的尺寸应该和初始化VideoWriter对象时指定的尺寸一样。

其他的OpenCV函数在前面的文章都应经提到了。如果还不熟悉这些OpenCV函数,可以查看OpenCV捕获视频一文。