OpenCV固定矩阵类Matx、矩阵类Mat初始化方法汇总

本文详细介绍了OpenCV中Mat对象的多种初始化方法,包括直接赋值、数组初始化、读图初始化等,并深入探讨了使用数组构造Mat时的注意事项及多通道浮点Mat的构造方法。

1,Matx初始化方法

1.1 用数组初始化

double vals[4] = {1,2,3,4};
Matx22d m(vals);

2,Mat初始化方法

2.1 直接赋值初始化

Mat C =(Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);

2.2 通过数组初始化

int a[3][3] = { 0, -1, 0,-1, 5, -1, 0, -1, 0};
Mat C(3,3,CV_32S,a);     //type不能错!int对应CV_32S,float对应CV_32F,double对应CV_64F

复杂点,可以通过3维数组构造多通道的浮点Mat:

int main()
{
    // 创建一个3行4列2通道的float数组
    float afTest[3][4][2] = { {
  
  {1.11,1.12},{1.21,1.22},{1.31,1.32},{1.41,1.42}},    
                              {
  
  {2.11,2.12},{2.21,2.22},{2.31,2.32},{2.41,2.42}},
                              {
  
  {3.11,3.12},{3.21,3.22},{3.31,3.32},{3.41,3.42}} };

    float fA = afTest[1][3][0];             // 索引第1行第3列的0通道
    Mat mA(3, 4, CV_32FC2, afTest);         // 数组转化为2
<think> 我们讨论的是OpenCV中的固定大小矩阵模板类 `cv::Matx`,特别是 `cv::Matx33f`(3x3单精度浮点矩阵)。访问 `Matx33f` 的元素有几种方法,下面将详细说明。 ### 访问 `cv::Matx33f` 元素的方法 #### 1. 使用括号运算符 `operator()` 这是最常用的方法,通过行和列索引访问: ```cpp cv::Matx33f mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f); // 访问第0行第1列的元素(值为2.0f) float element01 = mat(0, 1); ``` #### 2. 使用一维数组风格(按行优先顺序) `cv::Matx` 内部数据存储为一维数组,行优先(row-major)顺序: ```cpp // 访问第0行第1列(索引为1)和第2行第0列(索引为6) float element1 = mat.val[1]; // 即 (0,1) 位置 float element6 = mat.val[6]; // 即 (2,0) 位置 ``` #### 3. 通过成员函数 `row()` 和 `col()` 获取整行或整列(返回向量): ```cpp // 获取第0行(返回一个 cv::Vec3f) cv::Vec3f row0 = mat.row(0); // [1, 2, 3] // 获取第1列(返回一个 cv::Vec3f) cv::Vec3f col1 = mat.col(1); // [2, 5, 8] ``` #### 4. 使用迭代器 C++11 范围循环访问所有元素: ```cpp // 遍历所有9个元素(按行优先) for (float& elem : mat.val) { std::cout << elem << " "; } // 输出:1 2 3 4 5 6 7 8 9 ``` ### 完整示例代码 ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 初始化一个3x3矩阵 cv::Matx33f mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f); // 方法1:括号运算符 std::cout << "Element (0,1): " << mat(0, 1) << std::endl; // 2 std::cout << "Element (2,2): " << mat(2, 2) << std::endl; // 9 // 方法2:一维数组访问 std::cout << "Element [1]: " << mat.val[1] << std::endl; // 2(即(0,1)) std::cout << "Element [6]: " << mat.val[6] << std::endl; // 7(即(2,0)) // 方法3:获取行和列 cv::Vec3f row1 = mat.row(1); cv::Vec3f col2 = mat.col(2); std::cout << "Row 1: " << row1[0] << ", " << row1[1] << ", " << row1[2] << std::endl; // 4,5,6 std::cout << "Col 2: " << col2[0] << ", " << col2[1] << ", " << col2[2] << std::endl; // 3,6,9 // 方法4:迭代器遍历 std::cout << "All elements: "; for (const float& elem : mat.val) { std::cout << elem << " "; } std::cout << std::endl; return 0; } ``` ### 注意事项 - **索引范围**:行和列索引从0开始,必须在[0,2]范围内,否则行为未定义(可能崩溃)。 - **常量访问**:如果矩阵是常量,应使用 `const` 版本: ```cpp const cv::Matx33f cmat = ...; float val = cmat(0,0); // OK // cmat(0,0) = 5; // 错误:常量对象 ``` ### 性能提示 - 括号运算符 `operator()` 是编译时内联的,无函数调用开销。 - 一维数组访问 `val[i]` 同样高效,但需注意索引计算(行优先:`index = row * cols + col`)。 §§相关问题§§: 1. OpenCV 中 `cv::Vec` 和 `cv::Matx` 有什么区别? 2. 如何修改 `cv::Matx33f` 中的单个元素? 3. 在 `cv::Matx` 中,行优先(row-major)和列优先(col-major)存储有什么区别? 4. 如何将 `cv::Matx33f` 转换为 `cv::Mat` 对象? </think>### `cv::Matx33` 元素访问方法详解 `cv::Matx33` 是 OpenCV 中用于处理 3x3 固定大小矩阵的模板类(如 `Matx33f` 表示浮点矩阵)。以下是完整的访问方法: #### 1. 使用括号运算符 `operator()` ```cpp cv::Matx33f mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f); // 访问单个元素(行索引,列索引) float element_1_2 = mat(1, 2); // = 6.0f(第1行第2列) // 修改元素 mat(0, 1) = 10.0f; // 修改第0行第1列 ``` #### 2. 使用一维数组 `val` 成员 ```cpp // 通过一维索引访问(行优先顺序) float first = mat.val[0]; // = 1.0f (0,0) float sixth = mat.val[5]; // = 6.0f (1,2) float last = mat.val[8]; // = 9.0f (2,2) // 修改元素 mat.val[4] = 50.0f; // 修改 (1,1) 位置 ``` #### 3. 获取整行或整列 ```cpp // 获取整行(返回 Vec3f) cv::Vec3f row0 = mat.row(0); // [1.0f, 2.0f, 3.0f] // 获取整列 cv::Vec3f col1 = mat.col(1); // [2.0f, 5.0f, 8.0f] ``` #### 4. 使用迭代器遍历 ```cpp // 使用标准迭代器 for (auto it = mat.begin(); it != mat.end(); ++it) { std::cout << *it << " "; } // 输出:1 2 3 4 5 6 7 8 9 // C++11 范围循环 for (float& elem : mat.val) { elem *= 2; // 所有元素乘以2 } ``` #### 5. 通过模板方法 `get()`(编译时检查) ```cpp // 编译时索引访问(安全但冗长) float v00 = mat.template get<0, 0>(); // 第0行0列 float v12 = mat.template get<1, 2>(); // 第1行2列 ``` ### 完整示例代码 ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 创建并初始化3x3矩阵 cv::Matx33f mat(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f); // 1. 括号运算符访问 std::cout << "Element (1,1): " << mat(1, 1) << std::endl; // 2. 一维数组访问 std::cout << "Fifth element: " << mat.val[4] << std::endl; // 3. 获取整行 cv::Vec3f secondRow = mat.row(1); std::cout << "Second row: " << secondRow << std::endl; // 4. 迭代器修改 for (float& elem : mat.val) { elem = std::round(elem); // 四舍五入 } // 5. 输出修改后的矩阵 std::cout << "Rounded matrix:\n" << mat << std::endl; return 0; } ``` ### 访问注意事项 1. **索引范围**: - 行和列索引必须在 [0, 2] 范围内 - 一维索引必须在 [0, 8] 范围内 2. **内存布局**: ```mermaid graph LR A[内存地址] --> B[0: (0,0)] A --> C[1: (0,1)] A --> D[2: (0,2)] A --> E[3: (1,0)] A --> F[4: (1,1)] A --> G[5: (1,2)] A --> H[6: (2,0)] A --> I[7: (2,1)] A --> J[8: (2,2)] ``` 3. **性能特点**: - `operator()` 和 `val[]` 访问都是 O(1) 时间复杂度 - 行/列访问返回临时对象,有复制开销 - 迭代器访问适合批量操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值