当前位置:   article > 正文

cv::Mat使用笔记_cv::mat size

cv::mat size

本文深入探索OpenCV库中cv::Mat类的使用方法和技巧。cv::Mat作为OpenCV中用于存储图像数据的基本数据结构,其使用范围广泛且功能强大。通过本文,你将了解cv::Mat的创建、访问和修改数据的基本操作,以及其在图像处理任务中的具体应用。此外,我还会分享一些在使用cv::Mat时可能遇到的常见问题及其解决方案,帮助你更好地掌握这一工具。无论你是OpenCV的新手还是资深用户,相信这篇博客都能为你提供有价值的参考和启示。

1. 构造

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

2. 初始化

  • 使用函数初始化
  1. cv::Mat a = cv::Mat::eye(4, 4, CV_64FC1); // 单通道double类型
  2. cv::Mat b = cv::Mat::eye(4, 4, CV_8UC1); // 单通道char类型
  • 使用cv::Point3f和cv::Mat_初始化;
  1. cv::Point3f v1(34.0f, 21.34f, 32.0f);
  2. cv::Mat m{ cv::Mat_<cv::Point3f>(v1) };
  3. //得到1行1列3通道的矩阵 
  • 使用cv::Point3f初始化
  1. cv::Point3f point(34.0f, 21.34f, 32.0f);
  2. cv::Mat m(point);
  3. //得到3行1列1通道的矩阵 
  • 使用vector初始化
  1. std::vector<double> vec{ 21.3, -10, 34.0, 3.2, 3.4 };
  2. cv::Mat m{ vec };
  3. //得到5行1列1通道的矩阵 
  • 使用std::vector<cv::Point2f>初始化 
  1. //得到2行1列2通道的矩阵
  2. std::vector<cv::Point2f> vecpts{ cv::Point2f(2.3, 3.1), cv::Point2f(9.3, -10.0) };
  3. cv::Mat m{ vecpts };
  • 使用cv::Mat_初始化
  1. //得到3行3列1通道的矩阵
  2. cv::Mat C = (cv::Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

3. 对一部分进行赋值 

这些方式看似正确,但实际不行

  1. cv::Mat matrix = cv::Mat::zeros(4, 4, CV_64FC1);
  2. cv::Mat calibration = cv::Mat::eye(3, 3, CV_64FC1);
  3. // 方法一
  4. cv::Mat a = matrix.rowRange(0, 3).colRange(0, 3); // 共享内存
  5. a = calibration;
  6. // 方法二
  7. cv::Mat matrix = cv::Mat::zeros(4, 4, CV_64FC1);
  8. matrix.rowRange(0, 3).colRange(0, 3) = calibration.clone();
  9. // 方法三
  10. calibration.copyTo(matrix.rowRange(0, 3).colRange(0, 3)); // 编译失败

正确的方式

  1. cv::Mat matrix = cv::Mat::zeros(4, 4, CV_64FC1);
  2. cv::Mat a = matrix.rowRange(0, 3).colRange(0, 3); // 共享内存
  3. xa.copyTo(a);
  4. cv::Mat b = matrix.rowRange(0, 3).col(3); // 共享内存
  5. xb.copyTo(b);

4. 与Eigen矩阵的相互转化

注意:只支持double类型的转换,不支持float类型

  1. #include <opencv2/core/eigen.hpp>
  2. cv::cv2eigen(cv_matrix, eigen_matrx);
  3. cv::eigen2cv(eigen_matrx, cv_matrix);

5. 指针

  1. cv::Mat matrix = cv::Mat::zeros(4, 4, CV_64FC1);
  2. // 方法一
  3. const double *data = matrix.ptr<double>(0);
  4. // 方法二
  5. // img.data的默认类型是unsigned char*
  6. double* data = (matrix*)img.data;

6. cv::Mat的缺点

  • 弱类型

C++本来是强类型语言,但cv::Mat却是弱类型的,即当你拿到一个cv::Mat的时候你并不知道它里面存储的数据类型,很容易用错;

  • 不安全

当你把你的cv::Mat对象传给某函数时,即使函数的形参加了const关键字,但它依然可能会被修改,这是因为cv::Mat有共享内存机制,它的拷贝是浅拷贝;

  • 构造时间长

cv::Mat构造时间很长,如果非必要不建议使用,构造过程尽量写在循环外面;

7. 图像操作

  • 读入图像
  1. cv::Mat A = imread(“Imgpath”, CV_LOAD_IMAGE_COLOR);
  2. A.at<Vec3b>(row, col)[2] // 访问图像数据

注意 Mat::at 函数是个模板函数, 需要指明参数类型, 因为这张图是具有红蓝绿三通道的图,所以它的参数类型可以传递一个 Vec3b,这是一个存放 3 个 uchar 数据的 Vec(向量)。这里提供了索引重载,[2]表示的是返回第三个通道,在这里是 Red 通道,第一个通道(Blue)用[0]返回

  • 保存图像
imwrite(image_path, A);
  •  将彩色图片转为灰度图片
  1. Mat src(m, n CV_8UC3);
  2. Mat dst;
  3. cvtColor(src,dst,CV_BGR2GRAY);

参考文献

Mat 的几种初始化和赋值方法 - 骏腾 - 博客园

浅谈Opencv Mat类(常用构造函数和成员函数整理)_古天九等一缕的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/886818
推荐阅读
  

闽ICP备14008679号