OpenCV图像读取(imread) 显示(imshow) 保存(imwrite)的冷知识点
一、读取图像:imread() 与imreadmulti()
1. imread()函数第二个参数flags有很多选择,如下:
//! Imread flags
enum ImreadModes {
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image.
IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format.
IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image.
IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
};
默认是IMREAD_COLOR 模式读取,会将图片转为3通道BGR彩图,读入进来type变成了CV_8UC3,如果你想以原本类型读取,那就选择IMREAD_UNCHANGED,那么图像原本是什么类型,读进来还是什么类型,这个参数主要在我们读取一些16位或者32为浮点型图像时就比较有用,因为一些计算需要这样的类型,有时候也为了计算提高精度。
2. imreadmulti()函数是用来一次性读取多张图片的,看下定义:
CV_EXPORTS_W bool imreadmulti(const String& filename, CV_OUT std::vector<Mat>& mats, int flags = IMREAD_ANYCOLOR);
一个string类型的文件路径,输出是Mat类型的vector,也就是多张图像,比如这里我有一张tif格式的图片,它本来是2张图片组成的,那么我就可以一次性读进来,然后对vector进行处理,避免我对图片路径进行字符串的格式化。
二、显示图像:namedWindow() 和 imshow()
1. imshow()函数默认显示窗口模式是WINDOW_AUTOSIZE,它的好处是可以根据图像的大小自动调整大小显示,缺点是不能调整窗口大小,如果你想调整窗口大小,那么就要先使用namedWindow()函数,并将第二个参数设置为WINDOW_NORMAL
//! Flags for cv::namedWindow
enum WindowFlags {
WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.
WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.
WINDOW_OPENGL = 0x00001000, //!< window with opengl support.
WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen.
WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint).
WINDOW_KEEPRATIO = 0x00000000, //!< the ratio of the image is respected.
WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool bar
WINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way
};
2. 另外一个冷门知识点是imshow显示的时候,我们可以选中窗口,进行图片的复制(Ctrl + C)和保存(Ctrl + S)
int main()
{
Mat img = imread("./lena.jpg", IMREAD_UNCHANGED);
if (img.empty())
{
cout << "Image is empty, please check again!" << endl;
return -1;
}
namedWindow("img", WINDOW_NORMAL);
imshow("img", img);
while (1)
{
if (waitKey(0) == 27)
break;
}
return 0;
}
可以用上一段代码尝试,先选中窗口,然后按下Ctrl + C,打开画图工具或者PPT进行粘贴,或者Ctrl + S会弹出对话框保存本地,很方便调,避免去加imwrite().
三、保存图像:imwrite()
1. 大家比较熟悉的应该是用imwrite()来保存单张图片,我们也可以用它来一次性保存多张图片到一个文件中,看函数说明:
下面是代码演示:
vector<Mat>imgs;
Mat img1 = imread("./1.jpg", IMREAD_UNCHANGED);
Mat img2 = imread("./2.jpg", IMREAD_UNCHANGED);
imgs.push_back(img1);
imgs.push_back(img2);
imwrite("result.tif", imgs);
保存之后看不出来?那就用imreadmulti()函数来读取,代码如下:
vector<Mat>imgs;
imreadmulti("./result.tif", imgs, IMREAD_UNCHANGED);
cout << imgs.size() << endl;
//多张图片可以使用for循环来读取
imshow("1", imgs.at(0));
imshow("2", imgs.at(1));
waitKey(0);
.tif这个格式如果你用过halcon就会经常看到它的身影, 为什么老是用它?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PIMPL:休想窥探我的隐私!
- 树莓派基础实验37:pyserial模块通信实验
- 【答疑解惑】为什么你的 Charles 会抓包失败?
- Mybatis-generator 逆向工程 自定义PO,xml,mapper,example
- 高速上云/网络穿透/视频上云网关EasyNTS组网服务登录状态检测优化记录
- 树莓派基础实验38:逻辑分析仪分析PWM、UART信号
- 【终端设备】视频上云/网络穿透EasyNTS云组网硬件终端无法单独修改账号的优化方式
- 测试环境问题排查的那些事儿
- RTSP流媒体协议视频平台EasyNVR和EasyNTS智能云组网同一浏览器运行为什么会导致EasyNTS无法登陆?
- Java:手写线程安全LRU缓存X探究影响命中率的因素
- 视频上云/网络穿透/网络映射服务EasyNTS设备管理为什么会出现无法搜索到设备的情况?
- 快速打造属于你的接口自动化测试框架
- 大数据下的质量体系建设
- PostgreSQL 日志系统 及 设置错误导致磁盘塞满案例
- 六、乘胜追击,将剩下的Git知识点搞定