Mat类是OpenCV中的基本数据类型,是读取图像数据的容器,其由存储矩阵维度数据类型等的矩阵头和存储数据的部分组成。本身实现了内存的自动分配和释放。

1.定义OpenCV Mat类对象实例

OpenCVMat类中定义了大于25种的构造函数,简单介绍几种常见的定义初始化Mat对象的方法。

  • 1)从图像读取
    cv::Mat img = cv::imread(argv[1]);
    
  • 2)使用数组初始化
    double data[3][3][3] = {{12.3, 3.2, 4.5}};
    cv::Mat mat_from_array(cv::Size(3, 3), CV_64FC3, data);
    
  • 3) 使用流运算符
      cv::Mat mat_from_stream = (cv::Mat_<int>(3, 4) << 2,3,4,5,
                            8,5,1,10,
                            9,5,6,12);
    
  • 4) 取其他Mat的一部分
    // 4.1 by row_range and col_range
    cv::Range row_range(1, 3);
    cv::Range col_range(0, 3);
    cv::Mat crop_mat_by_range = mat_from_stream(row_range, col_range);
    
    // 4.2 by rectangel of roi
    cv::Rect roi(cv::Point(0, 0), cv::Point(2, 2)); // do not include the end
    cv::Mat crop_mat_by_rect = mat_from_stream(roi);
    
    // 4.3 range by pointer
    cv::Range rp[3];
    rp[0] = cv::Range(1, 3);
    rp[1] = cv::Range(0, 3);
    cv::Mat crop_by_roi_pointer = mat_from_stream(rp);
    
    // 4.4 range by vector
    std::vector<cv::Range> rv = {{1,3}, {0,3}};
    cv::Mat crop_by_roi_vec = mat_from_stream(rp);
    
    
  • 5)使用eye/zeros/ones/diag构造
    cv::Mat eye = cv::Mat::eye(cv::Size(5, 5), CV_64F);
    eye(cv::Range(0, 3), cv::Range(0, 2)).setTo(22);
    std::cout << "eye matrix: \n" << eye << std::endl;
    std::cout << "diag of eye matrix(d=0): " << eye.diag(0) << std::endl;
    std::cout << "diag of eye matrix(d=1): " << eye.diag(1) << std::endl;
    std::cout << "diag of eye matrix(d=-1): " << eye.diag(-1) << std::endl;
    cv::Mat val = (cv::Mat_<int>(2, 1) << 2,3);
    std::cout << "value of val: " << val << std::endl;
    cv::Mat diag = cv::Mat::diag(val);
    std::cout << "diag matrix of eye: \n" << diag << std::endl;
    

2.setTo

mask不为零的位置设置为指定的值.

cv::Mat setto_mat = cv::Mat::zeros(cv::Size(4,5), CV_64F);
cv::Mat setto_mask = cv::Mat::eye(cv::Size(4,5), CV_8U);
setto_mat.setTo(cv::Scalar(255.), setto_mask);    

3.dot_product

矩阵元素乘积和

cv::Mat mat1 = (cv::Mat_<int>(2, 3) << 2, 3, 4, 5, 0, 0);
cv::Mat mat2 = (cv::Mat_<int>(2, 3) << 0, 1, 0, 1, 1, 1);
std::cout << "mat1.dot(mat2): " << mat1.dot(mat2) << std::endl; 

4.forEach

遍历cv::Mat中的元素,支持C++ Lambda表达式。

cv::Mat image(4, 3, CV_8UC3);
typedef cv::Point3_<uint8_t> Pixel;
image.forEach<Pixel>([](Pixel &p, const int * position) -> void {
    p.x = 255;
});
std::cout << "image: " << image << std::endl;

5.ptr()

返回指向矩阵某1行的uchar型的指针

cv::Mat img_ptr = cv::Mat::eye(3, 3, CV_8UC1);
uchar *d0 = img_ptr.ptr<uchar>(0);
std::cout << "First Element of Img Ptr: " << d0[1] << std::endl;

6.push_back

Mat后追加行

cv::Mat row_mat = cv::Mat::ones(1, 3, CV_8UC1);
img_ptr.push_back(row_mat);
std::cout << "img_ptr after row_mat push: " << img_ptr << std::endl;

7.resize

改变矩阵的行数,新增加的行使用cv::Scalar填充

img_ptr.resize(5, cv::Scalar(12.));
std::cout << "Image resize: " << img_ptr << std::endl;

8.transpose/inverse/convertTo等

cv::Mat tmp_mat = (cv::Mat_<double>(2,2) << 0.,1,2,3);
std::cout << "tmp_mat.t: " << tmp_mat.t() << std::endl;
std::cout <<"tmp_mat.inv:" << tmp_mat.inv() << std::endl;
std::cout <<"tmp_mat.type:" << tmp_mat.type() << std::endl;
std::cout << CV_64FC1 << std::endl;
std::cout <<"tmp_mat.elemSize:" << tmp_mat.elemSize() << std::endl;
std::cout <<"channles of tmp_mat:" << tmp_mat.channels() << std::endl;
cv::Mat cmat;
tmp_mat.convertTo(cmat, CV_8UC1);
std::cout <<"type of mat after convertTo():" << cmat.type() << std::endl;
std::cout << CV_8UC1 << std::endl;
std::cout <<"cmat.elemSize:" << cmat.elemSize() << std::endl;
std::cout <<"total number of tmp_mat: " <<  tmp_mat.total() << std::endl;
std::cout <<"dims of tmp_mat: " <<  tmp_mat.dims << std::endl;
std::cout <<"cols of tmp_mat: " <<  tmp_mat.cols << std::endl;
std::cout <<"rows of tmp_mat: " <<  tmp_mat.rows << std::endl;
std::cout <<"flags of tmp_mat: " <<  tmp_mat.flags << std::endl;

参考:
1.https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html#a13acd320291229615ef15f96ff1ff738
2.https://docs.opencv.org/4.5.4/d6/d6d/tutorial_mat_the_basic_image_container.html
3.https://docs.opencv.org/4.5.4/db/da5/tutorial_how_to_scan_images.html

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