做法是先下取样,然后dct提取频率特征,把不重要的高频分量滤掉,再用二值化,再计算海明距离
显然,海明距离大的地方,就是镜头边缘
选取的视频有平移,变焦,渐变的镜头剪辑,可以用作测试,视频见附件。
import cv2
import numpy as np
cap = cv2.VideoCapture('./test.mp4')
dct=np.zeros([8,8])
hash_pre=np.zeros([8,8],dtype=np.bool_)
#视频帧数
length=180
hamming_string=np.zeros([length])
i=0
while cap.isOpened() and i<length:
#读取
_, frame = cap.read()
#下采样
frame_resize = cv2.resize(frame,(32,32),interpolation=cv2.INTER_CUBIC)
#灰度化
frame_gray = cv2.cvtColor(frame_resize,cv2.COLOR_RGB2GRAY)
#dct
frame_gray=np.float32(frame_gray)
frame_dct=cv2.dct(frame_gray)
#滤掉高频分量
dct=frame_dct[:8][:8]
#哈希
aver=np.sum(dct)/64
hash=np.zeros([8,8],dtype=np.bool_)
hamming=0
for row in range(8):
for col in range(8):
#二值化
if dct[row][col]>aver:
hash[row][col]=True
#汉明距离
if hash[row][col]!=hash_pre[row][col]:
hamming=hamming+1
hash_pre=hash
hamming_string[i]=hamming
i=i+1
#25ms一帧,即40帧/s
cv2.waitKey(25)
cap.release()
print(hamming_string)
[22. 0. 2. 3. 3. 1. 2. 3. 4. 3. 1. 2. 6. 3. 0. 3. 1. 3.
2. 2. 2. 2. 4. 3. 6. 4. 1. 2. 2. 1. 1. 3. 4. 3. 2. 2.
2. 2. 5. 1. 3. 2. 3. 11. 4. 9. 10. 15. 8. 9. 6. 8. 11. 5.
9. 9. 10. 15. 8. 6. 6. 5. 8. 9. 7. 7. 9. 10. 11. 9. 6. 5.
3. 3. 1. 1. 0. 0. 0. 0. 0. 0. 0. 3. 2. 6. 6. 4. 2. 2.
1. 1. 0. 1. 3. 4. 3. 5. 5. 4. 1. 2. 1. 7. 2. 0. 2. 10.
11. 4. 4. 8. 2. 8. 7. 6. 6. 9. 7. 7. 7. 9. 8. 9. 5. 5.
6. 5. 2. 2. 2. 2. 0. 1. 1. 0. 0. 1. 0. 1. 3. 12. 5. 12.
2. 1. 1. 0. 2. 2. 3. 1. 1. 1. 4. 2. 2. 4. 1. 2. 2. 2.
1. 3. 5. 7. 4. 5. 4. 1. 6. 5. 5. 8. 4. 3. 4. 3. 2. 0.]
得到了汉明距离序列
import matplotlib.pyplot as plt
plt.plot(hamming_string)
plt.show()
打印出来,有几个明显的峰值
index=np.arange(0,180,1)
gate=np.ones((180))*11
plt.plot(index,gate,"r--",index,hamming_string,"b--")
plt.show()
不断地调整阈值,选到一个合适的区间
key_point=[]
for i in range(length):
if(hamming_string[i]>11):
key_point.append(i)
str="%d in %d"%(hamming_string[i],i)
print(str)
22 in 0
15 in 47
15 in 57
12 in 141
12 in 143
就这样分好了
import random
key_fram=[]
for i in range(len(key_point)-1):
key_fram.append(random.randint(key_point[i],key_point[i+1]))
print(key_fram)
[35, 47, 58, 142]
尝试提取出关键帧来和手工提取的关键帧对比来验证效果
i=0
j=0
cap = cv2.VideoCapture('./test.mp4')
while cap.isOpened() and i<length:
#读取
_, frame = cap.read()
if i==key_fram[j]:
str="frame%d"%(i)
cv2.imshow(str,frame)
j=j+1
if j==len(key_fram):
break
i=i+1
#25ms一帧,即40帧/s
cv2.waitKey(25)
cap.release()
cv2.waitKey(0)
cv2.destroyAllWindows()