背景:
谁掌握了视频,谁就掌握了流量,谁掌握了流量,谁就掌握了金钱。在我们IT行业的很多部门都有涉及到视频,包括视频的制作,图片转视频,视频转图片等等。而我就有一部分工作就是测试合成视频这款工具的功能,其中有50多款视频合成模板,版本测试期间这款工具都是正常的,但是难免之后会出故障,所以平时也需要进行回归测试,如果手动进行回归,将是一个很大的工作量,所以自动化回归视频测试判断就孕育而生了。
简介:
主思想是:从视频中抽取部分帧进行对比,如果每一帧都一样,那么我们就可以认为这两个视频是一样的。在我的业务中就是合成的视频和标准的视频一样,那么就是我们的工具没有问题。
核心技术:
视频抽帧
图片对比(有两种方式)
一、视频抽帧
下面的为每隔200帧则写一帧到我们的本地文件中,当所有视频帧都读取完成后success则变成False,然后读帧结束,帧的图片名为四位数,如:1000.jpg、1001.jpg,1002.jpg
'''视频抽帧'''
cap = cv2.VideoCapture('c:/1/1.mp4')
# 第几帧
frame_count = 1
# 隔着多少帧取一张
frame_rate = 200
success = True
# 计数
num = 0
while (success):
#cap.read()进行读,cv2.imwrite()进行写,当读结束时,success变成False
success, frame = cap.read()
if success == True:
if frame_count % frame_rate == 0:
cv2.imwrite('c:/2/' + "%03d.jpg" % num, frame)
num += 1
frame_count = frame_count + 1
二、图片对比
方式一、使用math.sqrt就可对比两张图片,返回值是0.0则是图片一样,否则就是图片不一样
方式二、使用np.any(cv2.subtract(image1,imge2))就可对比两张图片,返回值是True则图片一样、
返回False就表示图片不一样
'''图片对比'''
#方式一
#使用对比两张图片的差值判断图片是否相同,值为0则相同,值越大则差异越大
image1 = Image.open(c:\2\1.jpg)
image2 = Image.open(c:\2\2.jpg)
histogram1 = image1.histogram()
histogram2 = image2.histogram()
differ = math.sqrt(reduce(operator.add, list(map(lambda a,b: (a-b)**2,histogram1, histogram2)))/len(histogram1))
if differ>0 or differ<0:
print('两张图片不一样')
if differ==0:
print('两张图片一样')
#方式二
#判断两张图片是否有差异,有差异则把差异的部分合成一张图片,用于观察差异的部分
image1 = cv2.imread(c:\2\1.jpg)
image2 = cv2.imread(c:\2\1.jpg)
difference = cv2.subtract(image1, image2)
result = not np.any(difference) # if difference is all zeros it will return False
if result is True:
print('图片一样')
else:
cv2.imwrite("c:\difference\result.jpg", difference)
return False
三、具体代码
以下是我自己封装的代码,适合于自动对比和识别dect文件夹里和source文件夹里的视频的一致性,(注:dect文件夹里的视频和source文件夹的视频名字格式需要一样)
# coding=utf-8
import os
import shutil
import cv2
import cv2
import numpy as np
from PIL import Image
import math
import operator
from functools import reduce
'''此方法用于视频切割为图片,入参为切割的视频地址和输出的图片地址'''
def videoImage(dir_vieo,dir_image):
# mp4存放的路径
videos_src_path = dir_vieo
# 保存的路径,会在路径下创建mp4文件名的文件夹保存图片
videos_save_path = dir_image
#获取目标文件夹得视频列表,方便下面遍历
videos = os.listdir(videos_src_path)
for each_video in videos:
print('Video Name :', each_video)
# get the name of each video, and make the directory to save frames
each_video_name, _ = each_video.split('.')
url = videos_save_path + '/' + each_video_name
if os.path.exists(url):
# image的文件夹作为临时存储容器,清空用于保持文件夹得简洁性
shutil.rmtree(url)
os.mkdir(url)
each_video_save_full_path = os.path.join(videos_save_path, each_video_name) + '/'
# get the full path of each video, which will open the video tp extract frames
each_video_full_path = os.path.join(videos_src_path, each_video)
#cv2.VideoCapture()是用于从视频文件、图片序列、摄像头捕获视频并返回为cap对象
cap = cv2.VideoCapture(each_video_full_path)
# 第几帧
frame_count = 1
# 隔着多少帧取一张
frame_rate = 200
success = True
# 计数
num = 0
while (success):
#cap.read()进行读,cv2.imwrite()进行写,当读结束时,success变成False
success, frame = cap.read()
if success == True:
if frame_count % frame_rate == 0:
cv2.imwrite(each_video_save_full_path + each_video_name + "%03d.jpg" % num, frame)
num += 1
frame_count = frame_count + 1
print('image numbers:', num)
'''使用对比两张图片的差值判断图片是否相同,值为0则相同,值越大则差异越大'''
def compare(pic1,pic2):
'''
:param pic1: 图片1路径
:param pic2: 图片2路径
:return: 返回对比的结果
'''
if os.path.exists(pic1):
pass
else:
raise IOError(f'图片不存在,请您仔细观察路径是否填写错误{pic1}')
if os.path.exists(pic2):
pass
else:
raise IOError(f'图片不存在,请您仔细观察路径是否填写错误{pic2}')
image1 = Image.open(pic1)
image2 = Image.open(pic2)
histogram1 = image1.histogram()
histogram2 = image2.histogram()
differ = math.sqrt(reduce(operator.add, list(map(lambda a,b: (a-b)**2,histogram1, histogram2)))/len(histogram1))
if differ>0 or differ<0:
return False
if differ==0:
return True
'''判断两张图片是否有差异,有差异则把差异的部分合成一张图片,用于观察差异的部分'''
def equalImage(file1,file2):
if os.path.exists(file1):
pass
else:
raise IOError(f'图片不存在,请您仔细观察路径是否填写错误{file1}')
if os.path.exists(file2):
pass
else:
raise IOError(f'图片不存在,请您仔细观察路径是否填写错误{file2}')
image1 = cv2.imread(file1)
image2 = cv2.imread(file2)
difference = cv2.subtract(image1, image2)
result = not np.any(difference) # if difference is all zeros it will return False
if result is True:
return True
else:
cv2.imwrite("./difference/result.jpg", difference)
return False
下面是总方法,用于调用上面的方法
'''此方法用于对比两个视频是否相同,为了清晰地说明技术,所以两个对比的视频名字需要一样'''
def equalsVideoVideo():
dir_vs = './video/source'
dir_is = './image/source'
dir_vd = './video/dect'
dir_id = './image/dect'
#使用自定义的方法对视频进行切割成多个图片
videoImage(dir_vs,dir_is)
videoImage(dir_vd,dir_id)
#遍历视频,对每个视频产生的图片进行对比
for video in os.listdir(dir_vs):
video_name,_ = video.split('.')
source_list = os.listdir(f'{dir_is}/{video_name}')
dect_list = os.listdir(f'{dir_id}/{video_name}')
result = True
for file1,file2 in zip(source_list,dect_list):
result = compare(dir_is+'/'+video_name+'/'+file1,dir_id+'/'+video_name+'/'+file2)
if result == False:
result = False
if result:
print(f'两个视频:{video_name}.mp4一样')
else:
print(f'两个视频:{video_name}.mp4不一样')
if __name__ == '__main__':
equalsVideoVideo()
测试人员使用python批量对比两个视频是否一致篇结束,欢迎到我的主页观看其他技术类博客~