pythonnumpyopenimageio

Separating channels with OpenImageIO python


I want to render level curves from an image, and for that I need only one channel. When using read_image, it generates RGBRGBRGB, which is incompatible with matplotlib contour. From the documentation of ImageInput, it looks like I should be able to do the following:

pixels = numpy.zeros((spec.nchannels, spec.height, spec.width), "uint8")
for channel in range(spec.nchannels) :
    pixels[channel] = file.read_image(0, 0, channel, channel + 1, "uint8")

Since I am using float, my code now looks like this:

import OpenImageIO as oiio
import matplotlib.pyplot
import numpy

inp = oiio.ImageInput.open('test.exr')
if inp:
    spec = inp.spec()
    xres = spec.width
    yres = spec.height
    nchannels = spec.nchannels
    print(nchannels)
    pixels = numpy.zeros((spec.nchannels, spec.height, spec.width), 'float')
    for channel in range(spec.nchannels) :
        pixels[channel] = inp.read_image(0, 0, channel, channel + 1, 'float')
    inp.close()
    matplotlib.pyplot.contour(pixels[0], extent = [0, 49152, 0, 49252])
    matplotlib.pyplot.colorbar()
    matplotlib.pyplot.show()

But the example seems buggy:

Traceback (most recent call last):
  File "/home/torbjorr/Dokument/terraformer/experiments/levelcurves.py", line 14, in <module>
    pixels[channel] = inp.read_image(0, 0, channel, channel + 1, 'float')
ValueError: could not broadcast input array from shape (1024,1024,1) into shape (1024,1024)

The correct shape in my case is (1024,1024).


Solution

  • I found the solution. It appears that there is a bug in that documentation. Here is a working solution:

    import OpenImageIO as oiio
    import matplotlib.pyplot
    import numpy
    
    inp = oiio.ImageInput.open('test.exr')
    if inp:
        spec = inp.spec()
        xres = spec.width
        yres = spec.height
        nchannels = spec.nchannels
        pixels = inp.read_image(0, 0, 0, nchannels, 'float')
        print(pixels[:, :, 0].ndim)
        inp.close()
        levels = numpy.linspace(0, 8192 + 512, 18)
        matplotlib.pyplot.contour(numpy.flipud(pixels[:, :, 0]), levels, extent = [0, 49152, 0, 49252], cmap='tab10')
        matplotlib.pyplot.colorbar()
        matplotlib.pyplot.show()