首页 游戏 软件 资讯 排行榜 专题
首页
编程语言
Python批量缩放图片并添加水印的OpenCV实现教程

Python批量缩放图片并添加水印的OpenCV实现教程

热心网友
38
转载
2026-05-11

图片批量处理是许多工作场景中的常见需求,无论是统一电商商品图尺寸、压缩活动照片体积,还是为资料截图添加品牌水印。面对成百上千的图片文件,手动操作不仅效率低下,还容易出错。这正是Python自动化脚本发挥价值的绝佳场景。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

本文将手把手教你使用opencv-python库,构建一个功能完善的“图片批量缩放与添加水印”工具。整个过程逻辑清晰、代码简洁,无需深入复杂的图像算法,非常适合Python初学者和希望提升办公自动化效率的开发者实践。

基于Python+OpenCV实现图片批量缩放与加水印功能

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文件夹。每张图片将经历两个核心处理步骤:

  1. 智能缩放:如果原图宽度超过预设的max_width(默认为1200像素),则会按比例缩放到该最大宽度,高度自动调整以保持原图比例。
  2. 添加水印:在图片右下角添加指定的半透明文字水印,水印大小会根据图片尺寸自适应调整。

得益于中文路径兼容处理,即使文件夹或文件名包含中文,整个流程也能顺畅执行。

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水印、支持递归目录处理、生成处理日志报告等,从而打造一个高度定制化、完全贴合个人或团队工作流的自动化图片处理工具。

来源:https://www.jb51.net/python/363522gn2.htm
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

Python如何覆盖与追加Excel文件数据
编程语言
Python如何覆盖与追加Excel文件数据

Python处理Excel文件时,覆盖写入和追加写入是常见需求。覆盖写入可使用pandas的to_excel方法或openpyxl创建新工作簿实现,直接替换原文件。追加写入分为在现有工作表末尾追加行和新增工作表两种情况。前者推荐使用openpyxl直接定位追加,高效且安全;后者可通过pandas的ExcelWriter在追加模式下完成,保留原有工作表。

热心网友
05.11
IntelliJ IDEA Python代码提示优化方法与设置教程
编程语言
IntelliJ IDEA Python代码提示优化方法与设置教程

IntelliJIDEA编写Python时,代码提示常不准确,导致运行时错误。优化方法包括:正确配置Python解释器、安装并启用Python插件、同步或重建项目索引、遵循PEP8规范保持代码清晰,以及定期更新IDEA至最新版本。通过调整这些配置与状态,可显著提升提示准确性和开发效率。

热心网友
05.11
Python 2.7 升级至 Python 3.7 完整迁移指南与步骤详解
编程语言
Python 2.7 升级至 Python 3.7 完整迁移指南与步骤详解

Python2 7已停止维护,需在CentOS7中升级至Python3 7并确保与系统组件共存。步骤包括安装编译环境、下载解压源码、配置编译安装。随后需创建新版本软链接以替换默认命令,并修改yum等系统工具的解释器路径指向Python2 7,从而在不影响系统稳定的前提下完成升级。

热心网友
05.11
Linux系统Python2升级Python3详细步骤与注意事项
编程语言
Linux系统Python2升级Python3详细步骤与注意事项

在Linux系统中将Python2升级至Python3时,需避免覆盖旧版本以防影响系统依赖。关键步骤包括:下载Python3源码包并解压,创建独立安装目录,配置编译选项后安装。随后备份原有Python链接,建立指向新版本的可执行文件软链接,最后验证版本确认升级成功。操作中需注意使用root权限执行相关命令。

热心网友
05.11
Python批量缩放图片并添加水印的OpenCV实现教程
编程语言
Python批量缩放图片并添加水印的OpenCV实现教程

批量处理图片是常见需求,手动操作效率低下。利用Python和OpenCV库可以自动化完成批量缩放与添加水印的任务。文章介绍了使用OpenCV进行图片读取、按比例缩放、添加半透明文字水印以及遍历文件夹批量处理的方法,并提供了兼容中文路径的解决方案。整个过程适合初学者实践,能显著提升图片处理效率。

热心网友
05.11

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

币安身份认证攻略:优化光线与证件类型,大幅提升人脸识别通过率
web3.0
币安身份认证攻略:优化光线与证件类型,大幅提升人脸识别通过率

进行币安身份认证时,除了准确上传照片,还需注意人脸光线和证件类型的选择。光线不佳可能导致系统无法识别,建议使用均匀柔和的正面光。证件类型上,护照通常比身份证更易通过,因其信息格式全球统一。确保证件照片清晰、四角完整、无反光,并严格按照提示操作,能有效提升一次性通过率,避免反复提交的麻烦。

热心网友
05.11
币安Binance新手入门教程:从注册到交易全流程详解
web3.0
币安Binance新手入门教程:从注册到交易全流程详解

本文旨在为初次接触币安平台的用户提供一份清晰、全面的操作指南。内容涵盖从官网访问与账户注册、安全设置与身份验证,到入金购买加密货币、进行现货交易以及资产管理的完整流程。重点解析了核心交易界面的功能与基础订单类型,并强调了安全措施与自主资产管理的重要性,帮助用户快速上手并安全地进行数字资产交易。

热心网友
05.11
iQOO 15手机浏览器历史记录与缓存数据清理步骤详解
手机教程
iQOO 15手机浏览器历史记录与缓存数据清理步骤详解

使用iQOO 15上网后,想要彻底清除浏览痕迹?掌握正确的方法至关重要。不同的清理方式,在效果和应用场景上各有侧重。本文为您梳理五种主流方案,涵盖快速清理、选择性删除、深度重置及自动防护,助您根据实际需求灵活选择,有效保护个人隐私。 一、通过浏览器历史页面一键清空 这是最便捷的解决方案,适合需要快速

热心网友
05.11
币安交易界面找不到按钮?新手必备的8个常见页面导航指南
web3.0
币安交易界面找不到按钮?新手必备的8个常见页面导航指南

币安平台界面功能丰富,新用户常因不熟悉而找不到关键操作按钮。本文梳理了资金充值、交易下单、资产管理、订单查看、理财申购、安全设置、身份认证和客服帮助这八个最容易迷路的页面,详细说明了各页面核心按钮的位置和功能逻辑,帮助用户快速适应平台操作,提升使用效率。

热心网友
05.11
币安提币前必查三步:地址验证、安全设置与到账链路详解
web3.0
币安提币前必查三步:地址验证、安全设置与到账链路详解

在加密货币提币操作中,确保资产安全的关键步骤往往被忽视。本文重点探讨了提币前必须仔细核对的三个核心环节:提币地址的准确性、平台安全验证的完整性,以及资产到账链路的清晰性。通过逐一分析这些环节的风险点与最佳实践,旨在帮助用户建立严谨的操作习惯,避免因疏忽导致的资产损失,实现更安全、顺畅的资产转移。

热心网友
05.11