首页 / 操作系统 / Linux / OpenCV学习笔记与源码分析: imread( )函数
引言 imread()函数在opencv使用比较。imread()函数 声明: Mat imread(const string& filename, int flags);这很标准的写法,传入一个string类型的常量引用。定义: Mat imread(const string& filename, int flags) { Mat img; //创建一个变量 imread_(filename,flags,LOAD_MAT,&img); return img; }其中imread_()中&img用的是地址符号,为什么呢?当然是为了改变其里面的数据了。imread( )函数是就这么几行么?这么几行能干什么呢?其实它把所有的事情交给了imread_()函数。所以,我们进一步分析imread_()函数。imread_()函数 声明: static void* imread_(const string& filename, int flags, int hdrtype, Mat* mat=0 );其中这个函数返回的是一个空指针,其实在上面,这个返回值时没有用到的。 filename:文件地址 flags:标志,读取什么样(灰度,彩色)图像hdrtype:传入的为载入什么类型(enum {LOAD_CVMAT=0,LOAD_IMAGE=1, LOAD_MAT=2 };这三个中的一个。) Mat :保存图像的Mat对象了。定义: static void* imread_(const string& filename, int flags, int hdrtype, Mat* mat=0) { IplImage* image = 0; CvMat *matrix = 0; Mat temp, *data = &temp; ImageDecoder decoder = findDecoder(filename);//这个是解析图像的后缀名的,用来决定读取特定图像的数据,所有的事情都是它干了。 if( decoder.empty() ) return 0; decoder->setSource(filename); if( !decoder->readHeader() )//读取图像的头部信息 return 0; CvSize size; //读取图像的大小 size.width = decoder->width(); size.height = decoder->height(); int type = decoder->type();//读取类型? 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);//灰度 } if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT ) { if( hdrtype == LOAD_CVMAT ) { matrix = cvCreateMat( size.height, size.width, type ); temp = cvarrToMat(matrix); //创建一个空的,即还没有图像数据的对象。 } else { mat->create( size.height, size.width, type ); data = mat; } } else//就是传入的类型都为IplImage*类型的 { image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) ); temp = cvarrToMat(image); } if(!decoder->readData(*data))//读取数据,这里应该是复制数据,想一想这个是要懂硬盘上去读取数据的。 {//失败 cvReleaseImage(&image); cvReleaseMat(&matrix);//c风格的释放 if( mat ) mat->release();//c++风格的释放 return 0; } return hdrtype == LOAD_CVMAT ? (void*)matrix : hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;//最后返回c类型的图像指针,这个是为了考虑c风格的 }上面看似不长啊,可这个怎么能干那么多的事情呢?那么就一步步的来分析吧。这个看了半天,是不是没有什么实质性的东西?一个到底怎么读图还没完全了解吧。全都封装了起来(decoder),你看不到所有的细节,而只是一个大概的流程。这个流程不是自己都知道了么?不管怎么样,我不想关注这个图是怎么解析的,只看这函数怎么把数据给读进了Mat中,先保持这个目标不变:首先:传入了一个Mat类型的变量,这个变量是传了地址的,也就是会改变这个mat类型变量。Mat在构造函数中开始会构造什么呢?尤其是默认构造函数?其实他什么也没有构造,因为什么都不知道。其次:Mat类型需要记录图像的哪些数据呢?一个是头:图像是灰度或彩色(这里姑且只考虑这两种),一个图像数据的大小(图像的宽与高);一个数据体:二维数组或是一维数组。最后:从decoder中读入data数据。当然这里会牵涉到图像解码过程的(这个如果特别感兴趣就看看了,否则不用了)。在第一篇处,我们只是在最表层的上面操作函数,当别人问我们时,我们其实什么也不知道的。就知道,imread是读取函数了,然后掉用其它的函数的乐乐。当然,上面我们可以好好学习人家为什么要这样做了!这里,看一个函数finddecoder()。这个函数主要是获取decoder对象,从而决定读取什么样后缀名的图像(jpg,bmp等等)推荐阅读: CentOS下OpenCV无法读取视频文件 http://www.linuxidc.com/Linux/2011-07/39295.htmUbuntu 12.04下安装OpenCV 2.4.5总结 http://www.linuxidc.com/Linux/2013-06/86704.htmUbuntu 10.04中安装OpenCv2.1九步曲 http://www.linuxidc.com/Linux/2010-09/28678.htm
收藏该网址