OpenCV(C++)中如何实现label值为5对应位置的mask赋值为255
OpenCV C++ 实现 Matlab/Python 风格的逻辑索引赋值
你要实现的逻辑是:将label矩阵中像素值等于5的所有位置,对应位置的mask像素值设为255。OpenCV C++没有提供Matlab、Python那种方括号逻辑索引的原生语法糖,直接用下面几种方案就能实现等价效果,优先选第一种就行。
方案1:内置API实现(效率最高,最推荐)
直接用OpenCV内置的比较函数和带掩码的赋值接口,内部做了SIMD优化,比手写循环快,也不用自己处理越界、内存步长问题:
// 写法1:显式调用compare,兼容性最好,所有OpenCV版本都支持 Mat cond; compare(label, 5, cond, CMP_EQ); // 生成二值掩码:值等于5的位置为255,其余为0 mask.setTo(255, cond); // 仅cond为非0的位置,mask会被赋值为255 // 写法2:OpenCV 2.x以上都支持的运算符重载写法,更简洁,效率和上面完全一致 mask.setTo(255, label == 5);
注意:这里的
label == 5是OpenCV为cv::Mat重载的比较运算符,不是C++原生的数值相等判断,返回值就是和第一种写法里的cond一样的二值矩阵。
方案2:指针遍历实现(适合需要叠加自定义逻辑的场景)
如果除了赋值255之外,你还要在遍历过程中加其他判断逻辑,可以用指针遍历,注意先判断内存连续性做优化,比用at<uchar>逐点访问快很多:
// 先做合法性校验,避免尺寸/类型不匹配导致越界 CV_Assert(mask.size() == label.size()); CV_Assert(mask.type() == CV_8UC1 && label.type() == CV_8UC1); int rows = mask.rows; int cols = mask.cols; // 矩阵内存连续时把二维数组转成一维遍历,减少循环开销 if (mask.isContinuous() && label.isContinuous()) { cols *= rows; rows = 1; } for (int i = 0; i < rows; i++) { uchar* mask_row = mask.ptr<uchar>(i); const uchar* label_row = label.ptr<uchar>(i); for (int j = 0; j < cols; j++) { if (label_row[j] == 5) { mask_row[j] = 255; // 这里可以追加其他自定义逻辑 } } }
避坑提醒
- 不要直接用两层循环套
mask.at<uchar>(i,j)做访问,at方法每次都会做坐标合法性校验,大分辨率图像下速度比指针遍历慢数倍 - 两个方案最终效果和你写的Matlab/Python逻辑完全一致,输入本身就是
CV_8UC1类型,不需要额外做类型转换
内容的提问来源于stack exchange,提问作者jwm
相关产品推荐
相关产品推荐

