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