如果想要自动截取一个视频的图片,又不想手动暂停截取,那可以试试用opencv自动截取(比如想要自动截取喜欢电影的经典台词与图片)。
背景说明:一个小意外,录屏视频没有声音,想着把视频里的PPT截取出来,1个小时的视频,自己挨个截取太慢了,灵机一动用opencv试试吧。
问题1:刚开始代码将每帧都进行了截取,发现一共42798帧,太多了,而且截取图片有很多重复的。
解决:隔帧截取保存,隔多少,暂时是默认了80,效果不错(可以根据自己的视频以及效果改动)。(代码如下)
问题2:能不能让代码自己根据图片差异判断保存?只留下变化的图片,
解决:解决见第二个程序。程序最核心的代码 skimage.measure.compare_ssim(X,Y,...) 计算两幅图像之间的平均结构相似性指数,可参考我的另一个博客
注意:
- 想要尝试代码,配置opencv,pip install -i https://mirrors.aliyun.com/pypi/simple opencv-python==4.1.0.25
详情见:- cap = cv2.VideoCapture('2.mp4') 2.mp4改为你的视频名字
- 以下代码只尝试了MP4类型文件,别的暂时没有尝试,有需要再来更新改进吧。
# 视频分解图片
# 1 load 2 info 3 parse 4 imshow imwrite
import cv2
import os
# 获取一个视频打开cap 参数1 file name
#cap = cv2.VideoCapture("1.mp4")
#cv2.VideoCapture(0, cv2.CAP_DSHOW) # 摄像头截取
cap = cv2.VideoCapture('2.mp4')
isOpened = cap.isOpened # 判断是否打开‘
print(isOpened)
# 获取信息 宽高
n_frame = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print('总帧数:',n_frame) # 整个视频的总帧数
fps = cap.get(cv2.CAP_PROP_FPS) # 帧率 每秒展示多少张图片
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # w
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # h
print('帧数、宽度、高度分别为:',fps,width,height) # 帧率 宽 高
i = 0 # 记录读取多少帧
frameFrequency = 80 # 每frameFrequency保存一张图片
while(isOpened):
# 结束标志是否读取到最后一帧
if i == n_frame:
break
else:
i = i+1
(flag,frame) = cap.read() # read方法 读取每一张 flag是否读取成功 frame 读取内容
fileName = 'image'+str(i)+'.jpg' # 名字累加
# True表示读取成功 进行·写入
# if 判断需要有冒号
#if flag == True:
outPutDirName = './d/' # 设置保存路径
if not os.path.exists(outPutDirName):
# 如果文件目录不存在则创建目录
os.makedirs(outPutDirName)
if i % frameFrequency == 0:
print(fileName)
cv2.imwrite(outPutDirName+fileName,frame,[cv2.IMWRITE_JPEG_QUALITY,100])# 质量控制 100最高
print('end!')
代码运行结果
import os
import cv2
from skimage.measure import compare_ssim
'''相邻两个文件比较相似度,相似就把第二个加到新列表(删除列表)里,然后进行新列表去重,统一删除。
例如:有文件1-10,首先1和2相比较,若相似,则把2加入到新列表里,再接着2和3相比较,若不相似,则继续进行3和4比较...一直比到最后,然后删除新列表里的图片
只对于连续图片(例一个视频里截下的图片)准确率也较高,其效率高'''
def delete(filename1):
os.remove(filename1)
if __name__ == '__main__':
path = r'./E/' # 文件所在路径
img_path = path
imgs_n = [] # 新建的删除列表
i = 0 # 用来统计删了第几张图片
img_files = [os.path.join(rootdir, file) for rootdir, _, files in os.walk(path) for file in files if
(file.endswith('.jpg'))]
for currIndex, filename in enumerate(img_files):
if not os.path.exists(img_files[currIndex]):
print('not exist', img_files[currIndex])
break
img = cv2.imread(img_files[currIndex])
img1 = cv2.imread(img_files[currIndex + 1])
# https://cloud.tencent.com/developer/section/1414961 开发者手册链接
# 本程序最核心的代码
# skimage.measure.compare_ssim(X,Y,...)
# 计算两幅图像之间的平均结构相似性指数
ssim = compare_ssim(img, img1, multichannel=True)
# 相似度大于0.9就加入删除列表
if ssim > 0.9:
imgs_n.append(img_files[currIndex + 1]) # 加入新建删除列表
i = i+1 # 每加入一个就会删除
print(img_files[currIndex], img_files[currIndex + 1], ssim)
print('删除次数', i)
# 否则不删除,给出两图片的相似度
else:
print('small_ssim',img_files[currIndex], img_files[currIndex + 1], ssim)
currIndex += 1
if currIndex >= len(img_files)-1:
break
for image in imgs_n:
delete(image)
- 运行结果
可发现共删除294张图片
处理前文件夹情况(共403):
处理后文件夹情况(剩下109)点开检查发现相似图片基本删除,达到目标: