Processing Camera RAWs with OpenImageIO and Python

15 Sep 2014

I recently discovered the library OpenImageIO, an awesome tool for reading and writing image files. What makes this of particular interest is the sheer variety of image files supported (BMP, Cineon, JPG, JPG-2000, GIF, DPX, OpenEXR, Targa, TIFF) (as well as variety of camera raw formats) and the fact it can perform image transformations upon them very easily. Given it's designed for use in media and VFX environments it sounds like it will be useful for the type of work I've previously been involved with in stop motion.

Additionally, it comes with Python bindings, so you can do all of this without having to learn C++ if, like me, it's been 10 years since you last used it. It also means not having to resort to use of the commandline tools I've often used in the past for similar transformations.

Mac Installation

I'm on a mac and as such, brew is my weapon of choice for installing libraries. Unfortunately, openimageio is only available through a tap and an old version at that. I managed to compile outside of brew, but found that I couldn't get python to read the bindings correctly. I wanted to install a 1.5 version of the library, so found the best solution was to download the formula, modify it and tap homebrew/science to get the libraries it depends on. Your local openimageio formula takes precedence over the tapped version, so it won't get overwritten.

wget -O /usr/local/Library/Formula/openimageio.rb https://raw.githubusercontent.com/Homebrew/homebrew-science/master/openimageio.rb
brew tap homebrew/science

You can edit the formula here if required, using more recent version.

brew install openimageio

If all goes to plan, brew should install openimageio along with all dependencies. Additionally, I've edited my $DYLD_LIBRARY_PATH to include the path to the installation (/usr/local/Cellar/openimageio/1.5.3dev/lib).

Reading and Processing RAWs

OpenImageIO uses the ImageBuf class to handle representation and manipulation of images in memory and functions of the ImageBufAlgo class to transform them. It's best to demonstrate through some examples.

import OpenImageIO as oiio

# Read a camera raw, crop and write out to a tiff
buf = oiio.ImageBuf("Dino_001_01_X1_0066.cr2")
cropped = oiio.ImageBuf()
oiio.ImageBufAlgo.crop(cropped, buf, oiio.ROI(1208, 4901, 814, 2385))
cropped.write("cropped.tiff")

# Create a new larger buffer and paste the crop into it, vertically centred
extended = oiio.ImageBuf(oiio.ImageSpec (3693, 2077, 3, oiio.FLOAT))
oiio.ImageBufAlgo.paste(extended, 0, 253, 0, 0, cropped)

# Create a new buffer, resize the extended image to 1920x1080 and add some text
resized = oiio.ImageBuf(oiio.ImageSpec (1920, 1080, 3, oiio.FLOAT))
oiio.ImageBufAlgo.resize(resized, extended)
oiio.ImageBufAlgo.render_text(resized, 1300, 1030, "00066.cr2", 50, "Arial")
oiio.ImageBufAlgo.render_text(resized, 1600, 1030, "00:00:02:18", 50, "Arial")
resized.write("final.jpg")

THat ultimately takes the following lovely shot of a dino from RAW form to that with extended borders and burnt in information.

What's great about this is that we've used a single library to perform this series of transformations and we've not had to break out to use commandline operations to do so, instead manipulating them from the comfort of python.

Chaining commands

From using various javascript libraries (jQuery, Underscore), I've become used to the simplicity of being able to quickly chain a whole bunch of commands together. For that reason, I wrapped a number of the OpenImageIO ImageBufAlgo methods up into a single class OiioChain so that it's possible to perform the same set of above transformations using a somewhat more concise syntax. You can find it on github.

from oiio_chain import OiioChain

chain = OiioChain("Dino_001_01_X1_0066.cr2")

chain.crop(1208, 4901, 814, 2385)\
    .extend(3693, 2077).resize(1920, 1080)\
    .text(1300, 1030, "00066.cr2").text(1600, 1030, "00:00:02:18")\
    .write("final.jpg")

Displaying Images with Image Viewer

OpenImageIO even comes with it's own built in image viewer, to handle quick display of images or to incorporate viewing capabilities into your own software. You can access this from the terminal by using the executable "iv".

I'm really enjoying experimenting with OpenImageIO and am currently experimenting putting it into a service which performs on demand storage and transformation of media which I'll write about further at a later date. Currently, there's no means of being able to process stills into videos, for which further tools would be required, but I've heard word that work is ongoing to implement libav capabilities.

There's such a huge amount that's possible with the library which I've not covered and it should definitely be at the top of your list if you're looking at handling RAW media for your own projects.

Tagged openimageio, python, | Leave a comment