【问题标题】:How to convert float16 to uint8 in Python for EXR files如何在 Python 中为 EXR 文件将 float16 转换为 uint8
【发布时间】:2018-10-23 18:28:52
【问题描述】:

我正在使用 OpenEXR 在 Python 中读取 EXR 文件。我有带有半数据(float16)的 R、G 和 B 通道。我尝试使用 Numpy 将数据从 float16 转换为 uint8(0-255 色),但未成功。

        rCh = getChanEXR(imageFile, 'R','HALF')
        rCh = np.array(rCh).astype('uint8')

因此,我将 R 通道像素值放入变量 rCh。然后我将 array.array 转换为 np.array,以便我可以使用 astype 方法将其转换为 uint8。我是新手,所以我显然不正确,因为所有值都变为 0。最初,这些值是这样的:0.0、2.9567511226945634e-14、1.2295237050707897e-10 等。

除了 float16 值之外,我还有一些常规的浮点值需要标准化。我想我需要标准化 float16 值,然后才能将它们设置在 0-255 的范围内。

有什么想法吗?谢谢。

添加这里提到的 def 的代码 getChanEXR(只是基于 python OpenEXR 文档中用于获取频道数据的代码的自定义 def。

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

【问题讨论】:

  • 感谢菲利波的回复。我认为您的答案是正确的,但是有一步使我无法做到。数据是 array.array 的形式,所以当我使用 min 或 max 时,它告诉我它不能与 array.array 一起使用。如果我使用 np.asarray 来转换它,所有的值都会变成 0。
  • 你应该规范化数据之前将其转换为np.uint8,你可以使用标准pythonmin()max()array.array或者你可以将它转换为一个 numpy 浮点数组,对其进行规范化,然后转换为 8 位
  • 什么是getChanEXR?它不会出现在 google search for openexr getchanexrOpenEXR documentation search for getChanEXR 中。
  • getChanEXR 只是我根据文档中的 openEXR python 代码创建的定义。这就是我获取频道数据的方式。 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

标签: python numpy data-conversion openexr


【解决方案1】:

我对@9​​87654321@ 没有太多经验,但我相信您可以将其转换为 numpy 浮点数组,这样使用起来会更容易一些:

rCh = np.asarray(rCh, dtype=np.float)

如果您的数据在 [0,1] 中进行了标准化,则在转换前将其乘以 255:

rCh = np.asarray(rCh * 255, dtype=np.uint8)

我相信它会截断小数部分。手动四舍五入应该更安全? (不太确定,请参阅 cmets 中的讨论,我相信正确的方法会在这里犹豫不决,但我想这件事值得针对您的特定用例进行更好的研究)

rCh = np.asarray(np.around(rCh * 255), dtype=np.uint8)

如果它没有标准化,你可以这样做

rCh -= rCh.min()
rCh /= rCh.max()

然后转成8bits

rCh = np.asarray(rCh * 255, dtype=np.uint8)

【讨论】:

  • 截断是正确的;舍入会引入错误,例如将 255.6 舍入到 256,然后由于 8 位溢出而变为 0。另外,array.array 是完全不同的数组类型。
  • 显然array.array 的困惑来自疯狂大师。目前尚不清楚我们正在使用哪种类型的数组。
  • @user2357112 嗯?如果您的数据在[0,1] 中标准化,则您不能拥有255.6
  • 嘘,哎呀。我以为你乘以 256,而不是 255。你应该乘以 256 并截断,而不是乘以 255 并四舍五入。乘以 255 和四舍五入不会将结果均匀地分箱。
  • @user2357112 很有趣,你有什么证明截断更好的参考吗?它是图像数据的特定内容吗,似乎违反直觉
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-12
  • 2022-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
相关资源
最近更新 更多