读取图像的基本语句有三条:
1.定义图像存放的矩阵——Mat;
2.读取图像——imread(与实例化Mat集成一条语句);
3.定义窗口——nameWindow(非必须);
4.显示图像——imshow;
以下为实例代码:
#include <iostream> // for standard I/O
//opencv头文件 opencv2与opencv3的引用路径一样
#include <opencv2/imgproc/imgproc.hpp> // Gaussian Blur
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
#include <opencv2/highgui/highgui.hpp> // OpenCV window I/O
using namespace std;
using namespace cv;
void main()
{
Mat myMat = imread("d:\\timg.jpg");
imshow("", myMat);
waitKey();
return ;
}
接下来对上面的代码进行简单分析:
Mat:这是一个类,其目的是在计算机中开辟一个容器(也可以称之为显存)用于存放从计算机硬盘中映射到内存中的图片;该类的原型是早期通过C语言编写的IplImage,但是C语言实现图片缓存映射的最大问题是手动内存管理(手动开辟和销毁内存空间),所以在opencv2中引入了C++接口后,给OpenCV带来了类的概念和自动内存管理的功能,使图片缓存的管理操作更加简洁。
Mat实际上是一个二维矩阵+矩阵信息(信息头)的类,具有C++类中常用的拷贝、赋值运算等操作;当使用拷贝、赋值运算得到多个Mat实例后,这些实例具有独立的信息头,但是所对应的图像矩阵是一样的(对应同一段内存区域)。当需要拷贝一幅图像的数据矩阵时可使用函数 clone() 或者 copyTo() 来拷贝一副图像的矩阵。
备注:
(1)图像的存储是以像素点的阵列存储在计算机中的(以位图为例);
(2)图像的矩阵信息中包含了图像的颜色、灰度、明暗对比度;
(3)图像的显示步骤为(以RGB为例):加载(把硬盘中的图像映射至显存空间)->在显卡上根据显存空间中的数据进行DA转换为R\G\B三色模拟输出信号->信号发送至显示器,控制显示器按改变一个区域内的每个像素点颜色->在显示器中能够观察到图片;
(4)关于位图:2位图(黑白)、4位图(16色)、16位图(256色)、24位图(65535色)(最典型的的格式是BMP),创建图标的时候常需要选择位图大小;
(5)显卡工作原理:显卡带有一个用于缓存待显示图像的二维缓存区,简称显存,这个显存中的每一个单元都与显示屏幕上的像素点存在一一对应的关系,需要在某个区域显示指定图像时把图像的缓存数据送入显卡显存区的对应区域即可。例如,在我屏幕上原本显示的是一张全屏显示的图片A,这时在显卡显存中存放的只有图片A的数据矩阵(大矩阵),现在我需要在屏幕的左半侧显示一张较小的图片B(小矩阵),就需要将图片B的数据矩阵送入显卡显存区中并替代显卡显存中(原有显卡显存被图片A的数据矩阵完全占满)的对应区域矩阵数据,这时得到的矩阵就是一个一半是图片B的完整数据+一半是图片A的右半边图片数据的显卡显存。此时显示器按显存所给的信号定时刷新屏幕即得到了图片(或视频)。
CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
imread函数:该函数从指定的目录读取图像文件,并返回一个Mat实例。
(1)函数将通过图像的内容来决定图像的类型,而不是通过图像的后缀名来判断(专业打假^_^);
(2)可以在函数中使用IMREAD_LOAD_GDAL标记,使用GDAL驱动按照指定解码格式(Raster、Vector)来加载图片;
(3)flags包含默认值(1),在加载图像时可以使用默认值;其他标志见下图
CV_EXPORTS_W void imshow(const String& winname, InputArray mat);
imshow函数:显示指定数据矩阵的图像;
(1)这个函数有两种用法,一种是在调用该函数之前使用nameWindow函数创建一个窗口,再使用该函数将指定的图像实现在刚创建的窗口上;另一种直接调用该函数,这种方法在显示图像之前会默认使用WINDOW_AUTOSIZE属性创建一个窗口(相当于namedWindow("", WINDOW_AUTOSIZE)),并显示图像。
(2)该函数调用后必须使用waitkey()函数,否则图像将无法显示;作者实验了在imshow函数后直接增加一个while死循环以替代waitkey函数,结果是图像不能正常加载,鼠标的光标在图像区域上显示等待形状。
(3)在图像正常显示后可以用鼠标点击图像区域,激活图像显示窗体,按住CTRL+S将打开图片另存为对话框;按住CTRL+C会将图像复制至剪贴板。
(4)不使用namedWindow将无法在图像显示后变更图像显示区域的大小。
CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
nameWindow函数在imshow调用之前被调用
(1)imshow函数中的窗口名称字符串必须与nameWindow函数中创建的窗口名称一样,否则会显示两个窗口;
(2)如果指定名称的窗口已经存在,则该语句不产生任何操作;
(3)nameWindow创建时的标记:
(4)可以调用destroyWindow(“窗口名称”)或者destroyAllWindows()函数来关闭窗口,并取消之前分配的与窗口相关的所有内存空间。