You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同源不同分辨率视频的帧比对方法求助及现有实现说明

同源不同分辨率视频差异比对实现方案

核心解决思路:先统一帧分辨率,再采用对分辨率、压缩不敏感的特征比对方案替代直接RGB矩阵比对,适配同源高相似度视频的差异识别。

优化点说明

  • 移除原有冗余的帧存盘逻辑,避免JPG压缩引入额外误差,直接基于内存中的帧数据处理
  • 统一两帧分辨率:默认将低分辨率帧等比缩放至高分辨率帧尺寸,采用线性插值保证特征不失真
  • 采用两种比对方案适配不同需求:
    • 感知哈希(dHash):快速判断帧是否存在差异,汉明距离≤3判定为无实质差异,运算速度快适合全量帧遍历
    • 结构相似性(SSIM):量化差异程度,取值越接近1相似度越高,可输出差异可视化掩码定位差异位置

可运行修改后代码

import cv2
import numpy as np

# 感知哈希dHash计算函数
def calculate_dhash(img, hash_size=8):
    # 缩放为hash_size+1 * hash_size的灰度图
    resized = cv2.cvtColor(cv2.resize(img, (hash_size + 1, hash_size)), cv2.COLOR_BGR2GRAY)
    # 计算相邻像素差异
    diff = resized[:, 1:] > resized[:, :-1]
    # 转换为哈希值
    return sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v])

# 汉明距离计算
def hamming_distance(hash1, hash2):
    return bin(hash1 ^ hash2).count('1')

# SSIM计算(可选,需要安装scikit-image:pip install scikit-image)
def calculate_ssim(img1, img2):
    from skimage.metrics import structural_similarity as ssim
    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    score, diff_mask = ssim(img1_gray, img2_gray, full=True)
    return score, (diff_mask * 255).astype("uint8")

if __name__ == "__main__":
    clip = cv2.VideoCapture('./resources/sample.m4v')
    converted_clip = cv2.VideoCapture('./resources/sample_convert.mp4')
    
    clip_nof = int(clip.get(cv2.CAP_PROP_FRAME_COUNT))
    con_clip_nof = int(converted_clip.get(cv2.CAP_PROP_FRAME_COUNT))
    original_fps = int(clip.get(cv2.CAP_PROP_FPS))
    convert_fps = int(converted_clip.get(cv2.CAP_PROP_FPS))

    # 可根据实际视频FPS调整该断言
    assert convert_fps == 30, "转换后视频FPS不为30"
    assert clip_nof == con_clip_nof, "两个视频总帧数不一致"

    id = 0
    conid = 0
    frame_count = 1
    # 差异帧存储阈值,汉明距离大于该值判定为差异帧
    DIFF_THRESHOLD = 3

    while True:
        clip.set(1, id)
        converted_clip.set(1, conid)
        ret, frame = clip.read()
        con_ret, con_frame = converted_clip.read()

        if not ret or not con_ret:
            break

        # 统一分辨率:将低分辨率帧缩放到高分辨率帧尺寸
        oh, ow = frame.shape[:2]
        ch, cw = con_frame.shape[:2]
        if oh * ow > ch * cw:
            # 转换后视频分辨率更低,缩放至原视频尺寸
            con_frame = cv2.resize(con_frame, (ow, oh), interpolation=cv2.INTER_LINEAR)
        else:
            # 原视频分辨率更低,缩放至转换后视频尺寸
            frame = cv2.resize(frame, (cw, ch), interpolation=cv2.INTER_LINEAR)
        
        # 方法1:dHash快速比对
        hash1 = calculate_dhash(frame)
        hash2 = calculate_dhash(con_frame)
        dist = hamming_distance(hash1, hash2)
        
        if dist > DIFF_THRESHOLD:
            print(f"第{frame_count}组帧存在差异,汉明距离:{dist}")
            # 可选:保存差异帧
            cv2.imwrite(f'./resources/diff/original_{frame_count}.jpg', frame)
            cv2.imwrite(f'./resources/diff/converted_{frame_count}.jpg', con_frame)

            # 可选:用SSIM计算具体差异程度
            # ssim_score, diff_mask = calculate_ssim(frame, con_frame)
            # print(f"该组帧SSIM相似度:{ssim_score:.4f}")
            # cv2.imwrite(f'./resources/diff/mask_{frame_count}.jpg', diff_mask)

        # 每隔2秒取一次帧,可根据需求调整间隔
        id += original_fps * 2
        conid += convert_fps * 2
        frame_count += 1

        if frame_count % 50 == 0:
            print(f"已检查帧数:{frame_count}")

    clip.release()
    converted_clip.release()
    cv2.destroyAllWindows()

使用说明

  • 无需额外配置的情况下默认使用dHash方案快速比对,适合大体积长视频快速扫描
  • 需要定位具体差异区域时,取消SSIM相关注释,安装scikit-image依赖即可使用
  • 可根据实际场景调整DIFF_THRESHOLD阈值,阈值越大对差异的容忍度越高

内容的提问来源于stack exchange,提问作者avishak chakroborty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:24:00