[1214]基于Python实现视频去重

2023-10-28

基于Python实现视频去重

基本原理

一款基于Python语言的视频去重复程序,它可以根据视频的特征参数,将重复的视频剔除,以减少视频的存储空间。它的基本原理是:首先利用Python语言对视频文件进行解析,提取视频的特征参数,如帧率、码率等;然后根据特征参数,生成视频的哈希值;最后,将每个视频的哈希值进行对比,如果哈希值相同,则表示视频内容相同,可以将其中一个视频剔除,以节省存储空间。

实现方法

基于Python实现视频去重小工具,需要使用Python语言的一些第三方库,如OpenCV、PIL等。实现的基本步骤如下:

1、首先,使用OpenCV库对视频文件进行解析,提取视频的特征参数;
2、然后,使用PIL库将视频的每一帧转换为灰度图片,计算每一帧图片的哈希值;
3、最后,将每个视频的哈希值进行对比,如果哈希值相同,则表示视频内容相同,可以将其中一个视频剔除。

  • 示例代码
import cv2
from PIL import Image
 
# 读取视频文件
video_file = "video.mp4"
cap = cv2.VideoCapture(video_file)
 
# 提取视频的特征参数
frame_rate = cap.get(cv2.CAP_PROP_FPS)
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
 
# 计算每一帧图片的哈希值
while True:
    # 读取每一帧图片
    success, frame = cap.read()
    if not success:
        break
    # 将图片转换为灰度图
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 计算图片的哈希值
    image = Image.fromarray(gray_frame)
    hash_value = image.hash()
    # 将哈希值进行对比,如果哈希值相同,则表示视频内容相同
    if hash_value == other_hash_value:
        # 剔除重复视频
        pass
 
# 释放视频文件
cap.release()

其它视频去重code

同级目录下新建dup_video

# -*- coding:utf-8 -*-
import json
import os
import shutil

import cv2
import imagehash
from PIL import Image
from loguru import logger
from PySimpleGUI import popup_get_folder


class VideoDuplicate(object):
    '''
    返回整个视频的图片指纹列表
    从1秒开始,每3秒抽帧,计算一张图像指纹
    '''

    def __init__(self):
        self._over_length_video: list = []
        self._no_video: list = []

    def _video_hash(self, video_path) -> list:
        '''
        @param video_path -> 视频绝对路径;
        '''
        hash_arr = []
        cap = cv2.VideoCapture(video_path)  ##打开视频文件
        logger.info(f'开始抽帧【{video_path}】')

        n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 视频的帧数
        logger.warning(f'视频帧数:{n_frames}')

        fps = cap.get(cv2.CAP_PROP_FPS)  # 视频的帧率
        logger.warning(f'视频帧率:{fps}')

        dur = n_frames / fps * 1000  # 视频大致总长度
        cap_set = 1000
        logger.warning(f'视频大约总长:{dur / 1000}')
        if dur // 1000 > 11:
            logger.error(f'视频时长超出规定范围【6~10】;当前时长:【{dur // 1000}】;跳过该视频;')
            self._over_length_video.append(video_path)
            return []

        while cap_set < dur:  # 从3秒开始,每60秒抽帧,计算图像指纹。总长度-3s,是因为有的时候计算出来的长度不准。
            cap.set(cv2.CAP_PROP_POS_MSEC, cap_set)
            logger.debug(f'开始提取:【{cap_set // 1000}】/s的图片;')
            # 返回该时间点的,图像(numpy数组),及读取是否成功
            success, image_np = cap.read()
            if success:
                img = Image.fromarray(cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB))  # 转成cv图像格式
                h = str(imagehash.dhash(img))
                logger.success(f'【{cap_set}/s图像指纹:【{h}】')
                hash_arr.append(h)  # 图像指纹
            else:
                logger.error(str(cap_set / 1000))
            cap_set += 1000 * 2
        cap.release()  # 释放视频
        return hash_arr

    def start(self, base_dir):
        '''
        @param base_dir -> 主文件路径;
        '''
        data: list = []
        for video in os.listdir(base_dir):
            logger.debug(f'-' * 80)
            name, ext = os.path.splitext(video)
            if ext not in ('.mp4', '.MP4'):
                logger.error(f'视频文件格式不符;【{video}】;执行跳过;')
                continue

            abs_video_path = os.path.join(base_dir, video)
            video_hash_list = self._video_hash(abs_video_path)
            if video_hash_list:
                data.append({'video_abs_path': abs_video_path, 'hash': video_hash_list})

        self._write_log(data)
        return data

    @staticmethod
    def _write_log(data: list) -> None:
        '''视频哈希后的值写入日志文件'''
        with open(f'log.txt', 'w+', encoding='utf-8') as f:
            f.write(json.dumps(data))

    def __call__(self, base_dir, *args, **kwargs):
        self.start(base_dir)
        logger.debug(f'-----------------------------------开始比对关键帧差值感知余弦算法-----------------------------')

        with open('log.txt') as f:
            data = json.loads(f.read())
            for i in range(0, len(data) - 1):
                for j in range(i + 1, len(data)):
                    if data[i]['hash'] == data[j]['hash']:
                        _, filename = os.path.split(data[i]['video_abs_path'])
                        logger.error(f'移动文件:【{filename}】')
                        shutil.move(
                            os.path.join(base_dir, filename),
                            os.path.join(os.path.join(os.getcwd(), 'dup_video'), filename)
                        )
        logger.warning('---------------------超长视频----------------------')
        for i in self._over_length_video:
            _, name = os.path.split(i)
            logger.error(name)


