参考自
《
K
e
y
F
r
a
m
e
E
x
t
r
a
c
t
i
o
n
o
f
O
n
l
i
n
e
V
i
d
e
o
B
a
s
e
d
o
n
O
p
t
i
m
i
z
e
d
F
r
a
m
e
D
i
f
f
e
r
e
n
c
e
》
《Key Frame Extraction of Online Video Based on Optimized Frame Difference》
《KeyFrameExtractionofOnlineVideoBasedonOptimizedFrameDifference》
作者
H
u
a
y
o
n
g
L
i
u
,
W
e
n
t
i
n
g
M
e
n
g
Huayong Liu, Wenting Meng
HuayongLiu,WentingMeng等人
帧差
首先对帧间进行平滑,减少过小的差异。
其次计算帧间差分均值。
最后计算局部最值,因为量过大,所以需要设计一个带局部最值窗口的求极值方法。
准确说就是,仅当你是
[
l
,
r
]
[l,r]
[l,r]区间的最值是你才是我们需要的极值。
所有极值点都是关键帧。
最后得到的分数是
6.89
6.89
6.89
gaoimport numpy as np
import cv2
ansl = [1,94,132,154,162,177,222,236,252,268,286,310,322,255,373,401,
423,431,444,498,546,594,627,681,759,800,832,846,932,1235,1369,1438,1529,1581,1847]
ansr = [93,131,153,161,176,221,235,251,267,285,309,321,354,372,400,
422,430,443,497,545,593,626,680,758,799,831,845,931,1234,1368,1437,
1528,1580,1846,2139]#关键帧区间
ansl = np.array(ansl)
ansr = np.array(ansr)
cap = cv2.VideoCapture('D:/ai/CV/pyt/1.mp4')
Frame_rate = cap.get(5)#一秒多少帧
Frame_number = cap.get(7)#帧数
Frame_time = 1000 / Frame_rate;#一帧多少秒
len_windows = 0
local_windows = 0
def smooth(swift_img,windows):
r = swift_img.shape[1]
c = swift_img.shape[2]
for i in range(r):
for j in range(c):
L = swift_img[:,i,j]
L = np.convolve(L,np.ones(windows),'same')
swift_img[:,i,j] = L
return swift_img
def get_block(img):
img = np.array(img)
return img
def dif(img1,img2):
diff = img1 - img2
diff = np.abs(np.array(diff))
diff = diff.mean()
return diff
def get_img(now_time = 0,get_number = Frame_number):#便于算法学习
swift_img = []#转换后
index = 0#标记第几个帧
time = now_time#当前时间
while (cap.isOpened()):
cap.set(cv2.CAP_PROP_POS_MSEC,time)
ret,img = cap.read()#获取图像
if not ret:
break
img0 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换成灰度图
img1 = get_block(img0)
swift_img.append(img1)
time += Frame_time
index += 1
if index >= get_number:
break
if index % 50 ==0:
print("当前到达"+str(index))
swift_img = np.array(swift_img)
return swift_img
def get_key_frame(swift_img,local_windows):
L = []
L.append(0)
for i in range(swift_img.shape[0]-1):
temp = dif(swift_img[i],swift_img[i+1])
L.append(temp)
L = np.array(L)
TL = []
for i in range(L.shape[0]):
l = i - local_windows // 2
r = i + local_windows // 2
l = max(l,0)
r = min(r,L.shape[0])
if i == l + np.argmax(L[l:r]):
TL.append(True)
else:
TL.append(False)
# print(TL)
TL = np.array(TL)
return TL
def preserve(L):
num = 0
time = 0
for i in range(L.shape[0]):
if L[i] == False:
continue
num += 1
cap.set(cv2.CAP_PROP_POS_MSEC,time)
ret,img = cap.read()#获取图像
cv2.imwrite('./1.1/{0:05d}.jpg'.format(num),img)#保存关键帧
time += Frame_time
def cal_ans(cal_L,l,r):
rate = []
add = 0
right = 0
for j in range(ansl.shape[0]):
num = 0
if not (l <= j and j <= r):
continue
ll = ansl[j]
rr = ansr[j]
for i in range(cal_L.shape[0]):
if cal_L[i] == False:
continue
if j == 0 :
print(i)
if i + ansl[l] >= ll and i + ansl[l] <= rr:
num += 1
if num == 0:
rate.append(0.0)
else:
right += 1
if num == 1:
rate.append(6.0)
continue
add += num - 1
rate.append(6.0)
rate = np.array(rate)
ret = np.sum(rate) / rate.shape[0]
print("多余的个数:")
print(add)
add = add / (5 * (r - l + 1))
add = min(add , 1)
print("多余的占比:")
print(add)
print("正确的评分:")
print(right)
ret += 4 * (1 - add) * right / (r - l + 1)#总共帧数中只有正确的部分才考虑时间因素。
print("评分是:")
print(ret)
return ret
def study():
window = 1
local = 2
mmax = 0
lindex = 4
rindex = 10
for i in range(10):
tmp = 1 + i
for j in range(10):
Tmp = 2 + j
print("当前参数: "+"卷积窗口"+str(tmp)+"最值窗口"+str(Tmp))
tmp_img = get_img(ansl[lindex],ansr[rindex])
tmp_img = smooth(tmp_img,tmp)
tmp_L = get_key_frame(tmp_img,Tmp)
ttmp = cal_ans(tmp_L,lindex,rindex)
if ttmp > mmax:
window = tmp
local = Tmp
mmax = ttmp
print("分割线--------------------")
return window,local
len_windows,local_windows = study()
print("最终:")
print(len_windows)
print(local_windows)
print("")
swift_img = get_img()
swift_img = smooth(swift_img,len_windows)
cal_L= get_key_frame(swift_img,local_windows)
cal_ans(cal_L,0,ansl.shape[0]-1)
#preserve(cal_L)
#结果:
#6.89