0

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).

user877329
  • 6,717
  • 8
  • 46
  • 88
  • So, obviously that `read_image` thing reads a subarray of channels, from `channel` to `channel+1`. Same difference as `np.arange(20)[12]` being number `12` and `np.array(20)[12:13]` being the singleton array `[12]`. Why don't you just squeeze the result? (Or add a `[...,0]`). – chrslg Jul 30 '23 at 10:08
  • `pixels[channel] = inp.read_image(0, 0, channel, channel + 1, 'float')[:,:,0]` – chrslg Jul 30 '23 at 10:08
  • or `pixels[channel] = inp.read_image(0, 0, channel, channel + 1, 'float').squeeze()` – chrslg Jul 30 '23 at 10:09
  • Note that both solution cost nothing. It doesn't change, copy or move any data. Just a single metadata – chrslg Jul 30 '23 at 10:11

1 Answers1

0

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()
user877329
  • 6,717
  • 8
  • 46
  • 88