OpenCV探索之路(十八):使用imwrite调整保存的图片质量
近日在用opencv做一些图像处理的操作时,需要对一些高分辨率的图像进行保存。比如,在操作一个容量为230M的图像后,并对该图像保存为JPG格式后,发现图像容量变为80M了!针对这个问题,忙了大半天,到处翻阅资料,终于知道为什么了。
先举个例子说明自己遇到的问题,为了看出效果,我特意用了一个高分辨率的图片做实验。
比如我有如下的一个233M的图片
经过下面的程序读进内存,再次保存后,图片容量就急剧变小了!
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("src1.jpg");
imwrite("test.jpg", img);
return 0;
}
保存后的图片,只剩下126M了!怎么回事!我什么都没做啊,图片大小怎么就大大缩水了呢?
通过翻阅一些资料才知道,原来是图片格式惹得祸。其实有些图片格式是自带压缩的,比如jpg格式,而bmp格式的图片是不带任何压缩,这就是每种图片的特点,如果对这些知识点不清楚的话,很容易踩坑!平时我们操作的图像大小大多数都以KB为单位,所以经过一番“隐形压缩”后我们很难发现图片大小变小了,但是,当我们操作大图的时候,这种压缩效果一下子就看出来了。
那么如果我们在使用imwrite保存图片时想提高保存图片的质量,该如何操作?
要改变保存的图片的质量,关键在于imwrite函数的第三个参数。
先看imwrite的声明
CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());
第三个参数说明:const std::vector&类型的params,表示为特定格式保存的参数编码,它有默认值std::vector(),所以一般情况下不需要填写。如果更改的话,对于不同的图片格式,其对应的值不同功能不同,如下:
-
对于JPEG格式的图片,这个参数表示从0-100的图片质量(CV_IMWRITE_JPEG_QUALITY),默认值是95.
-
对于PNG格式的图片,这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0-9.较高的值意味着更小的尺寸和更长的压缩时间而默认值是3.
-
对于PPM,PGM或PBM格式的图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,而默认值为1.
调整jpg图像格式的保存质量
opencv的imwrite默认存储的jpg图片质量为95,如果想进一步提高保存图片的质量,可以这么写
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("src1.jpg");
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); //选择jpeg
compression_params.push_back(100); //在这个填入你要的图片质量
imwrite("test2.jpg", img, compression_params);
return 0;
}
可以看出,经过参数调整后,jpg格式保存的图片的大小有了很大的提升。
但是无论如何,以jpg格式保存图片还是不能百分百保存原图像的!
但是即使我们把图片质量写成100,图片质量跟原图还是右一定压缩的,比如原图233M,读入再保存为jpg格式容量就变为229M。
那当我们不断读入图片,又不断存储图片为jpg格式,图片的质量就会不断降低!
所以有以下总结:
第一,opencv的存储图片函数imwrite是可以通过第三个函数参数来调整保存图片的压缩比的,比如保存图片为jpg格式,我们如果我们写成
第二,jpg格式的图片读进内存,如果再保存为jpg格式后,容量会被压缩的,这是jpg格式的特性,怎么调整压缩比都避免不了失真(损失图片质量)。
调整PNG图像格式的保存质量
如果操作的而是png格式的图像,我们同样可以调整其保存的质量。
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("src1.jpg");
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); //PNG格式图片的压缩级别
compression_params.push_back(9); //这里设置保存的图像质量级别
imwrite("test3.png", img,compression_params);
return 0;
}
那如何不损失图片质量地保存图片,那就得将图片保存为其他格式的图片了。现在,就简单介绍一下我最常用的图片格式以及他们的特点:
BMP格式(无压缩)
位图(外语简称:BMP、外语全称:BitMaP)BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。
JPEG格式(有损压缩)
联合照片专家组(外语简称JPEG外语全称:Joint Photographic Expert Group)JPEG也是最常见的一种图像格式,它是由联合照片专家组(外语全称:Joint Photographic Experts Group),文件后辍名为”.jpg”或”.jpeg”,是最常用的图像文件格式,由一个软件开发联合会组织制定,是一种有损压缩格式,能够将图像压缩在很小的储存空间,图像中重复或不重要的资料会被丢失,因此容易造成图像数据的损伤。尤其是使用过高的压缩比例,将使最终解压缩后恢复的图像质量明显降低,如果追求高品质图像,不宜采用过高压缩比例。但是JPEG压缩技术十分先进,它用有损压缩方式去除冗余的图像数据,在获得极高的压缩率的同时能展现十分丰富生动的图像,换句话说,就是可以用最少的磁盘空间得到较好的图像品质。而且JPEG是一种很灵活的格式,具有调节图像质量的功能,允许用不同的压缩比例对文件进行压缩,支持多种压缩级别,压缩比率通常在10:1到40:1之间,压缩比越大,品质就越低;相反地,压缩比越小,品质就越好。
PNG格式(无损压缩)
便携式网络图形(外语简称PNG、外语全称:Portable Network Graphics),是网上接受的最新图像文件格式。PNG能够提供长度比GIF小30%的无损压缩图像文件。它同时提供24位和48位真彩色图像支持以及其他诸多技术性支持。由于PNG非常新,所以并不是所有的程序都可以用它来存储图像文件,但Photoshop可以处理PNG图像文件,也可以用PNG图像文件格式存储。