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

OpenCV图像添加水印

一、前言

在数字图像处理中,为图片添加水印是一项常见且重要的技术。无论是版权保护、品牌宣传还是防止未经授权的使用,水印都能发挥重要作用。OpenCV作为一款强大的计算机视觉库,提供了丰富的功能来实现各种水印效果。本教程将详细介绍如何使用OpenCV为图像添加文字水印和图片水印。

二、环境准备

在开始之前,请确保已安装以下环境:

  • Python 3.x

  • OpenCV库(可通过pip install opencv-python安装)

  • NumPy库(OpenCV依赖)

# 导入必要的库
import cv2  # OpenCV库,用于图像处理
import numpy as np  # NumPy库,用于数值计算print("环境准备完成,OpenCV版本:", cv2.__version__)

三、文字水印实现

3.1 基本文字水印

OpenCV提供了cv2.putText()函数来在图像上添加文字。我们先来看这个函数的基本用法:

cv2.putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)

参数详解:

  1. img: 要添加文字的图像(numpy数组)

  2. text: 要添加的文字字符串

  3. org: 文字左下角的坐标(对于bottomLeftOrigin=False的情况),格式为(x, y)

  4. fontFace: 字体类型,常用的有:

    • cv2.FONT_HERSHEY_SIMPLEX: 普通大小无衬线字体

    • cv2.FONT_HERSHEY_PLAIN: 小号无衬线字体

    • cv2.FONT_HERSHEY_DUPLEX: 普通大小无衬线字体(比SIMPLEX更复杂)

    • cv2.FONT_HERSHEY_COMPLEX: 普通大小衬线字体

    • cv2.FONT_HERSHEY_TRIPLEX: 普通大小衬线字体(比COMPLEX更复杂)

    • cv2.FONT_HERSHEY_COMPLEX_SMALL: 小号COMPLEX字体

    • cv2.FONT_HERSHEY_SCRIPT_SIMPLEX: 手写风格字体

    • cv2.FONT_HERSHEY_SCRIPT_COMPLEX: 更复杂的手写风格字体

  5. fontScale: 字体缩放因子,影响字体大小

  6. color: 文字颜色,BGR格式的元组,如(255, 0, 0)表示蓝色

  7. thickness: 文字线条粗细(可选,默认为1)

  8. lineType: 线条类型(可选,默认为cv2.LINE_8)

  9. bottomLeftOrigin: 如果为True,org参数表示文字的左上角而非左下角(可选,默认为False)

示例代码:

# 读取图像
image = cv2.imread('input.jpg')# 设置水印文字参数
text = "Sample Watermark"
position = (50, 50)  # 从图像左上角开始的坐标
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
color = (255, 0, 0)  # 蓝色
thickness = 2
line_type = cv2.LINE_AA  # 抗锯齿线型# 添加文字水印
cv2.putText(image, text, position, font, font_scale, color, thickness, line_type)# 保存结果
cv2.imwrite('output_with_text.jpg', image)

3.2 透明文字水印

为了使水印更加美观且不影响原图内容,我们可以创建半透明的水印效果:

