本文主要针对需要通过查看视频,并对视频中的感兴趣部分进行截图,最终将两者匹配生成excel报告的工作需求。
其中涉及几个重要的部分:
1.对文件夹中的文件进行排序并存放到python列表中,通常我们通过python的os.listdir(path)函数得到的文件名称列表是通过字符顺序排序的,这样就是的12、13等这样的数字会排在2之前,本文通过字典中间变量实现了对文件名称列表的重新排列,使其按照数字的顺序排列。
2.本程序演示了通用的excel写入文本数据,单元格合并,以及插入图片的功能。
下面附上程序:
import os
import xlsxwriter
#本程序可以处理的图片的命名方式应为:
#数字(对应视频的序号,视频应按照名称进行升序排序)
#-数字(该视频中问题的序号)-问题描述-数字(该视频中发生某类问题的次数序号)
#-问题发生的时间-.png
#例如: 14-1-在十字路口将对向车道的机动车误判为CIPV-5-2分32秒-.png
#意思为:在第14个视频中第5次发生第1类问题的(
#在十字路口将对向车道的机动车误判为CIPV)的时间为该视频的2分32秒处
#定义截图路径和视频路径
pics_path=r'你的问题截图路径'
videos_path=r'你的视频路径'
videos=os.listdir(videos_path)
#新建excel文件并设置相关列的宽度
book= xlsxwriter.Workbook('LV问题记录.xlsx')
sheet=book.add_worksheet('sheet1')
style=book.add_format({'align':'vcenter','text_wrap':1})
sheet.set_column(0,0,2)
sheet.set_column(1,1,30)
sheet.set_column(2,2,40)
sheet.set_column(3,3,20)
#初始化变量
row_nums=[]#用于保存每个截图所对应的的视频序号
column=0#用于表示该截图应处于哪一列
forenum=0#前一个截图的问题序号
row_dic={}#字典的键表示行号,值表示视频序号,因此其表示某视频在excel中应处于哪行
real_row=0#用于表示该截图应处于哪行
new_times=''#问题发生的新时间
old_times=''#问题发生的旧时间
times=''#问题发生的时间中间变量
#将工作路径修改为截图所在路径,并获取截图所在文件夹的所有图片
#并将非图片文件从列表中删除
os.chdir(pics_path)
files=os.listdir()
for file in files:
if file[-4:].upper()!='.PNG':
del files[files.index(file)]
#由于获取的所有截图所构成的列表是按照字符顺序排序的,
#这样就导致11、12等文件会在2之前。
#因此通过字典作为中间变量,将列表按照数字顺序排序
key_dic={}
file_lists=[]
for index,file in enumerate(files):
key_dic[index]=int(file.split('-')[0])
while key_dic!={}:
file_lists.append(files[min(key_dic,key=lambda k:key_dic[k])])
key_dic.pop(min(key_dic,key=lambda k:key_dic[k]))
for file in file_lists:
print(file)
#开始处理
for file in file_lists:
file_split=file.split('-')#对截图名称进行分割
i=int(file_split[0])#将问题所对应的的视频的序号赋给i
column=int(file_split[3])-1#将视频中发生某类问题次数的序号赋给column
#这是为了将同一类问题的截图放在excel同一行
row_num=str(row_nums).count(str(i))#统计row_nums中该视频所对应的序号出现的次数
#一下6行主要用于将同一视频中发生同一类问题的不同时间进行拼接
new_times=file_split[4]
times=new_times
if row_num!=0 and int(file_split[1])==forenum:
real_row-=1#如果该视频的序号已经出现过且本截图的问题序号前一个相同
#这表明是同一类问题的不同发生时间,因此截图应保持在同一行
times=old_times+'\n'+new_times
old_times=times
forenum=int(file_split[1])#对前一个截图的问题序号重新赋值
sheet.set_row(real_row,120)#将视频序号所在行的高度设置为120
sheet.set_column(4+column,4+column,30)#将截图所在列的宽度设置为30
#插入该截图到相应位置,并进行比例缩放
sheet.insert_image(real_row,4+column,file,{'x_scale':0.2,'y_scale':0.25})
sheet.write(real_row,1,videos[i-1],style)#在截图所在行的第二列写入对应视频名称
sheet.write(real_row,0,i,style)#在截图所在行的第一列写入视频序号
#目前该序号可能是不连续的,后续再调整
sheet.write(real_row,2,file_split[2],style)#在截图所在行的第三列写入问题描述
sheet.write(real_row,3,times,style)#在截图所在行的第四列写入问题发生时间
row_nums.append(i)#将该视频序号添加到row_nums
row_dic[real_row]=i#将该视频序号及该视频的问题截图在excel中的行号写入字典
real_row+=1
#由于不一定所有视频均有问题截图,比如第1、3、4、8、12、14个视频存在问题,
#并进行了截图,经过以上操作后,第1、3、4、8、12、14个视频所对应的的序号
#为1、3、4、8、12、14,显然不连续,实际应为1、2、3、4、5、6。
#并且,倘若某个食品存在多类问题,每一类问题又占据excel中的一行,这样一来,
#存储同一视频不同类问题的行,其前两列(序号和视频名称)是相同的,
#将相同部分合并起来看着更舒服,因此以下程序主要为修正序号和合并单元格。
print(row_nums)
print(row_dic)
keys=list(row_dic.keys())
values=list(row_dic.values())
print(keys)
print(values)
a=[]#用于存储同一视频不同类问题所对应的行号,即某一类视频的问题占用了哪几行
merge_row=0
print(len(keys))
for i in range(len(keys)-1):
if values[i]==values[i+1]:#如果本行与下一行的视频序号相同
#且该行及下一行的序号不在a中,则将其添加到a中
if str(a).count(str(keys[i]))==0:
a.append(keys[i])
if str(a).count(str(keys[i+1]))==0:
a.append(keys[i+1])
if i==len(keys)-2:#如果此时已经搜索到倒数第二个元素,且该元素和
#最后一个元素的视频序号相同,则执行合并单元格操作
#因为搜索已经结束
print(a)
merge_row+=len(a)-1
print('merge_row'+str(merge_row))
mini=min(a)
maxa=max(a)
sheet.merge_range('A'+str(mini+1)+':A'+str(maxa+1),maxa-merge_row+1,style)
sheet.merge_range('B' + str(mini + 1) + ':B' + str(maxa + 1), videos[row_dic[mini]-1], style)
else:#如果本行与下一行的视频序号不同,则是不同视频
if len(a)!=0:#若此时a不为空,则表示本行前边的几行属于同一视频,因此将前边几行合并
print(a)
merge_row += len(a) - 1
print('merge_row' + str(merge_row))
mini = min(a)
maxa = max(a)
sheet.merge_range('A' + str(mini + 1) + ':A' + str(maxa + 1), maxa - merge_row + 1, style)
sheet.merge_range('B' + str(mini + 1) + ':B' + str(maxa + 1), videos[row_dic[mini] - 1], style)
a=[]
else:#如果a为空,则表示本行与前一行和后一行均不是同一视频
#所以本行不需要合并单元格,直接更新序号即可
sheet.write('A'+str(i+1),i-merge_row+1,style)
sheet.write('B'+str(i+1),videos[row_dic[i]-1],style)
if i==len(keys)-2:#如果此时已经搜索到倒数第二个元素,且该元素和
#最后一个元素的视频序号不同,直接更新最后一个元素的序号
#因为搜索已经结束
sheet.write('A'+str(len(keys)),len(keys)-merge_row,style)
sheet.write('B'+str(len(keys)),videos[row_dic[i+1]-1],style)
book.close()#关闭并保存excel
如果你的视频名称也需要以数字格式排序,可通过与排序截图名称相同的方法。