Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十二 简单图片添加水印效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十二 简单图片添加水印效果

目录

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十二 简单图片添加水印效果

一、简单介绍

二、简单图片添加水印效果实现原理

三、简单图片添加水印效果案例实现简单步骤

四、注意事项


一、简单介绍

Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。Python是一种解释型脚本语言,可以应用于以下领域: Web 和 Internet开发、科学计算和统计、人工智能、教育、桌面界面开发、软件开发、后端开发、网络爬虫。

这里使用 Python  基于 OpenCV 进行视觉图像处理,......

二、简单图片添加水印效果实现原理

给图片添加水印是指在图片上叠加额外的标识、文字、图形或者其他图像,以表明该图片的归属、来源、版权信息或者其他附加信息的过程。水印通常以半透明的方式显示在图片的某个位置,可以防止未经授权的复制和使用,并且可以提升图片的专业性和美观度。添加水印的过程可以通过图像处理技术来实现,包括图像叠加、透明度调整、文字绘制等。

  1. 添加文字水印 (add_watermark_text)

    • 原理:在原始图像上绘制指定的文字,作为水印。
    • 实现方法:使用 OpenCV 的 cv2.putText() 函数在图像上添加文字。
  2. 添加图片水印 (add_watermark_image)

    • 原理:将水印图片叠加到原始图像的指定位置。
    • 实现方法:将水印图片的 BGR 通道与原始图像的相应区域进行叠加,同时考虑水印图片的 alpha 通道,控制水印的透明度。

涉及的一些函数说明:

  1. cv2.putText()

    • 函数功能:在图像上绘制文本。
    • 参数:
      • image:要绘制文本的图像。
      • text:要绘制的文本内容。
      • org:文本的起始坐标,即文本左下角的坐标。
      • font:字体类型,默认为 cv2.FONT_HERSHEY_SIMPLEX
      • font_scale:字体缩放因子。
      • font_color:文本颜色,格式为 BGR。
      • thickness:文本线条粗细。
    • 返回值:无。
    • 注意事项:根据 org 参数确定文本的起始位置,确保文本不会超出图像范围。
  2. Array slicing (数组切片)

    • 函数功能:用于在图像上获取指定位置的子图像。
    • 参数:用于指定图像区域的坐标和大小。
    • 返回值:返回指定区域的子图像。
    • 注意事项:确保指定的区域不会超出图像范围。
  3. cv2.addWeighted()

    • 函数功能:对两个图像进行加权求和,实现图像叠加效果。
    • 参数:
      • src1:第一个输入图像。
      • alpha:第一个输入图像的权重。
      • src2:第二个输入图像。
      • beta:第二个输入图像的权重。
      • gamma:结果图像的亮度值,添加到加权和上。
    • 返回值:返回加权和后的图像。
    • 注意事项:通过调整 alphabeta 参数可以控制两个图像的显示比例,通过 gamma 参数可以调整结果图像的亮度。

三、简单图片添加水印效果案例实现简单步骤

1、编写代码

2、运行效果

3、具体代码

"""
简单图片添加水印效果
"""

import cv2


