Opencv--Mat,IplImage数据类型
2012-11-11 17:05
435 查看
OpenCV C++数据类型用了大量的STL通用编程技术。
主要概述了一下Mat类的基本操作:Mat类型的成员变量和CvMat结构体还是比较相像的,前面cxcore基本数据结构已经介绍过了。主要介绍下Mat的基本操作。Mat类型可以实现从CvMat IplImage CvMatND的转换。
1. Mat的拷贝只是复制了Mat的信息头,数据的指针也指向了被拷贝的数据地址,而没有真正新建一块内存来存放新的矩阵内容。这样带来的一个问题就是对其中一个Mat的数据操作就会对其他指向同一块数据的Mat产生灾难性的影响。
2.建立多维数组的格式是这样的
3.传统的lplImage格式也可直接转换为Mat格式
如果想将新版本的Mat格式转换为老版本,则需要如下调用:
4.Mat结构更加友好,很多操作更接近matlab的风格
5.也有Point2f,Point3f,vector等数据结构可以使用
6.RNG类可以产生随机数
7.实现颜色通道的分离使用函数split
Mat最大的优势跟STL很相似,都是对内存进行动态的管理,不需要之前用户手动的管理内存,对于一些大型的开发,有时候投入的lpImage内存管理的时间甚至比关注算法实现的时间还要多,这显然是不合适的。除了有些嵌入式场合必须使用c语言,我任何时候都强烈像大家推荐Mat。
Mat这个类有两部分数据。一个是matrix header,这部分的大小是固定的,包含矩阵的大小,存储的方式,矩阵存储的地址等等。另一个部分是一个指向矩阵包含像素值的指针。
需要注意的是,copy这样的操作只是copy了矩阵的matrix header和那个指针,而不是矩阵的本身,也就意味着两个矩阵的数据指针指向的是同一个地址,需要开发者格外注意。比如上面这段程序,A、B、C指向的是同一块数据,他们的header不同,但对于A的操作同样也影响着B、C的结果。刚刚提高了内存自动释放的问题,那么当我不再使用A的时候就把内存释放了,那时候再操作B和C岂不是很危险。不用担心,OpenCV的大神为我们已经考虑了这个问题,是在最后一个Mat不再使用的时候才会释放内存,咱们就放心用就行了。
如果想建立互不影响的Mat,是真正的复制操作,需要使用函数clone()或者copyTo()。
说到数据的存储,这一直就是一个值得关注的问题,Mat_<uchar>对应的是CV_8U,Mat_<uchar>对应的是CV_8U,Mat_<char>对应的是CV_8S,Mat_<int>对应的是CV_32S,Mat_<float>对应的是CV_32F,Mat_<double>对应的是CV_64F,对应的数据深度如下:
• CV_8U - 8-bit unsigned integers ( 0..255 )
• CV_8S - 8-bit signed integers ( -128..127 )
• CV_16U - 16-bit unsigned integers ( 0..65535 )
• CV_16S - 16-bit signed integers ( -32768..32767 )
• CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
• CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
• CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
这里还需要注意一个问题,很多OpenCV的函数支持的数据深度只有8位和32位的,所以要少使用CV_64F,但是vs的编译器又会把float数据自动变成double型,有些不太爽。
还有个需要注意的问题,就是流操作符<<对于Mat的操作,仅限于Mat是2维的情况。
还有必要说一下Mat的存储是逐行的存储的。
再说说Mat的创建,方式有两种,罗列一下:1.调用create(行,列,类型)2.Mat(行,列,类型(值))。例如:
要是想创建更高维的矩阵,要写成下面的方式
对于矩阵的行操作或者列操作,方式如下:(注意对列操作时要新建一个Mat,我想应该跟列地址不连续有关)
下面的东西就比较狂暴了,对于外来的数据,比如你从别的地方接受了一幅图片,但可以不是Mat结构的,而只有一个数据的指针,看看接下来的代码是如何应付的,重点哦,亲
亲,有木有很简单!!!
还有一种快速初始化数据的办法,如下:
也可以把原来的IplImage格式的图片直接用Mat(IplImage)的方式转成Mat结构,也可以像Matlab一样调用zeros()、ones()、eye()这样的函数进行初始化。
如果你需要提前释放数据的指针和内存,可以调用release()。
对于数据的获取,当然还是调用at<float>(3, 3)这样的格式为最佳。其他的方法我甚少尝试,就不敢介绍了。
最后要提的一点是关于Mat的表达式,这个也非常多,加减乘除,转置求逆,我怎么记得我以前介绍过呢。那就不多说啦
Mat类型较CvMat和IplImage有更强的矩阵运算能力,支持常见的矩阵运算(参照Matlab中的各种矩阵运算),所以将IplImage类型和CvMat类型转换为Mat类型更易于数据处理。
Mat类型可用于直接存储图像信息,通过函数imread、imwrite、imshow等实现(与Matlab中的函数相似),似乎在某种程度上可以取代IplImage类型。
(1)将IplImage类型转换到Mat类型
Mat::Mat(const IplImage* img, bool copyData=false);
默认情况下,新的Mat类型与原来的IplImage类型共享图像数据,转换只是创建一个Mat矩阵头。当将参数copyData设为true后,就会复制整个图像数据。
例:
IplImage* iplImg = cvLoadImage("greatwave.jpg", 1);
Mat mtx(iplImg); // IplImage* ->Mat 共享数据
// or : Mat mtx = iplImg;
(2)将Mat类型转换到IplImage类型
同样只是创建图像头,而没有复制数据。
例:
IplImage ipl_img = img; // Mat -> IplImage
(3)将CvMat类型转换为Mat类型
与IplImage的转换类似,可以选择是否复制数据。
Mat::Mat(const CvMat* m, bool copyData=false);
(4)将Mat类型转换为CvMat类型
与IplImage的转换类似,不复制数据,只创建矩阵头。
例:
// 假设Mat类型的imgMat图像数据存在
CvMat cvMat = imgMat; // Mat -> CvMat
/article/1390652.html
/article/1390615.html
/article/1390612.html
/article/1390614.html
主要概述了一下Mat类的基本操作:Mat类型的成员变量和CvMat结构体还是比较相像的,前面cxcore基本数据结构已经介绍过了。主要介绍下Mat的基本操作。Mat类型可以实现从CvMat IplImage CvMatND的转换。
Mat Mat::row(int i) const Mat Mat::col(int j) const Mat Mat::rowRange(int startrow,int endrow) const//注意:实际获得的矩阵是以0为索引开始的[startrow,endrow-1],这个概念类似于STL里的超尾。 Mat Mat::rowRange(const Range& r) const Mat Mat::colRange(int startcol,int endcol) const Mat Mat::colRange(const Range& r) const Mat Mat::clone() const //创建一个全拷贝,包括数据 void Mat::copyTo(Mat& m) const //m.col(0).copyTo(n)此函数并不是简单的数据拷贝,而是相当于n=m.col(0) void Mat::copyTo(Mat& m,const Mat& mask) const void Mat::create(int rows,int cols,int type) void Mat::create(Size size,int type) void Mat::create(int ndims,const int * sizes,int type) void Mat::resize(size_t sz) const //改变mat rows,数据区不受影响 template<typename T> void Mat::push_back(const T& elem) temolate<typename T> void Mat::push_back(const Mat_<T>& elem) //m.push_back<int> (n);T表示Mat数据类型 template<typename T> void Mat::pop_back(size_t nelems=1) //nelems:the number of rows removed,T is not used template<typename T> T& Mat::at(int i,int j) const //int i=m.at<int>(i,j);
1. Mat的拷贝只是复制了Mat的信息头,数据的指针也指向了被拷贝的数据地址,而没有真正新建一块内存来存放新的矩阵内容。这样带来的一个问题就是对其中一个Mat的数据操作就会对其他指向同一块数据的Mat产生灾难性的影响。
2.建立多维数组的格式是这样的
int sz[3] = {2, 2, 2}; Mat L(3, sz, CV_8UC(1), Scalar::all(0));
3.传统的lplImage格式也可直接转换为Mat格式
IplImage* img = cvLoadImage("greatwave.png", 1); Mat mtx(img); // convert IplImage* -> Mat
如果想将新版本的Mat格式转换为老版本,则需要如下调用:
Mat I; IplImage* pI = &I.operator IplImage(); CvMat* mI = &I.operator CvMat();
//不过更安全的调用格式为: Ptr<IplImage> piI = &I.operator IplImage();
4.Mat结构更加友好,很多操作更接近matlab的风格
5.也有Point2f,Point3f,vector等数据结构可以使用
6.RNG类可以产生随机数
7.实现颜色通道的分离使用函数split
Mat最大的优势跟STL很相似,都是对内存进行动态的管理,不需要之前用户手动的管理内存,对于一些大型的开发,有时候投入的lpImage内存管理的时间甚至比关注算法实现的时间还要多,这显然是不合适的。除了有些嵌入式场合必须使用c语言,我任何时候都强烈像大家推荐Mat。
Mat这个类有两部分数据。一个是matrix header,这部分的大小是固定的,包含矩阵的大小,存储的方式,矩阵存储的地址等等。另一个部分是一个指向矩阵包含像素值的指针。
Mat A, C; // creates just the header parts A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we’ll know the method used (allocate matrix) Mat B(A); // Use the copy constructor C = A; // Assignment operator
需要注意的是,copy这样的操作只是copy了矩阵的matrix header和那个指针,而不是矩阵的本身,也就意味着两个矩阵的数据指针指向的是同一个地址,需要开发者格外注意。比如上面这段程序,A、B、C指向的是同一块数据,他们的header不同,但对于A的操作同样也影响着B、C的结果。刚刚提高了内存自动释放的问题,那么当我不再使用A的时候就把内存释放了,那时候再操作B和C岂不是很危险。不用担心,OpenCV的大神为我们已经考虑了这个问题,是在最后一个Mat不再使用的时候才会释放内存,咱们就放心用就行了。
如果想建立互不影响的Mat,是真正的复制操作,需要使用函数clone()或者copyTo()。
说到数据的存储,这一直就是一个值得关注的问题,Mat_<uchar>对应的是CV_8U,Mat_<uchar>对应的是CV_8U,Mat_<char>对应的是CV_8S,Mat_<int>对应的是CV_32S,Mat_<float>对应的是CV_32F,Mat_<double>对应的是CV_64F,对应的数据深度如下:
• CV_8U - 8-bit unsigned integers ( 0..255 )
• CV_8S - 8-bit signed integers ( -128..127 )
• CV_16U - 16-bit unsigned integers ( 0..65535 )
• CV_16S - 16-bit signed integers ( -32768..32767 )
• CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
• CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
• CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
这里还需要注意一个问题,很多OpenCV的函数支持的数据深度只有8位和32位的,所以要少使用CV_64F,但是vs的编译器又会把float数据自动变成double型,有些不太爽。
还有个需要注意的问题,就是流操作符<<对于Mat的操作,仅限于Mat是2维的情况。
还有必要说一下Mat的存储是逐行的存储的。
再说说Mat的创建,方式有两种,罗列一下:1.调用create(行,列,类型)2.Mat(行,列,类型(值))。例如:
// make a 7x7 complex matrix filled with 1+3j. Mat M(7,7,CV_32FC2,Scalar(1,3)); // and now turn M to a 100x60 15-channel 8-bit matrix. // The old content will be deallocated M.create(100,60,CV_8UC(15));
要是想创建更高维的矩阵,要写成下面的方式
// create a 100x100x100 8-bit array int sz[] = {100, 100, 100}; Mat bigCube(3, sz, CV_8U, Scalar::all(0));
对于矩阵的行操作或者列操作,方式如下:(注意对列操作时要新建一个Mat,我想应该跟列地址不连续有关)
// add the 5-th row, multiplied by 3 to the 3rd row M.row(3) = M.row(3) + M.row(5)*3; // now copy the 7-th column to the 1-st column // M.col(1) = M.col(7); // this will not work Mat M1 = M.col(1); M.col(7).copyTo(M1);
下面的东西就比较狂暴了,对于外来的数据,比如你从别的地方接受了一幅图片,但可以不是Mat结构的,而只有一个数据的指针,看看接下来的代码是如何应付的,重点哦,亲
void process_video_frame(const unsigned char* pixels, int width, int height, int step) { Mat img(height, width, CV_8UC3, pixels, step); GaussianBlur(img, img, Size(7,7), 1.5, 1.5); }
亲,有木有很简单!!!
还有一种快速初始化数据的办法,如下:
double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; Mat M = Mat(3, 3, CV_64F, m).inv();
也可以把原来的IplImage格式的图片直接用Mat(IplImage)的方式转成Mat结构,也可以像Matlab一样调用zeros()、ones()、eye()这样的函数进行初始化。
如果你需要提前释放数据的指针和内存,可以调用release()。
对于数据的获取,当然还是调用at<float>(3, 3)这样的格式为最佳。其他的方法我甚少尝试,就不敢介绍了。
最后要提的一点是关于Mat的表达式,这个也非常多,加减乘除,转置求逆,我怎么记得我以前介绍过呢。那就不多说啦
#include "opencv2/core/core.hpp" #include <iostream> using namespace std; using namespace cv; void help() { cout << "\n--------------------------------------------------------------------------" << endl << "This program shows how to create matrices(cv::Mat) in OpenCV and its serial" << " out capabilities" << endl << "That is, cv::Mat M(...); M.create and cout << M. " << endl << "Shows how output can be formated to OpenCV, python, numpy, csv and C styles." << endl << "Usage:" << endl << "./cvout_sample" << endl << "--------------------------------------------------------------------------" << endl << endl; } int main(int,char**) { help(); // create by using the constructor Mat M(2,2, CV_8UC3, Scalar(0,0,255)); cout << "M = " << endl << " " << M << endl << endl; // create by using the create function() M.create(4,4, CV_8UC(2)); cout << "M = "<< endl << " " << M << endl << endl; // create multidimensional matrices int sz[3] = {2,2,2}; Mat L(3,sz, CV_8UC(1), Scalar::all(0)); // Cannot print via operator << // Create using MATLAB style eye, ones or zero matrix Mat E = Mat::eye(4, 4, CV_64F); cout << "E = " << endl << " " << E << endl << endl; Mat O = Mat::ones(2, 2, CV_32F); cout << "O = " << endl << " " << O << endl << endl; Mat Z = Mat::zeros(3,3, CV_8UC1); cout << "Z = " << endl << " " << Z << endl << endl; // create a 3x3 double-precision identity matrix Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cout << "C = " << endl << " " << C << endl << endl; Mat RowClone = C.row(1).clone(); cout << "RowClone = " << endl << " " << RowClone << endl << endl; // Fill a matrix with random values Mat R = Mat(3, 2, CV_8UC3); randu(R, Scalar::all(0), Scalar::all(255)); // Demonstrate the output formating options cout << "R (default) = " << endl << R << endl << endl; cout << "R (python) = " << endl << format(R,"python") << endl << endl; cout << "R (numpy) = " << endl << format(R,"numpy" ) << endl << endl; cout << "R (csv) = " << endl << format(R,"csv" ) << endl << endl; cout << "R (c) = " << endl << format(R,"C" ) << endl << endl; Point2f P(5, 1); cout << "Point (2D) = " << P << endl << endl; Point3f P3f(2, 6, 7); cout << "Point (3D) = " << P3f << endl << endl; vector<float> v; v.push_back( (float)CV_PI); v.push_back(2); v.push_back(3.01f); cout << "Vector of floats via Mat = " << Mat(v) << endl << endl; vector<Point2f> vPoints(20); for (size_t E = 0; E < vPoints.size(); ++E) vPoints[E] = Point2f((float)(E * 5), (float)(E % 7)); cout << "A vector of 2D Points = " << vPoints << endl << endl; return 0; }
OpenCV中Mat与IplImage和CvMat类型之间的相互转换
Mat类型较CvMat和IplImage有更强的矩阵运算能力,支持常见的矩阵运算(参照Matlab中的各种矩阵运算),所以将IplImage类型和CvMat类型转换为Mat类型更易于数据处理。Mat类型可用于直接存储图像信息,通过函数imread、imwrite、imshow等实现(与Matlab中的函数相似),似乎在某种程度上可以取代IplImage类型。
(1)将IplImage类型转换到Mat类型
Mat::Mat(const IplImage* img, bool copyData=false);
默认情况下,新的Mat类型与原来的IplImage类型共享图像数据,转换只是创建一个Mat矩阵头。当将参数copyData设为true后,就会复制整个图像数据。
例:
IplImage* iplImg = cvLoadImage("greatwave.jpg", 1);
Mat mtx(iplImg); // IplImage* ->Mat 共享数据
// or : Mat mtx = iplImg;
(2)将Mat类型转换到IplImage类型
同样只是创建图像头,而没有复制数据。
例:
IplImage ipl_img = img; // Mat -> IplImage
(3)将CvMat类型转换为Mat类型
与IplImage的转换类似,可以选择是否复制数据。
Mat::Mat(const CvMat* m, bool copyData=false);
(4)将Mat类型转换为CvMat类型
与IplImage的转换类似,不复制数据,只创建矩阵头。
例:
// 假设Mat类型的imgMat图像数据存在
CvMat cvMat = imgMat; // Mat -> CvMat
/article/1390652.html
/article/1390615.html
/article/1390612.html
/article/1390614.html
相关文章推荐
- opencv 数据类型转换:CvArr, Mat, CvMat, IplImage, BYTE 转
- opencv 数据类型转换:CvArr, Mat, CvMat, IplImage, BYTE
- OpenCV中Mat与IplImage和CvMat数据类型间的相互转换
- OpenCV中Mat与IplImage和CvMat数据类型间的相互转换
- OpenCV中Mat与IplImage和CvMat类型之间的相互转换
- OpenCV Mat数据类型及位数总结
- opencv 之Mat, vector<point2f>,Point3d Iplimage 常见类型转换
- opencv中Mat与IplImage,CVMat类型之间转换
- opencv数据容器Mat,cvMat和IplImage
- OpenCV中Mat与IplImage和CvMat类型之间的相互转换
- opencv中Mat与IplImage,CVMat类型之间转换
- Halcon 与 OpenCV 图像数据类型转换 HObject和 Mat
- OpenCV——Mat、CvMat、IplImage类型浅析【转】
- OpenCV中Mat与IplImage和CvMat类型之间的相互转换
- OpenCV Mat数据类型及位数总结
- opencv数据容器Mat,cvMat和IplImage
- 如何将unsigned char*(或BYTE*)图像数据封装成OpenCV中Mat类型
- VC下使用OpenCV最好先修改一下结构体IplImage中的数据指针imageData的类型...
- C++读写txt文件方式以及基于opencv的Mat数据类型读写txt文件
- OpenCV中Mat与IplImage和CvMat类型之间的相互转换