Пиксели, извлеченные из узла просмотра в Blender, темнее, чем фактически отрисованное изображение… Почему?

#python #blender #bpy

#питон #blender #bpy

Вопрос:

Я пытаюсь создать конвейер, в котором я сначала визуализирую изображение с помощью API blender python (я использую Blender 2.90), а затем выполняю некоторую обработку изображений на python. Я хочу извлечь изображение непосредственно из Blender, не записывая предварительно обработанное изображение на диск, а затем не загружая его снова. Для этого я запустил следующий код в графическом интерфейсе Blender:

 import bpy
import numpy as np
import PIL.Image as Image 
from skimage.util import img_as_ubyte 

resolution_x = 512
resolution_y = 512

# render settings
scene = bpy.context.scene
scene.render.engine = 'BLENDER_EEVEE'
scene.render.resolution_x = resolution_x
scene.render.resolution_y = resolution_y
scene.render.image_settings.file_format = 'PNG'
scene.render.filepath = "path/to/good_image.png"

# create Viewer Layer in Compositor
scene.use_nodes = True
tree = scene.node_tree 
nodes = tree.nodes
links = tree.links

for node in nodes:
    nodes.remove(node)

render_layer_node = nodes.new('CompositorNodeRLayers')
viewer_node = nodes.new('CompositorNodeViewer')

links.new(viewer_node.inputs[0], render_layer_node.outputs[0])

# render scene and get pixels from Viewer Node
bpy.ops.render.render(write_still=True) 
pixels = bpy.data.images['Viewer Node'].pixels

# do some processing and save
img = np.flip(img_as_ubyte(np.array(pixels[:]).reshape((resolution_y, resolution_x, 4))), axis=0)
Image.fromarray(img).save("path/to/bad_image.png")
 

Проблема: изображение, которое я получаю с узла просмотра, намного темнее (плохое изображение), чем изображение, сохраненное обычным способом (хорошее изображение). У кого-нибудь есть идеи, почему это происходит и как это исправить? Может быть, blender обрабатывает значения пикселей иначе, чем я ожидаю?

Некоторая дополнительная информация: Перед преобразованием в uint8 значения альфа-канала в темном изображении равны 1.0 (как и должно быть на самом деле). Значения фона на темном изображении не равны 0,0 или отрицательны (как можно было бы догадаться по внешнему виду), а равны 0,05…

Что я пробовал: я думал, что пиксели могут быть масштабированы в диапазоне от -1 до 1, поэтому я изменил масштаб пикселей в диапазоне от 0 до 1 перед преобразованием в uint8… Также не привело к правильному изображению : (

Ответ №1:

Это потому, что изображение, которое вы получаете из Viewer Node , — это изображение «прямо из компоновки» до того, как произойдет управление цветом. Вы можете ознакомиться с документацией здесь: это изображение все еще находится в линейном пространстве.

Ваш good_image.png , с другой стороны, получается после преобразования в «Пространство отображения» (см. Диаграмму в документе). Следовательно, он был преобразован в логарифмическое пространство, возможно, с гамма-коррекцией и т. Д.

Наконец, вы можете получить изображение, близкое (но немного отличающееся) к хорошему изображению с узла просмотра, вызвав bpy.data.images['Viewer Node'].save_render(filepath) вместо этого, но нет способа напрямую извлечь версию с управлением цветом без предварительного рендеринга в файл. Вероятно, вы можете сделать это сами, добавив PyOpenColorIO в свой скрипт и применив управление цветом из этого модуля.