一、前言

在数字图像处理中,为图片添加水印是一项常见且重要的技术。无论是版权保护、品牌宣传还是防止未经授权的使用,水印都能发挥重要作用。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.pswp.cn/pingmian/86409.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86409.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86409.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV CUDA模块设备层-----双曲正弦函数sinh()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 OpenCV的CUDA 模块&#xff08;cv::cudev&#xff09;中的一个设备端数学函数&#xff0c;用于在 GPU 上对 uchar3 类型的像素值&#xff08;如R…

使用 Xinference 命令行工具(xinference launch)部署 Nanonets-OCR-s

使用Xinference命令行工具(xinference launch)部署Nanonets-OCR-s 一、核心优势与适用场景 通过xinference launch命令可直接在命令行完成模型部署,无需编写Python代码,适合快速验证或生产环境批量部署。 二、部署步骤:从命令行启动模型 1. 确认环境与依赖 已安装Xinf…

鸿蒙 List 组件解析:从基础列表到高性能界面开发指南

一、引言&#xff1a;列表布局 —— 鸿蒙应用的数据展示中枢 在鸿蒙应用开发体系中&#xff0c;列表布局是处理结构化数据展示的核心场景。从新闻资讯的信息流、电商平台的商品陈列到任务管理的待办事项&#xff0c;几乎所有中大型应用都依赖高效的列表组件实现数据可视化。鸿…

原生微信小程序中限制多选框(Checkbox)可选个数的实现详解

在实际业务场景中&#xff0c;我们经常会遇到表单中的复选框多选限制需求。例如最多只能选择 3 个爱好、标签、兴趣点等&#xff0c;这时就需要在微信小程序中手动控制 Checkbox 的选择行为。 本文将通过一个完整的示例&#xff0c;演示如何实现最多只能选择 N 个的 Checkbox …

OpenCV CUDA模块设备层-----线性插值函数log()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于创建线性插值访问器&#xff0c;支持对GPU内存中的图像数据进行双线性插值采样。主要应用于图像缩放、旋转等几何变换中需要亚像素级精…

Redis 单线程的“天花板”与集群的必要性

虽然 Redis 以其单线程模型&#xff08;主要是处理请求的核心逻辑&#xff09;带来了极高的性能和简洁性&#xff0c;但这并不意味着它没有瓶颈。 CPU 瓶颈&#xff1a;当业务逻辑复杂&#xff0c;或者 Redis 执行大量计算密集型操作&#xff08;比如使用 Lua 脚本进行复杂处理…

16.7 Prometheus+Grafana实战:容器化监控与日志聚合一站式解决方案

《Prometheus+Grafana实战:容器化监控与日志聚合一站式解决方案》 关键词:容器化监控、日志聚合、Prometheus、Grafana、ELK Stack、用户反馈收集 容器化监控与日志系统的架构设计 在 LanguageMentor Agent 生产部署中,监控系统需要覆盖以下维度: #mermaid-svg-I7cOqUK0i…

商务创业项目策划计划书PPT模版

创业商业融资计划书PPT模版&#xff0c;商务商业计划融资书PPT模版&#xff0c;创业融资计划书PPT模版&#xff0c;框架完整创业融资计划书PPT模版 商务创业项目策划计划书PPT模版&#xff1a;https://pan.quark.cn/s/d07d22408497

【软考高级系统架构论文】论面向方面的编程技术及其应用

论文真题: 请围绕“论软件测试中缺陷管理及其应用”论题,依次从以下三个方面进行论述: 概要叙述你参与管理和开发的软件项目以及承担的工作。详细论述常见的缺陷种类及级别,论述缺陷管理的基本流程。结合你具体参与管理和开发的实际项目,说明是如何进行缺陷管理的。请具体…

人机协作新范式:GEO与COKE框架的融合应用与品牌大模型种草实践

在人工智能迅猛发展的今天&#xff0c;我们正经历着人机关系的根本性重构。从工具性使用到协作伙伴关系&#xff0c;AI正在以前所未有的方式融入企业运营和品牌建设的各个环节。尤其是在品牌传播领域&#xff0c;“品牌大模型种草”正在成为品牌实现优质曝光和用户信任构建的新…

