Examples

Simple

Easy to use function to run all the process at once

"""
Using the utility class Emva1288, process a descriptor file
print results and plot graphics
"""

import os
from emva1288.process import Emva1288
from emva1288.camera.dataset_generator import DatasetGenerator

# dir_ = '/home/work/1288/datasets/'
# fname = 'EMVA1288_ReferenceSet_001_CCD_12Bit/EMVA1288_Data.txt'
# fname = os.path.join(dir_, fname)

dataset_generator = DatasetGenerator(width=100,
                                     height=50,
                                     bit_depth=8,
                                     dark_current_ref=30)
fname = dataset_generator.descriptor_path

e = Emva1288(fname)
e.results()
e.plot()

Camera simulator

Use the camera simulator to capture images

import numpy as np
from emva1288.camera import Camera

c = Camera()

radiances = np.linspace(0, c.get_radiance_for(mean=200), num=20)
for radiance in radiances:
    img = c.grab(radiance)
    print(img.mean(), img.std())

Report

Generate a report

import emva1288
from emva1288 import process
from emva1288 import report
import os


def main(dataset_descripton_file,
         gain,
         black_level,
         bit_depth,
         steps
         ):
    # Load the dataset
    parser = process.ParseEmvaDescriptorFile(dataset_descripton_file)
    imgs = process.LoadImageData(parser.images)
    dat = process.Data1288(imgs.data)

    # Description of the setup
    setup = report.info_setup()
    setup['Standard version'] = emva1288.__standard_version__

    # Basic information
    basic = report.info_basic()
    basic['vendor'] = 'Simulation'
    basic['data_type'] = 'Single'
    basic['sensor_type'] = 'simulated sensor'
    basic['resolution'] = f'{dat.cols}x{dat.rows}'
    basic['model'] = 'Simulated camera'

    # Marketing information
    marketing = report.info_marketing()
    marketing['watermark'] = 'Example'

    # Initialize the report with the marketing data
    # Provide a non existent name for the output directory
    myreport = report.Report1288('myreport',
                                 marketing=marketing,
                                 setup=setup,
                                 basic=basic)

    # Operation point
    # bit_depth, gain, black_level, exposure_time, wavelength,
    # temperature, housing_temperature, fpn_correction,
    # summary_only

    op1 = report.info_op()
    op1['summary_only'] = False
    op1['camera_settings']['Gain'] = gain
    op1['camera_settings']['Black level'] = black_level
    op1['camera_settings']['Bit depth'] = f'{bit_depth} bits'
    op1['test_parameters']['Illumination'] = 'Variable with constant exposure time'
    op1['test_parameters']['Irradiation steps'] = steps

    # Add the operation point to the report
    # we can add as many operation points as we want
    # we pass the emva1288.Data1288 object to extract automatically all the results
    # and graphics
    myreport.add(op1, dat.data)

    # Generate the latex files
    myreport.latex()


if __name__ == '__main__':
    # Arguments used for dataset generation and report configuration
    gain = 0.1
    black_level = 29.4
    bit_depth = 12
    steps = 50

    # # Alternative 1: Load one test to add it as operation point
    # dir_ = '/path/to/emva1288/datasets/'
    # fname = 'EMVA1288_ReferenceSet_003_Simulation_12Bit/EMVA1288_Data.txt'
    # fname = os.path.join(dir_, fname)

    # Alternative 2: Generate a new test dataset
    from emva1288.camera.dataset_generator import DatasetGenerator

    dataset_generator = DatasetGenerator(width=640,
                                         height=480,
                                         K=gain,
                                         blackoffset=black_level,
                                         bit_depth=bit_depth,
                                         steps=steps,
                                         exposure_fixed=1000000,
                                         dark_current_ref=30)
    fname = dataset_generator.descriptor_path

    main(dataset_descripton_file=fname,
         gain=gain,
         black_level=black_level,
         bit_depth=bit_depth,
         steps=steps)

Module by module

EMVA1288 process calling all the modules

"""
Calling one by one the classes that compose the reference implementation
process a descriptor file, print the results and plot the graphics
"""

from emva1288 import process
from emva1288.camera.dataset_generator import DatasetGenerator

# dir_ = '/home/work/1288/datasets/'
# fname = 'EMVA1288_ReferenceSet_003_Simulation_12Bit/EMVA1288_Data.txt'

dataset_generator = DatasetGenerator(width=100, height=50, bit_depth=8,
                                     dark_current_ref=30)

# Parse the descriptor file
# parser = process.ParseEmvaDescriptorFile(os.path.join(dir_, fname))
parser = process.ParseEmvaDescriptorFile(dataset_generator.descriptor_path)

# Load images
imgs = process.LoadImageData(parser.images)

# Extract data from images
dat = process.Data1288(imgs.data)

# Compute the results
res = process.Results1288(dat.data)
res.print_results()

# Plot the graphics
plot = process.Plotting1288(res)
plot.plot()

Full capture simulation

Simulate the capture as it would be done in the lab.

import numpy as np
from emva1288.camera import Camera
from emva1288.process.routines import get_int_imgs
from emva1288 import process


