当前位置: 首页 > news >正文

OpenCV(二十):位运算

位运算的概念与基础

在图像处理中,“位运算”(Bitwise Operation)是一类直接作用于像素值二进制位的操作。
OpenCV 对灰度图和彩色图像都支持位运算,常用于掩膜处理、图像融合、背景替换、ROI(感兴趣区域)提取等。

每个像素通常用 8 位(0–255)表示,因此可进行逐位的逻辑计算。
常见的位运算包括:

运算类型数学符号功能描述
按位与AND (&)两个像素同时为 1 时结果为 1,否则为 0
按位或OR (``)
按位非NOT (~)对像素的每一位取反
按位异或XOR (^)两个像素的对应位不同则为 1,相同为 0

图像的位运算是逐像素逐通道进行的。即对每个像素点 (x, y)

dst(x, y, c) = src1(x, y, c) op src2(x, y, c)

其中 c 表示通道(0、1、2 对应 B、G、R)。

OpenCV 提供的位运算函数

OpenCV 封装了几种常用的位运算函数接口,这些函数均在 cv::core 模块中定义:

函数名功能函数原型
bitwise_and()按位与bitwise_and(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray())
bitwise_or()按位或bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray())
bitwise_xor()按位异或bitwise_xor(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray())
bitwise_not()按位取反bitwise_not(InputArray src, OutputArray dst, InputArray mask = noArray())

1. bitwise_and()

用于提取特定区域或进行掩膜计算。
例:

cv::Mat mask, result;
cv::bitwise_and(img1, img2, result, mask);

含义:result = (img1 & img2) & mask
mask 非零处才计算,其余置零。

2. bitwise_or()

可实现图像叠加或合成。
例:

cv::bitwise_or(img1, img2, dst);

通常用于合并两幅互补区域图像。

3. bitwise_xor()

用于检测差异或制作透明区域。
例:

cv::bitwise_xor(img1, img2, diff);

只有两个图像不同位置会得到高亮。

4. bitwise_not()

图像反色操作:黑变白,白变黑。

cv::bitwise_not(gray, inverted);

在遮罩图像处理中非常常见。

位运算的常见应用场景

1. 掩膜提取(Mask Operation)

掩膜是位运算最常用的场景。
例如从一张图中提取目标区域:

import cv2
import numpy as np# 1. 读取原图
img = cv2.imread('example.jpg')  # 请替换为你的图片路径
if img is None:raise FileNotFoundError("无法加载图片,请检查路径")# 2. 创建掩膜(mask),大小与原图相同,初始化为全零(黑色)
mask = np.zeros(img.shape[:2], dtype=np.uint8)# 3. 定义感兴趣区域(ROI),例如一个圆形区域
center = (img.shape[1] // 2, img.shape[0] // 2)  # 图像中心
radius = min(img.shape[:2]) // 4
cv2.circle(mask, center, radius, 255, -1)  # 白色圆形区域# 4. 通过掩膜提取ROI
result = cv2.bitwise_and(img, img, mask=mask)# 5. 显示结果
cv2.imshow('Original', img)
cv2.imshow('Mask', mask)
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里通过阈值生成二值掩膜,掩膜中白色区域被保留,黑色区域被屏蔽。

2. 背景替换与图像合成

位运算结合掩膜,可以方便地将前景叠加到新背景中。

import cv2
import numpy as np# 读取前景(人物)与背景图
fg = cv2.imread('person_green.jpg')
bg = cv2.imread('new_background.jpg')# 调整背景大小与前景一致
bg = cv2.resize(bg, (fg.shape[1], fg.shape[0]))# 转换到 HSV 空间
hsv = cv2.cvtColor(fg, cv2.COLOR_BGR2HSV)# 定义绿色范围(可根据情况调整)
lower_green = np.array([35, 40, 40])
upper_green = np.array([85, 255, 255])# 生成绿色掩膜
mask = cv2.inRange(hsv, lower_green, upper_green)# 反向掩膜(保留非绿区域)
mask_inv = cv2.bitwise_not(mask)# 提取前景中非绿色部分
fg_part = cv2.bitwise_and(fg, fg, mask=mask_inv)# 提取背景中对应绿色部分
bg_part = cv2.bitwise_and(bg, bg, mask=mask)# 合成新图像
result = cv2.add(fg_part, bg_part)cv2.imshow('Foreground', fg)
cv2.imshow('Background', bg)
cv2.imshow('Mask', mask)
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

这种方式广泛用于虚拟背景、更换人像背景、Logo 叠加等场景。

3. 图像差异检测(运动检测)

按位异或(XOR)常用于检测两帧之间的变化:

import cv2
import numpy as np# 打开视频或摄像头
cap = cv2.VideoCapture('video.mp4')  # 或 0 使用摄像头ret, prev_frame = cap.read()
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)while True:ret, frame = cap.read()if not ret:breakgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 计算相邻帧差异diff = cv2.absdiff(prev_gray, gray)# 二值化_, thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)# 形态学去噪kernel = np.ones((5, 5), np.uint8)thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel)# 找运动轮廓contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for c in contours:if cv2.contourArea(c) < 500:continuex, y, w, h = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)cv2.imshow('Frame', frame)cv2.imshow('Diff', diff)cv2.imshow('Motion Mask', thresh)prev_gray = gray.copy()if cv2.waitKey(30) & 0xFF == 27:  # 按 ESC 退出breakcap.release()
cv2.destroyAllWindows()

