How to convert float16 to uint8 in Python for EXR files

放肆的年华 提交于 2020-06-25 05:41:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!