我使用Cycles渲染表面法线并以EXR格式存储结果。 EXR格式的值在[-1, 1]
范围内,这意味着我无法直接将值存储在PNG文件中。以下是我如何阅读.exr
文件并将值存储在numpy
数组中:
import OpenEXR, array, Imath
exrFile = OpenEXR.InputFile('normal.exr')
FLOAT = Imath.PixelType(Imath.PixelType.FLOAT)
(RGB) = [array.array('f', exrFile.channel(Chan, FLOAT)).tolist() for Chan in ("R", "G", "B") ]
normalNPArray = np.array(RGB)
normalNPArray = normalNPArray.reshape((3, resolution, resolution))
我将值标准化为如下,并将曲面法线存储为PNG图像:
normalNPArray += 1
normalNPArray /= 2
normalNPArray *= 255
normalNPArray = normalNPArray.astype(np.uint8)
im = Image.fromarray(normalNPArray.transpose(1, 2, 0), mode='RGB')
im.save('temp.png')
如果我只是忽略零以下的值(删除/注释前两行),我会得到以下结果:
但是,如果我直接将曲面Normal存储为PNG图像而不是EXR,我会得到以下结果:
我想知道,如何才能获得看起来像PNG渲染的可视化效果? Blender如何规范化这些值?
答案 0 :(得分:0)
我有一位朋友帮我这个,希望对你有用:
为渲染器或着色器制作法线贴图时,需要考虑以下因素:
人们可以阅读有关格式的信息并弄清楚。或者简单地获得现有的法线贴图,并直观地计算出格式。例如,如果工作地图看起来是浅蓝色,那么它们很可能在切线空间中,而世界空间则有更纯净的红色,绿色和蓝色。
大多数人使用切线空间法线贴图,因为它允许变形。我相信Blender会为您提供所有三个HERE
的选项注意: 我检查您存储的图像(图像1),背景不是0.如果原始图像具有-1背景,则应为零。所以你在代码中做错了。如果您发布EXR图像以便我可以进行一些测试,那将非常有用。
答案 1 :(得分:0)
在其中一条评论中提及keltar,结果表明,在将数组类型转换为0
时,Numpy不会自动将负值设置为uint8
。例如,假设我有一个numpy数组如下:
array([ 46.73017823, -250.31618571, -247.44416527, 97.52841554,
-204.92988386, 191.09452493, 103.15708521, -86.10470495,
46.211924 , -195.30653599, 240.44499889, -169.42729244,
210.44996545, -182.04892973, -166.20581924, -221.11524425,
164.79367242, -199.80888341, 94.1786936 , 43.45477102])
我原以为normalNPArray = normalNPArray.astype(np.uint8)
会自动将负值设置为0
,因为uint8
自然不支持负值。但是,将数组转换为np.uint8
会给我以下内容:
array([ 46, 6, 9, 97, 52, 191, 103, 170, 46, 61, 240, 87, 210,
74, 90, 35, 164, 57, 94, 43], dtype=uint8)
执行normalNPArray[normalNPArray < 0] = 0
然后将数组转换为np.uint8
将解决此问题。