通过异或后再阈值化,就能获取运动区域。

4. ROI(感兴趣区域)提取

ROI 提取常结合掩膜和按位与使用:

import cv2
import numpy as np# 读取原图
img = cv2.imread('image.jpg')# 创建一个与原图大小一致的黑色掩膜
mask = np.zeros(img.shape[:2], np.uint8)# 定义 ROI 区域 (x, y, w, h)
x, y, w, h = 100, 100, 200, 150
mask[y:y+h, x:x+w] = 255  # 在掩膜上标记 ROI 区域为白色# 用掩膜提取 ROI
roi = cv2.bitwise_and(img, img, mask=mask)cv2.imshow('Original', img)
cv2.imshow('Mask', mask)
cv2.imshow('ROI Extracted', roi)
cv2.waitKey(0)
cv2.destroyAllWindows()

这样仅保留矩形区域内的像素,其余区域变为黑色。

5. 图像融合与透明叠加

位运算可用于图像融合前的预处理,例如使用 bitwise_and 控制叠加区域,addWeighted() 实现平滑融合:

import cv2
import numpy as np# 读取背景图与 logo
bg = cv2.imread('background.jpg')
logo = cv2.imread('logo.png')# 调整 logo 尺寸
rows, cols = logo.shape[:2]
roi = bg[0:rows, 0:cols]  # 选取背景左上角区域# 转换为灰度图,用于制作掩膜
logo_gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)# 生成掩膜和反掩膜
_, mask = cv2.threshold(logo_gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)# 从背景中抠出 ROI 区域(mask_inv=黑背景)
bg_part = cv2.bitwise_and(roi, roi, mask=mask_inv)# 从 logo 中抠出前景
logo_part = cv2.bitwise_and(logo, logo, mask=mask)# 融合两部分
dst = cv2.add(bg_part, logo_part)# 放回原图
bg[0:rows, 0:cols] = dstcv2.imshow('Mask', mask)
cv2.imshow('Result', bg)
cv2.waitKey(0)
cv2.destroyAllWindows()

这种做法比直接相加更精确,可以控制透明区域。

总结

OpenCV 的位运算是图像处理的基础工具之一,其优势在于:

  • 直接操作像素二进制,速度快、无精度损失;
  • 结合掩膜灵活控制区域
  • 在图像合成、抠图、分割中广泛使用
  • 支持硬件加速,可满足实时视频场景。

常见模式总结如下:

应用函数说明
提取目标区域bitwise_and保留 mask 白区
背景替换bitwise_not + bitwise_and + add前景/背景分离
差异检测bitwise_xor检测运动/变化
图像反色bitwise_not图像反相
局部ROI处理任意位运算 + mask精准控制计算范围
http://www.dtcms.com/a/577898.html

相关文章:

  • 重组蛋白纯化标签科普:从His到SUMO、Avi的全面解析
  • 【QT第三章】常用控件1
  • 鱼台做网站多少钱wordpress 防黑
  • 南通网站建设排名公司网站怎么做图片放映效果
  • AI Agent:突破工作流局限,开启智能决策新时代
  • 自己动手写深度学习框架(神经网络的引入)
  • 西安专业网站建设服务好查询食品注册商标查询官网
  • ref对比reactive
  • 基于融智学双重形式化的汉字汉语数学建模方法
  • 手机wap网站多少钱wordpress页面简码
  • 嘉兴网嘉兴网站建设网址大全汽车之家官方网
  • 基于单片机的智能高温消毒与烘干系统设计
  • vue.js设计与实现(待续)
  • 2025 Vue UI 组件库选型
  • 网站内置字体法治网站的建设整改措施
  • 杭州高端网站设计南宁伯才网络建站如何
  • 面试题001
  • 【C#】NLog配置同时写入网络共享路径与本地路径日志
  • 用通俗易懂 + Android 开发实战的方式,详细讲解 Kotlin Flow 中的 retryWhen 操作符
  • Android 四大组件——BroadcastReceiver(广播)
  • 好看的单页面网站模板免费下载百度知道怎么赚钱
  • HTTP与HTTPS的核心区别及加密流程全解析:从明文传输到安全通信的演进
  • 好大夫王建设在线个人网站第一推广网
  • QML学习笔记(五十三)QML与C++交互:数据转换——序列类型与 JavaScript 数组的转换
  • Spring AI Alibaba语音合成实战:从零开始实现文本转语音功能
  • 科技向善,让养老更有温度——智慧养老的痛点破局与趋势前瞻
  • flink开发遇到的问题
  • “IP 地址” 咋分类?用 “电话号码分区” 讲透 A/B/C 类地址​
  • 网站建站服务公司网站建设和续费
  • 北京朝阳双桥网站建设wordpress设置侧边栏