Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十二 简单把视频的水印去掉效果

ops/2024/9/18 23:20:11/ 标签: python, opencv, 图像处理, 去除水印, 视频处理

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十二 简单把视频的水印去掉效果

目录

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十二 简单把视频的水印去掉效果

一、简单介绍

二、简单把视频的水印去掉效果实现原理

三、简单把视频的水印去掉效果案例实现简单步骤

四、注意事项


一、简单介绍

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

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

二、简单把视频的水印去掉效果实现原理

去除视频水印是指在视频中移除嵌入的标识、图标、文字或任何其他可视元素的过程。这些水印通常是为了保护知识产权、标识所有权或添加额外信息而添加到视频中的。去除水印可以提高视频的质量和观看体验,特别是当水印影响了视频的内容或美观性时。去除水印的方法通常包括使用图像处理技术,如图像修复、遮罩生成、内容填充等。

实现原理

  • 代码首先获取视频的第一个有效帧,用于选择水印的ROI(感兴趣区域)。
  • 然后用户可以通过交互式界面在视频中选择水印的ROI,以便后续处理。
  • 接着,通过自适应的方法检测水印并生成水印的遮罩。
  • 最后,利用生成的水印遮罩,对视频进行修复,去除水印

实现方法

  • get_first_valid_frame(video_clip, threshold=10, num_frames=10):获取视频的第一个有效帧,用于选择水印的ROI。它通过计算视频中多个帧的均值来确定第一个有效帧。
  • select_roi_for_mask(video_clip):通过交互式界面在视频中选择水印的ROI,返回水印的ROI坐标和尺寸。
  • detect_watermark_adaptive(frame, roi):自适应检测水印并生成水印的遮罩。它在水印的ROI上应用灰度化和二值化来检测水印。
  • generate_watermark_mask(video_clip, num_frames=10, min_frame_count=7):生成水印的遮罩。它在视频的多个帧中检测水印,并根据水印像素点在至少指定数量的帧中出现的次数来生成最终的水印遮罩。
  • process_video(video_clip, output_path, apply_mask_func):处理视频并保存结果。它将给定的应用遮罩函数应用于视频的每一帧,并将处理后的视频保存到指定路径。

涉及的关键函数及其说明:

  1. get_first_valid_frame(video_clip, threshold=10, num_frames=10)

    • 功能:获取视频的第一个有效帧,用于选择水印的ROI。
    • 参数:
      • video_clip:视频剪辑对象。
      • threshold:判断帧是否有效的阈值,默认为10。
      • num_frames:用于选择的帧的数量,默认为10。
    • 返回值:第一个有效帧的图像数据。
  2. select_roi_for_mask(video_clip)

    • 功能:从视频剪辑中选择水印的ROI。
    • 参数:
      • video_clip:视频剪辑对象。
    • 返回值:水印ROI的坐标和尺寸 (x, y, w, h)。
  3. detect_watermark_adaptive(frame, roi)

    • 功能:自适应检测水印并生成遮罩。
    • 参数:
      • frame:视频帧的图像数据。
      • roi:水印的ROI坐标和尺寸 (x, y, w, h)。
    • 返回值:水印的遮罩图像数据。
  4. generate_watermark_mask(video_clip, num_frames=10, min_frame_count=7)

    • 功能:生成水印的遮罩。
    • 参数:
      • video_clip:视频剪辑对象。
      • num_frames:用于生成遮罩的帧的数量,默认为10。
      • min_frame_count:水印像素点在至少多少帧中出现才被认为是水印,默认为7。
    • 返回值:水印的遮罩图像数据。
  5. process_video(video_clip, output_path, apply_mask_func)

    • 功能:处理视频并保存结果。
    • 参数:
      • video_clip:视频剪辑对象。
      • output_path:输出视频路径。
      • apply_mask_func:应用遮罩的函数。
    • 返回值:无。

三、简单把视频的水印去掉效果案例实现简单步骤

1、编写代码

2、运行效果

操作:1、选择水印区域,2、然后空格或者回车,后台开始去除视频水印

3、具体代码

