Mat 类是OpenCV 中的基本数据类型,是读取图像数据的容器,其由存储矩阵维度数据类型等的矩阵头和存储数据的部分组成。本身实现了内存的自动分配和释放。
1.定义OpenCV Mat类对象实例
OpenCV 的Mat 类中定义了大于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
|