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图像文件格式存储。
OpenCV探索之路(十八):使用imwrite调整保存的图片质量的更多相关文章
- OpenCV探索之路(八):重映射与仿射变换
重映射 重映射就是把一幅图像中某个位置的像素放置到另一个图片中指定位置的过程. 用一个数学公式来表示就是: 其中的 f 就是映射方式,也就说,像素点在另一个图像中的位置是由 f 来计算的. 在Open ...
- Opencv笔记(十八)——轮廓的更多函数及其层次结构
凸缺陷 前面我们已经学习了轮廓的凸包,对象上的任何凹陷都被成为凸缺陷.OpenCV 中有一个函数 cv.convexityDefect() 可以帮助我们找到凸缺陷.函数调用如下: hull = cv2 ...
- 第十八篇、keychain保存UUID(保持唯一性,应用卸载,下载安装也不变)和获取IP地址
.h #import <Foundation/Foundation.h> #import <Security/Security.h> /**使用**/ //-(void) se ...
- OpenCV探索之路(二十四)图像拼接和图像融合技术
图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要. 再举一个身边的例子吧,你用你的手 ...
- 【OpenCV新手教程之十八】OpenCV仿射变换 & SURF特征点描写叙述合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/33320997 作者:毛星云(浅墨) ...
- 命令模式 Command 行为型 设计模式(十八)
命令模式(Command) 请分析上图中这条命令的涉及到的角色以及执行过程,一种可能的理解方式是这样子的: 涉及角色为:大狗子和大狗子他妈 过程为:大狗子他妈角色 调用 大狗子的“回家吃饭”方法 引子 ...
- 最全的MySQL基础【燕十八传世】
1.课前准备! 开启mysql服务:1).配置环境变量;2).net start mysql 将该sql文件导入到你的数据库中,以下所有操作都是基于该数据库表操作的!!! [此笔记是本人看着视频加上自 ...
- NeHe OpenGL教程 第四十八课:轨迹球
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
随机推荐
- 局域网内部署 Docker Registry
在局域网内部署 Docker Registry 可以极大的提升平时 pull.push 镜像的速度,从而缩短自动化操作的过程.同时也可以缓解带宽不足的问题,真是一举多得.本文将从创建单机的 Docke ...
- SimpleDateFormat使用和线程安全问题
SimpleDateFormat 是一个以国别敏感的方式格式化和分析数据的具体类. 它允许格式化 (date -> text).语法分析 (text -> date)和标准化. Simpl ...
- WebApi2 文件图片上传下载
Asp.Net Framework webapi2 文件上传与下载 前端界面采用Ajax的方式执行 一.项目结构 1.App_Start配置了跨域访问,以免请求时候因跨域问题不能提交.具体的跨域配置方 ...
- [netty源码分析]3 eventLoop 实现类SingleThreadEventLoop职责与实现
eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...
- Js之浅谈dom操作
JavaScript之浅谈dom操作 1.理解dom: DOM(Document Object Model ,文档对象模型)一种独立于语言,用于操作xml,html文档的应用编程接口. 怎么说,我从两 ...
- JavaScript:window.onload问题
前几天做一个点击按钮,就实现切换图片效果的小demo时,代码看上去没问题,就是达不到效果.让我百思不得其解. 代码如下: <!DOCTYPE html> <html> < ...
- MySql俩种分页区别(注意)
注意俩个分页的区别哦~ SELECT * FROM city LIMIT 2 OFFSET 1; 从第二条记录开始 取二条记录 如下: SELECT * FROM city LIMIT 3,2; 从第 ...
- 【FPGA】高斯白噪声的Verilog实现
本文章主要讨论高斯白噪声的FPGA实现.简单的方法可以采用在Matlab中产生服从一定均值和方差的I.Q两路噪声信号.然后将两组数据存在FPGA中进行回放,以此来产生高斯白噪声.这种方法优点是产生方法 ...
- [BZOJ4518]征途
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MB Description Pine开始了从S地到T地的征途. 从S地到T地的路可以 ...
- github--hello,world(参考官网)
官网:https://guides.github.com/activities/hello-world/ 一共分为5步. 1.为你的项目新建仓库(repository): 2.新建分支(branch) ...