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水印、支持递归目录处理、生成处理日志报告等,从而打造一个高度定制化、完全贴合个人或团队工作流的自动化图片处理工具。
相关攻略
Python处理Excel文件时,覆盖写入和追加写入是常见需求。覆盖写入可使用pandas的to_excel方法或openpyxl创建新工作簿实现,直接替换原文件。追加写入分为在现有工作表末尾追加行和新增工作表两种情况。前者推荐使用openpyxl直接定位追加,高效且安全;后者可通过pandas的ExcelWriter在追加模式下完成,保留原有工作表。
IntelliJIDEA编写Python时,代码提示常不准确,导致运行时错误。优化方法包括:正确配置Python解释器、安装并启用Python插件、同步或重建项目索引、遵循PEP8规范保持代码清晰,以及定期更新IDEA至最新版本。通过调整这些配置与状态,可显著提升提示准确性和开发效率。
Python2 7已停止维护,需在CentOS7中升级至Python3 7并确保与系统组件共存。步骤包括安装编译环境、下载解压源码、配置编译安装。随后需创建新版本软链接以替换默认命令,并修改yum等系统工具的解释器路径指向Python2 7,从而在不影响系统稳定的前提下完成升级。
在Linux系统中将Python2升级至Python3时,需避免覆盖旧版本以防影响系统依赖。关键步骤包括:下载Python3源码包并解压,创建独立安装目录,配置编译选项后安装。随后备份原有Python链接,建立指向新版本的可执行文件软链接,最后验证版本确认升级成功。操作中需注意使用root权限执行相关命令。
批量处理图片是常见需求,手动操作效率低下。利用Python和OpenCV库可以自动化完成批量缩放与添加水印的任务。文章介绍了使用OpenCV进行图片读取、按比例缩放、添加半透明文字水印以及遍历文件夹批量处理的方法,并提供了兼容中文路径的解决方案。整个过程适合初学者实践,能显著提升图片处理效率。
热门专题
热门推荐
进行币安身份认证时,除了准确上传照片,还需注意人脸光线和证件类型的选择。光线不佳可能导致系统无法识别,建议使用均匀柔和的正面光。证件类型上,护照通常比身份证更易通过,因其信息格式全球统一。确保证件照片清晰、四角完整、无反光,并严格按照提示操作,能有效提升一次性通过率,避免反复提交的麻烦。
本文旨在为初次接触币安平台的用户提供一份清晰、全面的操作指南。内容涵盖从官网访问与账户注册、安全设置与身份验证,到入金购买加密货币、进行现货交易以及资产管理的完整流程。重点解析了核心交易界面的功能与基础订单类型,并强调了安全措施与自主资产管理的重要性,帮助用户快速上手并安全地进行数字资产交易。
使用iQOO 15上网后,想要彻底清除浏览痕迹?掌握正确的方法至关重要。不同的清理方式,在效果和应用场景上各有侧重。本文为您梳理五种主流方案,涵盖快速清理、选择性删除、深度重置及自动防护,助您根据实际需求灵活选择,有效保护个人隐私。 一、通过浏览器历史页面一键清空 这是最便捷的解决方案,适合需要快速
币安平台界面功能丰富,新用户常因不熟悉而找不到关键操作按钮。本文梳理了资金充值、交易下单、资产管理、订单查看、理财申购、安全设置、身份认证和客服帮助这八个最容易迷路的页面,详细说明了各页面核心按钮的位置和功能逻辑,帮助用户快速适应平台操作,提升使用效率。
在加密货币提币操作中,确保资产安全的关键步骤往往被忽视。本文重点探讨了提币前必须仔细核对的三个核心环节:提币地址的准确性、平台安全验证的完整性,以及资产到账链路的清晰性。通过逐一分析这些环节的风险点与最佳实践,旨在帮助用户建立严谨的操作习惯,避免因疏忽导致的资产损失,实现更安全、顺畅的资产转移。





