cv::bitwise_and和cv::bitwise_or分别实现二值图像的交集与并集运算;要求输入掩码尺寸、类型、通道数完全一致(通常为CV_8UC1),需预先归一化为0/255,输出复用Mat对象以提升性能。

cv::bitwise_and 和 cv::bitwise_or 就是你要的交并集
OpenCV 里没有叫 intersection 或 union 的专用函数,但二值图像的“交”就是逐像素逻辑与,“并”就是逻辑或——cv::bitwise_and 和 cv::bitwise_or 完全对应,且底层高度优化,比手写循环快一个数量级。
两个掩码必须尺寸、类型、通道数完全一致(通常是 CV_8UC1),否则运行时抛出 OpenCV(4.x): error: (-215:Assertion failed) src1.size == src2.size && src1.type() == src2.type()。
- 确保输入是单通道
CV_8UC1:用mask1.convertScaleAbs(mask1)或mask1 = mask1 > 0归一化为 0/255 - 输出图像需预先分配内存(或传入空
cv::Mat,OpenCV 会自动创建),避免反复 realloc - 若掩码来自
cv::inRange或cv::threshold,通常已是正确格式,可直接用
交集 = 共同为 1 的区域,别误用 cv::multiply
cv::multiply 做的是逐像素乘法(0×0=0,0×255=0,255×255=65025),结果溢出后截断为 255,看似“对”,但语义错误:它不反映逻辑交集,且在非 0/255 值下行为不可控(比如中间灰度值 128×128=16384 → 255)。
- 交集务必用
cv::bitwise_and(mask1, mask2, dst) - 如果想统计交集像素个数:用
cv::countNonZero(dst),比sum(dst)[0]更快更准 - 注意:
dst类型和mask1一致,不会自动转成 float
并集计算后可能残留“脏值”,记得归一化
cv::bitwise_or 对 0/255 输入是安全的,但如果你的掩码含中间值(如浮点阈值后未二值化),或叠加了多次操作,bitwise_or 可能产出 >255 的值(虽然 OpenCV 内部会 saturate,但保险起见)。
- 稳妥做法:并集后加一步
dst = dst > 0(生成CV_8UC1布尔掩码) - 或者用
cv::threshold(dst, dst, 1, 255, cv::THRESH_BINARY) - 不要依赖
cv::bitwise_or输出“一定只有 0 和 255”——OpenCV 文档没保证这点,尤其跨版本时
性能关键:避免重复创建 Mat 对象
高频调用(如视频流中每帧算 IOU)时,反复构造 cv::Mat 会触发内存分配,成为瓶颈。
- 提前声明结果 Mat:
cv::Mat intersection, union_mask; - 首次调用后它们已有尺寸和类型,后续直接复用:
cv::bitwise_and(a, b, intersection) - 若尺寸可能变化,用
intersection.create(a.size(), a.type())主动重置,比构造新对象轻量得多 - 别用
cv::Mat dst = cv::bitwise_and(...)——这会强制拷贝
实际用的时候,交并集本身很简单,真正容易卡住的是掩码数据状态不干净、类型不匹配、或者在循环里反复 new Mat。把输入归一化、输出复用、结果再二值化这三步走稳,就基本不会掉坑里。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











