Проблемы с отображением обычных проходов из каналов EXR в RGB в скрипте PythonPython

Программы на Python
Ответить
Anonymous
 Проблемы с отображением обычных проходов из каналов EXR в RGB в скрипте Python

Сообщение Anonymous »

Проблема
Я работаю над сценарием Python для создания изображений из данных канала EXR для более крупного проекта, требующего точного сопоставления нормальных проходов. Скрипт обрабатывает каналы X, Y и Z из файла EXR и сопоставляет их с каналами RGB полученного изображения. Однако в выходном изображении наблюдаются значительные артефакты и искажения, из-за чего отображение нормального прохода становится неверным по сравнению с ожидаемым результатом.

Минимально воспроизводимый пример:

Вот минимальный пример сценария, демонстрирующий проблему. Этот скрипт предназначен для запуска в среде Python Blender. Он использует OpenEXR для чтения 16-битного файла EXR, обрабатывает обычный проход и сохраняет результат в виде PNG-изображения с помощью Pillow. Вы можете использовать этот 16-битный EXR: https://wetransfer.com/downloads/2855df ... 843/0172f8

Код: Выделить всё

import bpy
import OpenEXR
import Imath
import numpy as np
from PIL import Image
import os

def process_normal_pass(exr_path, output_path):
# Open EXR file
exr = OpenEXR.InputFile(exr_path)
header = exr.header()
channels = header['channels']

# Get image dimensions
dw = header['dataWindow']
width = dw.max.x - dw.min.x + 1
height = dw.max.y - dw.min.y + 1

# Process Normal Pass channels (assuming 16-bit)
channel_data = []
for channel in ['X', 'Y', 'Z']:
full_channel_name = f'ViewLayer.Normal.{channel}'
pixel_type = Imath.PixelType(Imath.PixelType.HALF)  # 16-bit
channel_str = exr.channel(full_channel_name, pixel_type)
channel_array = np.frombuffer(channel_str, dtype=np.float16).reshape(height, width)
channel_data.append(channel_array)

# Convert normal vectors to RGB colors
x, y, z = channel_data

# Normalize the vectors
magnitude = np.sqrt(x*x + y*y + z*z)
magnitude = np.where(magnitude > 0, magnitude, 1)
x = x / magnitude
y = y / magnitude
z = z / magnitude

# Map normal components to RGB (world space)
r = np.abs(x)  # X component to Red
g = np.zeros_like(y)  # Suppress green channel
b = np.abs(z)  # Z component to Blue

# Create the RGB representation
layer_data = np.dstack([r, g, b])

# Scale to 16-bit range and convert
layer_data = layer_data * 65535.0
layer_data = np.clip(layer_data, 0, 65535.0)
layer_data = layer_data.astype(np.uint16)

# Save as 16-bit PNG
img = Image.fromarray(layer_data, mode='RGB')
img.save(output_path, format='PNG', optimize=False)
print(f"Normal pass image saved to {output_path}")

# Example usage
exr_file = bpy.path.abspath('//normal_pass.exr')
output_png = bpy.path.abspath('//normal_pass_output.png')

process_normal_pass(exr_file, output_png)
Зависимости: Среда:
  • Среда Python Blender или ваша собственная.
Инструкции по запуску:
  • Убедитесь, что установлены необходимые пакеты Python (, Imath, numpy, Pillow) устанавливаются в среде Python Blender или в вашей собственной среде.
    < li>Замените '//path_to_your_exr_file.exr' фактическим путем к вашему EXR-файлу.
  • Запустите скрипт в редакторе сценариев Blender или в вашем собственном редакторе em>.
  • Проверьте выходное изображение PNG на наличие артефактов.
Ожидаемый результат: >
Плавное и точное представление векторов нормалей без видимых артефактов и искажений. ИЗОБРАЖЕНИЕ: Изображение
Фактический результат: >
Выходное изображение содержит концентрированные линии красного и синего цвета, нарушающие однородность и плавность обычного сопоставления проходов. ИЗОБРАЖЕНИЕ: Изображение
Я попытался внести две изменения в обычную обработку проходов. в скрипте для устранения артефактов:
  • Сохранение зеленого канала:
    Вместо подавления зеленого канал (

    Код: Выделить всё

    g = np.zeros_like(y)
    ), я изменил его, чтобы сохранить компонент Y, используя g = np.abs(y). Однако в результате результат был в десять раз хуже, а изображение вообще не напоминало ожидаемый нормальный проход. ИЗОБРАЖЕНИЕ: Изображение

    Код: Выделить всё

    # Original code
    r = np.abs(x)  # X component to Red
    g = np.zeros_like(y)  # Suppress green channel
    b = np.abs(z)  # Z component to Blue
    
    # Modification 1
    r = np.abs(x)
    g = np.abs(y)  # Preserving the Y component
    b = np.abs(z)
    
  • Альтернативный подход к сопоставлению:
    Я попробовал переназначить обычные компоненты из диапазона [-1, 1] до [0, 1] по следующим формулам: r = (x + 1,0) * 0,5, g = (y + 1,0) * 0,5 и b = (z + 1,0) * 0,5. Этот подход также привел к нежелательным результатам, поскольку нормальная интерпретация прохода должна осуществляться в мировом пространстве, а не в пространстве камеры или касательном пространстве. ИЗОБРАЖЕНИЕ: Изображение

    Код: Выделить всё

    # Modification 2
    r = (x + 1.0) * 0.5
    g = (y + 1.0) * 0.5
    b = (z + 1.0) * 0.5
    
Несмотря на эти попытки, выходные изображения по-прежнему не совсем точно представляют обычный проход, как предполагалось. Мне нужна помощь в определении основной причины этих искажений и поиске надежного решения для правильного сопоставления каналов X, Y и Z с RGB без появления артефактов.


Подробнее здесь: https://stackoverflow.com/questions/791 ... hon-script
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»