def add_transparent_watermark(input_path, output_path):"""添加半透明文字水印函数参数:input_path (str): 输入图片路径output_path (str): 输出图片路径功能:1. 创建原始图像的副本2. 在副本上添加白色文字3. 将副本与原图按透明度混合4. 保存输出图片"""# 读取原始图像original_image = cv2.imread(input_path)if original_image is None:print(f"错误:无法加载图片 {input_path}")return# 创建原始图像的副本# overlay将用于添加水印,output将保存最终结果overlay = original_image.copy()output = original_image.copy()# 水印文字参数设置watermark_text = "WATERMARK"  # 水印文字内容text_position = (50, 100)  # 文字位置(x,y)# 使用较复杂的字体# cv2.FONT_HERSHEY_COMPLEX: 普通大小衬线字体font_type = cv2.FONT_HERSHEY_COMPLEX  font_size = 1.5  # 较大的字体尺寸text_color = (255, 255, 255)  # 白色文字thickness = 3  # 较粗的线条# 在overlay上添加文字(此时文字是完全不透明的)cv2.putText(overlay,watermark_text,text_position,font_type,font_size,text_color,thickness,cv2.LINE_AA)# 设置透明度# alpha=0.6表示水印60%不透明,原图40%可见alpha = 0.6  """cv2.addWeighted()函数参数详解:src1: 第一个输入数组(overlay)alpha: 第一个数组的权重src2: 第二个输入数组(output)beta: 第二个数组的权重gamma: 标量,添加到每个和的标量dst: 输出数组dtype: 输出数组的可选深度"""# 将overlay和output按透明度混合cv2.addWeighted(overlay,  # 有水印的图像alpha,  # 水印图像的权重output,  # 原始图像1 - alpha,  # 原始图像的权重0,  # 添加到每个和的标量output  # 输出图像)# 保存结果if cv2.imwrite(output_path, output):print(f"透明水印添加成功,结果已保存到 {output_path}")else:print(f"错误:无法保存图片到 {output_path}")# 使用示例
add_transparent_watermark(input_path="input.jpg",output_path="output_transparent.jpg"
)

3.3 多行文字与文字属性获取

有时我们需要添加多行文字或计算文字占据的空间:

def add_multiline_text(image, text_lines=["LINE 1", "LINE 2", "LINE 3"], position=(20, 50), font=cv2.FONT_HERSHEY_PLAIN, font_scale=1.8, color=(0, 255, 0), line_spacing=40):x, y = positionfor line in text_lines:cv2.putText(image, line, (x, y), font, font_scale, color, 2, cv2.LINE_AA)y += line_spacingreturn image# 使用示例
image = cv2.imread('input.jpg')
watermarked = add_multiline_text(image)
cv2.imwrite('output_multiline.jpg', watermarked)

四、图片水印实现

除了文字水印,我们还可以将另一张图片作为水印添加到主图上。

4.1 基本图片水印

def add_image_watermark(background, watermark, position=(50, 50), alpha=0.4):h, w = watermark.shape[:2]roi = background[position[1]:position[1]+h, position[0]:position[0]+w]result = cv2.addWeighted(roi, 1, watermark, alpha, 0)background[position[1]:position[1]+h, position[0]:position[0]+w] = resultreturn background# 使用示例
background = cv2.imread('background.jpg')
watermark = cv2.imread('logo.png')  # 水印图片路径# 调整水印大小
watermark = cv2.resize(watermark, (100, 50))  # 固定尺寸100x50像素watermarked = add_image_watermark(background, watermark)
cv2.imwrite('output_with_logo.jpg', watermarked)

4.2 平铺水印效果

有时我们需要在整个图片上平铺水印:

def add_tiled_watermark(background, watermark, scale=0.1, alpha=0.3):"""添加平铺水印效果参数:background: 背景图像watermark: 水印图像scale: 水印缩放比例alpha: 透明度"""# 调整水印大小h, w = background.shape[:2]watermark = cv2.resize(watermark, (0, 0), fx=scale, fy=scale)wh, ww = watermark.shape[:2]# 计算平铺的行列数rows = h // wh + 1cols = w // ww + 1# 创建水印平铺图像tiled = np.tile(watermark, (rows, cols, 1))tiled = tiled[:h, :w]# 混合图像result = cv2.addWeighted(background, 1, tiled, alpha, 0)return result# 使用示例
background = cv2.imread('background.jpg')
watermark = cv2.imread('logo.png')result = add_tiled_watermark(background, watermark, scale=0.2, alpha=0.2)
cv2.imwrite('output_tiled.jpg', result)

五、高级水印技术

5.1 斜角水印

斜角水印是一种以对角线方向重复排列的水印设计方式,它通过在图像上沿斜线方向(通常是45度角)均匀分布水印元素(文字或Logo),形成有规律的网格化视觉效果。 

def add_diagonal_pattern_watermark(input_path, output_path):"""添加斜角重复水印函数参数:input_path (str): 输入图片路径output_path (str): 输出图片路径功能:1. 创建图像副本2. 计算图像对角线长度3. 沿对角线方向重复添加水印文字4. 与原图混合5. 保存结果"""# 读取原始图像image = cv2.imread(input_path)if image is None:print(f"错误:无法加载图片 {input_path}")return# 创建原始图像的副本overlay = image.copy()output = image.copy()# 获取图像尺寸height, width = image.shape[:2]print(f"图像尺寸: 宽度={width}, 高度={height}")# 水印文字参数watermark_text = "SAMPLE"  # 水印文字内容font_type = cv2.FONT_HERSHEY_SCRIPT_SIMPLEX  # 手写风格字体font_size = 1.8  # 较大的字体text_color = (200, 200, 200)  # 浅灰色# 计算图像对角线长度(勾股定理)diagonal_length = int(np.sqrt(height**2 + width**2))print(f"图像对角线长度: {diagonal_length}像素")# 设置水印间距spacing = 120  # 水印之间的间隔(像素)# 计算需要多少个水印num_watermarks = diagonal_length // spacing + 1print(f"将添加约 {num_watermarks} 个水印")# 添加斜角水印for i in range(-num_watermarks, num_watermarks + 1):# 计算每条斜线的起始x坐标x_start = i * spacing# 沿斜线方向放置水印for j in range(0, diagonal_length, spacing):x = x_start + j  # 当前x坐标y = j  # 当前y坐标# 检查坐标是否在图像范围内if 0 <= x < width and 0 <= y < height:cv2.putText(overlay,watermark_text,(x, y),  # 当前位置font_type,font_size,text_color,2,  # 线条粗细cv2.LINE_AA)# 设置水印整体透明度alpha = 0.15  # 水印不透明度(15%)# 混合图像cv2.addWeighted(overlay,  # 有水印的图像alpha,  # 水印权重output,  # 原始图像1 - alpha,  # 原始图像权重0,  # 标量值output  # 输出图像)# 保存结果if cv2.imwrite(output_path, output):print(f"斜角水印添加成功,结果已保存到 {output_path}")else:print(f"错误:无法保存图片到 {output_path}")# 使用示例
add_diagonal_pattern_watermark(input_path="input.jpg",output_path="output_diagonal.jpg"
)

5.2 自适应水印位置 

def add_adaptive_watermark(image, text, font, font_scale, color, alpha=0.5):"""根据图像内容自适应选择水印位置参数:image: 原始图像text: 水印文字font: 字体类型font_scale: 字体大小color: 文字颜色alpha: 透明度"""# 转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 计算图像梯度grad_x = cv2.Sobel(gray, cv2.CV_32F, 1, 0, ksize=3)grad_y = cv2.Sobel(gray, cv2.CV_32F, 0, 1, ksize=3)magnitude = np.sqrt(grad_x**2 + grad_y**2)# 获取文本尺寸(text_width, text_height), _ = cv2.getTextSize(text, font, font_scale, thickness=2)# 寻找梯度最小的区域放置水印min_magnitude = float('inf')best_position = (0, 0)for y in range(0, image.shape[0] - text_height, 10):for x in range(0, image.shape[1] - text_width, 10):region = magnitude[y:y+text_height, x:x+text_width]current_magnitude = np.mean(region)if current_magnitude < min_magnitude:min_magnitude = current_magnitudebest_position = (x, y + text_height)  # putText使用左下角坐标# 添加水印overlay = image.copy()output = image.copy()cv2.putText(overlay, text, best_position, font, font_scale, color, 2, cv2.LINE_AA)cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, output)return output# 使用示例
image = cv2.imread('input.jpg')
watermarked = add_adaptive_watermark(image, "ADAPTIVE", cv2.FONT_HERSHEY_COMPLEX, 1.2, (0, 0, 255), 0.6)
cv2.imwrite('output_adaptive.jpg', watermarked)

六、水印安全与反去除