def add_watermark_text(image, text, position='bottom-right', x=None, y=None, font=cv2.FONT_HERSHEY_SIMPLEX,
                       font_scale=1.0, font_color=(255, 255, 255), thickness=1):
    """
    简单添加文字水印效果
    :param image:
    :param text:
    :param position:
    :param x:
    :param y:
    :param font:
    :param font_scale:
    :param font_color:
    :param thickness:
    :return:
    """
    # 复制原始图像,以免修改原始图像
    result = image.copy()

    # 确定水印文本的位置
    text_size, _ = cv2.getTextSize(text, font, font_scale, thickness)
    image_height, image_width = image.shape[:2]
    if position == 'top-left':
        text_position = (10, text_size[1] + 10)
    elif position == 'top-right':
        text_position = (image_width - text_size[0] - 10, text_size[1] + 10)
    elif position == 'bottom-left':
        text_position = (10, image_height - 10)
    elif position == 'center':
        text_position = ((image_width - text_size[0]) // 2, (image_height + text_size[1]) // 2)
    else:  # 默认为 'bottom-right'
        text_position = (image_width - text_size[0] - 10, image_height - 10)

    # 如果用户指定了位置,则使用用户指定的位置
    if x is not None and y is not None:
        text_position = (x, y)

    # 添加水印文本
    cv2.putText(result, text, text_position, font, font_scale, font_color, thickness)

    return result


def add_watermark_image(image, watermark_image, position='bottom-right', x=None, y=None):
    """
    简单添加图片水印效果
    :param image:
    :param watermark_image:
    :param position:
    :param x:
    :param y:
    :return:
    """
    # 复制原始图像,以免修改原始图像
    result = image.copy()

    # 确定水印图片的位置
    watermark_height, watermark_width = watermark_image.shape[:2]
    image_height, image_width = image.shape[:2]
    if position == 'top-left':
        watermark_position = (0, 0)
    elif position == 'top-right':
        watermark_position = (image_width - watermark_width, 0)
    elif position == 'bottom-left':
        watermark_position = (0, image_height - watermark_height)
    elif position == 'center':
        watermark_position = ((image_width - watermark_width) // 2, (image_height - watermark_height) // 2)
    else:  # 默认为 'bottom-right'
        watermark_position = (image_width - watermark_width, image_height - watermark_height)

    # 如果用户指定了位置,则使用用户指定的位置
    if x is not None and y is not None:
        watermark_position = (x, y)

    # 获取水印图片的 alpha 通道
    watermark_alpha = watermark_image[:, :, 3] / 255.0

    # 提取水印图片的 BGR 通道
    watermark_bgr = watermark_image[:, :, :3]

    # 将水印图片叠加到原始图像上
    for c in range(3):
        result[watermark_position[1]:watermark_position[1] + watermark_height,
        watermark_position[0]:watermark_position[0] + watermark_width, c] = \
            (1 - watermark_alpha) * result[watermark_position[1]:watermark_position[1] + watermark_height,
                                    watermark_position[0]:watermark_position[0] + watermark_width, c] + \
            watermark_alpha * watermark_bgr[:, :, c]

    return result


def main():
    # 调用函数并指定输入图像、水印和输出图像文件路径
    input_image_path = "Images/DogFace.jpg"
    watermark_path = "Images/Watermark.png"
    output_image_path = "Images/DogFace_Watermark.jpg"

    image = cv2.imread(input_image_path)

    # 设置窗口属性,并显示图片
    cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
    cv2.imshow('Dog', image)

    output_image = add_watermark_text(image, "Water mark", x=200, y=300, font_scale=2.0, thickness=2)

    # 保存处理后的图像
    # 设置窗口属性,并显示图片
    cv2.namedWindow("add_watermark_text", cv2.WINDOW_KEEPRATIO)
    cv2.imshow("add_watermark_text", output_image)

    watermark = cv2.imread(watermark_path, cv2.IMREAD_UNCHANGED)
    output_image = add_watermark_image(image, watermark, position="center")

    # 保存处理后的图像
    # 设置窗口属性,并显示图片
    cv2.namedWindow("add_watermark_image", cv2.WINDOW_KEEPRATIO)
    cv2.imshow("add_watermark_image", output_image)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

四、注意事项

1、确保水印文本位置不会超出图像范围,可以根据指定的位置参数调整水印的位置。

2、考虑水印图片的 alpha 通道,以防止水印添加后出现黑色边框或不透明度不一致的情况。

3、可以根据需要调整水印图片的显示位置和透明度参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/545153.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++ - 类的默认成员函数

文章目录 前言一、构造函数二、析构函数三、拷贝构造函数四、重载赋值操作符五、取地址及const取地址操作符重载 前言 默认成员函数是编译器自动生成的,也可以自己重写,自己重写之后编译器就不再生成,下面是深入了解这些成员函数。 一、构造…

每个人都可以做一个赚钱的社群

如何创建并运营一个赚钱的社群 一、引言 大家好,今天,我想和大家分享一下如何创建并运营一个赚钱的社群。我的分享目的是希望能够持续输出有价值的内容。 二、心态建设 1. 重要性:创业心态与平常心 在开始社群运营之前,我们需…

面试官:MySQL的自增 ID 用完了,怎么办?

如果你用过或了解过MySQL,那你一定知道自增主键了。每个自增id都是定义了初始值,然后按照指定步长增长(默认步长是1)。虽然,自然数是没有上限的,但是我们在设计表结构的时候,通常都会指定字段长…

Flink入门学习 | 大数据技术

⭐简单说两句⭐ ✨ 正在努力的小新~ 💖 超级爱分享,分享各种有趣干货! 👩‍💻 提供:模拟面试 | 简历诊断 | 独家简历模板 🌈 感谢关注,关注了你就是我的超级粉丝啦! &…

优化汽车制造中的库存管理

在拥有足够的库存以满足客户需求和最大限度地减少过剩库存之间取得适当的平衡,对于高效运营和正向现金流运营至关重要。我们将探讨如何利用数据见解和预测技术来支持汽车制造商进行精益运营,避免库存过多或不足的缺陷。 销售模式告诉我们什么&#xff1…

手拉手安装启动Kafka2.13

启动Kafka本地环境需Java 8以上 Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 Kafka启动…

创新营销利器:淘宝扭蛋机小程序开发全解析

在数字化浪潮的推动下,淘宝扭蛋机小程序的开发成为了一种全新的购物体验。它巧妙地将传统扭蛋机的乐趣与移动技术的便捷相结合,为用户带来了前所未有的惊喜与互动。 淘宝扭蛋机小程序的开发,不仅是一次技术的革新,更是一次购物方…

c++中常用库函数

大小写转换 islower/isupper函数 char ch1 A; char ch2 b;//使用islower函数判断字符是否为小写字母 if(islower(ch1)){cout << ch1 << "is a lowercase letter." << end1; } else{cout << ch1 << "is not a lowercase lette…

Java单例集合

Collection接口介绍 Collection 表示一组对象&#xff0c;它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。 Collection接口中定义的方法 方法说明boolean add(Object element)增加元素到容器中boolean remove(Object element)从容器中移除元素 boolean c…

【源码】2024全开源多语言多商户跨境商城源码|多语言跨境外贸电商系统App

ikTok SHOP跨境电商系统V8版是一套B2CB2B跨境电商商城系统源码&#xff0c;多商户多语言&#xff0c;全新百变DIY模板&#xff1b;该系统支持B-C自营、B-B-C第三方卖家系统、B2B批发电商模式&#xff1b;该源码是使用Laravel框架PHP开发的&#xff0c;前后端全开源可二开。 版…

行业模板|DataEase批发零售大屏模板推荐

DataEase开源数据可视化分析平台于2022年6月发布模板市场&#xff08;https://templates-de.fit2cloud.com&#xff09;&#xff0c;并于2024年1月新增适用于DataEase v2版本的模板分类。模板市场旨在为DataEase用户提供专业、美观、拿来即用的大屏模板&#xff0c;方便用户根据…

构建跨设备3D应用:HOOPS的跨平台开发能力

在当今数字化和可视化需求不断提升的时代&#xff0c;三维技术的应用越来越广泛&#xff0c;尤其在制造、建筑、工程及媒体行业。HOOPS&#xff0c;由Tech Soft 3D开发&#xff0c;是一套全面的软件开发工具包&#xff0c;用于构建高性能的三维应用程序。该工具包涵盖了从三维渲…

韩国ECS电子离心开关的安装和应用

韩国ECS电子式离心开关是一种新型的固体开关&#xff0c;其工作原理是通过采样电动机的电流、电压、相位等参数来判定电动机的启动转速。当电动机转速达到额定转速的72%~83%时&#xff0c;启动电容将被断开&#xff0c;使电动机启动运转。这种开关具有工作精确、可靠性高、一致…

【新特性】专为开发者设计的 Jira 个性化工作建议

开发者体验&#xff08;Developer Experience&#xff0c;简称 DX&#xff09;是指开发人员在使用工具、框架或平台时所体验到的整体感受和印象。类似于用户体验&#xff08;User Experience&#xff0c;简称UX&#xff09;&#xff0c;开发者体验关注的是开发者在他们的工作中…

DrugBAN:基于双线性注意力网络进行药物-靶点结合预测。

DrugBan&#xff1a;一种可解释的双线性注意力网络进行药物-靶点结合预测。 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 DrugBan&#xff1a;一种可解释的双线性注意力网络进行药物-靶点结合预测。前言一、模型…

gcn代码处理出现的问题

README 版本不一致 python 2.7 PYTHON 3.7 切换 TensorFlow系统的学习使用 数据集下载

yolo系列(之一)

深度学习经典检测算法 two-stage (两阶段) : Faster-rcnn Mask-Rcnn系列 &#xff08;输入图像---》CNN特征---》预选框---》输出结果&#xff09; one-stage (单阶段): YOLO系列 &#xff08;输入图像---》CNN特征---》输出结果&#xff09; one-stage的特点&#xff1a;&…

无人机GB42590接收端 +接收端,同时支持2.4G与5.8G双频WIFI模组

严格按照GB42590的协议开发的发射端&#xff0c;通过串口和模块通讯&#xff0c;默认波特率 921600。 http://www.doit.am/首页-深圳四博智联科技有限公司-淘宝网https://shop144145132.taobao.com/?spma230r.7195193.1997079397.2.71f6771dJHT2r0 二、接口文档 单片机和模…

Netron 显示每层输入shape

前言 我是用yolov5s直接export的onnx&#xff0c;用netron打卡&#xff0c;发现看不到每层的输入&#xff0c;又不想自己算。 步骤 1.准备好onnx 2 执行以下代码 import onnx onnx_ori"yolov5s.onnx" onnx_show"yolov5s_show.onnx" onnx_graph onnx.l…

MGRE-OSPF接口网络类型实验

OSPF接口网络类型实验 一&#xff0c;实验拓扑 初始拓扑&#xff1a; 最终拓扑&#xff1a; 二&#xff0c;实验要求及分析 要求&#xff1a; 1&#xff0c;R6为ISP只能配置IP地址&#xff0c;R1-R5的环回为私有网段 2&#xff0c;R1/R4/R5为全连的MGRE结构&#xff0c;R…