OpenCV 算术运算四件套:NOT/AND/OR 位运算与图像混合

OpenCV 算术运算四件套:NOT/AND/OR 位运算与图像混合

OpenCV 图像处理课程 · 第 5 章「Arithmetic Operation」学习笔记

环境:Python 3.10 + opencv-python 4.5.5.64 + PyCharm(chapter5 目录)

包含 4 课:Not / AND / OR 位运算 + 图像混合


章节总览

主题 核心函数 文件
01 非操作 NOT cv2.bitwise_not() not_operation.py
02 与操作 AND cv2.bitwise_and() and_operation.py
03 或操作 OR cv2.bitwise_or() or_operation.py
04 图像混合 cv2.addWeighted() image_blending.py

本章说明 :位运算用于图像掩码(masking) ,提取图像关键部分。多个输入图像的尺寸必须相同,输出尺寸与输入一致,逐像素运算。


第 1 课 · 非操作 NOT(cv2.bitwise_not)

真值表

输入 输出
0 1
1 0

概念

  • 常用于二值图像(像素只有 0 和 255 两个值:黑/白)
  • cv2.bitwise_not 输出图像的反色:0→255,255→0

函数签名

python 复制代码
cv2.bitwise_not(src, dst=None, mask=None)
  • src:输入二值图像
  • dst / mask:可选,一般传 None(可省略)

完整代码(not_operation.py)

python 复制代码
import cv2

image_path = "../data/mask.jpg"
image = cv2.imread(image_path)

not_image = cv2.bitwise_not(image)

