今天遇到一个小问题,图片太大,保存是报错,说数组越界,然后试着更改一下压缩率可以正常保存图片了
转自:http://windrocblog.sinaapp.com/?p=465
OpenCV中最基本的操作:读取、显示、保存图片。
OpenCV2.0版本引入与Matlab命令相同的函数,imread、imshow、imwrite,获取图片更将方便。
读取文件 imread
其中flags表示载入后图片的颜色模式。
CV_LOAD_IMAGE_UNCHANGED (0) 以RGB模式载入图片
显示图片需要一个窗口。
创建窗口 namedWindow
CV_WINDOW_AUTOSIZE 窗口大小自动调整到显示图片的大小
CV_WINDOW_NORMAL 只在Qt中使用,可以改变窗口大小
显示图片 imshow
在窗口中显示图片,对于NORMAL的窗口,把图片缩放到窗口固定大小,再显示。根据图像数据的深度,对图像进行下面的处理:
8-bit unsigned 直接显示
16-bit unsigned or 32-bit integer 像素点值除以256,即把[0,255*256] 映射到 [0,255]
32-bit floating-point 像素点值乘以255,即把[0,1] 映射到 [0,255]
所以,imshow可以正常显示取值范围[0,255]的uchar型图像、取值范围[0,1]的float或double类型图像,中间一种数据格式没用过。
显示图像后,为了避免程序向下运行以致窗口一闪而过,需要等待一旦时间,waitKey正是这个功能。
等待键盘按键 waitKey
delay小于等于0时,一直等待,只到用户按键,再继续执行。
delay大于0时,在delay微秒内等待用户按键。
处理过的图像需要保存到文件中。
保存图像 imwrite
params中的每个参数成对出现,即paramId_1, paramValue_1, paramId_2, paramValue_2, … ,当前支持如下参数:
JPEG:压缩质量 ( CV_IMWRITE_JPEG_QUALITY ),从0到100(数值越高质量越好),默认值为95。
PNG:compression level ( CV_IMWRITE_PNG_COMPRESSION ) 从0到9。 数值越高,文件大小越小,压缩时间越长。默认值为3。
PPM, PGM, or PBM:二进制标志 ( CV_IMWRITE_PXM_BINARY ),0 或 1。默认值为1。
还有一组函数,用于从内存读取数据和向内存写入数据。
从内存读图片 imdecode
写图片到内存 imencode
ext – 图片的扩展名
img – 要保存的图片
buf – 输出缓存,改变大小以适应数据
params – 格式相关的参数,参见imwrite。
上面两个函数的示例代码如下所示,来自http://code.google.com/p/opencvjp-sample/source/browse/trunk/cpp/encode_decode_test.cpp?r=63 。
最后,应该释放窗口。窗口可以自动释放,也可以手动关闭。
释放窗口 destroyWindow destroyAllWindow
第一个释放单个窗口,第二个释放所有窗口。
压缩率使用:
转自:http://www.cnblogs.com/tornadomeet/archive/2012/12/26/2834336.html
前言
OpenCV中保存图片的函数在c++版本中变成了imwrite(),这应该是向matlab中图像处理的的一些函数风格靠近吧。保存图片这个功能还是很重要的,比如说在写科研论文的时候需要把一些中间图片给贴出来,这样就可以在程序中间利用该函数保存图片了。甚至还可以将这些保存的图片供后续的matlab处理。本文就简单介绍下OpenCV中imwrite()函数的用法。不过个人感觉这个函数功能还是不够强大,使用时有很多限制。
开发环境:QtCreato2.5.1+OpenCV2.4.3
实验基础
本次实验主要是测试imwrite()函数的2个功能:
1. 测试其是否能够保存Mat图像中截取的一部分图像,比如说用Rect矩阵截取大的图像中的一部分,由于此时两者只是用了自己的文件头,数据是共享的(没有采用copyTo()函数或者clone()函数复制),所以这种测试想法很正常。
2. 测试imwrite()函数的第3个参数的使用。
在针对第1个测试时,是给定一张原图,截取一部分,然后保存。针对第2个功能是采用OpenCV官网文件中的一个例子,创建一个alpha表,然后保存为png格式的图片,压缩参数自设定。
首先来看看imwrite()函数的具体用法。
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() )
该函数是把程序中的Mat类型的矩阵保存为图像到指定位置。
参数filename为所需保存图像的文件目录和文件名。这里的文件名需要带有图像格式后缀的,目前OpenCV该函数只支持JPEG,PNG,PPM,PGM,PBM,TIFF等。并不是所有Mat类型都支持。
img参数为图像数据来源,其类型为Mat。注意也不是所有格式的Mat型数据都能被使用保存为图片,目前OpenCV主要只支持单通道和3通道的图像,并且此时要求其深度为8bit和16bit无符号(即CV_16U)。所以其他一些数据类型是不支持的,比如说float型等。如果Mat类型数据的深度和通道数不满足上面的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。
参数params是用来设置对应图片格式的参数的,因为一般情况下这些图片格式都是经过了压缩的,这里就是设置这些压缩参数来控制图片的质量。该参数是一个vector<int>类型,里面分别存入paramId_1, paramValue_1, paramId_2, paramValue_2, ... 也就是说存入一对属性值。如果不设置该参数的话,则程序会自动根据所保存的图像格式采用一个默认的参数。
本实验中还用到了下面这个函数。
template<...> _Tp saturate_cast(_Tp2 v)
将参数v转换成模板中的类型,比如说:
uchar a = saturate_cast<uchar>(-100);
OpenCV知识点总结:
Rect的构造函数中不能重载3个参数,比如左上角点的坐标,宽和高这时候应该改成4个,左上角点的坐标直接分开为2个写,对应着了点的x和y。
实验结果
程序执行后工程文件夹中显示如下:
说明截取图像部分并保存是成功的。
原图像和截取原图中间1/4大小的图像如下:
后台输出如下:
说明此时也保存成功了。
生成的alpha表图像显示如下:
实验代码及注释
main.cpp:
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; Mat src; Mat image; string str = "./"; /*创建alpha表,整体偏红色,左上角到右下角呈现从完全透明到完全不透明变化趋势*/ void createAlphaMat(Mat &mat) { for (int i = 0; i < mat.rows; ++i) { for (int j = 0; j < mat.cols; ++j) { Vec4b& rgba = mat.at<Vec4b>(i, j); rgba[0] = UCHAR_MAX; //r分量一直最大,所以整体偏红 rgba[1] = saturate_cast<uchar>((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); rgba[2] = saturate_cast<uchar>((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2])); } } } int main() { /*采用默认参数进行图片的保存*/ src = imread("test.jpg"); imwrite(str+"原图.jpg", src); //c版本中的保存图片为cvSaveImage()函数,c++版本中直接与matlab的相似,imwrite()函数。 imshow("src", src); Rect rect(src.cols/4, src.rows/4, src.cols/2, src.rows/2); image = src(rect); imwrite(str+"截取原图中的一部分区域小图.jpg", image); imshow("image", image); /*采用自己设置的参数来保存图片*/ Mat mat(480, 640, CV_8UC4); createAlphaMat(mat); vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); //png格式下,默认的参数为3. try { imwrite("alpha.png", mat, compression_params); } catch (runtime_error& ex) { fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); return 1; } fprintf(stdout, "Saved PNG file with alpha data.\n"); waitKey(0); return 0; }
实验总结
Imwrite()函数可以保存截取出的图像,但是这个函数使用时受限制太多,希望后面的版本对其进行加强。
参考资料