| #!/usr/bin/env python |
| ## Copyright (c) 2021, Alliance for Open Media. All rights reserved |
| ## |
| ## This source code is subject to the terms of the BSD 3-Clause Clear License and the |
| ## Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License was |
| ## not distributed with this source code in the LICENSE file, you can obtain it |
| ## at aomedia.org/license/software-license/bsd-3-c-c/. If the Alliance for Open Media Patent |
| ## License 1.0 was not distributed with this source code in the PATENTS file, you |
| ## can obtain it at aomedia.org/license/patent-license/. |
| ## |
| __author__ = "maggie.sun@intel.com, ryanlei@meta.com" |
| |
| import re |
| import os |
| import csv |
| import openpyxl |
| import xlsxwriter |
| import shutil |
| import Config |
| from Config import QPs, DnScaleRatio, CTC_ASXLSTemplate, CTC_RegularXLSTemplate, InterpolatePieces, \ |
| UsePCHIPInterpolation |
| import Utils |
| from Utils import ParseCSVFile, plot_rd_curve, Interpolate_Bilinear, Interpolate_PCHIP, convex_hull |
| import matplotlib.pyplot as plt |
| from matplotlib.backends.backend_pdf import PdfPages |
| from CalcBDRate import BD_RATE |
| from itertools import cycle |
| import numpy as np |
| import pandas as pd |
| from tabulate import tabulate |
| |
| CTC_RESULT_PATH = "..\\ctc_result" |
| |
| qtys = ["psnr_y", "psnr_u", "psnr_v", "overall_psnr", "ssim_y", "ms_ssim_y", |
| "vmaf", "vmaf_neg", "psnr_hvs","ciede2k", "apsnr_y", "apsnr_u", |
| "apsnr_v", "overall_apsnr"] |
| |
| csv_paths = { |
| "v1.0.0" : "%s\\AV2-CTC-v1.0.0-alt-anchor-r3.0" % (CTC_RESULT_PATH), |
| "v2.0.0" : "%s\\AV2-CTC-v2.0.0" % (CTC_RESULT_PATH), |
| "v3.0.0" : "%s\\AV2-CTC-v3.0.0" % (CTC_RESULT_PATH), |
| "v4.0.0" : "%s\\AV2-CTC-v4.0.0" % (CTC_RESULT_PATH), |
| "v5.0.0" : "%s\\AV2-CTC-v5.0.0" % (CTC_RESULT_PATH), |
| "v6.0.0" : "%s\\AV2-CTC-v6.0.0" % (CTC_RESULT_PATH), |
| "v7.0.0" : "%s\\AV2-CTC-v7.0.0" % (CTC_RESULT_PATH), |
| "v8.0.0" : "%s\\AV2-CTC-v8.0.0" % (CTC_RESULT_PATH), |
| } |
| |
| start_row = { |
| "AI": 2, |
| "AS": 2, |
| "RA": 2, |
| "Still": 2, |
| "LD": 50, |
| } |
| |
| formats = { |
| "v1.0.0": ['r', '-', 'o'], |
| "v2.0.0": ['g', '-', '*'], |
| "v3.0.0": ['b', '-', '^'], |
| "v4.0.0": ['g', '-', 'o'], |
| "v5.0.0": ['b', '-', '*'], |
| "v6.0.0": ['c', '-', 'o'], |
| "v7.0.0": ['r', '-', '+'], |
| "v8.0.0": ['g', '-', '^'], |
| } |
| |
| AS_formats = { |
| "3840x2160": ['r', '-.', 'o'], |
| "2560x1440": ['g', '-.', '*'], |
| "1920x1080": ['b', '-.', '^'], |
| "1280x720": ['y', '-.', '+'], |
| "960x540": ['c', '-.', 'x'], |
| "640x360": ['k', '-.', '<'], |
| } |
| |
| anchor = "v1.0.0" |
| rd_curve_pdf = "%s\\rdcurve.pdf" % (CTC_RESULT_PATH) |
| combined_rd_curve_pdf = "%s\\combined_rdcurve.pdf" % (CTC_RESULT_PATH) |
| combined_runtime_pdf = "%s\\combined_runtime.pdf" % (CTC_RESULT_PATH) |
| bdrate_summary = "%s\\Bdrate-Summary-AV1-vs-AV2.csv" % (CTC_RESULT_PATH) |
| avg_bdrate_by_tag_class = "%s\\AverageBdrateByTagClass-Summary-AV1-vs-AV2.csv" % (CTC_RESULT_PATH) |
| avg_bdrate_by_tag = "%s\\AverageBdrateByTag-Summary-AV1-vs-AV2.csv" % (CTC_RESULT_PATH) |
| per_video_bdrate = "%s\\PerVideoBdrate-Summary-AV1-vs-AV2.csv" % (CTC_RESULT_PATH) |
| avg_bdrate_by_tag_pdf = "%s\\AverageBdrateByTag-Summary-AV1-vs-AV2.pdf" % (CTC_RESULT_PATH) |
| avg_bdrate_by_tag_class_pdf = "%s\\AverageBdrateByTagClass-Summary-AV1-vs-AV2.pdf" % (CTC_RESULT_PATH) |
| per_video_bdrate_by_tag_class_pdf = "%s\\PerVideoBdrate-Summary-AV1-vs-AV2.pdf" % (CTC_RESULT_PATH) |
| |
| colors = cycle('bgrycmk') |
| markers = cycle('o*^+<x') |
| |
| def populate_stats_files(): |
| stats_files = {} |
| for tag in csv_paths.keys(): |
| stats_files[tag] = {} |
| for cfg in ["AI", "LD", "RA", "Still", "AS"]: |
| if cfg == "Still": |
| stats_files[tag][cfg] = os.path.join(csv_paths[tag], "RDResults_aom_av2_STILL_Preset_0.csv") |
| else: |
| stats_files[tag][cfg] = os.path.join(csv_paths[tag], "RDResults_aom_av2_%s_Preset_0.csv"%cfg) |
| return stats_files |
| |
| def WriteSheet(csv_file, sht, start_row): |
| csv = open(csv_file, 'rt') |
| row = start_row |
| for line in csv: |
| if not line.startswith('TestCfg'): |
| words = re.split(',', line.strip()) |
| col = 1 |
| for word in words: |
| mycell = sht.cell(row=row, column=col) |
| if col >= 12 and col <= 30 and word != "": |
| mycell.value = float(word) |
| else: |
| mycell.value = word |
| col += 1 |
| row += 1 |
| csv.close() |
| |
| |
| def FillXlsFile(): |
| for tag in csv_files.keys(): |
| if tag == anchor: |
| continue |
| else: |
| for cfg in csv_files[anchor].keys(): |
| anchor_sht_name = "Anchor-%s" % cfg |
| test_sht_name = "Test-%s" % cfg |
| if cfg == "AS": |
| xls_template = CTC_ASXLSTemplate |
| xls_file = "%s//CTC_AS_%s-%s.xlsm" % (CTC_RESULT_PATH, anchor, tag) |
| shutil.copyfile(xls_template, xls_file) |
| anchor_sht_name = "Anchor" |
| test_sht_name = "Test" |
| elif cfg == "AI": |
| xls_template = CTC_RegularXLSTemplate |
| xls_file = "%s//CTC_Regular_%s-%s.xlsm" % (CTC_RESULT_PATH, anchor, tag) |
| shutil.copyfile(xls_template, xls_file) |
| |
| wb = openpyxl.load_workbook(filename=xls_file, read_only=False, keep_vba=True) |
| anchor_sht = wb[anchor_sht_name] |
| anchor_csv = csv_files[anchor][cfg] |
| WriteSheet(anchor_csv, anchor_sht, start_row[cfg]) |
| |
| test_sht = wb[test_sht_name] |
| test_csv = csv_files[tag][cfg] |
| WriteSheet(test_csv, test_sht, start_row[cfg]) |
| |
| wb.save(xls_file) |
| |
| def DrawIndividualRDCurve(records, anchor, pdf): |
| with PdfPages(pdf) as export_pdf: |
| for cfg in records[anchor].keys(): |
| videos = records[anchor][cfg].keys() |
| for video in videos: |
| if cfg == "AS": |
| DnScaledRes = [(int(3840/ratio), int(2160/ratio)) for ratio in DnScaleRatio] |
| Int_RDPoints = {} |
| # draw individual rd curves |
| for tag in records.keys(): |
| Int_RDPoints[tag] = [] |
| record = records[tag][cfg][video] |
| plt.figure(figsize=(15, 10)) |
| plt.suptitle("%s : %s: %s" % (cfg, video, tag)) |
| |
| br = {}; apsnr = {} |
| for key in record.keys(): |
| res = re.split('_', key)[0] |
| if res not in br.keys(): |
| br[res] = [] |
| apsnr[res] = [] |
| br[res].append(record[key].bitrate) |
| apsnr[res].append(record[key].overall_apsnr) |
| |
| for res in br.keys(): |
| rdpnts = [(brt, qty) for brt, qty in zip(br[res], apsnr[res])] |
| if UsePCHIPInterpolation: |
| int_rdpnts = Interpolate_PCHIP(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| else: |
| int_rdpnts = Interpolate_Bilinear(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| Int_RDPoints[tag] += int_rdpnts |
| plot_rd_curve(br[res], apsnr[res], "overall_apsnr", res, "bitrate(Kbps)", |
| AS_formats[res][0], AS_formats[res][1], AS_formats[res][2]) |
| plt.legend(loc='lower right') |
| plt.grid(True) |
| export_pdf.savefig() |
| plt.close() |
| |
| #draw convex hull |
| plt.figure(figsize=(15, 10)) |
| plt.suptitle("%s : %s: convex hull" % (cfg, video)) |
| for tag in records.keys(): |
| lower, upper = convex_hull(Int_RDPoints[tag]) |
| br = [h[0] for h in upper] |
| apsnr = [h[1] for h in upper] |
| plot_rd_curve(br, apsnr, "overall_apsnr(dB)", tag, "bitrate(kbps)", |
| formats[tag][0], formats[tag][1], formats[tag][2]) |
| plt.legend(loc='lower right') |
| plt.grid(True) |
| export_pdf.savefig() |
| plt.close() |
| else: |
| # bit rate to quality |
| plt.figure(figsize=(15, 10)) |
| plt.suptitle("%s : %s" % (cfg, video)) |
| for tag in records.keys(): |
| record = records[tag][cfg][video] |
| br = [record[key].bitrate for key in record.keys()] |
| apsnr = [record[key].overall_apsnr for key in record.keys()] |
| plot_rd_curve(br, apsnr, "overall_apsnr(dB)", tag, "bitrate(kbps)", |
| formats[tag][0], formats[tag][1], formats[tag][2]) |
| plt.legend(loc='lower right') |
| plt.grid(True) |
| export_pdf.savefig() |
| plt.close() |
| |
| |
| def DrawCombinedRDCurve(records, pdf): |
| with PdfPages(pdf) as export_pdf: |
| for tag in csv_files.keys(): |
| for cfg in csv_files[tag].keys(): |
| videos = records[tag][cfg].keys() |
| plt.figure(figsize=(30, 30)) |
| plt.suptitle("%s : %s" % (tag, cfg)) |
| |
| for video in videos: |
| short_name = video.split('_')[0] |
| if cfg == "AS": |
| Int_RDPoints = [] |
| record = records[tag][cfg][video] |
| br = {}; |
| apsnr = {} |
| for key in record.keys(): |
| res = re.split('_', key)[0] |
| if res not in br.keys(): |
| br[res] = [] |
| apsnr[res] = [] |
| br[res].append(record[key].bitrate) |
| apsnr[res].append(record[key].overall_apsnr) |
| |
| for res in br.keys(): |
| rdpnts = [(brt, qty) for brt, qty in zip(br[res], apsnr[res])] |
| if UsePCHIPInterpolation: |
| int_rdpnts = Interpolate_PCHIP(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| else: |
| int_rdpnts = Interpolate_Bilinear(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| Int_RDPoints += int_rdpnts |
| |
| # draw convex hull |
| lower, upper = convex_hull(Int_RDPoints) |
| br = [h[0] for h in upper] |
| apsnr = [h[1] for h in upper] |
| plot_rd_curve(br, apsnr, "overall_apsnr(dB)", short_name, "bitrate(kbps)", |
| next(colors), '-', next(markers)) |
| else: |
| record = records[tag][cfg][video] |
| br = [record[key].bitrate for key in record.keys()] |
| apsnr = [record[key].overall_apsnr for key in record.keys()] |
| plot_rd_curve(br, apsnr, "overall_apsnr(dB)", short_name, "bitrate(kbps)", |
| next(colors), '-', next(markers)) |
| |
| plt.legend(loc='lower right') |
| plt.grid(True) |
| export_pdf.savefig() |
| plt.close() |
| |
| def DrawCombinedRuntime(records, pdf): |
| with PdfPages(pdf) as export_pdf: |
| for tag in csv_files.keys(): |
| for cfg in csv_files[tag].keys(): |
| if cfg == "RA": |
| continue |
| videos = records[tag][cfg].keys() |
| plt.figure(figsize=(30, 30)) |
| plt.suptitle("%s : %s" % (tag, cfg)) |
| |
| for video in videos: |
| short_name = video.split('_')[0] |
| if cfg == "AS": |
| record = records[tag][cfg][video] |
| br = {}; |
| enc_time = {} |
| for key in record.keys(): |
| res = re.split('_', key)[0] |
| if res not in br.keys(): |
| br[res] = [] |
| enc_time[res] = [] |
| br[res].append(record[key].bitrate) |
| enc_time[res].append(record[key].enc_time) |
| |
| for res in br.keys(): |
| plot_rd_curve(br[res], enc_time[res], "enc_time(s)", short_name+'_'+res, "bitrate(kbps)", |
| next(colors), '-', next(markers)) |
| else: |
| record = records[tag][cfg][video] |
| br = [record[key].bitrate for key in record.keys()] |
| enc_time = [record[key].enc_time for key in record.keys()] |
| plot_rd_curve(br, enc_time, "enc_time(s)", short_name, "bitrate(kbps)", |
| next(colors), '-', next(markers)) |
| |
| plt.legend(loc='lower right') |
| plt.grid(True) |
| export_pdf.savefig() |
| plt.close() |
| |
| def GetQty(record, key, qty): |
| if qty == 'psnr_y': |
| q = record[key].psnr_y |
| elif qty == 'psnr_u': |
| q = record[key].psnr_u |
| elif qty == 'psnr_v': |
| q = record[key].psnr_v |
| elif qty == 'overall_psnr': |
| q = record[key].overall_psnr |
| elif qty == 'ssim_y': |
| q = record[key].ssim_y |
| elif qty == 'ms_ssim_y': |
| q = record[key].ms_ssim_y |
| elif qty == 'vmaf': |
| q = record[key].vmaf_y |
| elif qty == 'vmaf_neg': |
| q = record[key].vmaf_y_neg |
| elif qty == 'psnr_hvs': |
| q = record[key].psnr_hvs |
| elif qty == 'ciede2k': |
| q = record[key].ciede2k |
| elif qty == 'apsnr_y': |
| q = record[key].apsnr_y |
| elif qty == 'apsnr_u': |
| q = record[key].apsnr_u |
| elif qty == 'apsnr_v': |
| q = record[key].apsnr_v |
| elif qty == 'overall_apsnr': |
| q = record[key].overall_apsnr |
| else: |
| assert(0) |
| return q |
| |
| def CalcBDRate(tag, cfg, cls, video, anchor, test): |
| bdrate = {}; anchor_qty = {}; test_qty = {} |
| br_anchor = []; br_test = [] |
| for key in anchor.keys(): |
| br_anchor.append(anchor[key].bitrate) |
| for key in test.keys(): |
| br_test.append(test[key].bitrate) |
| |
| for qty in qtys: |
| anchor_qty[qty] = []; test_qty[qty] = [] |
| for key in anchor.keys(): |
| anchor_qty[qty].append(GetQty(anchor, key, qty)) |
| for key in test.keys(): |
| test_qty[qty].append(GetQty(test, key, qty)) |
| |
| bdrate["tag"] = tag |
| bdrate["cfg"] = cfg |
| bdrate["class"] = cls |
| bdrate["video"] = video |
| |
| for qty in qtys: |
| (err, bd ) = BD_RATE(qty, br_anchor, anchor_qty[qty], |
| br_test, test_qty[qty]) |
| if err == 0: |
| bdrate[qty] = bd |
| else: |
| bdrate[qty] = 0.0 |
| return bdrate |
| |
| |
| def CalcConvexHull(record): |
| br = {}; quality = {} |
| cvx_hull = {} |
| |
| for key in record.keys(): |
| res = re.split('_', key)[0] |
| if res not in br.keys(): |
| br[res] = [] |
| quality[res] = {} |
| |
| br[res].append(record[key].bitrate) |
| for q in qtys: |
| if q not in quality[res].keys(): |
| quality[res][q] = [] |
| quality[res][q].append(GetQty(record, key, q)) |
| |
| for q in qtys: |
| Int_RDPoints = [] |
| for res in br.keys(): |
| rdpnts = [(brt, qty) for brt, qty in zip(br[res], quality[res][q])] |
| if UsePCHIPInterpolation: |
| int_rdpnts = Interpolate_PCHIP(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| else: |
| int_rdpnts = Interpolate_Bilinear(rdpnts, QPs['AS'][:], InterpolatePieces, True) |
| Int_RDPoints += int_rdpnts |
| |
| lower, upper = convex_hull(Int_RDPoints) |
| cvx_hull[q] = upper |
| |
| return cvx_hull |
| |
| def CalcASBDRate(tag, cfg, cls, video, anchor, test): |
| # first produce convex hull for each quality |
| convex_hull = {} |
| convex_hull['anchor'] = CalcConvexHull(anchor) |
| convex_hull['test'] = CalcConvexHull(test) |
| |
| # calculate bdrate for each quality metric |
| bdrate = {}; |
| bdrate["tag"] = tag |
| bdrate["cfg"] = cfg |
| bdrate["class"] = cls |
| bdrate["video"] = video |
| |
| for q in qtys: |
| br_anchor = list(zip(*convex_hull['anchor'][q]))[0] |
| br_test = list(zip(*convex_hull['test'][q]))[0] |
| quality_anchor = list(zip(*convex_hull['anchor'][q]))[1] |
| quality_test = list(zip(*convex_hull['test'][q]))[1] |
| |
| (err, bd ) = BD_RATE(q, br_anchor, quality_anchor, br_test, quality_test) |
| if err == 0: |
| bdrate[q] = bd |
| else: |
| bdrate[q] = 0.0 |
| return bdrate |
| |
| def CalcFullBDRate(anchor): |
| bdrate = []; seq_time = [] |
| for cfg in csv_files[anchor].keys(): |
| for video in records[anchor][cfg].keys(): |
| for tag in records.keys(): |
| record = records[tag][cfg][video] |
| time = 0; instr = 0 |
| for key in record.keys(): |
| time += record[key].enc_time |
| instr += record[key].enc_instr |
| video_class = record[key].file_class |
| |
| total_time = {} |
| total_time["tag"] = tag |
| total_time["cfg"] = cfg |
| total_time["class"] = video_class |
| total_time["video"] = video |
| total_time["time"] = time |
| total_time["instr"] = instr |
| |
| seq_time.append(total_time) |
| |
| if tag == anchor: |
| continue |
| if cfg == "AS": |
| bd = CalcASBDRate(tag, cfg, video_class, video, records[anchor][cfg][video], records[tag][cfg][video]) |
| else: |
| bd = CalcBDRate(tag, cfg, video_class, video, records[anchor][cfg][video], records[tag][cfg][video]) |
| bdrate.append(bd) |
| |
| return (bdrate, seq_time) |
| |
| |
| def WriteSummaryXlsFile(bdrate, seq_time, seq_instr, summary): |
| csv = open(summary+".csv", "wt") |
| csv.write('Video,mode') |
| for qty in qtys: |
| csv.write(',%s'%qty) |
| csv.write(",EncTime(s),EncInstr\n") |
| |
| wb = xlsxwriter.Workbook(summary + ".xlsx") |
| shts = [] |
| |
| for mode in csv_files.keys(): |
| total = {}; avg_bdrate = {} |
| sht = wb.add_worksheet(mode) |
| shts.append(sht) |
| row = 0; col = 0 |
| sht.write(row, 0, 'Video') |
| for qty in qtys: |
| col = qtys.index(qty) + 1 |
| sht.write(row, col, qty) |
| sht.write(row, col + 1, "EncTime(s)") |
| sht.write(row, col + 2, "EncInstr") |
| row = 1 |
| for video in bdrate.keys(): |
| csv.write("%s,%s"%(video, mode)) |
| for qty in qtys: |
| if mode == anchor: |
| csv.write(',0.0') |
| elif not str(bdrate[video][mode][qty]).startswith('Error'): |
| csv.write(',%f' % bdrate[video][mode][qty]) |
| else: |
| csv.write(',%s' % bdrate[video][mode][qty]) |
| |
| csv.write(",%f,%f\n" % (seq_time[video][mode], seq_instr[video][mode])) |
| |
| sht.write(row, 0, video) |
| for qty in qtys: |
| if not qty in total.keys(): |
| total[qty] = 0 |
| avg_bdrate[qty] = 0 |
| |
| if mode != anchor and not str(bdrate[video][mode][qty]).startswith('Error'): |
| total[qty] += 1 |
| avg_bdrate[qty] += bdrate[video][mode][qty] |
| |
| col = qtys.index(qty) + 1 |
| if mode == anchor: |
| sht.write(row, col, 0.00) |
| elif (mode in bdrate[video].keys()): |
| sht.write(row, col, bdrate[video][mode][qty]) |
| sht.write(row, col + 1, seq_time[video][mode]) |
| sht.write(row, col + 2, seq_instr[video][mode]) |
| row += 1 |
| row += 1 |
| for qty in qtys: |
| if total[qty] != 0: |
| avg_bdrate[qty] /= total[qty] |
| else: |
| avg_bdrate[qty] = 0.0 |
| |
| sht.write(row, 0, "Average") |
| for qty in qtys: |
| col = qtys.index(qty) + 1 |
| sht.write(row, col, avg_bdrate[qty]) |
| row += 1 |
| |
| wb.close() |
| csv.close() |
| |
| |
| def write_bdrate(bdrate, bdrate_csv): |
| # Open the CSV file for writing |
| with open(bdrate_csv, 'w', encoding='utf8', newline='') as csvfile: |
| fc = csv.DictWriter(csvfile, fieldnames=bdrate[0].keys(), ) |
| fc.writeheader() |
| fc.writerows(bdrate) |
| |
| def write_avg_bdrate(bdrate_csv, avg_bdrate_by_tag_csv, avg_bdrate_by_tag_class_csv, per_video_bdrate_csv): |
| df = pd.read_csv(bdrate_csv) |
| average_bdrate_by_tag_class = df.groupby(['tag', 'cfg', 'class']).agg({ |
| 'psnr_y': ['mean'], |
| 'psnr_u': ['mean'], |
| 'psnr_v': ['mean'], |
| 'overall_psnr': ['mean'], |
| 'ssim_y': ['mean'], |
| 'ms_ssim_y':['mean'], |
| 'vmaf':['mean'], |
| 'vmaf_neg':['mean'], |
| 'psnr_hvs':['mean'], |
| 'ciede2k':['mean'], |
| 'apsnr_y':['mean'], |
| 'apsnr_u':['mean'], |
| 'apsnr_v':['mean'], |
| 'overall_apsnr':['mean'] |
| }) |
| |
| fields_name = ['psnr_y','psnr_u','psnr_v','overall_psnr','ssim_y','ms_ssim_y','vmaf','vmaf_neg','psnr_hvs','ciede2k','apsnr_y','apsnr_u','apsnr_v','overall_apsnr'] |
| #print(average_bdrate_by_tag_class) |
| #print(tabulate(average_bdrate_by_tag_class, headers='keys', tablefmt='psql')) |
| |
| # Write output summary csv file |
| average_bdrate_by_tag_class.columns = fields_name |
| average_bdrate_by_tag_class.reset_index(inplace=True) |
| average_bdrate_by_tag_class.to_csv(avg_bdrate_by_tag_class_csv, index=False) |
| |
| average_bdrate_by_tag = df.groupby(['tag', 'cfg']).agg({ |
| 'psnr_y': ['mean'], |
| 'psnr_u': ['mean'], |
| 'psnr_v': ['mean'], |
| 'overall_psnr': ['mean'], |
| 'ssim_y': ['mean'], |
| 'ms_ssim_y': ['mean'], |
| 'vmaf': ['mean'], |
| 'vmaf_neg': ['mean'], |
| 'psnr_hvs': ['mean'], |
| 'ciede2k': ['mean'], |
| 'apsnr_y': ['mean'], |
| 'apsnr_u': ['mean'], |
| 'apsnr_v': ['mean'], |
| 'overall_apsnr': ['mean'] |
| }) |
| |
| #print(average_bdrate_by_tag) |
| #print(tabulate(average_bdrate_by_tag, headers='keys', tablefmt='psql')) |
| # Write output summary csv file |
| average_bdrate_by_tag.columns = fields_name |
| average_bdrate_by_tag.reset_index(inplace=True) |
| average_bdrate_by_tag.to_csv(avg_bdrate_by_tag_csv, index=False) |
| |
| average_bdrate_by_video = df.groupby(['cfg', 'class', 'video', 'tag']).agg({ |
| 'psnr_y': ['mean'], |
| 'psnr_u': ['mean'], |
| 'psnr_v': ['mean'], |
| 'overall_psnr': ['mean'], |
| 'ssim_y': ['mean'], |
| 'ms_ssim_y': ['mean'], |
| 'vmaf': ['mean'], |
| 'vmaf_neg': ['mean'], |
| 'psnr_hvs': ['mean'], |
| 'ciede2k': ['mean'], |
| 'apsnr_y': ['mean'], |
| 'apsnr_u': ['mean'], |
| 'apsnr_v': ['mean'], |
| 'overall_apsnr': ['mean'] |
| }) |
| |
| average_bdrate_by_video.columns = fields_name |
| average_bdrate_by_video.reset_index(inplace=True) |
| average_bdrate_by_video.to_csv(per_video_bdrate_csv, index=False) |
| |
| def plot_avg_bdrate_by_tag(avg_bdrate_by_tag_csv, avg_bdrate_by_tag_pdf): |
| df = pd.read_csv(avg_bdrate_by_tag_csv, index_col=0) |
| #print(df) |
| with PdfPages(avg_bdrate_by_tag_pdf) as export_pdf: |
| for cfg in df['cfg'].unique().tolist(): |
| for qty in ['overall_psnr', 'ssim_y', 'vmaf']: |
| ax = df[df['cfg']==cfg][qty].plot( |
| kind='bar', |
| figsize=(30, 15), |
| fontsize=20 |
| ) |
| ax.set_title("BDRATE-%s for %s" % (qty, cfg), fontsize=40) |
| ax.set_xlabel('Tag', fontsize=20) |
| ax.set_ylabel('BDRATE', fontsize=20) |
| for q in ax.containers: |
| ax.bar_label(q, fontsize=20) |
| plt.xticks(rotation=30, horizontalalignment="center") |
| plt.grid(True) |
| plt.show() |
| export_pdf.savefig() |
| plt.close() |
| |
| |
| def plot_avg_bdrate_by_tag_class(avg_bdrate_by_tag_class_csv, avg_bdrate_by_tag_class_pdf): |
| df = pd.read_csv(avg_bdrate_by_tag_class_csv, index_col=0) |
| print(df) |
| with PdfPages(avg_bdrate_by_tag_class_pdf) as export_pdf: |
| for cfg in df['cfg'].unique().tolist(): |
| print(df['class'].unique().tolist()) |
| for cls in df['class'].unique().tolist(): |
| for qty in ['overall_psnr', 'ssim_y', 'vmaf']: |
| selected_rows = df[(df['cfg']==cfg) & (df['class']==cls)] |
| if selected_rows.empty: |
| continue |
| print(selected_rows) |
| ax = selected_rows[qty].plot( |
| kind='bar', |
| figsize=(30, 15), |
| fontsize=20 |
| ) |
| ax.set_title("BDRATE-%s for %s class %s" % (qty, cfg, cls), fontsize=40) |
| ax.set_xlabel('Tag', fontsize=20) |
| ax.set_ylabel('BDRATE', fontsize=20) |
| for q in ax.containers: |
| ax.bar_label(q, fontsize=20) |
| plt.xticks(rotation=30, horizontalalignment="center") |
| plt.grid(True) |
| plt.show() |
| export_pdf.savefig() |
| plt.close() |
| |
| def plot_per_video_bdrate_by_tag_class(per_video_bdrate_csv, per_video_bdrate_by_tag_class_pdf): |
| df = pd.read_csv(per_video_bdrate_csv) |
| print(df) |
| with PdfPages(per_video_bdrate_by_tag_class_pdf) as export_pdf: |
| for cfg in df['cfg'].unique().tolist(): |
| for cls in df['class'].unique().tolist(): |
| for video in df['video'].unique().tolist(): |
| for qty in ['overall_psnr', 'ssim_y', 'vmaf']: |
| selected_rows = df[(df['cfg']==cfg) & (df['class']==cls) & (df['video']==video)] |
| if selected_rows.empty: |
| continue |
| print(selected_rows) |
| tags = selected_rows['tag'].unique().tolist() |
| idx = np.asarray([i for i in range(len(tags))]) |
| ax = selected_rows[qty].plot( |
| kind='bar', |
| figsize=(30, 15), |
| fontsize=20 |
| ) |
| ax.set_title("BDRATE-%s for %s class %s %s" % (qty, cfg, cls, video), fontsize=40) |
| ax.set_xlabel('Tag', fontsize=20) |
| ax.set_ylabel('BDRATE', fontsize=20) |
| for q in ax.containers: |
| ax.bar_label(q, fontsize=20) |
| ax.set_xticks(idx) |
| ax.set_xticklabels(tags, rotation=30, horizontalalignment="center") |
| plt.grid(True) |
| plt.tight_layout() |
| plt.show() |
| export_pdf.savefig() |
| plt.close() |
| ###################################### |
| # main |
| ###################################### |
| if __name__ == "__main__": |
| csv_files = populate_stats_files() |
| records = {} |
| for tag in csv_files.keys(): |
| records[tag] = {} |
| for test_cfg in csv_files[tag].keys(): |
| IgnorePerf = (test_cfg in ["RA", "AS"]) |
| records[tag][test_cfg] = ParseCSVFile(csv_files[tag][test_cfg], IgnorePerf) |
| |
| FillXlsFile() |
| |
| DrawCombinedRDCurve(records, combined_rd_curve_pdf) |
| DrawCombinedRuntime(records, combined_runtime_pdf) |
| DrawIndividualRDCurve(records, anchor, rd_curve_pdf) |
| |
| #Calculate BDRate and collect total time |
| (bdrate, seq_time) = CalcFullBDRate(anchor) |
| |
| write_bdrate(bdrate, bdrate_summary) |
| |
| write_avg_bdrate(bdrate_summary, avg_bdrate_by_tag, avg_bdrate_by_tag_class, per_video_bdrate) |
| |
| plot_avg_bdrate_by_tag(avg_bdrate_by_tag, avg_bdrate_by_tag_pdf) |
| |
| plot_avg_bdrate_by_tag_class(avg_bdrate_by_tag_class, avg_bdrate_by_tag_class_pdf) |
| |
| plot_per_video_bdrate_by_tag_class(per_video_bdrate, per_video_bdrate_by_tag_class_pdf) |