cv2.imshow("image", image)
cv2.imshow("not image", not_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

演示结果

  • 输入黑色像素(0)→ 输出白色像素(255)
  • 输入白色像素(255)→ 输出黑色像素(0)

#mermaid-svg-jolaS1Eew2QJRSaN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jolaS1Eew2QJRSaN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jolaS1Eew2QJRSaN .error-icon{fill:#552222;}#mermaid-svg-jolaS1Eew2QJRSaN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jolaS1Eew2QJRSaN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jolaS1Eew2QJRSaN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jolaS1Eew2QJRSaN .marker.cross{stroke:#333333;}#mermaid-svg-jolaS1Eew2QJRSaN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jolaS1Eew2QJRSaN p{margin:0;}#mermaid-svg-jolaS1Eew2QJRSaN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jolaS1Eew2QJRSaN .cluster-label text{fill:#333;}#mermaid-svg-jolaS1Eew2QJRSaN .cluster-label span{color:#333;}#mermaid-svg-jolaS1Eew2QJRSaN .cluster-label span p{background-color:transparent;}#mermaid-svg-jolaS1Eew2QJRSaN .label text,#mermaid-svg-jolaS1Eew2QJRSaN span{fill:#333;color:#333;}#mermaid-svg-jolaS1Eew2QJRSaN .node rect,#mermaid-svg-jolaS1Eew2QJRSaN .node circle,#mermaid-svg-jolaS1Eew2QJRSaN .node ellipse,#mermaid-svg-jolaS1Eew2QJRSaN .node polygon,#mermaid-svg-jolaS1Eew2QJRSaN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jolaS1Eew2QJRSaN .rough-node .label text,#mermaid-svg-jolaS1Eew2QJRSaN .node .label text,#mermaid-svg-jolaS1Eew2QJRSaN .image-shape .label,#mermaid-svg-jolaS1Eew2QJRSaN .icon-shape .label{text-anchor:middle;}#mermaid-svg-jolaS1Eew2QJRSaN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jolaS1Eew2QJRSaN .rough-node .label,#mermaid-svg-jolaS1Eew2QJRSaN .node .label,#mermaid-svg-jolaS1Eew2QJRSaN .image-shape .label,#mermaid-svg-jolaS1Eew2QJRSaN .icon-shape .label{text-align:center;}#mermaid-svg-jolaS1Eew2QJRSaN .node.clickable{cursor:pointer;}#mermaid-svg-jolaS1Eew2QJRSaN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jolaS1Eew2QJRSaN .arrowheadPath{fill:#333333;}#mermaid-svg-jolaS1Eew2QJRSaN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jolaS1Eew2QJRSaN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jolaS1Eew2QJRSaN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jolaS1Eew2QJRSaN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jolaS1Eew2QJRSaN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jolaS1Eew2QJRSaN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jolaS1Eew2QJRSaN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jolaS1Eew2QJRSaN .cluster text{fill:#333;}#mermaid-svg-jolaS1Eew2QJRSaN .cluster span{color:#333;}#mermaid-svg-jolaS1Eew2QJRSaN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jolaS1Eew2QJRSaN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jolaS1Eew2QJRSaN rect.text{fill:none;stroke-width:0;}#mermaid-svg-jolaS1Eew2QJRSaN .icon-shape,#mermaid-svg-jolaS1Eew2QJRSaN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jolaS1Eew2QJRSaN .icon-shape p,#mermaid-svg-jolaS1Eew2QJRSaN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jolaS1Eew2QJRSaN .icon-shape .label rect,#mermaid-svg-jolaS1Eew2QJRSaN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jolaS1Eew2QJRSaN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jolaS1Eew2QJRSaN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jolaS1Eew2QJRSaN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出图像(反色)
cv2.bitwise_not
输入图像(二值)
黑 (0)
白 (255)
逐像素取反
白 (255)
黑 (0)

真实演示图(用遮罩图测试反色):

输入(二值遮罩) 输出(NOT 反色)

白色(255)区域 → 变黑;黑色(0)区域 → 变白。


第 2 课 · 与操作 AND(cv2.bitwise_and)

真值表

输入 A 输入 B 输出
0 0 0
0 1 0
1 0 0
1 1 1

只有当两个像素都大于 0 时结果为真。

概念

  • 逐像素 AND:任一输入像素为 0,输出就为 0(黑色)
  • 用于掩码:保留两图都亮(>0)的区域,遮掉其他

函数签名

python 复制代码
cv2.bitwise_and(src1, src2, dst=None, mask=None)
  • src1 / src2:两个输入数组/标量
  • 两个输入图像形状必须相同,否则报错

完整代码(and_operation.py)

python 复制代码
import cv2

image_path1 = "../data/mask.jpg"
image_path2 = "../data/horse.jpg"
image_one = cv2.imread(image_path1)
image_two = cv2.imread(image_path2)

image_and = cv2.bitwise_and(image_one, image_two)

cv2.imshow("image_one", image_one)
cv2.imshow("image_two", image_two)
cv2.imshow("image and", image_and)
cv2.waitKey(0)
cv2.destroyAllWindows()

要点

  • 两图交点:亮度>0 的区域保留,否则变黑
  • 例:用 mask.jpg(黑白遮罩)对 horse.jpg 做 AND → 只显示马匹区域
  • 形状必须一致,否则抛错

#mermaid-svg-LAKRQm964kqBUyr7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LAKRQm964kqBUyr7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LAKRQm964kqBUyr7 .error-icon{fill:#552222;}#mermaid-svg-LAKRQm964kqBUyr7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LAKRQm964kqBUyr7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LAKRQm964kqBUyr7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LAKRQm964kqBUyr7 .marker.cross{stroke:#333333;}#mermaid-svg-LAKRQm964kqBUyr7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LAKRQm964kqBUyr7 p{margin:0;}#mermaid-svg-LAKRQm964kqBUyr7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LAKRQm964kqBUyr7 .cluster-label text{fill:#333;}#mermaid-svg-LAKRQm964kqBUyr7 .cluster-label span{color:#333;}#mermaid-svg-LAKRQm964kqBUyr7 .cluster-label span p{background-color:transparent;}#mermaid-svg-LAKRQm964kqBUyr7 .label text,#mermaid-svg-LAKRQm964kqBUyr7 span{fill:#333;color:#333;}#mermaid-svg-LAKRQm964kqBUyr7 .node rect,#mermaid-svg-LAKRQm964kqBUyr7 .node circle,#mermaid-svg-LAKRQm964kqBUyr7 .node ellipse,#mermaid-svg-LAKRQm964kqBUyr7 .node polygon,#mermaid-svg-LAKRQm964kqBUyr7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LAKRQm964kqBUyr7 .rough-node .label text,#mermaid-svg-LAKRQm964kqBUyr7 .node .label text,#mermaid-svg-LAKRQm964kqBUyr7 .image-shape .label,#mermaid-svg-LAKRQm964kqBUyr7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-LAKRQm964kqBUyr7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LAKRQm964kqBUyr7 .rough-node .label,#mermaid-svg-LAKRQm964kqBUyr7 .node .label,#mermaid-svg-LAKRQm964kqBUyr7 .image-shape .label,#mermaid-svg-LAKRQm964kqBUyr7 .icon-shape .label{text-align:center;}#mermaid-svg-LAKRQm964kqBUyr7 .node.clickable{cursor:pointer;}#mermaid-svg-LAKRQm964kqBUyr7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LAKRQm964kqBUyr7 .arrowheadPath{fill:#333333;}#mermaid-svg-LAKRQm964kqBUyr7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LAKRQm964kqBUyr7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LAKRQm964kqBUyr7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LAKRQm964kqBUyr7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LAKRQm964kqBUyr7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LAKRQm964kqBUyr7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LAKRQm964kqBUyr7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LAKRQm964kqBUyr7 .cluster text{fill:#333;}#mermaid-svg-LAKRQm964kqBUyr7 .cluster span{color:#333;}#mermaid-svg-LAKRQm964kqBUyr7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LAKRQm964kqBUyr7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LAKRQm964kqBUyr7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-LAKRQm964kqBUyr7 .icon-shape,#mermaid-svg-LAKRQm964kqBUyr7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LAKRQm964kqBUyr7 .icon-shape p,#mermaid-svg-LAKRQm964kqBUyr7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LAKRQm964kqBUyr7 .icon-shape .label rect,#mermaid-svg-LAKRQm964kqBUyr7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LAKRQm964kqBUyr7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LAKRQm964kqBUyr7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LAKRQm964kqBUyr7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AND 运算结果
原图 horse
遮罩 mask(黑白)
白色区域

(255, 保留)
黑色区域

(0, 遮掉)
马匹区域
背景区域
只保留白色遮罩覆盖区

= 马匹
背景被遮成黑

真实演示图(遮罩对场景图做 AND 抠取):

输入1(遮罩) 输入2(场景图) 输出(AND)

白色遮罩区域内的内容(蓝色矩形+红圆)被保留,黑色遮罩区域被遮成黑色。


第 3 课 · 或操作 OR(cv2.bitwise_or)

真值表

输入 A 输入 B 输出
0 0 0
0 1 1
1 0 1
1 1 1

只要任一个像素大于 0 结果就为真。

概念

  • 逐像素 OR:任一像素为 255,输出就为 255(白)
  • 用于合并/取消掩码区域:两图像素都 >0 则保留

函数签名

python 复制代码
cv2.bitwise_or(src1, src2, dst=None, mask=None)
  • src1 / src2 形状必须相同

完整代码(or_operation.py)

python 复制代码
import cv2

image_path1 = "../data/mask.jpg"
image_path2 = "../data/horse.jpg"
image_one = cv2.imread(image_path1)
image_two = cv2.imread(image_path2)

image_or = cv2.bitwise_or(image_one, image_two)

cv2.imshow("image_one", image_one)
cv2.imshow("image_two", image_two)
cv2.imshow("image or", image_or)
cv2.waitKey(0)
cv2.destroyAllWindows()

要点

  • 两图中任意亮度>0 的区域都被合并保留
  • 两图像素都为 0 才是黑色

#mermaid-svg-DfmVvdxZEhQuwVyk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DfmVvdxZEhQuwVyk .error-icon{fill:#552222;}#mermaid-svg-DfmVvdxZEhQuwVyk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DfmVvdxZEhQuwVyk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DfmVvdxZEhQuwVyk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DfmVvdxZEhQuwVyk .marker.cross{stroke:#333333;}#mermaid-svg-DfmVvdxZEhQuwVyk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DfmVvdxZEhQuwVyk p{margin:0;}#mermaid-svg-DfmVvdxZEhQuwVyk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster-label text{fill:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster-label span{color:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster-label span p{background-color:transparent;}#mermaid-svg-DfmVvdxZEhQuwVyk .label text,#mermaid-svg-DfmVvdxZEhQuwVyk span{fill:#333;color:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk .node rect,#mermaid-svg-DfmVvdxZEhQuwVyk .node circle,#mermaid-svg-DfmVvdxZEhQuwVyk .node ellipse,#mermaid-svg-DfmVvdxZEhQuwVyk .node polygon,#mermaid-svg-DfmVvdxZEhQuwVyk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DfmVvdxZEhQuwVyk .rough-node .label text,#mermaid-svg-DfmVvdxZEhQuwVyk .node .label text,#mermaid-svg-DfmVvdxZEhQuwVyk .image-shape .label,#mermaid-svg-DfmVvdxZEhQuwVyk .icon-shape .label{text-anchor:middle;}#mermaid-svg-DfmVvdxZEhQuwVyk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DfmVvdxZEhQuwVyk .rough-node .label,#mermaid-svg-DfmVvdxZEhQuwVyk .node .label,#mermaid-svg-DfmVvdxZEhQuwVyk .image-shape .label,#mermaid-svg-DfmVvdxZEhQuwVyk .icon-shape .label{text-align:center;}#mermaid-svg-DfmVvdxZEhQuwVyk .node.clickable{cursor:pointer;}#mermaid-svg-DfmVvdxZEhQuwVyk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DfmVvdxZEhQuwVyk .arrowheadPath{fill:#333333;}#mermaid-svg-DfmVvdxZEhQuwVyk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DfmVvdxZEhQuwVyk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DfmVvdxZEhQuwVyk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DfmVvdxZEhQuwVyk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DfmVvdxZEhQuwVyk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DfmVvdxZEhQuwVyk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster text{fill:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk .cluster span{color:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DfmVvdxZEhQuwVyk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DfmVvdxZEhQuwVyk rect.text{fill:none;stroke-width:0;}#mermaid-svg-DfmVvdxZEhQuwVyk .icon-shape,#mermaid-svg-DfmVvdxZEhQuwVyk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DfmVvdxZEhQuwVyk .icon-shape p,#mermaid-svg-DfmVvdxZEhQuwVyk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DfmVvdxZEhQuwVyk .icon-shape .label rect,#mermaid-svg-DfmVvdxZEhQuwVyk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DfmVvdxZEhQuwVyk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DfmVvdxZEhQuwVyk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DfmVvdxZEhQuwVyk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OR 运算结果
图像二
图像一
亮区 (255, 保留)
暗区 (0)
亮区 (255, 保留)
暗区 (0)
任一图亮即保留

= 两图内容合并
都暗才为黑

真实演示图(两图合并):

输入1 输入2 输出(OR)

两图中任一可见的区域都被合并保留,只有两图都是黑的区域才为黑。


第 4 课 · 图像混合(cv2.addWeighted)

概念

  • 图像混合 :把两个图像的对应像素值按权重相加,生成新图像
  • 用处:让两图内容同时出现在输出里(叠加/透明效果)
  • 公式:输出 = alpha × img1 + beta × img2 + gamma

函数签名

python 复制代码
cv2.addWeighted(src1, alpha, src2, beta, gamma)
参数 含义
src1 / src2 两个输入图像
alpha src1 的权重(通常 0~1)
beta src2 的权重(通常 0~1)
gamma 加到所有像素的静态权值

通常 alpha + beta = 1。两图尺寸必须一致。

完整代码(image_blending.py)

python 复制代码
import cv2

image_path1 = "../data/horse.jpg"
image_path2 = "../data/horse1.jpg"

image_one = cv2.imread(image_path1)
image_two = cv2.imread(image_path2)

print("image1 shape:", image_one.shape)   # (360, 540, 3)
print("image2 shape:", image_two.shape)   # 尺寸不同!

# 若两图尺寸不同,先把 img2 缩放到 img1 尺寸
height, width, channels = image_one.shape
image_two = cv2.resize(image_two, (width, height))

blend_image = cv2.addWeighted(image_one, 0.5, image_two, 0.5, 0)

cv2.imshow("image_one", image_one)
cv2.imshow("image_two", image_two)
cv2.imshow("blend image", blend_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

要点

  • alpha=0.5, beta=0.5 → 两图各占一半透明叠加
  • 调 betabeta=0.1 → 图2 很淡;beta=0 → 图2 完全消失
  • 尺寸不同要先 resize (用 cv2.resize(image_two, (width, height))),否则抛错

#mermaid-svg-f1sgpg6sXftCsOcW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-f1sgpg6sXftCsOcW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-f1sgpg6sXftCsOcW .error-icon{fill:#552222;}#mermaid-svg-f1sgpg6sXftCsOcW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-f1sgpg6sXftCsOcW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-f1sgpg6sXftCsOcW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-f1sgpg6sXftCsOcW .marker.cross{stroke:#333333;}#mermaid-svg-f1sgpg6sXftCsOcW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-f1sgpg6sXftCsOcW p{margin:0;}#mermaid-svg-f1sgpg6sXftCsOcW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-f1sgpg6sXftCsOcW .cluster-label text{fill:#333;}#mermaid-svg-f1sgpg6sXftCsOcW .cluster-label span{color:#333;}#mermaid-svg-f1sgpg6sXftCsOcW .cluster-label span p{background-color:transparent;}#mermaid-svg-f1sgpg6sXftCsOcW .label text,#mermaid-svg-f1sgpg6sXftCsOcW span{fill:#333;color:#333;}#mermaid-svg-f1sgpg6sXftCsOcW .node rect,#mermaid-svg-f1sgpg6sXftCsOcW .node circle,#mermaid-svg-f1sgpg6sXftCsOcW .node ellipse,#mermaid-svg-f1sgpg6sXftCsOcW .node polygon,#mermaid-svg-f1sgpg6sXftCsOcW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-f1sgpg6sXftCsOcW .rough-node .label text,#mermaid-svg-f1sgpg6sXftCsOcW .node .label text,#mermaid-svg-f1sgpg6sXftCsOcW .image-shape .label,#mermaid-svg-f1sgpg6sXftCsOcW .icon-shape .label{text-anchor:middle;}#mermaid-svg-f1sgpg6sXftCsOcW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-f1sgpg6sXftCsOcW .rough-node .label,#mermaid-svg-f1sgpg6sXftCsOcW .node .label,#mermaid-svg-f1sgpg6sXftCsOcW .image-shape .label,#mermaid-svg-f1sgpg6sXftCsOcW .icon-shape .label{text-align:center;}#mermaid-svg-f1sgpg6sXftCsOcW .node.clickable{cursor:pointer;}#mermaid-svg-f1sgpg6sXftCsOcW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-f1sgpg6sXftCsOcW .arrowheadPath{fill:#333333;}#mermaid-svg-f1sgpg6sXftCsOcW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-f1sgpg6sXftCsOcW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-f1sgpg6sXftCsOcW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f1sgpg6sXftCsOcW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-f1sgpg6sXftCsOcW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f1sgpg6sXftCsOcW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-f1sgpg6sXftCsOcW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-f1sgpg6sXftCsOcW .cluster text{fill:#333;}#mermaid-svg-f1sgpg6sXftCsOcW .cluster span{color:#333;}#mermaid-svg-f1sgpg6sXftCsOcW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-f1sgpg6sXftCsOcW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-f1sgpg6sXftCsOcW rect.text{fill:none;stroke-width:0;}#mermaid-svg-f1sgpg6sXftCsOcW .icon-shape,#mermaid-svg-f1sgpg6sXftCsOcW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f1sgpg6sXftCsOcW .icon-shape p,#mermaid-svg-f1sgpg6sXftCsOcW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-f1sgpg6sXftCsOcW .icon-shape .label rect,#mermaid-svg-f1sgpg6sXftCsOcW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f1sgpg6sXftCsOcW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-f1sgpg6sXftCsOcW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-f1sgpg6sXftCsOcW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 混合图像
cv2.addWeighted
两个输入图像(先 resize 对齐尺寸)
image_one

horse.jpg
image_two

horse1.jpg
输出 = α·img1 + β·img2 + γ

(α=0.5, β=0.5, γ=0)
两图各占 50% 半透明叠加

真实演示图(50% 加权混合):

输入1 (α=0.5) 输入2 (β=0.5) 输出(混合)

两图各贡献 50%,两个场景内容都能看到(半透明叠加)。


本章小结(速查表)

运算 函数 真值逻辑 用途
NOT cv2.bitwise_not(src) 0↔1 反色
AND cv2.bitwise_and(s1, s2) 都>0 才真 掩码/抠局部
OR cv2.bitwise_or(s1, s2) 任一>0 即真 合并区域
混合 cv2.addWeighted(s1,a,s2,b,γ) 加权相加 图像叠加

核心易错点

  1. 位运算输入尺寸必须相同(不同会抛错)
  2. 颜色/像素都是 BGR,位运算是逐像素的
  3. addWeighted 的 alpha+beta 通常=1,gamma 加在全体像素上
  4. 混合前若两图尺寸不同,先 cv2.resize 对齐
相关推荐
这张生成的图像能检测吗39 分钟前
(综述)基于遗传神经网络的不平衡故障诊断技术综述
人工智能·生成对抗网络·故障诊断
我叫张土豆41 分钟前
在 OpenClaw Java 对话框输入一句话后,系统是如何运行的?
java·开发语言·人工智能
边吃番茄边敲代码42 分钟前
企业智能助手Agent 安全测试,包含Prompt Injection 和越权工具调用
人工智能·python·功能测试·ai·单元测试·prompt·模块测试
科技小E43 分钟前
自建团队、买SaaS、还是用自动化AI算法训练服务器DLTM?企业AI视觉三条路线算笔账
人工智能·深度学习·自动化
小鹿软件办公1 小时前
Apple Music 将于 2026 年底强制为 AI 音乐添加“由 AI 制作”标签
人工智能·苹果音乐ai生成标签·apple music
AI模型调用笔记1 小时前
Codex mcp-server 被弃用:不是 MCP 退场,App Server、SDK 与 Claude Code 插件怎么选?
人工智能
hyuk的AI工坊1 小时前
多模态图文理解:LangChain4j 视觉理解实战(DashScope 通义千问 qwen-vl)
人工智能
KKKlucifer1 小时前
异构融合与大规模割接——某电信运营商融合4A平台建设实践
大数据·网络·人工智能·安全
GIR7201 小时前
重构全球关节腔内注射物行业竞争格局:市场占有率、销量排名及主要竞争对手分析
大数据·人工智能