视频截帧大概率避免连续重复图片
深度学习在数据准备准备方面,有时我们需要把一个长视频截取成一张张的图片,来扩充我们的数据量,但是在按照一定的帧率去截取图片试我们会发现有好多相似且重复的图片出现,但是我们增加训练样本时有需要样式不同风格不同角度不同的一系列的图片去扩充,这个时候就需要在视频截图过程中简单的去判断一下前后之前图片的相似程度
目录
简单的查阅资料以后发现有以下这几种简单的且快捷的算法可以比较图像之间的相似度
余弦距离
哈希算法(采用汉明距离计算)
直方图计算图片的相似度
SSIM(结构相似度度量)计算图片的相似度
基于互信息(Mutual Information)计算图片的相似度
综合上面的比较方法,我最终选定的是差异值哈希+明汉距离算法,精确度较高,且速度也非常快,你们也可以试一试各个算法的效果比较实现代码都在上面可以直接运行
下面开始进入正题,获取视频中的图片
cv读取视频,获取视频的总帧数,自己定义一个变量需要每隔多少帧获取一张图片,记录前后两张图片,进行图片相似度比较,差异比较大的时候记录帧数并且保存图片,差异不大的时候跳过,不保存图片,通过cap.get(propld)访问视频的某些功能,propld是0到16之间的数字。每个数字表示视频的属性
可以分享一点我生成一些效果样本
样例1
样例2
结论
总结
简单的查阅资料以后发现有以下这几种简单的且快捷的算法可以比较图像之间的相似度
余弦距离
- 把图片表示成一个向量,通过计算向量之间的余弦距离来表征两张图片的相似度(值越大相似度越高)
from PIL import Image from numpy import average, dot, linalgdef get_img(image, size=(64, 64)):# 利用image对图像大小重新设置, Image.ANTIALIAS为高质量的image = image.resize(size, Image.ANTIALIAS)# 将图片转换为L模式,其为灰度图,其每个像素用8个bit表示image = image.convert('L')return image# 计算图片的余弦距离 def image_similarity(image1, image2):image1 = get_thum(image1)image2 = get_thum(image2)images = [image1, image2]vectors = []norms = []for image in images:vector = []for i in image.getdata():vector.append(average(i))vectors.append(vector)#2范数norms.append(linalg.norm(vector, 2))a, b = vectorsa_norm, b_norm = norms# dot返回的是点积,对二维数组(矩阵)进行计算res = dot(a / a_norm, b / b_norm)return res
哈希算法(采用汉明距离计算)
- 用汉明距离去计算图像指纹获得去的值就是衡量两个图片之间的差异(值越大图片越不像,值越小图像相似度越高)
- 图像指纹就是图片的身份的象征,指纹的计算方法就是按照一定的哈希算法得到一组二进制数字,
- 哈希的计算法方式有以下几种
- aHash:平均哈希
import cv2def ahash(image):# 将图片缩放为8*8的image = cv2.resize(image, (8, 8), interpolation=cv2.INTER_CUBIC)# 将图片转化为灰度图gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)# s为像素和初始灰度值,hash_str为哈希值初始值s = 0# 遍历像素累加和for i in range(8):for j in range(8):s = s + gray[i, j]# 计算像素平均值avg = s / 64# 灰度大于平均值为1相反为0,得到图片的平均哈希值,此时得到的hash值为64位的01字符串ahash_str = ''for i in range(8):for j in range(8):if gray[i, j] > avg:ahash_str = ahash_str + '1'else:ahash_str = ahash_str + '0'result = ''# 将上面的hash值转换为16位的for i in range(0, 64, 4):result += ''.join('%x' % int(ahash_str[i: i + 4], 2))# print("ahash值:",result)return result
感知哈希
import cv2 import numpy as npdef phash(img):# 加载并调整图片为32*32的灰度图片img1 = cv2.resize(img, (32, 32),cv2.COLOR_RGB2GRAY)# 创建二维列表h, w = img.shape[:2]vis0 = np.zeros((h, w), np.float32)vis0[:h, :w] = img1# DCT二维变换"""离散余弦变换(DCT)是种图像压缩算法,它将图像从像素域变换到频率域。然后一般图像都存在很多冗余和相关性的,所以转换到频率域之后,只有很少的一部分频率分量的系数才不为0,大部分系数都为0(或者说接近于0)。Phash哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法。"""# 离散余弦变换,得到dct系数矩阵img_dct = cv2.dct(cv2.dct(vis0))# 缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率img_dct.resize(8,8)# 把list变成一维listimg_list = np.array().flatten(img_dct.tolist())# 计算均值img_mean = cv2.mean(img_list)# 进一步减小DCT:大于平均值记录为1,反之记录为0.avg_list = ['0' if i<img_mean else '1' for i in img_list]return ''.join(['%x' % int(''.join(avg_list[x:x+4]),2) for x in range(0,64,4)])
差值哈希
import cv2def dHash(img):# 差值哈希算法# 先将图片压缩成9*8的小图,有72个像素点img = cv2.resize(img, (9, 8))# 转换灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# print(gray.shape)hash_str = ''# 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值,或者是32位01字符串for i in range(8):for j in range(8):if gray[i, j] > gray[i, j+1]:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_str
汉明距离计
def cmpHash(hash1, hash2):# Hash值对比# 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定,但是比较的时候必须是相同的顺序。# 对比两幅图的指纹,计算汉明距离,即两个64位的hash值有多少是不一样的,不同的位数越小,图片越相似# 汉明距离:一组二进制数据变成另一组数据所需要的步骤,可以衡量两图的差异,汉明距离越小,则相似度越高。汉明距离为0,即两张图片完全一样n = 0# hash长度不同则返回-1代表传参出错if len(hash1) != len(hash2):return -1# 遍历判断for i in range(len(hash1)):# 不相等则n计数+1,n最终为相似度if hash1[i] != hash2[i]:n = n + 1return n
- 用汉明距离去计算图像指纹获得去的值就是衡量两个图片之间的差异(值越大图片越不像,值越小图像相似度越高)
直方图计算图片的相似度
- 利用直方图计算图片的相似度时,是按照颜色的全局分布情况来看待的,无法对局部的色彩进行分析,同一张图片如果转化成为灰度图时,在计算其直方图时差距就更大了。对于灰度图可以将图片进行等分,然后在计算图片的相似度。
import cv2# 直方图计算相似度 def calc_similar(img1, img2):# 计算图img的直方图H1 = cv2.calcHist([img1], [1], None, [256], [0, 256])# 对图片进行归一化处理H1 = cv2.normalize(H1, H1, 0, 1, cv2.NORM_MINMAX, -1) # 计算图img2的直方图H2 = cv2.calcHist([img2], [1], None, [256], [0, 256])# 对图片进行归一化处理H2 = cv2.normalize(H2, H2, 0, 1, cv2.NORM_MINMAX, -1) # 利用compareHist()进行比较相似度similarity = cv2.compareHist(H1, H2, 0)return similarity
- 利用直方图计算图片的相似度时,是按照颜色的全局分布情况来看待的,无法对局部的色彩进行分析,同一张图片如果转化成为灰度图时,在计算其直方图时差距就更大了。对于灰度图可以将图片进行等分,然后在计算图片的相似度。
SSIM(结构相似度度量)计算图片的相似度
from skimage.measure import compare_ssim from scipy.misc import imread import numpy as np # 读取图片 img1 = imread('1.jpg') img2 = imread('2.jpg') # 使得两图片大小相等 img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2])) ssim = compare_ssim(img1, img2, multichannel = True)
- SSIM是一种全参考的图像质量评价指标,分别从亮度、对比度、结构三个方面度量图像相似性。SSIM取值范围[0, 1],值越大,表示图像失真越小。在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性SSIM。
基于互信息(Mutual Information)计算图片的相似度
from sklearn import metrics as mr from scipy.misc import imread import numpy as npimg1 = imread('1.jpg') img2 = imread('2.jpg') # 使得两图片大小相等 img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))img1 = np.reshape(img1, -1) img2 = np.reshape(img2, -1) mutual_infor = mr.mutual_info_score(img1, img2)
- 通过计算两个图片的互信息来表征他们之间的相似度,如果两张图片尺寸相同,还是能在一定程度上表征两张图片的相似性的。但是,大部分情况下图片的尺寸不相同,如果把两张图片尺寸调成相同的话,又会让原来很多的信息丢失,所以很难把握。经过实际验证,此种方法的确很难把握
综合上面的比较方法,我最终选定的是差异值哈希+明汉距离算法,精确度较高,且速度也非常快,你们也可以试一试各个算法的效果比较实现代码都在上面可以直接运行
下面开始进入正题,获取视频中的图片
cv读取视频,获取视频的总帧数,自己定义一个变量需要每隔多少帧获取一张图片,记录前后两张图片,进行图片相似度比较,差异比较大的时候记录帧数并且保存图片,差异不大的时候跳过,不保存图片,通过cap.get(propld)访问视频的某些功能,propld是0到16之间的数字。每个数字表示视频的属性
cv2.CAP_PROP_POS_MSEC 0 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳 cv2.CAP_PROP_POS_FRAMES 1 基于0的索引将被解码/捕获下一帧 cv2.CAP_PROP_POS_AVI_RATIO 2 视频文件的相对位置:0 - 视频的开始,1 - 视频的结束 cv2.CAP_PROP_FRAME_WIDTH 3 帧的宽度 cv2.CAP_PROP_FRAME_HEIGHT 4 帧的高度 cv2.CAP_PROP_FPS 5 帧速 cv2.CAP_PROP_FOURCC 6 4个字符表示的视频编码器格式 cv2.CAP_PROP_FRAME_COUNT 7 帧数 cv2.CAP_PROP_FORMAT 8 byretrieve()返回的Mat对象的格式 cv2.CAP_PROP_MODE 9 指示当前捕获模式的后端特定值 cv2.CAP_PROP_BRIGHTNESS 10 图像的亮度(仅适用于相机) cv2.CAP_PROP_CONTRAST 11 图像对比度(仅适用于相机) cv2.CAP_PROP_SATURATION 12 图像的饱和度(仅适用于相机) cv2.CAP_PROP_HUE 13 图像的色相(仅适用于相机) cv2.CAP_PROP_GAIN 14 图像的增益(仅适用于相机) cv2.CAP_PROP_EXPOSURE 15 曝光(仅适用于相机) cv2.CAP_PROP_CONVERT_RGB 16 表示图像是否应转换为RGB的布尔标志
import cv2def cmpHash(hash1, hash2):n = 0if len(hash1) != len(hash2):return -1for i in range(len(hash1)):if hash1[i] != hash2[i]:n = n + 1return ndef dHash(img):img = cv2.resize(img, (9, 8))gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)for i in range(8):for j in range(8):if gray[i, j] > gray[i, j+1]:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_strdef get_fraem(file_path):# file_path是文件的绝对路径,防止路径中含有中文时报错,需要解码cap = cv2.VideoCapture(file_path)# 记录前后图片的地址dict_img = {"1": [], }# 每隔多少帧获取一张图片img_fream = 60# 差异值img_dif = 20if cap.isOpened(): # 当成功打开视频时cap.isOpened()返回True,否则返回Falserate = int(cap.get(5)) # 帧速率FrameNumber = cap.get(7) # 视频文件的帧数# duration = FrameNumber/rate/60 # 帧速率/视频总帧数 是时间,除以60之后单位是分钟# timeF = int(FrameNumber // rate) # 每秒获取1张图片timeF = int(FrameNumber // img_fream)print(rate)print(timeF)print(FrameNumber)c = 1while True:sm_img = 0# 视频读取完毕退出if c > timeF * rate + 1:print('######################')break# 视频读取完毕退出if c > FrameNumber:print('******************')break# 读取当前帧数图片success, frame = cap.read()# 帧数到你需要截取的帧数时if c % rate == 0:# 记录上一张图片和当前图片if "2" in dict_img:# 计算图片的差异值哈希dict_img["1"] = dict_img["2"]else:dict_img["1"] =dHash(frame)# 计算图片的差异值哈希dict_img["2"] = dHash(frame)# 明汉距离计算差异值sm_img = cmpHash(dict_img["1"], dict_img["2"])if sm_img:# 当差异值不为0且大于我们预设的阈值的时候打印当前帧数并且保存图片if sm_img >=img_dif:cv2.imwrite('img/{}.jpg'.format(c), frame)print(c)c += 1if not success:print('video is all read')break
可以分享一点我生成一些效果样本
样例1
结论
- 做这两个样本时我都是默认20的阈值没有细微调整,看效果都还挺不错,后期阈值细微上的调整可以使得重复的图片不是很多,各个角度的样本图都会有一些
总结
- 以后优化猜想,在阈值方面做成可以自适应的,先统计全部的阈值放到set集合里面,再按照由小到大排序放入list,我猜想阈值一般在list长度的5/7左右附近,或是各位有更好的什么优化思路可以和我交流一波
- 以上就是全部内容,有什么不对的地方请尽管指出,我会马上修改,有什么疑问也可以在评论区评论,我都会解答
- 对你有帮助或是喜欢的朋友可以帮忙点个赞谢谢
视频截帧大概率避免连续重复图片相关推荐
- 用opencv抽取视频的帧并保存为连续的图片
转自http://blog.csdn.net/timidsmile/article/details/8283319 #include"stdafx.h" #include < ...
- 实战 | 基于 Serverless 技术的视频截帧架构如何实现?
前言 视频直播是一种创新的在线娱乐形式,具有多人实时交互特性,在电商.游戏.在线教育.娱乐等多个行业都有着非常广泛的应用.随着网络基础设施的不断改善以及社交娱乐需求的不断增长,视频直播在持续渗透进大家 ...
- 华为云获取OBS中视频截帧图片
华为云获取OBS中视频截帧图片 华为云的文档比较少,想要用到阿里云的视频截帧功能,找了半天没找到.最后跟客服沟通后,拿到了这个文档,完美解决(注:获取截帧图片请用视频原始链接不要用cdn的链接) 步骤 ...
- 基于FFmpeg和Wasm的Web端视频截帧方案
作者 | 小萱 导读 基于实际业务需求,介绍了自定义Wasm截帧方案的实现原理和实现方案.解决传统的基于canvas的截帧方案所存在的问题,更高效灵活的实现截帧能力. 全文10103字,预计阅读时间2 ...
- python 摄像头录制帧率_实践:用python实现把视频以帧数输出成连续的多图片
在处理图像的时候,如果获取了一个视频,想把视频以帧数输出成连续的多图片构成图像数据集. 有人就想问什么软件可以把一段电影视频的每一帧连续自动保存成图片? 其实用很短的python程序就能快速实现该功能 ...
- 视频截帧:javacv实现视频截帧功能
javacv实现视频截帧功能 引入依赖 使用 引入依赖 <dependency><groupId>org.bytedeco</groupId><artifac ...
- qt制作简易视频截帧软件
qt制作简易视频截帧软件 1.视频进度条滑动参考 https://blog.csdn.net/zong596568821xp/article/details/78991397?spm=1001.201 ...
- 学习笔记二:OSS上传视频截帧
简介 这章主要是上传视频截帧,公司需求对动态上传需求是OSS上传和截帧(最开始时没有需求,自己用的是FFmpeg 多媒体处理工具截取的),最后因为服务器上没有FFmpeg 工具,导致上传docker报 ...
- javaCV - 视频截帧,清晰度调整,转gif,视频转音频
最近有视频处理的需求,自己调研javaCV. 官网没有详细的API,各种轮子翻遍了也没找到几个有用的,以下是自己整理一些视频处理功能:截取视频指定帧生成gif,将图片旋转指定度,截取视频指定帧保存为指 ...
最新文章
- 10年工作经验老程序员推荐的7个开发类工具
- PyTorch 版 EfficientDet 比官方 TF 实现快 25 倍?这个 GitHub 项目数天狂揽千星
- 关键词词云怎么做_制作CVPR 热词云(并爬取pdf地址 名称)
- oracle备份 ram,Oracle备份时出现AIX系统的3D32B80D错误
- 微软发布新的 Azure Pipelines 功能和集成
- java springmvc权限校验_详解Spring MVC使用Filter实现登录及权限验证判断
- eclipse IDE中無法打開android模擬器
- 我不捐了!日本前首富孙正义欲提供肺炎检测试剂遭网友攻击:被骂到放弃
- L1-017. 到底有多二-PAT团体程序设计天梯赛GPLT
- MYSQL中5.7.10ROOT密码及创建用户
- 【数字信号处理】基于matlab GUI IIR低通+FIR高通信号时域+频谱分析【含Matlab源码 1029期】
- Java .class 反编译 Luyten,导出 .java文件,查看jar 包目录,超级简单,实用
- 【JVM】尚硅谷宋红康JVM系列1:内存与垃圾回收篇
- 原装win10下安装双系统win7
- 电脑上查看自己连接的WIFI密码
- [青海、甘南之行散记] 当风吹过高原,一颗心在说话
- 2021-03-19Windows取消禁止驱动签名的方法
- java arraylist 添加_java ArrayList添加元素全部一样
- redis连接与关闭
- 银行购房按揭贷款利息计算