首页 > 代码库 > opencv笔记(一)——Mat的引用计数机制
opencv笔记(一)——Mat的引用计数机制
Mat是Opencv2里面主要的类。Mat的对象常常用来表示一副图像的信息。
Mat的基本操作十分简单,不多说了。下面这段代码能够读七八分明白,应该就算对Mat有大体了解。
1 /* For description look into the help() function. */ 2 3 #include "opencv2/core/core.hpp" 4 #include <iostream> 5 6 using namespace std; 7 using namespace cv; 8 9 static void help()10 {11 cout12 << "\n--------------------------------------------------------------------------" << endl13 << "This program shows how to create matrices(cv::Mat) in OpenCV and its serial"14 << " out capabilities" << endl15 << "That is, cv::Mat M(...); M.create and cout << M. " << endl16 << "Shows how output can be formated to OpenCV, python, numpy, csv and C styles." << endl17 << "Usage:" << endl18 << "./cvout_sample" << endl19 << "--------------------------------------------------------------------------" << endl20 << endl;21 }22 23 int main(int,char**)24 {25 help();26 // create by using the constructor27 Mat M(2,2, CV_8UC3, Scalar(0,0,255));28 cout << "M = " << endl << " " << M << endl << endl;29 30 // create by using the create function()31 M.create(4,4, CV_8UC(2));32 cout << "M = "<< endl << " " << M << endl << endl;33 34 // create multidimensional matrices35 int sz[3] = {2,2,2};36 Mat L(3,sz, CV_8UC(1), Scalar::all(0));37 // Cannot print via operator <<38 39 // Create using MATLAB style eye, ones or zero matrix40 Mat E = Mat::eye(4, 4, CV_64F);41 cout << "E = " << endl << " " << E << endl << endl;42 43 Mat O = Mat::ones(2, 2, CV_32F);44 cout << "O = " << endl << " " << O << endl << endl;45 46 Mat Z = Mat::zeros(3,3, CV_8UC1);47 cout << "Z = " << endl << " " << Z << endl << endl;48 49 // create a 3x3 double-precision identity matrix50 Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);51 cout << "C = " << endl << " " << C << endl << endl;52 53 Mat RowClone = C.row(1).clone();54 cout << "RowClone = " << endl << " " << RowClone << endl << endl;55 56 // Fill a matrix with random values57 Mat R = Mat(3, 2, CV_8UC3);58 randu(R, Scalar::all(0), Scalar::all(255));59 60 // Demonstrate the output formating options61 cout << "R (default) = " << endl << R << endl << endl;62 cout << "R (python) = " << endl << format(R,"python") << endl << endl;63 cout << "R (numpy) = " << endl << format(R,"numpy" ) << endl << endl;64 cout << "R (csv) = " << endl << format(R,"csv" ) << endl << endl;65 cout << "R (c) = " << endl << format(R,"C" ) << endl << endl;66 67 Point2f P(5, 1);68 cout << "Point (2D) = " << P << endl << endl;69 70 Point3f P3f(2, 6, 7);71 cout << "Point (3D) = " << P3f << endl << endl;72 73 74 vector<float> v;75 v.push_back( (float)CV_PI); v.push_back(2); v.push_back(3.01f);76 77 cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;78 79 vector<Point2f> vPoints(20);80 for (size_t i = 0; i < vPoints.size(); ++i)81 vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));82 83 cout << "A vector of 2D Points = " << vPoints << endl << endl;84 return 0;85 }
文档上边说,Mat的数据成员由头部和数据组成。我们打开core.hpp,看看Mat类的声明中的数据成员部分:
1 /*! includes several bit-fields: 2 - the magic signature 3 - continuity flag 4 - depth 5 - number of channels 6 */ 7 int flags; 8 //! the matrix dimensionality, >= 2 9 int dims;10 //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions11 int rows, cols;12 //! pointer to the data13 uchar* data;14 15 //! pointer to the reference counter;16 // when matrix points to user-allocated data, the pointer is NULL17 int* refcount;
Mat的头部信息:flags,dims,rows,cols,data指针,refcount指针。
Mat的数据部分:显然,意味着data指针指向的空间。
而refcount指针,就是起引用计数的作用。有了引用计数机制,使得我们的Mat能够很好地支持浅拷贝的操作:使用等号操作符给Mat赋值(或者使用拷贝构造的时候),仅拷贝头部信息,如此能够节约许多的空间和时间。而深拷贝的工作,就交给成员方法clone()和copyTo()。、
现在假设我们有Mat的对象A,当我们对A进行初始化工作的时候,引用计数为1(对相关的代码有疑问,所以此处不给出。)以下引用官方文档。
- If the current array shape and the type match the new ones, return immediately. Otherwise, de-reference the previous data by calling Mat::release().
- Initialize the new header.
- Allocate the new data of total()*elemSize() bytes.
- Allocate the new, associated with the data, reference counter and set it to 1.
令Mat的对象B=A,此时将引用计数增到2。
1 inline Mat& Mat::operator = (const Mat& m) 2 { 3 if( this != &m ) 4 { 5 if( m.refcount ) 6 CV_XADD(m.refcount, 1); 7 release(); 8 flags = m.flags; 9 if( dims <= 2 && m.dims <= 2 )10 {11 dims = m.dims;12 rows = m.rows;13 cols = m.cols;14 step[0] = m.step[0];15 step[1] = m.step[1];16 }17 else18 copySize(m);19 data =http://www.mamicode.com/ m.data;20 datastart = m.datastart;21 dataend = m.dataend;22 datalimit = m.datalimit;23 refcount = m.refcount;24 allocator = m.allocator;25 }26 return *this;27 }
1 static inline int CV_XADD(int* addr, int delta)2 {3 int tmp = *addr;4 *addr += delta; 5 return tmp;6 }
当B析构的时候,将引用计数减1,当前引用计数为1:
1 inline Mat::~Mat() 2 { 3 release(); 4 if( step.p != step.buf ) 5 fastFree(step.p); 6 } 7 8 inline void Mat::release() 9 {10 if( refcount && CV_XADD(refcount, -1) == 1 )11 deallocate();12 data = http://www.mamicode.com/datastart = dataend = datalimit = 0;13 size.p[0] = 0;14 refcount = 0;15 }
当A析构的时候,引用计数为0,于是调用deallocate(),数据信息和头部信息一起清空。
opencv笔记(一)——Mat的引用计数机制
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。