速通KVM(云计算学习指南)

第一章 云端的变形金刚&#xff1a;KVM的云计算基因 1.1 云计算与KVM的共生关系 想象一下&#xff0c;你有一台魔法服务器&#xff0c;它能像变形金刚一样随时分解成多台独立的小服务器&#xff0c;又能瞬间合体恢复原状——这就是KVM在云计算中扮演的角色。作为Linux内核的原…

C#最佳实践:为何优先使用隐式类型

C#最佳实践:为何优先使用隐式类型 在C#的编程世界里,类型声明是编写代码的重要环节。从早期严格指定变量类型,到引入隐式类型var,编程方式发生了不小的变革。隐式类型并非简单的语法糖,合理使用它能让代码更简洁、更易读,还能适应复杂的编程场景。接下来,我们就深入探讨…

PG靶机复现 Squid

官方定义为easy级别&#xff0c;因为省略了提权阶段&#xff0c;这个靶机主要是利用3128 Squid服务 枚举 通过nmap扫描到3128端口开启。 Squid 是一个缓存和转发的 HTTP 网络代理。它有多种用途&#xff0c;包括通过缓存重复请求来加速 web 服务器&#xff0c;为共享网络资源…

Java底层原理:深入理解JVM类加载机制与反射机制

一、JVM类加载机制 JVM类加载机制是Java运行时环境的重要组成部分&#xff0c;它负责将字节码文件加载到JVM内存中&#xff0c;并将其转换为可执行的类。类加载机制的实现涉及类加载器&#xff08;ClassLoader&#xff09;、类加载过程和类加载器的层次结构。 &#xff08;一…

系统思考:结构影响行为

感谢今天参与沙龙伙伴的评价&#xff0c;虽然只有短短半天的时间&#xff0c;希望今天的交流能为大家带来一些思考的火花。真正的改变&#xff0c;往往不仅来自一次启发&#xff0c;更来自一个支持改变的结构。 就像系统思考中所说的&#xff1a;“结构影响行为。”如果我们希望…

Ubuntu 20.04 系统上运行 SLAM卡顿是什么原因

在 Ubuntu 20.04 系统上运行 SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;数据集时出现卡顿&#xff0c;可能是由硬件、软件配置或数据集处理需求等多方面原因导致。以下是一些可能的原因和解决建议&#xff1a; 1. 硬件性能瓶颈 尽管你使用的是 NVID…

Starwind商用共享存储解决方案——安装篇

介绍 StarWind 是一家提供虚拟化和存储解决方案的软件公司&#xff0c;主要专注于为中小企业&#xff08;SME&#xff09;和远程办公室/分支机构&#xff08;ROBO&#xff09;环境提供高性价比的虚拟化存储解决方案。其核心产品包括 StarWind Virtual SAN 和 StarWind NAS 等&…

Unity | AmplifyShaderEditor插件基础(第十集:噪声的种类+火焰制作-中)

一、&#x1f44b;&#x1f3fb;前言 你现在看见的是一套非常系统的ASE入门学习教程&#xff0c;并不是心血来潮随心创作的。 up原来是初中物理老师&#xff08;有教师资格证&#xff09;后转入程序行业&#xff0c;认真学习过课程设计等相关知识&#xff0c;只要你认真的学每一…

从零开始的二三维CAD|CAE轻量级软件开发:学习以及研发,Gmsh的脚本编辑器设计!

背景: 痛点: 1.编写.geo脚本, 没有智能提示很头大; 2.没有高亮显示很头大! 在数值仿真过程中,大家离不开gmsh这个软件,而在学习的过程中,也离不开要编写.geo脚本, 写这种脚本麻烦的要死,那么多脚本函数要记? 反正写的很头大, 所以,既然为了方便大家,也为了方便自己,不如自…

ModerationModel温和模式

ModerationModel能够对内容进⾏合规检测&#xff0c;屏蔽那些不合规的内容。未来如果你的⼤模型应⽤需要对外提供 服务时&#xff0c;合规就是⼀个必须的标准。 1、代码 import dev.langchain4j.model.moderation.Moderation; import dev.langchain4j.model.moderation.Modera…