OpenCV学习--Mat::rowRange函数

Mat::rowRange函数学习

Mat的rowRange和colRange函数可以获取某些范围内行或列的指针,具体使用方法如下:

Mat::rowRange

为矩阵的指定行区间创建一个矩阵头。
C++: Mat Mat::rowRange(int startrow, int endrow) const
C++: Mat Mat::rowRange(const Range& r) const

Parameters:
- startrow – An inclusive 0-based start index of the row span.// 从0开始的行间距索引
- endrow – An exclusive 0-based ending index of the row span.//终止索引
- r – Range structure containing both the start and the end indices.

The method makes a new header for the specified row span of the matrix. Similarly to Mat::row() and Mat::col() , this is an O(1) operation.


其实最简单的方法就是在程序里测试,这个函数的含义。
这里参考: OpenCV从Mat中提取某些行或列
Mat类中的rowRange和colRange的用法
程序参考的是第一篇博文,但是我修改了所取矩阵行的范围,(0,1)
代码如下:

    Mat Test = (Mat_<double>(3,3) << 0,1,2, 3,4,5, 6,7,8);  
    cout << "Total matrix:" << endl;  
    cout << Test << endl;  

    Mat testrow = Test.rowRange(0,1).clone();  
    cout << "Row range:" << endl;  
    cout << testrow << endl;  
    cout << "Test 1 row:" << endl; 
    cout << Test.row(0) << endl;

    Mat testcol = Test.colRange(0,1).clone();  
    cout << "Col range:" << endl;  
    cout << testcol << endl;  

这里写图片描述
因此可以看到,该函数包括左边界,但是不包括右边界。

PS:这里的边界指的是下标索引。因为索引为0才表示第一行,而不是索引为1 表示第一行。

