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

news2024/12/23 15:02:35

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

目录

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

一、简单介绍

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

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

四、注意事项


一、简单介绍

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

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

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

视频水印是指在视频内容中添加图像、文字或其他标识符的技术,以表明视频的所有权、来源、版权信息或其他相关信息。视频水印可以是透明的或半透明的,通常位于视频画面的角落或其他不影响主要内容的位置。视频水印可以用于保护视频内容的版权,防止未经授权的复制和使用,以及增加视频的专业性和可识别性。

实现原理:

  1. 打开输入视频文件,并获取其每一帧的大小。
  2. 打开水印图像文件,并获取其大小。
  3. 遍历视频的每一帧,将水印图像叠加到视频帧上。
  4. 根据指定的位置参数确定水印在视频帧上的位置,并将水印图像叠加到相应的位置上。
  5. 将带有水印的视频帧写入输出视频文件。

实现方法:

  1. 使用 OpenCV 的 VideoCapture 类打开输入视频文件,并读取每一帧。
  2. 使用 OpenCV 的 VideoWriter 类创建输出视频文件,并指定视频编码器、帧率和大小。
  3. 使用 OpenCV 的 imread 函数读取水印图像。
  4. 遍历视频的每一帧,在每一帧上叠加水印图像。
  5. 根据指定的位置参数确定水印的位置,并将水印图像叠加到视频帧的相应位置上。
  6. 使用 OpenCV 的 addWeighted 函数将水印图像叠加到视频帧上,实现透明度叠加效果。
  7. 将带有水印的视频帧写入输出视频文件。

涉及了一些关键函数:

  1. cv2.VideoCapture(): 用于打开视频文件并创建一个视频捕获对象。在这里,它被用于打开输入视频文件并创建一个用于读取帧的视频捕获对象。

  2. cap.isOpened(): 用于检查视频是否成功打开。在这里,它被用于检查输入视频文件是否成功打开。

  3. cap.read(): 用于读取视频的下一帧。在这里,它被用于循环遍历视频的每一帧并读取帧内容。

  4. cv2.VideoWriter(): 用于创建一个视频写入对象,可以将帧写入视频文件。在这里,它被用于创建一个用于写入帧的视频写入对象。

  5. cv2.imread(): 用于读取图像文件。在这里,它被用于读取水印图像文件。

  6. cv2.imwrite(): 用于将图像写入文件。虽然在这里没有直接使用,但可以用它来保存添加水印后的帧。

  7. cv2.putText(): 用于向图像中添加文字。在这里,虽然没有直接使用,但可以用它来添加文字水印。

  8. cv2.addWeighted(): 用于将两个图像进行加权叠加。在这里,它被用于将水印图像叠加到视频帧上。

  9. cap.release(): 用于释放视频捕获对象的资源。

  10. out.release(): 用于释放视频写入对象的资源。

  11. cv2.destroyAllWindows(): 用于关闭所有窗口,通常在程序结束时调用。

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

1、编写代码

2、运行效果

3、具体代码

"""
简单给视频添加水印图片效果
    1、打开输入视频文件,并获取其每一帧的大小。
    2、打开水印图像文件,并获取其大小。
    3、遍历视频的每一帧,将水印图像叠加到视频帧上。
    4、根据指定的位置参数确定水印在视频帧上的位置,并将水印图像叠加到相应的位置上。
    5、将带有水印的视频帧写入输出视频文件。
"""

import cv2
import os


def add_watermark_to_video(input_video_path, output_video_path, watermark_image_path, alpha=1.0,
                           position='bottom-right'):
    """
    简单给视频添加水印图片效果
    :param input_video_path: 原视频路径
    :param output_video_path: 添加水印后保存视频路径
    :param watermark_image_path: 水印图片路径
    :param alpha: 控制水印整体透明度的参数,范围为 0 到 1
    :param position: 控制水印位置的参数,可选值包括 'top-left', 'top-right', 'bottom-left', 'center', 'bottom-right'
    :return:
    """
    # 检查输入视频文件是否存在
    if not os.path.isfile(input_video_path):
        print("Error: Input video file does not exist.")
        return

    # 检查水印图像文件是否存在
    if not os.path.isfile(watermark_image_path):
        print("Error: Watermark image file does not exist.")
        return

    # 打开视频文件
    cap = cv2.VideoCapture(input_video_path)

    # 检查视频是否成功打开
    if not cap.isOpened():
        print("Error: Failed to open input video.")
        return

    # 获取视频的宽度和高度
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # 创建VideoWriter对象用于写入输出视频
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_video_path, fourcc, 30.0, (width, height))

    # 读取水印图像
    watermark = cv2.imread(watermark_image_path, cv2.IMREAD_UNCHANGED)

    # 检查水印图像是否成功读取
    if watermark is None:
        print("Error: Failed to read watermark image.")
        return

    # 检查水印图像的透明度通道是否存在
    if watermark.shape[2] < 4:
        print("Error: Watermark image does not have an alpha channel.")
        return

    # 循环遍历视频的每一帧
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        # 将水印叠加到当前帧上
        overlay = frame.copy()
        h, w = watermark.shape[:2]

        # 根据位置参数确定水印的位置
        if position == 'top-left':
            x_offset, y_offset = 10, 10
        elif position == 'top-right':
            x_offset, y_offset = width - w - 10, 10
        elif position == 'bottom-left':
            x_offset, y_offset = 10, height - h - 10
        elif position == 'center':
            x_offset, y_offset = (width - w) // 2, (height - h) // 2
        else:  # 默认为 'bottom-right'
            x_offset, y_offset = width - w - 10, height - h - 10

        for c in range(0, 3):
            overlay[y_offset:y_offset + h, x_offset:x_offset + w, c] = \
                watermark[:, :, c] * (watermark[:, :, 3] / 255.0 * alpha) + frame[y_offset:y_offset + h,
                                                                            x_offset:x_offset + w, c] * (
                        1.0 - watermark[:, :, 3] / 255.0 * alpha)

        # 将帧写入输出视频
        out.write(overlay)

    # 释放资源
    cap.release()
    out.release()
    cv2.destroyAllWindows()


