Create a gist now

Instantly share code, notes, and snippets.

@figgis /vqm.py
Last active Mar 30, 2017

What would you like to do?
vqm 2 xlsx
#!/usr/bin/env python
#
# vqm Run and parse the output of mitsuLinuxMultithread.
# Generate a xlsx-file with all the data as well as a summary sheet.
# Tested on Linux only.
#
# USAGE: vqm path
#
# NOTE: YCbcr files needs to be adhere to the following naming convention:
# NAME_WIDTHxHEIGHT_FPS_...yuv
# Example: BQMall_832x480_60.yuv
#
# NOTE: mitsuLinuxMultithread must reside in the same folder as this python
# program
#
# Copyright (c) 2015 Fredrik Pihl, Fredrik.Pihl@axis.com
# Licensed under The MIT License (MIT)
#
# 24-Sep-2015 Fredrik Pihl Created this.
from __future__ import print_function
from StringIO import StringIO
import argparse
import glob
import numpy as np
import operator
import os.path
import pickle
import subprocess
import xlsxwriter
MAPPING = {
'frame': 0,
'blockiness': 1,
'spatialactivity': 2,
'letterbox': 3,
'pillarbox': 4,
'blockloss': 5,
'blur': 6,
'temporalact': 7,
'blackout': 8,
'freezing': 9,
'exposure': 10,
'contrast': 11,
'brightness': 12,
'interlace': 13,
'noise': 14,
'slice': 15,
'flickering': 16,
}
class VQM(object):
'''
VQM Class
'''
def __init__(self, path, numframes=None):
self.path = path
self.numframes = numframes
self.files = []
self.data = []
self.__get_files()
self.__gen_data()
# Uncomment line to generate a simple pickle file with all the data
#self.__end()
def __get_files(self):
'''
Do globbing to get all *.yuv files in path
'''
# Sort the file names to have a nice grouping in the output
self.files = sorted(glob.glob(os.path.join(self.path, '*.yuv')))
def __gen_data(self):
'''
Generate data structure for each file in self.files
'''
for i in self.files:
p, w, h, f = self.__extract_param(i)
self.__parse_data(p, self.__run_cmd(i, w, h, f, self.numframes))
@staticmethod
def __run_cmd(p, w, h, f, n):
'''
Run binary on each file
p - path
w - width
h - height
f - file
n - numframes
'''
if n is None:
cmd = ['./mitsuLinuxMultithread', str(p), str(w), str(h), str(f)]
else:
cmd = ['./mitsuLinuxMultithread',
str(p), str(w), str(h), str(f), str(n)]
try:
print('Parsing {} ...'.format(os.path.basename(p)))
result = subprocess.check_output(cmd)
except:
print('ERROR')
return result
def __parse_data(self, key, result):
'''
Parse the output from the binary and put into an array of dictionaries
'''
# Use the basename as the key
self.data.append(
(key, np.genfromtxt(
# StringIO(result), skip_header=5,skip_footer=1, unpack=True)
StringIO(result), skip_header=5, skip_footer=1)
)
)
def __debug(self):
'''
debug
'''
pass
def __end(self):
'''
Use this method to generate a pickle file of the
parsed data
'''
output = open('data.pkl', 'wb')
# Pickle dictionary using protocol 0.
pickle.dump(self.data, output)
output.close()
for i in self.data:
print(i[0])
@staticmethod
def __extract_param(path):
'''
Extract basename, width, height and fps from filename
'''
f = os.path.basename(path)
fields = f.split('_')
width, height = map(int, fields[1].split('x'))
fps = fields[2].split('.')[0]
return (f, width, height, fps)
def create_xlsx(self):
'''
Generate a xlsx workbook
'''
# Create an new Excel file and add a worksheet.
workbook = xlsxwriter.Workbook('vqm.xlsx')
header = sorted(MAPPING.items(), key=operator.itemgetter(1))
# loop over all entries in db and create a worksheet
# for all entries
sheets = len(self.data)
for sheet in range(sheets):
# Add worksheet
worksheet = workbook.add_worksheet()
# Write filename in cell A1
worksheet.write(0, 0, self.data[sheet][0])
# Write header
for col, x in enumerate(header):
worksheet.write(1, col, x[0])
lines = len(self.data[sheet][1])
for row in range(lines):
data = self.data[sheet][1][row]
for col, x in enumerate(data):
worksheet.write(row+2, col, x)
# loop over all entries in db and create a summary worksheet
worksheet = workbook.add_worksheet('summary')
# Widen the first column to make the text clearer.
width = max([len(f[0]) for f in self.data])
worksheet.set_column('A:A', width)
# Write header
for col, x in enumerate(header):
worksheet.write(0, col+1, x[0])
# Write summary data, i.e. average value of all columns
# for each sheet
sheets = len(self.data)
for sheet in range(sheets):
# Write filename in cell A1
worksheet.write(sheet+1, 0, self.data[sheet][0])
# Add summation formulas
startrow = 3
lines = len(self.data[sheet][1])
for col, x in enumerate(header):
c = chr(ord('A')+col)
formula = "=AVERAGE(Sheet{}{}{}{}:{}{})".format(
sheet+1, '!', c, startrow, c, startrow+lines-1)
worksheet.write_formula(sheet+1, col+1, formula)
# Write number of frames for each sequence
formula = "=MAX(Sheet{}{}{}{}:{}{})+1".format(
sheet+1, '!', 'A', startrow, 'A', startrow+lines-1)
worksheet.write_formula(sheet+1, 1, formula)
workbook.close()
def main():
'''
Main function
'''
parser = argparse.ArgumentParser(
description='Extract metrics from all YCbCr files in folder',
epilog="Example: ./vqm.py ~/yuvfolder")
parser.add_argument(
'path',
type=str,
help='Source file path, YCbCr 4:2:0')
parser.add_argument(
'-n',
'--numframes',
type=int,
help='Number of frames to analyze')
args = parser.parse_args()
vqm = VQM(**vars(args))
vqm.create_xlsx()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment