opencv源码解读
2013-05-22 21:10
141 查看
今天是开始看opencv源码的第一天,想看看opencv2.0以上版本是怎么实现的。当然,这只是最初的一步,现在我就连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_()函数。下面我们跟进去:
声明:
static void*
imread_( const string& filename, int flags, int hdrtype, Mat* mat=0 );
定义:
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对象了。
{
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()函数的解析。
声明:
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_()函数。下面我们跟进去:
声明:
static void*
imread_( const string& filename, int flags, int hdrtype, Mat* mat=0 );
定义:
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对象了。
{
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数据。当然这里会牵涉到图像解码过程的(这个如果特别感兴趣就看看了,否则不用了)。
相关文章推荐
- OpenCv学习笔记(一)--OpenCv中Mat类源码的详细解读(1)
- opencv EM算法 源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- opencv全景拼接源码解读与修改。
- 史上最全opencv源码解读,opencv源码详细解读目录
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- OpenCv学习笔记(九)再谈OpenCv中Mat类源码的详细解读
- OpenCV的GrabCut函数使用和源码解读
- [OpenCV]图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 【图像处理】图像分割之(一~四)GraphCut,GrabCut函数使用和源码解读(OpenCV)
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- Opencv 源码解读之 ImageEncoder
- 【图割】opencv中构建图和最大流/最小割的gcgraph.h源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- opencv之构建图和最大流/最小割的gcgraph.h源码解读