同源不同分辨率视频的帧比对方法求助及现有实现说明
同源不同分辨率视频差异比对实现方案
核心解决思路:先统一帧分辨率,再采用对分辨率、压缩不敏感的特征比对方案替代直接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
相关产品推荐
相关产品推荐

