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显示的只是当前传入的图像矩阵,如果之后的图像信息发生变化,该窗口的信息还是不变

猜你喜欢

转载自blog.csdn.net/CJ_035/article/details/82077812