为了提高水印的安全性,防止轻易被去除,可以考虑以下技术:

  1. 频域水印:将水印嵌入到图像的频域中(如DCT或DWT变换域)

  2. 随机点水印:在图像中随机位置添加微小的像素变化

  3. 多重水印:结合文字和图片水印,在不同位置添加

def add_frequency_domain_watermark(image, watermark_text, strength=0.1):"""在频域添加简单文字水印参数:image: 原始图像watermark_text: 水印文字strength: 水印强度"""# 将图像转换为YCrCb颜色空间,只对亮度通道(Y)进行操作ycrcb = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)y = ycrcb[:, :, 0].astype(np.float32)# 执行DCT变换dct = cv2.dct(y)# 创建水印模式watermark = np.zeros_like(y)cv2.putText(watermark, watermark_text, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2, cv2.LINE_AA)watermark = cv2.resize(watermark, (dct.shape[1], dct.shape[0]))# 在频域添加水印dct_watermarked = dct + watermark * strength# 执行逆DCT变换y_watermarked = cv2.idct(dct_watermarked)# 将结果放回原图像ycrcb[:, :, 0] = np.clip(y_watermarked, 0, 255)watermarked = cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2BGR)return watermarked# 使用示例
image = cv2.imread('input.jpg')
watermarked = add_frequency_domain_watermark(image, "FREQ_DOMAIN", 0.05)
cv2.imwrite('output_frequency.jpg', watermarked)

七、总结

本教程详细介绍了使用OpenCV添加各种水印的方法,包括:

  1. 基本文字水印和透明文字水印

  2. 多行文字水印和文字属性处理

  3. 图片水印和透明图片水印

  4. 平铺水印和斜角水印效果

  5. 自适应水印位置选择

  6. 频域水印等高级技术

每种方法都提供了详细的参数解释和示例代码,读者可以根据自己的需求选择合适的水印方式。在实际应用中,可能需要结合多种技术来提高水印的效果和安全性。

希望本教程能够帮助您掌握OpenCV添加水印的各种技巧,为您的图像处理项目提供有价值的参考。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

http://www.lryc.cn/news/575921.html

相关文章:

  • word中如何保存高清图片,并保存为高质量的pdf文件(图像不失真)
  • 51c~嵌入式~PLC~西门子~合集1
  • GO 语言学习 之 语句块
  • 汉中农业服务——激活田野的希望,共绘乡村振兴图
  • Guava Cache 本地项目缓存
  • 昇腾910(NPU)安装paddlepaddle【自用版】
  • LinuxBridge的作用与发展历程:从基础桥接到云原生网络基石
  • 【Linux指南】压缩、网络传输与系统工具
  • 用 pnpm + TurboRepo,构建多项目高效开发体系
  • 人工智能-基础篇-4-人工智能AI、机器学习ML和深度学习DL之间的关系
  • 几种基于Doherty结构的GAN氮化镓功放设计方法介绍
  • Ehcache、Caffeine、Spring Cache、Redis、J2Cache、Memcached 和 Guava Cache 的主要区别
  • 算法-堆排序
  • 飞算科技依托 JavaAI 核心技术,打造企业级智能开发全场景方案
  • AIOps与人工智能的融合:从智能运维到自适应IT生态的革命
  • 【网络】Linux 内核优化实战 - net.ipv4.tcp_rmem 和 net.core.rmem_default 关系
  • MySQL(1)——count()聚合函数
  • V-by-One V1.4协议介绍
  • QT基础知识3——文件操作:QFile类
  • windows11 源码本地部署大模型anythingllm
  • web布局26
  • sqlite如何存储日期
  • 【数据交易】全国数据交易所的发展现状
  • 开源 java android app 开发(十三)绘图定义控件、摇杆控件的制作
  • OpenLayers 拖动旋转和缩放
  • Python打卡训练营-Day44-预训练模型
  • 生成式人工智能实战 | WGAN(Wasserstein Generative Adversarial Network, GAN)
  • Thread Network:物联网时代的低功耗网状网络协议解析
  • 使用 Vcpkg 安装 Qt 时的常见问题与解决方法
  • SQL Server for Linux 如何实现高可用架构