Mat常用构造函数及IplImage 与Mat 之间的相互转换

Mat常用构造函数及IplImage 与Mat 之间的相互转换

Mat对象构造函数与常用方法

常用的构造函数有:

  • Mat::Mat()
    无参数构造方法;
  • Mat::Mat(int rows,  int cols,  int type)
    创建行数为 rows,列数为 col,类型为 type 的图像;
  • Mat::Mat(Size size,  int type)
    创建大小为 size,类型为 type 的图像;
  • Mat::Mat(int rows,  int cols,  int type,  const Scalar& s)
    创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s;
  • Mat::Mat(Size size,  int type, const Scalar& s)
    创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
  • Mat::Mat(const Mat& m)
    将 m 赋值给新创建的对象,此处不会对图像数据进行复制,m 和新对象共用图像数据;
  • Mat::Mat(int rows,  int cols,  int type,  void* data,  size_t step=AUTO_STEP)
    创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step指定。
  • Mat::Mat(Size size,  int type,  void* data,  size_t step=AUTO_STEP)
    创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。
  • Mat::Mat(const Mat& m,  const Range& rowRange,  const Range& colRange)
    创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据;
  • Mat::Mat(const Mat& m,  const Rect& roi)
    创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据。

这些构造函数中,很多都涉及到类型 type。type 可以是 CV_8UC1,CV_16SC1,...,CV_64FC4 等。里面的 8U 表示 8 位无符号整数,16S 表示 16 位有符号整数,64F表示 64 位浮点数(即 double 类型);C 后面的数表示通道数,例如 C1 表示一个通道的图像,C4 表示 4 个通道的图像,以此类推。
如果你需要更多的通道数,需要用宏 CV_8UC(n),例如:

Mat M(3,2, CV_8UC(5));//创建行数为3,列数为2,通道数为5的图像

有些 type 参数如 CV_32F未注明通道数目,这种情况下它表示单通道。


常用方法
void copyTo(); //拷贝
Mat clone(); //拷贝
int channels(); //通道,矩阵中的每一个矩阵元素拥有的值的个数
int depth(); //深度,即每一个像素的位数(bits)
bool empty() const; //判断是否为空
uchar* ptr(int i0=0); //指针取第0行数据
void convertTo(oclMat& m, int rtype, double alpha=1, double beta=0);
//m:转为目标数据类型的矩阵;
//rtype: 指定目标数据类型,或者是depth(通道数),如果rtype:是负值,那么目标矩阵的数据类型和源矩形的数据类型是一致的;
//alpha:基于尺度的变化值;
//beta:在尺度上的加和;

四个要点:

  • 输出图像的内存是自动分配的
  • 使用OpenCV的C++接口,不需要考虑内存分配的问题
  • 赋值操作和拷贝构造函数只会复制头部分
  • 使用clone()与copyTo()两个函数实现数据完全复制

create()函数创建对象

除了在构造函数中可以创建图像,也可以使用 Mat 类的 create()函数创建图像。如果 create()函数指定的参数与图像之前的参数相同,则不进行实质的内存申请操作;如果参数不同,则减少原始数据内存的索引,并重新申请内存。使用方法如下面例程所示:

Mat M(2,2, CV_8UC3);//构造函数创建图像

M.create(3,2, CV_8UC2);//释放内存重新创建图像

需要注意的时,使用 create()函数无法设置图像像素的初始值。

 

Mat 与 IplImage间相互转换

/**///-----以下方法在opencv3及以下版本中可行,opencv4中没有IplImage结构------

//IplImage—>Mat
//使用Mat的构造函数:
Mat::Mat(const IplImage* img, bool copyData=false);//默认情况下copyData为false

IplImage* srcImg = cvLoadImage("Lena.jpg");

//注意:以下三种效果一致,均为浅拷贝.
Mat M(srcImg);
Mat M(srcImg, false);
Mat M = srcImg;

//注意:当将参数copyData设为true后,则为深拷贝(复制整个图像数据).
Mat M(srcImg, true);

//converting IplImage to cv::Mat  
 Mat image=cvarrToMat(srcImg,true); 



//Mat—>IplImage
//注意:浅拷贝 --- 同样只是创建图像头,而没有复制数据.
Mat M;

IplImage img = M;
IplImage img = IplImage(M);

//深拷贝
cv::Mat img2;

IplImage imgTmp = img2;
IplImage *input = cvCloneImage(&imgTmp);
----------------------------------------------///*/

/*-----以下方法在opencv3及以下版本中可行,opencv4中没有IplImage结构----

//IplImage—>Mat

//使用Mat的构造函数:

Mat::Mat(const IplImage* img, bool copyData=false); 默认情况下copyData为false

IplImage* srcImg = cvLoadImage("Lena.jpg");

//注意:以下三种效果一致,均为浅拷贝.

Mat M(srcImg);

Mat M(srcImg, false);

Mat M = srcImg;

//注意:当将参数copyData设为true后,则为深拷贝(复制整个图像数据).

Mat M(srcImg, true);

//converting IplImage to cv::Mat  

 Mat image=cvarrToMat(srcImg); 

 

//Mat—>IplImage

//注意:浅拷贝 --- 同样只是创建图像头,而没有复制数据.

Mat M;

IplImage img = M;

IplImage img = IplImage(M);

//深拷贝

cv::Mat img2;

IplImage imgTmp = img2;

IplImage *input = cvCloneImage(&imgTmp);

//-----------------------------------------------------------/*/

 

3、数据备份/拷贝

1“ = ” 浅拷贝

        浅拷贝 - 不复制数据只创建矩阵头,数据共享(更改a, b, c的任意一个都会对另外2个产生同样的作用)

Mat a = imread("1.jpg");

Mat b = a; //a "copy" to b

Mat c(a); //a "copy" to c

a.col(10) = 0;//把a的第十列全置0,b和c也相应发生变化

2“clone()” 完全深拷贝

clone 是完全的深拷贝,在内存中申请新的空间

Mat A = Mat::ones(4, 5, CV_32F);

Mat B = A.clone()    //clone 是完全的深拷贝,在内存中申请新的空间,与A独立

3“copyTo()” 也是深拷贝

copyTo 也是深拷贝,但是否申请新的内存空间,取决于dst矩阵头中的大小信息是否与src一至,若一致则只深拷贝并不申请新的空间,否则先申请空间后再进行拷贝.

Mat A = Mat::ones(4, 5, CV_32F);

Mat C;

 

A.copyTo(C) //此处的C矩阵大小与A大小不一致,则申请新的内存空间,并完成拷 贝,等同于clone()

Mat D = A.col(1);

A.col(0).copyTo(D) //此处D矩阵大小与A.col(0)大小一致,因此不会申请空间,而是直接进行拷贝,相当于把A的第1列赋值给第二列

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/yishuihanq/article/details/114535415