问题
I'm using OpenEXR to read EXR files in Python. I have R, G and B channels with Half data (float16). Using Numpy, I tried, unsuccessfully to convert the data from float16 to uint8 (0-255 colors).
rCh = getChanEXR(imageFile, 'R','HALF')
rCh = np.array(rCh).astype('uint8')
So, I put the R channel pixel values to a variable rCh. Then I convert the array.array to an np.array so that I can use the astype method to convert it to uint8. I am new to this, so I clearly do not have it right as all values become 0. Originally, the values are like this: 0.0, 2.9567511226945634e-14, 1.2295237050707897e-10 etc.
In addition to the float16 values, I also have some regular float values that need to be normalized. I think I need to normalize the float16 values before they can be set in a range from 0-255.
Any ideas? Thank you.
Adding the code for the def mentioned in here getChanEXR (just a custom def based on code from the python OpenEXR docs for getting channel data.
def getChanEXR(curEXRStr, curChannel, dataType):
#import OpenEXR, Imath, array
pt = 'none'
if dataType == 'HALF':
pt = Imath.PixelType(Imath.PixelType.HALF)
if dataType == 'FLOAT':
pt = Imath.PixelType(Imath.PixelType.FLOAT)
if dataType == 'UINT':
pt = Imath.PixelType(Imath.PixelType.UINT)
chanstr = OpenEXR.InputFile(curEXRStr).channel(curChannel, pt)
chan = array.array('f', chanstr)
return chan
回答1:
I haven't got much experience with array.array
but I believe you can convert it to a numpy float array so it's a bit easier to work with:
rCh = np.asarray(rCh, dtype=np.float)
If your data is normalized in [0,1]
multiply it by 255 before the conversion:
rCh = np.asarray(rCh * 255, dtype=np.uint8)
I believe it's truncating away the fractional part though. Manually rounding it should be safer? (not so sure, see discussion in the comments, I believe the correct approach will be dithering here, but I guess the matter deserves better research regarding your specific use case)
rCh = np.asarray(np.around(rCh * 255), dtype=np.uint8)
If it's not normalized you could just do
rCh -= rCh.min()
rCh /= rCh.max()
And then convert it to 8bits
rCh = np.asarray(rCh * 255, dtype=np.uint8)
来源:https://stackoverflow.com/questions/50324495/how-to-convert-float16-to-uint8-in-python-for-exr-files