def main():
    # 调用函数并指定输入和输出视频文件路径以及水印图像路径
    input_video_path = "Videos/CatRun.mp4"
    output_video_path = "Videos/CatRun_Wartermark.mp4"
    watermark_image_path = "Images/Watermark.png"
    alpha = 0.5  # 控制水印整体透明度的参数,范围为 0 到 1
    position = 'top-right'  # 控制水印位置的参数,可选值包括 'top-left', 'top-right', 'bottom-left', 'center', 'bottom-right'

    # 执行函数
    add_watermark_to_video(input_video_path, output_video_path, watermark_image_path, alpha, position)


if __name__ == "__main__":
    main()

四、注意事项

  1. 参数安全性:对于输入的参数,需要进行安全校验,以确保输入的参数值在有效范围内,避免出现错误。
  2. 图像大小匹配:确保水印图像的大小与视频帧的大小匹配,否则可能导致叠加时的错误。
  3. 透明度处理:根据水印图像的透明度信息,合理处理水印图像与视频帧的叠加透明度,以保持水印的透明效果。
  4. 位置处理:根据指定的位置参数,确保水印图像叠加到视频帧的正确位置上,避免覆盖重要信息或者显示不完整。
  5. 资源释放:在处理完所有帧之后,及时释放视频读取和写入的资源,以避免内存泄漏或资源浪费。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux——信号量与基于环形队列的生产者消费者模型

目录 前言 一、信号量 二、信号量的接口 1.初始化 2.销毁 3.申请信号量 4. 释放信号量 三、基于环形队列的生产者消费者模型 1.环形队列的理解 2.生产者消费者的设计 3.单消费者单生产者环形队列的实现 4.多消费者多生产者环形队列的实现 前言 之前&#xff0c;…

MGRE中的OSPF配置

一、实验图 二、实验配置 R1 R2 R3 R4 R5 R6

EXCEL中COUNT和COUNTIF的参数类型有什么不同?

来看一下它们的语法&#xff1a; 1.COUNT(值) COUNT函数是计数数字的个数&#xff0c;注意是数值型数字&#xff0c;可不包括文本型数字&#xff0c;它的参数“值”可以是来自单元格的单一区域&#xff0c;如A1:C2&#xff0c;也可以是来自单元格的复合不规则区域&#xff0c…

技术方案应该这么写

简介 新入职一个华为十年工作经验的老Java。让写一个设计方案&#xff0c;其实也不算难&#xff0c;根据业务需要存取三千万数据&#xff0c;三天没写出来&#xff0c;最后做了辞退处理。其实我相信这个老技术员是有能力的&#xff0c;只是没有合适的机会表达。但是也侧面的说明…

9. Spring Boot 日志文件

本篇文章源码位置延续上个章节&#xff1a;SpringBoot_demo 本篇文章内容源码位于上述地址的com/chenshu/springboot_demo/logging包下 1. 日志的作用 发现和定位问题&#xff1a; 日志是程序的重要组成部分&#xff0c;它在系统、程序出现错误或异常时提供诊断和解决问题的线…

学习经验分享【32】本科/硕士开题报告、中期报告等写作经验分享

本科/硕士阶段首先就是要写开题报告&#xff0c;然后中期报告&#xff0c;这篇博文就是分享一下写报告的经验&#xff0c;避免被老师打回来。本人有丰富的写报告经验&#xff0c;有需要的朋友可添加文末联系方式与我联系。 一、本科开题报告的提纲 课题来源及研究的目的和意义…

C++内存分布