def main():
    path = popup_get_folder('请选择[视频去重]文件夹')
    v = VideoDuplicate()
    v(path)


if __name__ == '__main__':
    main()

参考:https://blog.csdn.net/weixin_44634704/article/details/128563576
https://fiime.cn/blog/202363

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[1214]基于Python实现视频去重 的相关文章

  • 下载 PyQt6 的 Qt Designer 并使用 pyuic6 将 .ui 文件转换为 .py 文件

    如何下载 PyQt6 的 QtDesigner 如果没有适用于 PyQt6 的 QtDesigner 我也可以使用 PyQt5 的 QtDesigner 但是如何将此 ui 文件转换为使用 PyQt6 库而不是 PyQt5 的 py 文件
  • 如何在python中读取多个文件中的文本

    我的文件夹中有许多文本文件 大约有 3000 个文件 每个文件中第 193 行是唯一包含重要信息的行 我如何使用 python 将所有这些文件读入 1 个文本文件 os 模块中有一个名为 list dir 的函数 该函数返回给定目录中所有文
  • Python PAM 模块的安全问题?

    我有兴趣编写一个 PAM 模块 该模块将利用流行的 Unix 登录身份验证机制 我过去的大部分编程经验都是使用 Python 进行的 并且我正在交互的系统已经有一个 Python API 我用谷歌搜索发现pam python http pa
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • pandas 替换多个值

    以下是示例数据框 gt gt gt df pd DataFrame a 1 1 1 2 2 b 11 22 33 44 55 gt gt gt df a b 0 1 11 1 1 22 2 1 33 3 2 44 4 3 55 现在我想根据
  • 如何使用包含代码的“asyncio.sleep()”进行单元测试?

    我在编写 asyncio sleep 包含的单元测试时遇到问题 我要等待实际的睡眠时间吗 I used freezegun到嘲笑时间 当我尝试使用普通可调用对象运行测试时 这个库非常有用 但我找不到运行包含 asyncio sleep 的测
  • Python 中的二进制缓冲区

    在Python中你可以使用StringIO https docs python org library struct html用于字符数据的类似文件的缓冲区 内存映射文件 https docs python org library mmap
  • NameError:名称“urllib”未定义”

    CODE import networkx as net from urllib request import urlopen def read lj friends g name fetch the friend list from Liv
  • python 集合可以包含的值的数量是否有限制?

    我正在尝试使用 python 设置作为 mysql 表中 ids 的过滤器 python集存储了所有要过滤的id 现在大约有30000个 这个数字会随着时间的推移慢慢增长 我担心python集的最大容量 它可以包含的元素数量有限制吗 您最大
  • Pandas Dataframe 中 bool 值的条件前向填充

    问题 如何转发 fill boolTruepandas 数据框中的值 如果是当天的第一个条目 True 到一天结束时 请参阅以下示例和所需的输出 Data import pandas as pd import numpy as np df
  • Geopandas 设置几何图形:MultiPolygon“等于 len 键和值”的 ValueError

    我有 2 个带有几何列的地理数据框 我将一些几何图形从 1 个复制到另一个 这对于多边形效果很好 但对于任何 有效 多多边形都会返回 ValueError 请指教如何解决这个问题 我不知道是否 如何 为什么应该更改 MultiPolygon
  • 使用 OpenPyXL 迭代工作表和单元格,并使用包含的字符串更新单元格[重复]

    这个问题在这里已经有答案了 我想使用 OpenPyXL 来搜索工作簿 但我遇到了一些问题 希望有人可以帮助解决 以下是一些障碍 待办事项 我的工作表和单元格数量未知 我想搜索工作簿并将工作表名称放入数组中 我想循环遍历每个数组项并搜索包含特
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • Nuitka 未使用 nuitka --recurse-all hello.py [错误] 编译 exe

    我正在尝试通过 nuitka 创建一个简单的 exe 这样我就可以在我的笔记本电脑上运行它 而无需安装 Python 我在 Windows 10 上并使用 Anaconda Python 3 我输入 nuitka recurse all h
  • 在Python中重置生成器对象

    我有一个由多个yield 返回的生成器对象 准备调用该生成器是相当耗时的操作 这就是为什么我想多次重复使用生成器 y FunctionWithYield for x in y print x here must be something t
  • 如何在 Django 中使用并发进程记录到单个文件而不使用独占锁

    给定一个在多个服务器上同时执行的 Django 应用程序 该应用程序如何记录到单个共享日志文件 在网络共享中 而不保持该文件以独占模式永久打开 当您想要利用日志流时 这种情况适用于 Windows Azure 网站上托管的 Django 应
  • 从 Python 中的类元信息对 __init__ 函数进行类型提示

    我想做的是复制什么SQLAlchemy确实 以其DeclarativeMeta班级 有了这段代码 from sqlalchemy import Column Integer String from sqlalchemy ext declar
  • 在 Python 类中动态定义实例字段

    我是 Python 新手 主要从事 Java 编程 我目前正在思考Python中的类是如何实例化的 我明白那个 init 就像Java中的构造函数 然而 有时 python 类没有 init 方法 在这种情况下我假设有一个默认构造函数 就像
  • 改变字典的哈希函数

    按照此question https stackoverflow com questions 37100390 towards understanding dictionaries 我们知道两个不同的字典 dict 1 and dict 2例
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data

随机推荐

  • 制造企业有没有APS系统?生产车间如何计划排程和安排生产计划的?

    生产车间从组织职能上来说是以生产为重点的部门 生产计划应该由生产计划部来安排 如果从职能上来说 生产计划和生产车间放在一起会产生类似又当运动员又当裁判员的角色一样 从管理角度来看 生产计划和生产管理需要分开 原则上一个属于计划调度部门 一个
  • 记录一下实体类模型(Entity)的常用注解

    1 Data lombok注解 Data 注解的主要作用是提高代码的简洁 使用这个注解可以省去代码中大量的get set toString 等方法 2 TableName MybatisPlus注解 TableName注解主要是实现实体类型
  • 树莓派外设小开发(继电器、语音模块、超声波模块)

    wiringPi库安装与查看 首先要了解wiringPi库 wiringPi是一个很棒的树莓派IO控制库 使用C语言开发 提供了丰富的接口 GPIO控制 中断 多线程 等等 验证wiringPi的是否安装成功 输入gpio v 会在终端中输
  • 单片机C语言常用的头文件与库函数

    单片机C语言常用的头文件与库函数 以下头文件与库函数 只用头文件包含以下相应头文件即可调用 持续更新中 Intrins h头文件 函数名 函数原型 功能 返回值 crol unsigned char crol unsigned char v
  • 计算机密码输入正确,Win10输入正确密码却提示“密码不正确”如何解决

    在使用windows10系统过程中 很多用户都会遇到一些奇怪的问题 比如 有用户反馈开机登录win10的时候输入正确的登入密码 却碰到 密码不正确 请确认您的微软账户密码正确 的错误提示 无法登录 是怎么回事呢 在出现该问题的时候首先我们可
  • QT定时器的几种用法

    一 自定义定时器 定义一个定时器对象 绑定自定义槽函数 也可以定义定时器对象指针 这样可以一次性让多个定时器绑定同一个槽函数 头文件中加入 QTimer myTimer void myTimerEvent 自定义定时处理槽函数 在需要启动的
  • TCP的三次握手与四次挥手以及面试常见题

    TCP 是什么 TCP Transmission Control Protocol 传输控制协议 是一种面向连接的 可靠的 基于字节流的传输层通信协议 而且TCP是全双工模式 面向连接 你和你女朋友聊天是面向连接的 只有连接起来才可以通信的
  • 【Jmeter】什么是BeanShell?

    一 什么是BeanShell BeanShell是用Java写成的 一个小型的 免费的 可以下载的 嵌入式的Java源代码解释器 JMeter性能测试工具也充分接纳了BeanShell解释器 封装成了可配置的BeanShell前置和后置处理
  • 花生壳 linux客户端 命令

    phddns start service sshd status phddns status phddns version
  • HJ32密码截取

    有一定难度 难在考虑不周全 最后还是看了别人提到的方法 自己独立实现了一下 可能没有别人的简洁 但是易懂 调试的时候有些小毛病 但自己解决了 原因不是很清楚 最后总结里会提到 目标 在输入的字符串里找到对称的且是最长的那个字符串 思路 参考
  • 【Zabbix实战之部署篇】Zabbix使用SNMP监控Linux系统

    Zabbix实战之部署篇 Zabbix使用SNMP监控Linux系统 一 SNMP协议介绍 1 SNMP协议简介 2 SNMP协议特点 二 实践环境介绍 三 检查Zabbix监控平台环境 1 检查Zabbix相关组件容器状态 2 检查Zab
  • day05:js基础——函数、作用域问题

    js函数 作用域问题 概述 1 函数 1 1 函数概念 函数作用 函数构成 1 2 定义函数 调用函数 1 3 函数参数 1 4 函数返回值 1 5 js中的特殊函数 1 6 函数demo 2 变量作用域 3 js中的预解析 3 1 声明式
  • 用c语言制作一个简单的答题系统

    首先制作一个答题系统需要有一个题库 其次要有完整的出题系统 然后要能够进行答题和判断答案对错 最后就是统计答案正确率了 实现创建一个题库并不难 仅需要使用数组保存题目与标准答案就行了 使用strcpy函数将题目分别输入进题库 部分代码如下
  • Web自动化测试 —— 测试环境搭建 (Selenium+Python)及视频操作

    一 什么样项目适合做web自动化 1 软件需求不会频繁的变更 2 项目周期比较长 3 自动化的脚本能够重复利用 介入点 第一个版本的核心功能确认以后 系统测试 自动化的实施过程 1 可行性分析 2 框架的选择 selenum rf 框架的搭
  • 使用 maven 自动将源码打包并发布

    在pom xml中添加maven source plugin插件 maven生成 jar的同时生成 sources包
  • 用分布式锁和redis实现原子性递增,解决编号重复问题

    import com baomidou mybatisplus core conditions query QueryWrapper import lombok extern slf4j Slf4j import org apache co
  • C语言-二维数组做函数的参数

    文章目录 1 引例 2 观点1 这种使用方法是错误的 3 观点2 根本不需要这么做 4 二维数组做函数参数的方法 4 1 方法1 4 2 方法2 4 3 方法3 5 与Java的不同 1 引例 下面的程序很简单 定义了一个PrintMatr
  • Talib技术因子详解(一)

    talib安装方式 pip install Ta lib Tushare数据获取请参考 金融量化分析基础环境搭建 数据获取代码 import tushare as ts ts set token Tushare的token pro ts p
  • 如何解决从git上下载很慢的问题

    在国内从git上面下载代码的速度峰值通常都是20kB s 这种速度对于那些小项目还好 而对于大一些的并且带有很多子模块的项目来讲就跟耽误时间 虽然有很多提速的方法 但是实际用起来并不稳定 这里提供一套新的方法 下载速度可以至少达到 2MB
  • [1214]基于Python实现视频去重

    文章目录 基于Python实现视频去重 基本原理 实现方法 其它视频去重code 基于Python实现视频去重 基本原理 一款基于Python语言的视频去重复程序 它可以根据视频的特征参数 将重复的视频剔除 以减少视频的存储空间 它的基本原