python">"""
简单的框选水印位置,移除水印1、代码首先获取视频的第一个有效帧,用于选择水印的ROI(感兴趣区域)。2、然后用户可以通过交互式界面在视频中选择水印的ROI,以便后续处理。3、接着,通过自适应的方法检测水印并生成水印的遮罩。4、最后,利用生成的水印遮罩,对视频进行修复,去除水印。
"""import cv2
import numpy as np
from moviepy.editor import VideoFileClip
import os
from tqdm import tqdmdef get_first_valid_frame(video_clip, threshold=10, num_frames=10):"""获取视频的第一个有效帧,用于选择水印的ROI:param video_clip: 视频剪辑对象:param threshold: 判断帧是否有效的阈值:param num_frames: 用于选择的帧的数量:return: 第一个有效帧的图像数据"""total_frames = int(video_clip.fps * video_clip.duration)frame_indices = [int(i * total_frames / num_frames) for i in range(num_frames)]for idx in frame_indices:frame = video_clip.get_frame(idx / video_clip.fps)if frame.mean() > threshold:return frame# 注意:不一定第一帧就有水印return video_clip.get_frame(0)def select_roi_for_mask(video_clip):"""从视频剪辑中选择水印的ROI:param video_clip: 视频剪辑对象:return: 水印ROI的坐标和尺寸 (x, y, w, h)"""frame = get_first_valid_frame(video_clip)# 将视频帧调整为720p显示display_height = 720scale_factor = display_height / frame.shape[0]display_width = int(frame.shape[1] * scale_factor)display_frame = cv2.resize(frame, (display_width, display_height))instructions = "Select ROI and press SPACE or ENTER"font = cv2.FONT_HERSHEY_SIMPLEXcv2.putText(display_frame, instructions, (10, 30), font, 1, (255, 255, 255), 2, cv2.LINE_AA)r = cv2.selectROI(display_frame)cv2.destroyAllWindows()r_original = (int(r[0] / scale_factor), int(r[1] / scale_factor), int(r[2] / scale_factor), int(r[3] / scale_factor))return r_originaldef detect_watermark_adaptive(frame, roi):"""自适应检测水印并生成遮罩。:param frame: 视频帧的图像数据:param roi: 水印的ROI坐标和尺寸 (x, y, w, h)。:return: 水印的遮罩图像数据。"""roi_frame = frame[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2]]gray_frame = cv2.cvtColor(roi_frame, cv2.COLOR_BGR2GRAY)_, binary_frame = cv2.threshold(gray_frame, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)mask = np.zeros_like(frame[:, :, 0], dtype=np.uint8)mask[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2]] = binary_framereturn maskdef generate_watermark_mask(video_clip, num_frames=10, min_frame_count=7):"""生成水印的遮罩:param video_clip: 视频剪辑对象:param num_frames: 用于生成遮罩的帧的数量:param min_frame_count: 水印像素点在至少多少帧中出现才被认为是水印:return: 水印的遮罩图像数据"""total_frames = int(video_clip.duration * video_clip.fps)frame_indices = [int(i * total_frames / num_frames) for i in range(num_frames)]frames = [video_clip.get_frame(idx / video_clip.fps) for idx in frame_indices]r_original = select_roi_for_mask(video_clip)masks = [detect_watermark_adaptive(frame, r_original) for frame in frames]final_mask = sum((mask == 255).astype(np.uint8) for mask in masks)# 根据像素点在至少min_frame_count张以上的帧中的出现来生成最终的遮罩final_mask = np.where(final_mask >= min_frame_count, 255, 0).astype(np.uint8)kernel = np.ones((5, 5), np.uint8)return cv2.dilate(final_mask, kernel)def process_video(video_clip, output_path, apply_mask_func):"""处理视频并保存结果:param video_clip: 视频剪辑对象:param output_path: 输出视频路径:param apply_mask_func: 应用遮罩的函数:return:"""total_frames = int(video_clip.duration * video_clip.fps)progress_bar = tqdm(total=total_frames, desc="Processing Frames", unit="frames")def process_frame(frame):result = apply_mask_func(frame)progress_bar.update(1000)return resultprocessed_video = video_clip.fl_image(process_frame, apply_to=["each"])processed_video.write_videofile(f"{output_path}.mp4", codec="libx264")if __name__ == "__main__":input_video_path = "Videos/CatRun_Wartermark.mp4"output_video_path = "Videos/CatRun_Wartermark_ToRemove.mp4"watermark_mask = Nonevideo_clip = VideoFileClip(input_video_path)if watermark_mask is None:watermark_mask = generate_watermark_mask(video_clip)mask_func = lambda frame: cv2.inpaint(frame, watermark_mask, 3, cv2.INPAINT_NS)video_name = os.path.basename(input_video_path)process_video(video_clip, output_video_path, mask_func)print(f"Successfully processed {video_name}")

四、注意事项

  1. 代码中使用了交互式界面让用户选择水印的ROI,因此运行代码时需要有图形界面的支持。
  2. 自适应检测水印的方法在一定程度上能够应对不同类型的水印,但并不是万能的,可能会存在一定的误差。
  3. 在检测水印时,需要根据实际情况调整参数,以获得最佳的检测效果。
  4. 去除水印时,采用了基于遮罩的修复方法,可能会对图像的质量产生一定的影响,需要根据实际需求权衡。

http://www.ppmy.cn/ops/2604.html

相关文章

Debian

文章目录 前言一、使用root用户操作二、配置用户使用sudo命令三、添加桌面图标显示1.打开终端2.执行安装命令3.执行成功后重启4. 打开扩展,配置图标 四、图形化界面关闭和打开五、设置静态IP1.查询自己系统网络接口2.修改网络配置文件 总结 前言 Debian 系统在安装…

利用正射影像对斜射图像进行反向投影

在图像投影和映射领域,有两种类型的投影:正向投影和反向投影。正向投影涉及使用内部方向(即校准相机参数)将 3D 点(例如地面上的物体)投影到 2D 图像平面上。另一方面,向后投影是指根据 2D 图像确定地面物体的 3D 坐标的过程。 为了匹配倾斜图像和正射影像并确定相机位置…

意大利侍酒师Galvan Maurizia分享意大利葡萄酒与美食文化魅力

在酒水行业日益繁荣的今天,消费者对酒类产品的品质、文化和品味的追求不断提升。为了满足这一市场需求,云仓酒庄近日宣布开启首届《综合品酒师》培训,旨在培养更多具备专业素养和品鉴能力的品酒师,为酒水行业的专业化和形象提升注…

浅谈mybatis

说说mybaits原理 首先,之前Java连接数据库jdk有定义一套规范JDBC,但是这个规范使用起来太麻烦, 流程大概有加载驱动、连接数据库、执行sql、处理结果、释放资源。 特别是sql是以字符串的形式进行传参的, 所以在写sql时需要在代码…

【opencv】示例-phase_corr.cpp 捕获视频流并通过计算相位相关性来检测画面中的移动...

// 包含OpenCV库的头文件 #include "opencv2/core.hpp" // 包含OpenCV核心功能 #include "opencv2/videoio.hpp" // 包含视频IO功能 #include "opencv2/highgui.hpp" // 包含高级GUI功能,显示图像 #include "opencv2/imgproc.hp…

【Java实战】使用自定义注解实现参数校验详解

文章目录 前言📝一、Java注解简介二、启用注解校验1.启用注解2.注解@Valid和 @Validated2.1@Valid级联校验2.2@Validated高级使用三、自定义注解1.统一异常处理2.编写注解2.1 自定义校验2.2 多参数校验总结前言📝 由于实际开发中遇到大量相同的条件参数验证,不想写重复代…

天空盒1-天空盒的实现原理

天空盒是一种常用的实时渲染技术,用于在三维场景中模拟远处环境,例如天空、山脉或城市等。它通过将一个立方体贴图(也称为环境贴图)投影到场景的背景中,给人一种无限远的感觉。以下是天空盒的实现原理: 创建…

git中checkout的用法总结

切换分支 # 切换分支,如果有本地分支,则表示切换到该分支上; # 如果是远端仓库分支,表示把远端仓库分支下载到本地仓库中 git checkout 分支名# 创建一个分支,并进行切换 git checkout -b 分支名撤销对文件的修改 # …

【点云语义分割】自适应一致性正则化的弱监督点云分割

Reliability-Adaptive Consistency Regularization for Weakly-Supervised Point Cloud Segmentation 摘要: 本文探讨了将弱监督学习中常用的一致性正则化应用于具有多种特定数据增强功能的点云学习中,而对这一问题的研究还不够深入。我们发现&#xff…

招联新任董事长任职资格获批,头部优势如何延续?

来源 | 镭射财经(leishecaijing) 4月9日,国家金融监督管理总局深圳监管局核准陈忠岳招联消费金融董事、董事长的任职资格。公开资料显示,陈忠岳为中国联合网络通信集团有限公司董事长、党组书记。 作为持牌消金行业头部玩家&…

BI数据分析软件:行业趋势与功能特点剖析

随着数据量的爆炸性增长,企业对于数据的需求也日益迫切。BI数据分析软件作为帮助企业实现数据驱动决策的关键工具,在当前的商业环境中扮演着不可或缺的角色。本文将从行业趋势、功能特点以及适用场景等方面,深入剖析BI数据分析软件&#xff0…

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中,温湿度传感器(DHT11)以及光照强度传感器(BH1750)往往是必不可少的两个外设,下面我们来剖析这两个外设的原理,以及使用。 1. 温湿度传感…

谷歌google浏览器无法更新Chrome至最新版本怎么办?浏览器Chrome无法更新至最新版本

打开谷歌google浏览器提示:无法更新Chrome,Chrome无法更新至最新版本,因此您未能获得最新的功能和安全修复程序。点击「重新安装Chrome」后无法访问此网站,造成谷歌浏览器每天提示却无法更新Chrome至最新版本。 谷歌google浏览器无…

数据结构--循环队列

1.队列的定义: 和栈相反,队列(queue)是一种先进先出(first in first out,缩写为FIFO)的线性表.它只允许在表的一端进行插入,而在另一端删除元素. 在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front). 2.循环队列的设计图示: 3.循环队列的结构设计: ty…

Flask前端页面文本框展示后端变量,路由函数内外两类

一、外&#xff01;路由函数外的前后端数据传输 Flask后端 ↓ 首先导入包&#xff0c;需要使用 后端&#xff1a;flask_socketio来进行路由外的数据传输&#xff0c; from flask_socketio import SocketIO, emit 前端&#xff1a;还有HTML头文件的设置。 <!DOCTYPE …

已经下载了pytorch,但在正确使用一段时间后出现No module named torch的错误

问题描述 使用的是叫做m2release的虚拟环境&#xff0c;在此环境下使用conda list可以发现是存在pytorch的&#xff0c;但是运行代码时却报No module named torch的错误。 解决方案 想尝试卸掉这个pytorch重新装一次&#xff0c;但是想卸载会提示找不到&#xff0c;想重新…

Qt_30道常见面试题及答案

1. 简述 Qt 是什么&#xff1f; 答&#xff1a;Qt 是一个跨平台的应用程序开发框架&#xff0c;它提供了一系列的工具和库&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序。 2. Qt 有哪些主要模块&#xff1f; 答&#xff1a;Qt 的主要模块包括 Qt Co…

AndroidAutomotive模块介绍(二)应用及接口介绍

前言 上一篇文章中从整体角度描述了 Android Automotive 模块。本篇文章将对 Android Automotive 中的 APP 以及 API 部分展开描述。 上一篇&#xff1a;AndroidAutomotive模块介绍&#xff08;一&#xff09;整体介绍 下一篇&#xff1a;AndroidAutomotive模块介绍&#xff0…

Steam平台游戏发行流程

Steam平台游戏发行流程 大家好我是艾西&#xff0c;一个做服务器租用的网络架构师也是游戏热爱者&#xff0c;经常在steam平台玩各种游戏享受快乐生活。去年幻兽帕鲁以及雾锁王国在年底横空出世&#xff0c;幻兽帕鲁更是在短短一星期取得了非常好的成绩&#xff0c;那么作为游戏…

常用UI组件

一、文本组件 1.1 概述 Text为文本组件&#xff0c;用于显示文字内容 1.2 参数 Text组件的参数类型为string | Resource Entry Component struct Index {build() {Column({space : 50}) {Text(你好).fontSize(50)}.width(100%).height(100%).justifyContent(FlexAlign.Cent…