Python批量缩放图片并添加水印的OpenCV实现教程
图片批量处理是许多工作场景中的常见需求,无论是统一电商商品图尺寸、压缩活动照片体积,还是为资料截图添加品牌水印。面对成百上千的图片文件,手动操作不仅效率低下,还容易出错。这正是Python自动化脚本发挥价值的绝佳场景。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
本文将手把手教你使用opencv-python库,构建一个功能完善的“图片批量缩放与添加水印”工具。整个过程逻辑清晰、代码简洁,无需深入复杂的图像算法,非常适合Python初学者和希望提升办公自动化效率的开发者实践。

1. OpenCV 是什么
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它提供了丰富的图像处理功能,从基础的读写、裁剪、缩放、滤镜,到高级的人脸识别、物体追踪等。在Python中,我们通过安装opencv-python包来调用其核心功能:
pip install opencv-python
安装成功后,可以通过以下代码验证环境是否配置正确:
import cv2 print(cv2.__version__)
2. 图片读取与保存
OpenCV提供了直观的图片读写接口:cv2.imread()用于读取图片,cv2.imwrite()用于保存图片。
import cv2
image = cv2.imread("input.jpg")
if image is None:
raise FileNotFoundError("图片读取失败,请检查文件路径")
cv2.imwrite("output.jpg", image)
需要了解一个关键概念:OpenCV将读取的图片转换为NumPy多维数组进行处理。数组的形状(shape)遵循(高度, 宽度, 通道数)的格式。例如,一张1920x1080的彩色图片,其形状通常为(1080, 1920, 3),分别对应高度、宽度和BGR三个颜色通道。
3. 图片缩放
调整图片尺寸主要依赖cv2.resize()函数,它支持多种缩放模式。
3.1 按指定宽高缩放
直接设定目标宽度和高度即可,注意参数顺序为(宽度, 高度)。
resized = cv2.resize(image, (800, 600))
3.2 按比例缩放
通过设置缩放因子,可以实现等比例缩放。例如,将图片宽高均缩小为原来的一半:
resized = cv2.resize(image, None, fx=0.5, fy=0.5)
其中,fx为宽度缩放比例,fy为高度缩放比例。
3.3 按目标宽度等比例缩放
在实际应用中,更常见的需求是限制图片的最大宽度,同时保持原始宽高比,防止图片变形。实现方法是先计算缩放比例,再推导出对应的高度。
height, width = image.shape[:2] target_width = 1000 scale = target_width / width target_height = int(height * scale) resized = cv2.resize(image, (target_width, target_height))
4. 添加文字水印
使用cv2.putText()函数可以在图片上绘制文字。该函数参数明确,易于理解:
watermarked = image.copy()
cv2.putText(
watermarked,
text="Python OpenCV", # 水印文字内容
org=(30, 60), # 文字左下角的起始坐标(x, y)
fontFace=cv2.FONT_HERSHEY_SIMPLEX, # 字体类型
fontScale=1.2, # 字体缩放系数
color=(255, 255, 255), # 文字颜色(BGR顺序)
thickness=2, # 字体粗细
lineType=cv2.LINE_AA # 抗锯齿线型,使边缘平滑
)
一个重要的细节是:OpenCV默认使用BGR颜色通道顺序,这与常见的RGB顺序不同。因此,纯白色是(255, 255, 255),而纯红色是(0, 0, 255)。
5. 半透明文字水印
直接绘制不透明水印可能过于突兀。更优的方案是创建一个覆盖层(overlay),在其上绘制文字,然后通过图像混合技术,以一定的透明度叠加到原图上。
overlay = image.copy() output = image.copy() # 在覆盖层上绘制文字 cv2.putText(overlay, "Python OpenCV", (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 255), 2, cv2.LINE_AA) # 混合图像,alpha参数控制水印透明度 alpha = 0.35 watermarked = cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0)
alpha参数是关键,其值范围在0到1之间。值越大,水印越明显;值越小,水印越淡雅。
6. 批量处理整个文件夹图片
实现批量处理的逻辑非常清晰:遍历指定输入文件夹,筛选出所有支持的图片格式,然后对每一张图片执行“读取->缩放->添加水印->保存”的标准化流程。
首先,定义常见的图片文件扩展名集合:
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
接着,利用Python的pathlib模块优雅地遍历文件夹:
from pathlib import Path
input_dir = Path("input_images")
for file_path in input_dir.iterdir():
if file_path.suffix.lower() in IMAGE_EXTENSIONS:
print(file_path) # 识别出一张待处理的图片
7. 中文路径兼容处理
在Windows系统下,当文件路径或名称包含中文字符时,标准的cv2.imread()和cv2.imwrite()函数可能会报错。一个可靠的解决方案是使用numpy.fromfile()结合cv2.imdecode()来读取图片,使用cv2.imencode()结合tofile()来保存图片。
7.1 兼容中文路径读取
import cv2
import numpy as np
def imread_unicode(file_path):
data = np.fromfile(str(file_path), dtype=np.uint8)
image = cv2.imdecode(data, cv2.IMREAD_COLOR)
return image
7.2 兼容中文路径保存
def imwrite_unicode(file_path, image):
ext = file_path.suffix
success, encoded_image = cv2.imencode(ext, image)
if not success:
return False
encoded_image.tofile(str(file_path))
return True
8. 完整项目代码
将上述所有功能模块整合,即可得到一个健壮、实用的批量图片处理脚本。建议将其保存为batch_resize_watermark.py。
假设项目目录结构如下:
image_project/ ├─ batch_resize_watermark.py ├─ input_images/ │ ├─ 示例图片1.jpg │ ├─ 示例图片2.png │ └─ 示例图片3.webp └─ output_images/
完整的脚本代码如下:
from pathlib import Path
import cv2
import numpy as np
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
def imread_unicode(file_path: Path):
"""兼容中文路径的图片读取。"""
data = np.fromfile(str(file_path), dtype=np.uint8)
image = cv2.imdecode(data, cv2.IMREAD_COLOR)
return image
def imwrite_unicode(file_path: Path, image) -> bool:
"""兼容中文路径的图片保存。"""
file_path.parent.mkdir(parents=True, exist_ok=True)
ext = file_path.suffix
success, encoded_image = cv2.imencode(ext, image)
if not success:
return False
encoded_image.tofile(str(file_path))
return True
def resize_keep_ratio(image, max_width: int = 1200):
"""按最大宽度等比例缩放图片。"""
height, width = image.shape[:2]
if width <= max_width:
return image.copy()
scale = max_width / width
target_height = int(height * scale)
resized = cv2.resize(
image,
(max_width, target_height),
interpolation=cv2.INTER_AREA
)
return resized
def add_text_watermark(
image,
text: str,
alpha: float = 0.35,
margin: int = 30
):
"""在图片右下角添加半透明文字水印。"""
output = image.copy()
overlay = image.copy()
height, width = image.shape[:2]
font_face = cv2.FONT_HERSHEY_SIMPLEX
font_scale = max(width / 1200, 0.7)
thickness = max(int(width / 600), 1)
text_size, baseline = cv2.getTextSize(
text,
font_face,
font_scale,
thickness
)
text_width, text_height = text_size
x = max(width - text_width - margin, margin)
y = max(height - margin, text_height + margin)
# 先绘制一层深色阴影,增强在浅色背景下的可读性
cv2.putText(
overlay,
text,
(x + 2, y + 2),
font_face,
font_scale,
(0, 0, 0),
thickness + 1,
cv2.LINE_AA
)
# 再绘制白色文字主体
cv2.putText(
overlay,
text,
(x, y),
font_face,
font_scale,
(255, 255, 255),
thickness,
cv2.LINE_AA
)
watermarked = cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0)
return watermarked
def process_image(
input_path: Path,
output_path: Path,
watermark_text: str,
max_width: int
) -> bool:
"""处理单张图片:读取、缩放、加水印、保存。"""
image = imread_unicode(input_path)
if image is None:
print(f"读取失败: {input_path}")
return False
resized = resize_keep_ratio(image, max_width=max_width)
watermarked = add_text_watermark(resized, watermark_text)
success = imwrite_unicode(output_path, watermarked)
if not success:
print(f"保存失败: {output_path}")
return False
return True
def batch_process_images(
input_dir: Path,
output_dir: Path,
watermark_text: str = "Python OpenCV",
max_width: int = 1200
) -> None:
"""批量处理文件夹中的图片。"""
if not input_dir.exists():
raise FileNotFoundError(f"输入文件夹不存在: {input_dir}")
output_dir.mkdir(parents=True, exist_ok=True)
image_files = [
file_path
for file_path in input_dir.iterdir()
if file_path.is_file() and file_path.suffix.lower() in IMAGE_EXTENSIONS
]
if not image_files:
print(f"没有找到可处理的图片: {input_dir}")
return
success_count = 0
for input_path in image_files:
output_path = output_dir / input_path.name
success = process_image(
input_path=input_path,
output_path=output_path,
watermark_text=watermark_text,
max_width=max_width
)
if success:
success_count += 1
print(f"处理完成: {input_path.name}")
print(f"批量处理结束,成功 {success_count}/{len(image_files)} 张")
print(f"输出目录: {output_dir.resolve()}")
def main():
input_dir = Path("input_images")
output_dir = Path("output_images")
batch_process_images(
input_dir=input_dir,
output_dir=output_dir,
watermark_text="Python OpenCV",
max_width=1200
)
if __name__ == "__main__":
main()
在命令行中运行此脚本:
python batch_resize_watermark.py
运行成功后,终端将显示类似以下信息,表明所有图片均已处理完毕:
处理完成: 示例图片1.jpg 处理完成: 示例图片2.png 处理完成: 示例图片3.webp 批量处理结束,成功 3/3 张 输出目录: D:\image_project\output_images
9. 效果演示说明
脚本执行前,请将待处理的原始图片放入input_images文件夹。脚本执行后,处理完成的图片将保存至output_images文件夹。每张图片将经历两个核心处理步骤:
- 智能缩放:如果原图宽度超过预设的
max_width(默认为1200像素),则会按比例缩放到该最大宽度,高度自动调整以保持原图比例。 - 添加水印:在图片右下角添加指定的半透明文字水印,水印大小会根据图片尺寸自适应调整。
得益于中文路径兼容处理,即使文件夹或文件名包含中文,整个流程也能顺畅执行。
10. 常见问题
10.1 为什么 OpenCV 的颜色是 BGR
这是OpenCV库早期的一个设计决策,其默认颜色通道顺序为BGR(蓝-绿-红),而许多其他图像库(如PIL/Pillow、Matplotlib)采用RGB顺序。在涉及颜色操作时,需要注意此区别并进行必要的转换。
10.2 PNG 透明背景会保留吗
本文示例代码使用cv2.IMREAD_COLOR模式读取图片,此模式会忽略PNG图像的透明通道(Alpha通道)。如果需要处理带透明背景的PNG图片,应改用cv2.IMREAD_UNCHANGED模式读取,并在后续的图像处理步骤中妥善维护Alpha通道数据。
10.3 水印位置如何调整
水印位置由add_text_watermark函数中的坐标计算逻辑决定。默认位置是右下角。若想将水印置于左上角,可修改坐标计算部分:
x = margin y = text_height + margin
10.4 如何递归处理子文件夹
当前脚本仅处理输入目录的顶层文件。若要递归处理所有子目录中的图片,可将遍历代码从input_dir.iterdir()替换为input_dir.rglob("*")。同时,在生成输出路径时,需要保留原文件的相对目录结构,以防止不同子目录下的同名文件相互覆盖。
总结
通过本项目,我们系统性地实践了使用OpenCV进行图像处理的几个核心操作:图片的读取与保存、等比例缩放、文字水印添加以及透明度混合。同时,也解决了实际开发中常见的中文路径兼容性与批量文件遍历问题。
掌握这些基础知识后,你可以轻松扩展脚本功能,例如实现批量格式转换、添加图片Logo水印、支持递归目录处理、生成处理日志报告等,从而打造一个高度定制化、完全贴合个人或团队工作流的自动化图片处理工具。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
Python提取Word表格并导出为Excel的详细步骤教程
在日常办公与数据处理工作中,将Word文档中的表格高效、准确地迁移到Excel中进行计算与分析,是一项常见且重要的需求。面对数十页乃至上百页的文档,传统的手动复制粘贴不仅耗时费力,还极易引发数据错位、格式丢失等问题。那么,是否存在一种方法,能够彻底告别这种低效重复劳动,实现一键自动化处理呢?答案是肯
C#教程如何设置Excel单元格编辑权限与保护
FreeSpire XLSfor NET库可在C 中实现Excel单元格编辑权限控制。其核心原理是:先解除全表锁定,再锁定特定单元格或区域,最后启用工作表保护并设置密码。该库支持锁定特定单元格、整行整列,并能通过SheetProtectionType精细控制操作权限,还可设置允许编辑区域及文档级密码保护。
C#编程教程Excel雷达图制作方法与实例详解
雷达图,也被称为蜘蛛图或星状图,是一种强大的多变量数据可视化工具。它能够在同一坐标系内清晰展示多个对象在不同维度上的表现差异,例如对比不同员工在沟通能力、专业技能、工作效率等多个考核指标上的评分。通过将各维度数据点连接成多边形,雷达图能够直观揭示数据的整体均衡性、突出优势与短板,因此在绩效评估、竞品
Java 17 新特性详解:语言增强与运行时优化全解析
Java 17 作为 Java 11 之后的下一个长期支持(LTS)版本,其战略地位至关重要。它不仅提供免费使用直至2024年9月,更将获得Oracle的扩展支持直至2029年9月,确保了企业级应用的长期稳定。此版本汇集了Java 12至16的众多关键特性,并在语言语法、核心API、运行时安全及性能
Ubuntu系统下Java项目依赖管理方法与步骤详解
在Ubuntu系统进行Java开发,需先安装OpenJDK及Maven或Gradle等构建工具。依赖管理主要通过项目的pom xml或build gradle文件声明。使用依赖树命令可分析冲突,并通过排除传递依赖或强制指定版本等方式解决。建议采用父POM版本管理或Gradle版本目录实现依赖版本统一。
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

