Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Once we have these images collected in a folder named “DeviceX”, we define our lighting conditions, initialize the Imatest IT library and run our processing function on this and a number of other devices:

Code Block
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()

The main processing script invokes the five modules, collects their data outputs and saves them to a JSON file:

Code Block
languagepy
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

We call the Imatest eSFR ISO module for each specified lighting condition:

Code Block
languagepy
# 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

On the fly INI file changes

...

In this case, we are we replacing the [sg] roi, nwid_save, and nht_save keys with the values stored in this multicharts-rois.json file:

Code Block
languagejson
{
"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"
}

We use this script to modify INI files to dynamically insert different settings:

Code Block
languagepy
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
Note

Imatest INIs are case sensitive. Make sure any INI manipulator will preserve the case of sections and keys.

These functions are then called using the values loaded from the JSON file inside of our multicharts function call:

Code Block
languagepy
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)

Extracting Scores

Finally, we extract Key Performance Indicators (KPI), which are all in perceptual quality loss (QL) in units of just noticeable differences (JND).  This script is a bit long for this post, so view the source on Github if you are interested./

Here is the resulting set of calculated metrics in JSON format:

Code Block
languagejson
{ '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
}

...