<think>嗯,用户想知道如何用OpenCV和C++提取cv::Mat中指定列区间的数据作为新数组。首先,我需要回忆一下OpenCVMat结构的基本操作。记得Mat类有很多成员函数函数库中的方法可以处理这种需求。 首先,用户提到的“指定列区间”应该是指从某一列到另一列的范围,比如第2列到第5列。这时候,可能需要用到矩阵的ROI(Region of Interest)或者类似的方法来截取部分数据。OpenCV中有一个colRange函数,应该就是用来选择特定列范围的。或者也可以用Rect来指定区域,不过Rect通常用于矩形区域,包括行和列,而如果只是列的话,colRange可能更直接。 接下来,需要确认如何正确使用colRange。比如,假设原矩阵是Mat src,想要提取从start_col到end_col的列,那么应该是src.colRange(start_col, end_col + 1),因为colRange的参数是左闭右开的区间,对吗?比如,colRange(2,5)会包括列2、3、4,所以用户如果想要的区间是包含end_col的话,可能需要调整参数。 另外,需要注意的是,使用colRange或者rowRange返回的是Mat的头部,也就是浅拷贝,如果用户需要新的独立数组,应该使用clone()方法进行深拷贝,否则修改新矩阵会影响原数据。因此,在示例代码中应该提醒用户这一点。 可能还需要考虑异常情况,比如输入的列区间是否超出原Mat的范围,这时候需要确保参数的有效性,避免程序崩溃。不过用户的问题可能更关注基本用法,所以可以在示例中简单处理。 然后,考虑如何将这些步骤用C++代码写出来。比如,先创建一个源矩阵,然后使用colRange获取指定列,再clone成一个新的Mat。例如: cv::Mat src = cv::Mat::ones(3, 5, CV_32F); // 3行5列的矩阵 int start_col = 1; int end_col = 3; cv::Mat dst = src.colRange(start_col, end_col + 1).clone(); 这样dst就会包含原矩阵的第1、2、3列(因为end_col是3,所以end_col+1是4,左闭右开)。这样是否正确? 另外,另一种方法是使用cv::Rect,比如指定x(列起始),宽度,以及y为0,高度为原行数。例如: cv::Mat dst = src(cv::Rect(start_col, 0, end_col - start_col + 1, src.rows)).clone(); 这里需要注意Rect的参数是x, y, width, height,所以width应该是列的数量,比如从start_col到end_col共有end_col - start_col +1列。这样是否正确? 这两种方法哪种更推荐呢?可能colRange更直观,因为直接处理列范围,而Rect更适用于二维区域,但两者都可以实现。用户可能需要知道这两种方法,所以应该在回答中同时给出,并说明区别。 另外,是否需要处理连续存储的情况?可能大多数情况下,clone()会处理好内存,所以用户只需要调用clone即可。 最后,应该给出一个完整的示例代码,包括头文件、主函数等,让用户可以直接复制运行测试。例如: #include <opencv2/opencv.hpp> int main() { cv::Mat src = (cv::Mat_<int>(2, 5) << 1,2,3,4,5,6,7,8,9,10); int start_col = 1; int end_col = 3; cv::Mat dst = src.colRange(start_col, end_col + 1).clone(); // 或者使用Rect // cv::Mat dst = src(cv::Rect(start_col, 0, end_col - start_col +1, src.rows)).clone(); std::cout << "Original:\n" << src << std::endl; std::cout << "Extracted columns:\n" << dst << std::endl; return 0; } 这样运行后应该输出原矩阵和提取后的矩阵,用户可以看到结果是否正确。 需要提醒用户注意列索引是从0开始的,避免出现off-by-one错误。例如,如果原矩阵有5列,有效的列索引是0到4,所以用户传入的start_col和end_col必须在这个范围内,否则会出错。此外,使用clone()是为了深拷贝,否则dst会是src的一个视图,修改dst会影响src的数据。 总结步骤应该是:1.确定列区间;2.使用colRange或Rect提取;3.clone生成新矩阵。确保用户理解每一步的作用,以及注意事项,比如索引范围和深拷贝的重要性。</think>在 OpenCV 中提取 `cv::Mat` 的指定列区间数据为独立数组,可通过以下步骤实现: --- ### **步骤 1:理解列区间范围** - OpenCV 的列索引从 `0` 开始。 - 区间遵循 **左闭右开** 原则,例如 `colRange(1,4)` 包含列 `1,2,3`。 --- ### **步骤 2:使用 `colRange()` 方法** #### 方法 1:直接提取列区间 ```cpp cv::Mat src = cv::Mat::ones(3, 5, CV_32FC1); // 示例:3行5列的矩阵 int start_col = 1; // 起始列索引 int end_col = 3; // 结束列索引(实际包含 end_col-1) // 提取列区间并深拷贝为新数组 cv::Mat dst = src.colRange(start_col, end_col + 1).clone(); ``` #### 方法 2:使用 `cv::Rect` 区域截取 ```cpp cv::Rect roi(start_col, 0, end_col - start_col + 1, src.rows); cv::Mat dst = src(roi).clone(); ``` --- ### **步骤 3:验证结果** 输出原始矩阵和提取结果: ```cpp std::cout << "原始矩阵:\n" << src << std::endl; std::cout << "提取的列区间数据:\n" << dst << std::endl; ``` --- ### **完整代码示例** ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 创建一个示例矩阵(2行5列) cv::Mat src = (cv::Mat_<int>(2, 5) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int start_col = 1; // 起始列索引 int end_col = 3; // 结束列索引 // 方法1:colRange提取列区间 cv::Mat dst_colRange = src.colRange(start_col, end_col + 1).clone(); // 方法2:Rect区域截取 cv::Rect roi(start_col, 0, end_col - start_col + 1, src.rows); cv::Mat dst_rect = src(roi).clone(); // 输出结果 std::cout << "原始矩阵:\n" << src << std::endl; std::cout << "colRange提取结果:\n" << dst_colRange << std::endl; std::cout << "Rect提取结果:\n" << dst_rect << std::endl; return 0; } ``` --- ### **输出结果** ``` 原始矩阵: [1, 2, 3, 4, 5; 6, 7, 8, 9, 10] colRange提取结果: [2, 3, 4; 7, 8, 9] Rect提取结果: [2, 3, 4; 7, 8, 9] ``` --- ### **注意事项** 1. **索引范围**:确保 `start_col` 和 `end_col` 在 `[0, src.cols-1]` 范围内。 2. **深拷贝必要性**:`.clone()` 确保新数组独立于原数据;省略 `.clone()` 会得到原矩阵的引用(浅拷贝)。 3. **数据类型一致**:操作需保证矩阵数据类型(如 `CV_8UC1`, `CV_32FC1` 等)匹配。 通过上述方法,可高效提取 `cv::Mat` 的指定列区间数据。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值