C代码编译过程 预处理 宏定义展开、头文件展开、条件编译&#xff0c;这里并不会检查语法编译检查语法&#xff0c;将预处理后文件编译生成汇编文件汇编将汇编文件生成目标文件(二进制文件)链接将目标文件链接为可执行程序 进程的内存分布 程序运行起来(没有结束前)就是一个…

openjudge_2.5基本算法之搜索_166:The Castle

题目 166:The Castle 总时间限制: 1000ms 内存限制: 65536kB 描述 Figure 1 shows the map of a castle.Write a program that calculates how many rooms the castle hashow big the largest room is The castle is divided into m * n (m<50, n<50) square modules.…

如何应对Android面试官 -> startActivity 流程详解

前言 本章主要讲解下 Activity 的启动流程&#xff1b; 整体概念 点击桌面图标&#xff0c;启动目标应用程序的 Activity&#xff0c;首先会跟 AMS 打交道&#xff0c;也就是 SystemServer 进程中启动的AMS&#xff0c;Launcher 进程和 SystemServer 进程中的 AMS 通信「一次跨…

(九)C++自制植物大战僵尸游戏自定义对话框的实现

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/m0EtD 对话框在游戏的交互中非常重要。在游戏中&#xff0c;对话框不仅可以提醒用户下达任务指令&#xff0c;而且还可以让用户进行操作&#xff0c;自定义游戏中的各种属性。对话框在游戏的交互中非常常见且大量使用。Co…

树莓集团与天府新区信息职业学院在国际数字影像产业园成功举办授牌仪式

2024年4月12日&#xff0c;树莓集团与天府新区信息职业学院共同在国际数字影像产业园举办授牌仪式。这场仪式不仅标志着双方合作的正式开启&#xff0c;更是为未来的产教融合、学生实训与就业推荐树立了坚实的基石。 仪式上&#xff0c;天府新区信息职业学院领导与树莓集团的代…

Qt QStyle详解

1.简介 QStyle类是 Qt 框架中用于控制应用程序界面元素外观的一个抽象基类。这个类提供了一种方式来定制窗口部件&#xff08;widgets&#xff09;的绘制和行为&#xff0c;可以通过改变主题或风格来更改应用程序的外观&#xff0c;而无需修改窗口部件本身的代码。 Qt包含一组…

抽奖系统设计

如何设计一个百万级用户的抽奖系统&#xff1f; - 掘金 如何设计百万人抽奖系统…… 在实现抽奖逻辑时&#xff0c;Redis 提供了多种数据结构&#xff0c;选择哪种数据结构取决于具体的抽奖规则和需求。以下是一些常见场景下推荐使用的Redis数据结构&#xff1a; 无序且唯一奖…

系统边界图

系统边界图的定义&#xff1a; 系统边界图是系统工程和软件工程中的一种图形化工具&#xff0c;用于描述系统与外部世界之间的交互和界限。它展示了系统的组成部分以及这些组件如何与外部实体进行通信和交互。系统边界图通常包括系统内部的各个组件、外部实体以及它们之间的通信…

【Qt】:事件的处理

系统相关 一.鼠标事件二.键盘事件三.定时器 事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在个同的的刻友出的。当用广投下鼠标、敲下键盘&#xff0c;或者是窗口需要…

掼蛋残局技巧

一、根据对手张数出牌 口诀&#xff1a;十打二来九打一&#xff0c;打成八张不着急&#xff1b; 对手七张或八张&#xff0c;可以反手打一夯&#xff1b; 五打二来六打三&#xff0c;打得对手把眼翻&#xff1b; 枪不打四&#xff1b; 两张&#xff1a;出两张以上的牌&#xff…

AI预测福彩3D第36弹【2024年4月15日预测--第8套算法开始计算第4次测试】

今天咱们继续测试第8套算法和模型&#xff0c;今天是第3次测试&#xff0c;目前的测试只是为了记录和验证&#xff0c;不建议大家盲目跟买。。我的目标仍旧是10次命中3-4次!~废话不多说了&#xff0c;直接上结果&#xff01; 2024年4月15日3D的七码预测结果如下 第一套…

【Leetcode每日一题】 动态规划 - 下降路径最小和(难度⭐⭐)(55)

1. 题目解析 题目链接&#xff1a;931. 下降路径最小和 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了. 2.算法原理 对于这类路径类问题&#xff0c;通常我们首先需要分析状态表示以及状态转移的过程。特别地&#xff0c;本题涉及…

虚良SEOPython脚本寄生虫程序源码

本程序&#xff0c;快速收录百度首页&#xff0c;3-5天就可以有流量&#xff0c;长期稳定&#xff0c;可以设置自动推送。 点这里 Python脚本寄生虫程序源码&#xff08;寄生虫电影脚本&#xff09; - 虚良SEO 模板可以自己修改&#xff0c;源码带模板标签说明&#xff0c;简…

106.从中序与后序遍历构造二叉树

给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 思路&#xff1a; 中序遍历数组中&#xff0c;找到一个根节点&#xff0c;那么其前为其左子树&a…