Colour - HDRI - Examples: Merge from Low Dynamic Range Files

Through this example, some Canon EOS 5D Mark II CR2 files converted to low dynamic range sRGB colourspace Tiff files will be merged together in order to create a single radiance image.

The following steps will be taken:

  • Conversion of the CR2 files to low dynamic range sRGB colourspace Tiff files using Dave Coffin's dcraw.
  • Creation of a camera response functions computation dedicated image stack using cherry picked Tiff files. The two files with lowest luminance are discarded as their contribution is biasing the resulting camera response functions.
    • Reading of the Tiff files Exif metadata using Phil Harvey's ExifTool.
    • Reading of the intermediate Tiff files pixel data using OpenImageIO.
  • Computation of the camera response functions.
  • Creation of an image stack using Tiff files.
  • Merging of the image stack into a radiance image using the camera response functions.
  • Display of the final resulting radiance image.

In [1]:
import glob
import logging
import matplotlib.pyplot as plt
import numpy as np
import os
import shlex
import subprocess

import colour
from colour.plotting import *

from colour_hdri import (
    EXAMPLES_RESOURCES_DIRECTORY,
    ImageStack,
    camera_response_functions_Debevec1997,
    filter_files,
    image_stack_to_radiance_image,
    weighting_function_Debevec1997)
from colour_hdri.plotting import plot_radiance_image_strip

logging.basicConfig(level=logging.INFO)

RESOURCES_DIRECTORY = os.path.join(EXAMPLES_RESOURCES_DIRECTORY,
                                   'frobisher_001')

colour.utilities.filter_warnings()

colour.utilities.describe_environment();


===============================================================================
*                                                                             *
*   Interpreter :                                                             *
*       python : 3.7.4 (default, Sep  7 2019, 18:27:02)                       *
*                [Clang 10.0.1 (clang-1001.0.46.4)]                           *
*                                                                             *
*   colour-science.org :                                                      *
*       colour : 0.3.14                                                       *
*       colour-hdri : v0.1.5-60-g9648d86                                      *
*                                                                             *
*   Runtime :                                                                 *
*       imageio : 2.6.1                                                       *
*       matplotlib : 3.0.3                                                    *
*       numpy : 1.17.3                                                        *
*       scipy : 1.3.1                                                         *
*       six : 1.12.0                                                          *
*       recordclass : 0.12.0.1                                                *
*                                                                             *
===============================================================================

In [2]:
colour_style();

CR2 Files Conversion to Tiff Files


In [3]:
RAW_FILES = filter_files(RESOURCES_DIRECTORY, ('CR2',))

for path in RAW_FILES:
    logging.info('Converting "{0}" to "Tiff" file...'.format(path))
    subprocess.call(['dcraw'] + shlex.split('-w -W -H 0 -q 3 -T "{0}"'.format(path)))

TIFF_FILES = sorted(glob.glob('{0}/*.tiff'.format(RESOURCES_DIRECTORY)))


INFO:root:Converting "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598.CR2" to "Tiff" file...
INFO:root:Converting "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2599.CR2" to "Tiff" file...
INFO:root:Converting "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.CR2" to "Tiff" file...
INFO:root:Converting "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.CR2" to "Tiff" file...
INFO:root:Converting "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.CR2" to "Tiff" file...

Camera Response Functions Computation


In [4]:
CRFS = camera_response_functions_Debevec1997(
    ImageStack.from_files(TIFF_FILES[2:5]))

CRFS = CRFS[np.all(CRFS, axis=1)]

CRFS = colour.utilities.linear_conversion(CRFS, (np.min(CRFS), 1), (0, 1))

plt.plot(CRFS)
plt.show();


INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff' image exif data.
/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/calibration/debevec1997.py:106: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
  x = np.squeeze(np.linalg.lstsq(A, b)[0])
/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/calibration/debevec1997.py:165: RuntimeWarning: overflow encountered in exp
  crfs = np.exp(tstack(np.array(g_c)))

Radiance Image Merge


In [5]:
def merge_from_ldr_files(
        ldr_files,
        output_directory,
        camera_response_functions,
        batch_size=5):
    paths = []
    for ldr_files in colour.utilities.batch(ldr_files, batch_size):
        image_stack = ImageStack.from_files(ldr_files)

        path = os.path.join(
            output_directory,
            '{0}_{1}_MLF.{2}'.format(
                os.path.splitext(os.path.basename(image_stack.path[0]))[0],
                batch_size,
                'exr'))
        paths.append(path)
        
        logging.info('Merging "{0}"...'.format(path))
        logging.info('\tImage stack "F Number" (Exif): {0}'.format(
            image_stack.f_number))
        logging.info('\tImage stack "Exposure Time" (Exif): {0}'.format(
            image_stack.exposure_time))
        logging.info('\tImage stack "ISO" (Exif): {0}'.format(
            image_stack.iso))
        image = image_stack_to_radiance_image(
            image_stack, camera_response_functions=camera_response_functions)
        image[np.isnan(image)] = 0

        logging.info('Writing "{0}"...'.format(path))
        colour.write_image(image, path)

    return paths

PATHS = merge_from_ldr_files(
    TIFF_FILES, RESOURCES_DIRECTORY, CRFS)


INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2599.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2599.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2599.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2600.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2601.tiff' image exif data.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff" image.
INFO:root:Reading "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff" image metadata.
INFO:root:Reading '/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2602.tiff' image exif data.
INFO:root:Merging "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598_5_MLF.exr"...
INFO:root:	Image stack "F Number" (Exif): [ 8.  8.  8.  8.  8.]
INFO:root:	Image stack "Exposure Time" (Exif): [  1.95300000e-03   1.56250000e-02   1.25000000e-01   1.00000000e+00
   8.00000000e+00]
INFO:root:	Image stack "ISO" (Exif): [ 100.  100.  100.  100.  100.]
/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/generation/radiance.py:130: RuntimeWarning: invalid value encountered in true_divide
  image_c /= weight_c
INFO:root:Writing "/Users/kelsolaar/Documents/Development/colour-science/colour-hdri/colour_hdri/resources/colour-hdri-examples-datasets/frobisher_001/IMG_2598_5_MLF.exr"...

Radiance Image Display


In [6]:
plot_radiance_image_strip(colour.read_image(PATHS[0]));