OpenCV在MFC窗口显示图像

1. OpenCV创建一个窗口并在其中显示图像

前言:第一部分是关于opencv显示图像的一些相关函数的详细解释,第二部分则是MFC显示图像的一些介绍

1.1 读入图像文件

Mat类是存储和操作OpenCV中图像的主要数据结构。这个类是在core模块中定义的。OpenCV已经实现了对于这些数据结构自动分配和释放内存的机制。但是,当数据结构共享相同的缓冲存储器时,程序员仍然应该特别注意。
使用函数imread()将图像文件读入到Mat对象中,函数imread的原型为:
Mat imread(const String& filename, int flags = IMREAD_COLOR)
这里,第一个参数是图像文件名字符串,第二个参数flag指定读取图像的颜色,并在imgcodecs.hpp头文件中由如下枚举类型定义和解释:
enum {
IMREAD_UNCHANGED = -1, // 8 位,彩色或非彩色
IMREAD_GRAYSCALE = 0, // 8 位,灰度
IMREAD_COLOR = 1, //未改变深度、颜色
IMREAD_ANYDEPTH = 2, //任意深度,未改变颜色
IMREAD_ANYCOLOR = 4, //未改变深度,任意颜色
IMREAD_LOAD_GDAL = 8 // 使用 gdaL 驱动程序
};
注意,在OpenCV 3.0版本中,函数imread是在imgcodecs模块中,而不是像OpenCV 2.x在highgui模块中。另外,因为一些函数和声明被移入到OpenCV 3.0中,所以连接器可能会由于找不到一个或多个声明(符号和/或函数)而得到一些编译错误。
读取输入的图像文件之后,应检查操作是否成功。可使用Mat类的成员函数empty()来实现这个检查。

1.2 创建一个窗口

void namedWindow(const String& winname,int flags = WINDOW_AUTOSIZE)
OpenCV窗口是通过程序中一个意义明确的名字来识别的。第一个参数是窗口名称字符串,第二个参数flags定义了窗口的属性,通过highgui.hpp头文件中的枚举给出该标志的定义及其说明:
enum {
WINDOW_NORMAL = 0x00000000,
//用户可以调整窗口的大小(无约束)
//还可以将一个全屏窗口切换为常规窗口
WINDOW_AUTOSIZE = 0x00000001,
//用户不能调整窗口的大小,
//窗口的大小由显示的图像所限制
WINDOW_OPENGL = 0x00001000, // OpenGL 支持的窗口
WINDOW_FULLSCREEN = 1,
WINDOW_FREERATIO=0x00000100,
//图像可任意使用(调整图像时可没有比例限制)
WINDOW_KEEPRATIO = 0x00000000
//调整图像时保持图像的缩放比例
};

1.3 在一个窗口中显示一幅图像(属于highgui模块)

void imshow(const String& winname,InputArray mat)
第一个参数是窗口名称字符串,所指定窗口如果还没创建则会新创建出来,第二个参数是包含待显示文件的Mat类变量。
如果使用WINDOW_AUTOSIZE标志创建该窗口(winname),那么所显示的是原始大小的图像(mat)。
在一个程序中创建的任何窗口都可以从默认设置下调整大小和进行移动。当不再需要任何窗口时,应该销毁窗口,以便释放其资源,在一个程序结束时,会隐式地完成资源的释放。

1.4. 显式地销毁指定窗口

void destroyWindow(const string& winname);
关闭窗口并释放该窗口所分配的所有内存(包括窗口内部的图像内存缓区:保存了与img指针相关的图像文件像素的一个副本)。
当应用程序的窗口被关闭时,该应用程序窗口所占用的一切资源都会由操作系统自动释放,所以对一些简单的程序,不必调用destroyWindow()函数显式释放资源。但是,养成习惯每次都调用这些函数显式释放资源总是好的。

1.5. 显式地销毁所有HighGUI窗口

void destroyAllWindows();

1.6 移动窗口到屏幕上指定位置

void moveWindow(const String& winname, int x, int y);
默认显示屏左上角为原点;x,y:为偏移位置。

1.7. 重新指定窗口尺寸为指定宽度和高度

void resizeWindow(const String& winname, int width, int height);
设定的窗口尺寸是指显示图像的窗口尺寸,不包含工具条。
只有创建的窗口flag属性不为CV_WINDOW_AUTOSIZE时才能够调用此函数。

1.8 把程序中的Mat类型的矩阵保存为图像(imagecodecs.hpp)

bool imwrite(const String& filename, InputArray img, const vector& params=vector());
参数filename为所需保存图像的文件目录和文件名。这里的文件名需要带有图像格式后缀,目前该函数只支持JPEG、PNG、PPM、PGM、PBM、TIFF等。
参数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类型,里面分别存入paramId_1, paramValue_1, paramId_2, paramValue_2, …,也就是“属性-值”对,一个“属性-值”对的向量指定编解码器的参数。如果不设置该参数的话,则程序会自动根据所保存的图像格式采用一个默认的参数,编解码器由文件的扩展名决定。
参数params可以有三种,分别是:
a、JPEG,参数为CV_IMWRITE_JPEG_QUALITY,它的值是从0到100,值越小压缩的越多,默认值是95.
b、PNG,参数为CV_IMWRITE_PNG_COMPRESSION,它的值是从0到9,值越大表示图片尺寸越小,压缩时间越长。默认值是3。
c、PPM,PGM或者PBM,参数为CV_IMWRITE_PXM_BINARY,它的值是0或者1。默认值是1。
下面是一个使用imwrite()函数保存图像文件的程序段:
vector compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
imwrite(“my.jpg”,imgsrc,compression_params);

2. OpenCV读取图像显示在MFC窗口上

本人通过了大量时间,在网上搜索相关知识,最终使用VS2013与opencv3.0实现了一个简单的界面程序,其具有打开文件读取图片、简单图像处理(灰度化)、保存图片到指定文件夹等功能,具体效果如下:

2.1打开图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2图像处理

在这里插入图片描述

2.3保存图片

在这里插入图片描述
在这里插入图片描述

2.4相关资源

  • 经过编译后生成的exe文件如下
    https://download.csdn.net/download/qq_44870829/12643003
  • 由VS2013与opencv3.0所生成的简单图像处理源文件如下
    https://download.csdn.net/download/qq_44870829/12643040
  • 关于如何从零开始搭建上方的简单图像处理框架,Word文件详细说明(不含源文件,但根据步骤能搭建出此简单框架) https://download.csdn.net/download/qq_44870829/12643059