一个朋友想用python来读取视频帧,根据帧和帧之间相似度判断剪辑痕迹;但是最后发现并没什么用......
原理就是遍历地读取图像相邻帧,将图像相邻帧前处理后,缩小什么的,计算d_hash,然后计算其汉明距离,然后把汉明距离变成相似度,比较相似度,如果相似度低于阈值,就标记时间什么的
不过我一想,欸!好像可以用来解GIF隐写
我就把代码放这里了
1.处理视频版本的
python
import cv2
import numpy as np
from PIL import Image
# Constants
VIDEO_FILE = "faker.mp4"
FRAME_PREFIX = "frame"
FAIL_THRESHOLD = 0.77
def d_hash(image):
"""Calculate the difference hash for the given image."""
hash_bits = []
for i in range(8):
for j in range(8):
hash_bits.append(1 if image[i, j] > image[i, j + 1] else 0)
return hash_bits
def hamming_distance(hash1, hash2):
"""Calculate the Hamming distance between two hashes."""
return sum(1 for x, y in zip(hash1, hash2) if x != y)
def process_frame(frame):
"""Process frame to convert it to a format suitable for hash computation."""
return np.array(Image.fromarray(frame).resize((9, 8), Image.LANCZOS).convert('L'), 'f')
def main():
video = cv2.VideoCapture(VIDEO_FILE)
edit_detected = False
while True:
# Read two consecutive frames from the video
success, frame0 = video.read()
success1, frame1 = video.read()
if not success or not success1:
break
# Process frames
frame0_processed = process_frame(frame0)
frame1_processed = process_frame(frame1)
# Calculate hashes and distance
hash0 = d_hash(frame0_processed)
hash1 = d_hash(frame1_processed)
distance = hamming_distance(hash0, hash1)
similarity = 1.0 - distance / 64.0
# Check similarity against the threshold
if similarity < FAIL_THRESHOLD:
msec = video.get(cv2.CAP_PROP_POS_MSEC)
minute, second = divmod(msec // 1000, 60)
print(f"{int(minute)} minute {int(second)} second detected with similarity {similarity}")
edit_detected = True
if not edit_detected:
print("No edit detected.")
if __name__ == "__main__":
main()
2.处理GIF版本的
处理GIF的时候如果遇到相似度过低的帧,就标记出来,而不是时间
python
from PIL import Image, ImageSequence
import numpy as np
# Constants
GIF_FILE = "aaa.gif"
FRAME_PREFIX = "frame"
FAIL_THRESHOLD = 0.77
def d_hash(image):
"""Calculate the difference hash for the given image."""
hash_bits = []
for i in range(8):
for j in range(8):
hash_bits.append(1 if image[i, j] > image[i, j + 1] else 0)
return hash_bits
def hamming_distance(hash1, hash2):
"""Calculate the Hamming distance between two hashes."""
return sum(1 for x, y in zip(hash1, hash2) if x != y)
def process_frame(frame):
"""Process frame to convert it to a format suitable for hash computation."""
return np.array(frame.resize((9, 8), Image.LANCZOS).convert('L'), 'f')
def main():
gif = Image.open(GIF_FILE)
frames = [frame.copy() for frame in ImageSequence.Iterator(gif)]
edit_detected = False
previous_hash = None
for index, frame in enumerate(frames):
# Process frame
frame_processed = process_frame(frame)
# Calculate hash
current_hash = d_hash(frame_processed)
if previous_hash is not None:
# Calculate distance and similarity
distance = hamming_distance(previous_hash, current_hash)
similarity = 1.0 - distance / 64.0
# Check similarity against the threshold
if similarity < FAIL_THRESHOLD:
print(f"Frame {index} detected with similarity {similarity}")
edit_detected = True
previous_hash = current_hash
if not edit_detected:
print("No edit detected.")
if __name__ == "__main__":
main()
FAIL_THRESHOLD那里可以调节灵敏度,越高越容易筛选帧对
不过话说回来,好像还是很鸡肋......算了......写都写了
兴许以后有用呢。