def get_emva_blackoffset(cam):
    """Find the blackoffset to satifsfy EMVA1288 requirements"""
    bini = cam.blackoffset
    # Find black offset with a maximum of 0.5% of values at Zero
    bo = cam.blackoffsets[0]
    pixels = cam.width * cam.height
    for i in cam.blackoffsets:
        cam.blackoffset = i
        img = cam.grab(0)
        bo = i
        if np.count_nonzero(img) > pixels * .995:
            break
    cam.blackoffset = bini
    return bo


def get_emva_gain(cam):
    """Find the gain to satisfy EMVA1288 requirements"""
    gini = cam.K
    # Find gain with a minum temporal noise of 0.5DN
    g = cam.Ks[0]
    for gain in cam.Ks:
        cam.K = gain
        g = gain
        img1 = cam.grab(0).astype(np.int64)
        img2 = cam.grab(0).astype(np.int64)
        if (img1 - img2).std() > 0.5:
            break
    cam.K = gini
    return g


def get_temporal(cam, radiance):
    img1 = cam.grab(radiance)
    img2 = cam.grab(radiance)
    imgs = get_int_imgs((img1, img2))
    return {'sum': np.sum(imgs['sum']), 'pvar': np.sum(imgs['pvar'])}


def get_spatial(cam, radiance, L=50):
    imgs = []
    for i in range(L):
        imgs.append(cam.grab(radiance))
    return get_int_imgs(imgs)


data = {'temporal': {},
        'spatial': {},
        'width': None, 'height': None}


# Intialize the camera, here we can specify different image size
# or any other parameter that Camera allows
c = Camera(bit_depth=10,
           width=100,
           height=50)

# Fill the information
data['width'] = c.width
data['height'] = c.height

# Maximum exposure for test
exposure_max = 9000000

# Find the camera parameters for the test
c.exposure = exposure_max
c.blackoffset = get_emva_blackoffset(c)
c.K = get_emva_gain(c)

# Find the radiance that will saturate the camera at our maximum exposure time
saturation_radiance = c.get_radiance_for()

# Initialize the exposure for the spatial measure
exposure_spatial = None

# Loop through the exposures
for exposure in np.linspace(c.exposure_min, exposure_max, 100):
    c.exposure = exposure
    data['temporal'][exposure] = {}

    # For each exposure, take to measurements (bright, dark)
    for radiance in (saturation_radiance, 0.0):
        photons = c.get_photons(radiance)

        # Get the temporal data
        data['temporal'][exposure].setdefault(photons, {})
        data['temporal'][exposure][photons] = get_temporal(c, radiance)

        # Check if we are at the middle of the range, to set the spatial exp
        img = c.grab(radiance)
        if not exposure_spatial and (img.mean() > c.img_max / 2.):
            exposure_spatial = exposure

        # Get the spatial data
        if exposure_spatial == exposure:
            data['spatial'].setdefault(exposure, {})
            data['spatial'][exposure].setdefault(photons, {})
            data['spatial'][exposure][photons] = get_spatial(c, radiance)


# Process the collected data
dat = process.Data1288(data)
res = process.Results1288(dat.data, pixel_area=c.pixel_area)
res.print_results()
plot = process.Plotting1288(res)
plot.plot()

Custom plot

Add custom image to the generated plots

# This example shows how to extend/modify the plots generated

from emva1288.process import Emva1288
from emva1288.camera.dataset_generator import DatasetGenerator
from emva1288.process.plotting import Emva1288Plot, EVMA1288plots


# Create a plot
class PRNUImage(Emva1288Plot):
    name = 'PRNU Image'

    def plot(self, test):
        self.ax.imshow(test.spatial['avg'],
                       aspect='auto',
                       gid='%d:data' % test.id)


# Get a results object
dataset_generator = DatasetGenerator(width=100,
                                     height=50,
                                     bit_depth=8,
                                     dark_current_ref=30)
fname = dataset_generator.descriptor_path
e = Emva1288(fname)

######
# To plot only the PRNUImage
e.plot(PRNUImage)

#####
# To plot all plus PRNUImage
plots = EVMA1288plots + [PRNUImage]
e.plot(*plots)

Results exchange file generation

Create a results xml file for comparison

import os
from emva1288 import process

# specify the path to the image stack
dir_ = '/home/work/1288/datasets/EMVA1288_ReferenceSet_001_CCD_12Bit/'
fname = 'EMVA1288_Data.txt'
fname = os.path.join(dir_, fname)
fresult = 'EMVA1288_Result.xml'
fresult = os.path.join(dir_, fresult)

parser = process.ParseEmvaDescriptorFile(os.path.join(dir_, fname))
imgs = process.LoadImageData(parser.images)
dat = process.Data1288(imgs.data)

res = process.Results1288(dat.data)

res.print_results()
f = open(os.path.join(dir_, fresult), "wb")
f.write(res.xml())
f.close()

Results comparison

Compare two result files

import os
from emva1288 import process

# specify the path to the files to compare
dir_ = '/home/work/1288/datasets/EMVA1288_ReferenceSet_001_CCD_12Bit/'
fresult1 = 'EMVA1288_Result1.xml'
fresult2 = 'EMVA1288_Result2.xml'
fcompare = 'EMVA1288_Compare.txt'

u = process.routines.compare_xml(os.path.join(dir_, fresult1),
                                 os.path.join(dir_, fresult2),
                                 os.path.join(dir_, fcompare))
print(u)

Structure of the image data

Image data.

ipython