OpenCV之源码分析 imread(),imshow(),waitKey()函数
参考原博客:https://blog.csdn.net/hujingshuang/article/details/47184717#t1
imread()
Mat imread( const string& filename, int flags )
{
Mat img;//定义一个Mat类,用于装载图片
imread_( filename, flags, LOAD_MAT, &img );//读图像
return img;
}
//imread_( const string& filename, int flags, int hdrtype, Mat* mat=0 )
整个函数的执行过程:imread --> imread_ --> 对路径文件进行解码(读取文件二进制信息 -> 确定解码器)--> 根据flag的参数会创建一个type类型 --> imread_函数中不同的 hdrtype 的值(有LOAD_CVMAT,LOAD_MAT,等)-->根据不同的值返回不同的矩阵,现在用的都是Mat()类型的矩阵,所以现在版本的opencv把imread内的imread_的第三个参数定为LOAD_MAT。
下面面通过实例讲解一下flag这个参数,我分别加载了灰度图跟彩色图两种类型,通过不同的flag值去确定最后imread函数返回的图像channels,type,depth。
关于flag参数设置产生不同的channels:
灰度图:
#include <opencv2\opencv.hpp>
#include <iostream>
#include<string>
using namespace std;
using namespace cv;
int main()
{
Mat srcImg[11];
for (int i = 0; i < 11; i++)
{
srcImg[i] = imread("images\\1.png", i-4);
}
printf("下面加载的图像是灰度图像\n");
for (int i = 0; i < 11; i++)
{
string str = "srcImg" + to_string(i - 4) + "images";
// imshow(str, srcImg[i]);
printf("flag is %2d channels is %2d ,type is %2d ,depth is %2d\n",
i-4,srcImg[i].channels(),srcImg[i].type(),srcImg[i].depth());
}
waitKey(0);
return 0;
}
结果:
可以看出只有在flag的值为1 3 5(我这里用最大值是6去检测,如果值越大也会不一样),所以还是要看下下面来自imread_函数的一部分源码关于flag参数这一块的,想要看全部的源码,可以打开最上面的链接
if( flags != -1 )//③
{
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);//彩色
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);//灰度
}
源码的程序这里是通过 & 与运算符去判断加载图像的,所以就可以知道为什么上面程序执行结果的原因啦!也就是flag的值大于0不一定会返回三通道
彩色图:
int main()
{
int n = 11;
Mat srcImg[100];
for (int i = 0; i < n; i++)
{
srcImg[i] = imread("images\\1.jpg", i-4);
}
printf("下面加载的图像是彩色图像\n");
for (int i = 0; i < n; i++)
{
string str = "srcImg" + to_string(i - 4) + "images";
// imshow(str, srcImg[i]);
printf("flag is %2d channels is %2d ,type is %2d ,depth is %2d\n",
i-4,srcImg[i].channels(),srcImg[i].type(),srcImg[i].depth());
}
waitKey(0);
return 0;
}
结果:
可以看出,尽管我用的是彩色三通道的图,但是当flag==18的时候,还是会加载为单通道的图像返回
OpenCV中imread函数默认加载BGR格式图像,即灰度图也会被转成BGR3通道。
关于type:
opencv中Mat存在各种类型,其中mat有一个type()的函数可以返回该Mat的类型。类型表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
可以从上面的两个运行结果看出,图像的type代表图像的通道的多少与channels的概念有区别,type更强调的是位数,而每8位为一个通道
关于depth:
可以从上面的两个运行结果结合这张表看出,图像的depth表示图像是8为无符号,还是8位有符号等的;
imshow()
1.详细的看最上面的那个链接,这里只写下个人理解,imshow内部调用cvShowImage( const char* name, const CvArr* arr )函数,流程是:找到名称为name的窗口体,找不到就自己创建一个窗口 --> 会有一个判断(如果window==NULL 或者 arr==NULL就exit(0)) --> 设置图片与窗口的属性,将二者属性设为一致 -->还有一个判断(如果窗口体大小发生变化,就更新窗体)
2.imshow显示的只是当前传入的图像矩阵,如果之后的图像信息发生变化,该窗口的信息还是不变