cv::Mat——Mat对象创建方法 OpenCV (一)

OpenCV (一)——Mat对象创建方法

1.cv::Mat优点及原理(本质类)

  • 不需要手动申请一块内存;
  • 在不需要时不用再手动释放内存;
  • 可以通过类的封装,方便的获取到数据的相关信息。

  它利用了类的特性,将内存管理和数据信息封装在类的内部,用户只需要对Mat类对象进行数据或面向对象操作即可。
Mat类分为两个部分:矩阵头矩阵数据。如果我们在操作一副图像的数据量时,矩阵数据量一般很大,那么针对拷贝和赋值函数的操作如果的深拷贝的话,效率会大大的降低。所以,Opencv的做法是只复制其矩阵头信息,而矩阵数据采用引用的方式,即多个Mat对象共享同一个矩阵数据,这里使用的原理类似c++11中的共享指针(本质类)

	cv::Mat A = cv::imread("image.jpg");
	cv::Mat B(A);
//浅层拷贝:Mat B=A;B就是浅层拷贝A,B只拷贝了A的的头部和地址,当B被操作后A也随之改变。

memcpy(A.data, output.data(), rows * cols * sizeof(uint16_t));

	cv::Mat C = A;
//深层拷贝:Mat A=imread("x.jpg"); Mat B=A.clone();B是开辟了新的内存完全的复制了A的内容,操作B不会对A造成影响。
	printf("A.data = %p\nB.data = %p\nC.data = %p\n", A.data, B.data, C.data);
output:
A.data =  00240AA0ADHH00C0
B.data =  00240AA0ADHH00C0
C.data =  00240AA0ADHH00C0

释放内存原则:由于内部使用了引用计数的方法,类似共享指针,当引用计数变为0的时候才会真正的释放内存。

temp_thin.convertTo(temp_thin_image, CV_8UC1, 1, 0);

Mat F = A.clone();
Mat G;
A.copyTo(G);
  • 输出图像分配 OpenCV 功能是自动 (除非另行指定,否则)。
  • 用c + + OpenCV的接口就无需考虑内存释放。
  • 赋值运算符和复制构造函数 (构造函数)只复制头。
  • 使用clone () 或copyTo () 函数将复制的图像的基础矩阵。
//二值化,类型转换,赋值
    memcpy(cv_thin_image_rgb_.data, output.data(), rows * cols * sizeof(uint16_t));
    temp_thin = cv_thin_image_rgb_;
    uint16_t* tdata = (uint16_t*) (temp_thin.data);
    uint8_t* bdata = cv_binary_image_rgb_.data;
    for (int i = 0; i < cols; i++) {
      for (int j = 0; j < rows; j++) {
        if (*tdata == 0) {
          *bdata = 0;
        } else {
          *bdata = 1;
        }
        tdata++;
        bdata++;
      }
    }
    temp_binary = cv_binary_image_rgb_;

2.cv::Mat 类对象的创建方法

cv::Mat roi_image_color = temp_thin_image_color(cv::Rect(119, 69, 210, 260));//139,129,168,168

Mat E = A(Range:all(), Range(1,3)); // 用行和列来界定

 上文中的所有对象,以相同的单个数据矩阵的结束点。他们头不同,但是使用的其中任何一个对矩阵进行任何修改,也将影响所有其他的。在实践中的不同对象只是提供相同的底层数据不同的访问方法,然而,它们的头部是不同的。真正有趣的部分是您可以创建仅指向完整数据的一小部分的头。例如,要在图像中创建兴趣区域 ( ROI) 您只需创建一个新头设置新边界: 

cv::Mat M4 = (cv::Mat_<double>(3, 3) << 0, -1, 0, -1, 0, 0, 0, 0, 1);
std::cout << "M4 = " << std::endl << M4 << std::endl;

Mat drawing_poly_color = Mat::zeros(roi_image_color.size(), CV_8UC1);

cv::Mat temp_thin_image_color = cv::imread("../example/mask.bmp", CV_LOAD_IMAGE_UNCHANGED);


//这里是将PCL的点云数据中的RGB信息提取出来进行赋值输出图片
cv::Mat gray(cloud->height, cloud->width, CV_8UC1);
//前两个参数是矩阵的行数和列数,后一个矩阵类型8U 8位无符号整数,c1表示1个channel,rgb图片这里就需要设置为CV_8UC3

for (int i = 0; i < cloud->points.size(); i++){
	uchar* grayrowptr = gray.ptr<uchar>(i / cloud->width);//提取行指针
	grayrowptr[i%cloud->width] = cloud->points[i].r;
}

cv::imwrite("gray_zxr.bmp", gray);

3.cv::Mat 类对象元素访问方法

ptr访问效率比较高,程序也比较安全,有越界判断。

//方法1:
	Mat img(1000, 1000, CV_32F);
	
	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			img.at<float>(i,j) = 3.2f;//方法1:
            img.ptr<float>(i)[j] = 3.2f;//方法2:
		}
	}
	//***方法3********推荐使用。耗时最短******************************
	Mat img3(1000, 1000, CV_32F);
	float* pData = (float*)img3.data;

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			*(pData) = 3.2f;
			pData++;
		}
	}
	//***方法4************************************************************
	Mat img4(1000, 1000, CV_32F);

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			((float*)img3.data)[i*1000+j] = 3.2f;
		}
	}

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值