cv2.bitwise_and(src1, src2, mask=None)
src1:参与运算的第一幅图(决定输出图像的颜色)。src2:参与运算的第二幅图(决定输出图像的尺寸 和位深 ,通常与src1相同)。mask:可选参数。如果是单通道图像(黑白),只有值为 255 (白色) 的像素才会进行运算,值为 0 (黑色) 的像素结果强制为 0 (黑色)。
2. 为什么要传两个 img?
因为按位与运算(Bitwise AND)是两个图像之间 的运算:
Result ( x , y ) = src1 ( x , y ) & src2 ( x , y ) \text{Result}(x,y) = \text{src1}(x,y) \ \& \ \text{src2}(x,y) Result(x,y)=src1(x,y) & src2(x,y)
- 如果
src1和src2都是原图img:- 数学上: A & A = A A \ \& \ A = A A & A=A (任何数和自己做"与"运算,结果还是它自己)。
- 实际效果 :颜色完全保留原图,唯一改变图像的是
mask。
3. 如果没有 mask 会怎样?
如果不传 mask,代码变成:
python
red_object = cv2.bitwise_and(img, img)
- 结果:
red_object会和img一模一样 (因为 A & A = A A \ \& \ A = A A & A=A)。 - 毫无意义。
4. 加上 mask 后发生了什么?
python
red_object = cv2.bitwise_and(img, img, mask=mask)
OpenCV 内部逻辑如下:
- 遍历每一个像素点 ( x , y ) (x, y) (x,y) :
- 如果
mask[x, y] == 255(白色):- 计算
img[x, y] & img[x, y]→ 结果保留原图颜色。
- 计算
- 如果
mask[x, y] == 0(黑色):- 结果直接设为
0(黑色),不执行上面的与运算。
- 结果直接设为
- 如果
🎨 视觉效果演示
假设原图是一个红苹果,mask 是一个圆形的白色区域(苹果形状),背景是黑色。
| 步骤 | 图像内容 | 作用 |
|---|---|---|
| src1 | 🍎 红苹果 | 提供"红色"这个颜色数据 |
| src2 | 🍎 红苹果 | 提供"苹果形状"这个尺寸数据 |
| mask | ⚪ 白圆圈 + ⚫ 黑背景 | 关键! 告诉程序:只保留圆圈里的东西 |
| 结果 | 🍎 红苹果 + ⚫ 黑背景 | 圆圈外变成了纯黑,圆圈内保留了红色 |
❓ 常见疑问
Q: 第二个 img 可以换成别的吗?
A: 可以,但必须满足两个条件:
- 尺寸必须完全一致(高、宽一样)。
- 通道数必须兼容(通常也是一样的 BGR 三通道)。
如果你传一张全白的图作为第二个参数:
python
white_img = np.ones_like(img) * 255
result = cv2.bitwise_and(img, white_img, mask=mask)
- 逻辑:
原图颜色 & 白色 (255)。 - 数学: A & 255 = A A \ \& \ 255 = A A & 255=A。
- 结果:和传两个
img是一模一样的。
结论 :传两个 img 只是最方便、最直观的写法,表示"我想保留原图的颜色,但在 mask 指定的区域显示"。
✅ 总结代码意图
python
# 这句话的直译:
# "请给我原图 (img),但是在 mask 为黑色的地方把它涂黑,只留下 mask 为白色的部分。"
red_object = cv2.bitwise_and(img, img, mask=mask)
这就是提取红色物体(或任何掩膜区域)的标准写法!
🔦 超级通俗理解:手电筒照画
想象你在一个漆黑的房间里:
- 第一个
img= 墙上挂的一幅画(这是你要看的东西)。 - 第二个
img= 另一幅一模一样的画 (这是为了配合运算规则,暂时先不管它,你就当它是备用的画)。 mask= 一个手电筒 。- 手电筒照到的地方(白色区域)= 亮。
- 没照到的地方(黑色区域)= 暗。
🎬 现在的操作是:
你拿着手电筒(mask),对着第一幅画 (第一个 img)照。
- 被照亮的地方:你看到了画原本的颜色(保留了原图)。
- 没照到的地方:一片漆黑(变成了黑色背景)。
❓ 那为什么要拿第二幅画 (第二个 img)出来?
这是因为电脑(OpenCV)是个死脑筋的会计,它的规矩是:
"要做'与'运算(bitwise_and),我必须手里拿着两张纸进行对比,少一张我都不干活!"
- 既然你的目的是**"保留第一张画的原样",那你只能再拿一张 一模一样**的画(第二个
img)递给它。 - 电脑拿着两张一模一样的画一比对:
- "嗯,这张是红色,那张也是红色 → 结果还是红色。"
- "嗯,这张是蓝色,那张也是蓝色 → 结果还是蓝色。"
- 最后,它再盖上"手电筒"(mask)的章:只有光照到的地方才把比对结果显示出来,没照到的地方直接涂黑。
💡 一句话总结
传两个 img,是因为电脑强制要求必须有两张图才能做运算。
- 因为我们不想改变颜色,所以故意传了两张一模一样的图去"骗"过电脑的规则。
- 真正起作用的"剪刀",其实是后面的
mask。
如果写成人类语言,这行代码的意思是:
"电脑,给你两张一模一样的图(
img,img),请你帮我做个比对(结果肯定还是原图),但是! 只用把手电筒(mask)照到的地方显示出来,其他地方给我涂黑!"