使用 Imatest IT 和 Python 实现 CPIQ 分析自动化

Imatest IT的Python 接口提供了一种简便的方法来调用 Imatest 的测试。本文将展示如何自动化 Imatest 的运行,以及如何收集和轻松处理这些测试结果。在本示例中,我们将针对三个光照等级运行五个 Imatest 模块,然后提取CPIQ质量损失指标。

开发环境

图片集

对于每台设备,我们在不同的光照强度下拍摄以下不同测试图表的图像:(注:完整细节将在2017年3月标准发布时提供)

运行所有测试

我们将这些图像收集到名为“DeviceX”的文件夹中后,定义照明条件,初始化Imatest IT库,并在该设备和其他一些设备上运行处理函数:

led5k = "5000KLED_1000lux"               # Light Levels
tl84 = "TL84_100lux"
tung = "Tung_10lux"
light_conditions = [led5k, tl84, tung]
imatest = ImatestLibrary()
phones = ['DeviceX',                     # Just for example...
          'DeviceY',
          'DeviceZ']
for phone in phones:
    calc_phone(phone)
 
imatest.terminate_library()

主处理脚本调用五个模块,收集它们的数据输出并将其保存到 JSON 文件中:

def calc_phone(phone):
    print('Calculating Metrics for '+phone+ ' *****************************')
    uniformity_results = uniformity(phone) # Uniformity
    multitest_results  = multitest(phone) # Multitest
    dotpattern_results = dotpattern(phone) # Dot Pattern
    esfriso_results    = esfriso(phone) # eSFR ISO
    random_results     = random(phone) # Random
 
    # Output data to disk
    file_name = os.path.join(images_dir, phone, phone + '.json')
    with open(file_name, 'w') as outfile:
        full_data = {'multitest'  : multitest_results,
                     'dotpattern' : dotpattern_results,
                     'esfriso' : esfriso_results,
                     'random' : random_results,
                     'uniformity' : uniformity_results}
        json.dump(full_data, outfile, indent=4, separators=(',',': '))
 
    return full_data

我们针对每种指定的照明条件调用 Imatest eSFR ISO 模块:

# eSFR ISO (ISO 12233:2014) is used to test Visual Noise (VN) 
# and Spatial Frequency Response (SFR)
def esfriso(base):
    global images_dir, ini_file, light_conditions, op_mode
    output = {}
    for light_source in light_conditions:
        print('Testing ' + base + ' eSFR ISO at ' + light_source)
        input_file = os.path.join(images_dir, base, base+'_eSFR_'+light_source+'.jpg')
        if os.path.exists(input_file) != True:
            raise Exception('File ' + input_file + 'not found!')
        print('opening ' + input_file)
        result = imatest.esfriso_json(input_file=input_file, root_dir=root_dir, 
                                      op_mode=op_mode, ini_file=ini_file)
        data = json.loads(result)
        output[light_source] = data['esfrisoResults'];
 
return output

实时更改 INI 文件

此处理过程中最困难的部分是手动更新 Multitest 调用中的区域选择,因为 Multitest 目前还没有 Colorchecker SG 目标的自动区域检测功能(即将推出……)。

在这种情况下,我们将 [sg] roi、nwid_save 和 nht_save 键替换为存储在 multicharts-rois.json 文件中的值:

{
"DeviceX_SG_5000KLED_1000lux.JPG": "468 417 2122 1578 468 1588 2102 397",
"DeviceX_SG_TL84_100lux.JPG":"482 376 2142 1571 482 1561 2157 376",
"DeviceX_SG_Tung_10lux.JPG":"386 336 2016 1492 401 1497 2021 321",
"width":"2592",
"height":"1936"
}

我们使用此脚本修改 INI 文件,以动态插入不同的设置:

import ConfigParser
 
def get_config(path): # Used make ConfigParser case sensitive
    config = ConfigParser.ConfigParser()
    config.optionxform=str  # make configparser preserve case
    try:
        config.read(os.path.expanduser(path))
        return config
     except Exception, e:
        log.error(e)
 
def setROI(roi,width,height):
    global ini_file
    imatestini = get_config(ini_file)
 
    imatestini.set('ccsg', 'roi', roi)
    imatestini.set('ccsg', 'nwid_save', width)
    imatestini.set('ccsg', 'nht_save', height)
    with open(tempINI, 'w') as outfile:
        imatestini.write(outfile)
    return

Imatest 的 INI 文件区分大小写。请确保任何 INI 文件修改工具都能保留节和键的大小写。

然后,在我们的 multicharts 函数调用中,使用从 JSON 文件加载的值来调用这些函数:

roi_overrides = {}
roi_overrides_lower = {}
roi_override_file = os.path.join(images_dir,base,'multicharts-rois.json')
if os.path.exists(roi_override_file):
    with open(roi_override_file,'r') as fh: # read ROI override file
        roi_overrides = json.load(fh)
    for override, rois in roi_overrides.iteritems(): # convert to lowercase
        roi_overrides_lower[override.lower()] = rois
else:
    raise Exception('ROI override file ' + roi_override_file + ' not found.')
 
if image_file.lower() in roi_overrides_lower:
     setROI(roi_overrides_lower[image_file.lower()], roi_overrides['width'], roi_overrides['height'])
     selectedINI = tempINI
else:
     raise Exception('Missing ROI override for ' + image_file)

提取分数

最后,我们提取关键绩效指标 (KPI),这些指标均以感知质量损失 (QL) 表示,单位为最小可觉差 (JND)。此脚本篇幅较长,不适合在此文中讨论,如果您感兴趣,请在 Github 上查看源代码。

以下是计算出的指标集(JSON 格式):

{ 'DeviceX': 
    { 'CL_QL': { '5000KLED_1000lux': 0.9142,
                 'TL84_100lux': 0.1803,
                 'Tung_10lux': 2.565},
      'CU_QL': 0.07498,
      'LCD_QL': 0,
      'LGD_QL': 0,
      'SFR_QL': { '5000KLED_1000lux': 0.0,
                  'TL84_100lux': 0.1969,
                  'Tung_10lux': 0.3946},
      'TB_QL': { '5000KLED_1000lux': 1.2,
                 'TL84_100lux': 6.25,
                 'Tung_10lux': 9.1},
      'VN_QL': { '5000KLED_1000lux': 1.113,
                 'TL84_100lux': 2.409,
                 'Tung_10lux': 8.531}},
      'Combined_QL': 11.0245
}

一旦IEEE 合格评定计划最终确定了测试程序和综合评分计算方法,这些输出结果将被合并成一个简单的拍照手机评分。

该示例的完整 Python 源代码已发布在 GitHub 上。

要将这些自动化功能添加到您现有的 Imatest Master 许可证中,请升级到Imatest Ultimate 。您也可以申请 Imatest IT 的30 天免费试用版,以便在购买前了解其功能是否适合您。

相关网络研讨会