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

基于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

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
视频指纹去重主要涉及到两个方面的内容:视频指纹提取和视频指纹比对。 视频指纹提取是指从视频中提取出一些能够代表该视频内容的特征,例如视频的关键帧、颜色直方图、帧间差分等。OpenCV库中提供了一些常用的方法来实现视频指纹提取。 视频指纹比对是指将提取出来的视频指纹与已有的指纹进行比对,判断两个视频是否相同。这里需要用到一些比对算法,例如哈希算法、感知哈希算法、余弦相似度等。在实际应用中,一般会选择一种或多种算法来进行比对,提高去重的准确性。 下面是一个简单的短视频指纹去重Python实现,使用了颜色直方图作为视频指纹,并使用余弦相似度来进行比对。该代码将短视频按照指定大小分为多个块,对每个块进行颜色直方图提取,最终将所有块的直方图拼接为一个向量,作为该视频的指纹。在比对时,将两个视频的指纹向量进行余弦相似度计算,如果相似度超过阈值,则认为两个视频相同。 ```python import cv2 import numpy as np # 视频指纹提取 def extract_fingerprint(video_path, block_size=8): # 读取视频 cap = cv2.VideoCapture(video_path) # 获取视频信息 fps = int(cap.get(cv2.CAP_PROP_FPS)) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 计算视频块数 block_w = width // block_size block_h = height // block_size block_num = block_w * block_h # 初始化颜色直方图 hist = np.zeros((block_num, 256 * 3)) # 逐帧提取颜色直方图 while True: ret, frame = cap.read() if ret: # 将帧转换为HSV颜色空间 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 分割成块并计算直方图 for i in range(block_h): for j in range(block_w): block = hsv[i * block_size:(i + 1) * block_size, j * block_size:(j + 1) * block_size, :] hist_idx = i * block_w + j hist[hist_idx, :] += cv2.calcHist([block], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256]).flatten() else: break # 归一化直方图 hist = hist / total_frames # 将所有块的直方图拼接为一个向量 fingerprint = hist.flatten() # 释放资源 cap.release() return fingerprint # 视频指纹比对 def compare_fingerprint(fingerprint1, fingerprint2, threshold=0.9): # 计算余弦相似度 cos_sim = np.dot(fingerprint1, fingerprint2) / (np.linalg.norm(fingerprint1) * np.linalg.norm(fingerprint2)) # 判断是否相同 if cos_sim > threshold: return True else: return False # 视频指纹修改 def modify_fingerprint(video_path, modified_path, block_size=8): # 读取视频 cap = cv2.VideoCapture(video_path) # 获取视频信息 fps = int(cap.get(cv2.CAP_PROP_FPS)) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 创建新视频 fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(modified_path, fourcc, fps, (width, height)) # 逐帧修改视频 while True: ret, frame = cap.read() if ret: # 在这里实现视频指纹修改的代码 # 修改后的帧保存在变量frame中 # ... # 将修改后的帧写入新的视频中 out.write(frame) else: break # 释放资源 cap.release() out.release() # 测试代码 if __name__ == '__main__': video1_path = 'video1.mp4' video2_path = 'video2.mp4' modified_path = 'modified.mp4' threshold = 0.9 # 提取视频指纹 fingerprint1 = extract_fingerprint(video1_path) fingerprint2 = extract_fingerprint(video2_path) # 比对视频指纹 if compare_fingerprint(fingerprint1, fingerprint2, threshold): print('视频相同') else: print('视频不同') # 修改视频指纹 modify_fingerprint(video1_path, modified_path) ``` 需要注意的是,视频指纹的提取和比对效果和有效性需要根据具体情况进行验证和评估。此外,对于视频指纹修改部分,需要根据具体的修改需求进行实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周小董

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值