Проблема
Я работаю над сценарием Python для создания изображений из данных канала EXR для более крупного проекта, требующего точного сопоставления нормальных проходов. Скрипт обрабатывает каналы X, Y и Z из файла EXR и сопоставляет их с каналами RGB полученного изображения. Однако в выходном изображении наблюдаются значительные артефакты и искажения, из-за чего отображение нормального прохода становится неверным по сравнению с ожидаемым результатом.
Минимально воспроизводимый пример:
Вот минимальный пример сценария, демонстрирующий проблему. Этот скрипт предназначен для запуска в среде Python Blender. Он использует OpenEXR для чтения 16-битного файла EXR, обрабатывает обычный проход и сохраняет результат в виде PNG-изображения с помощью Pillow. Вы можете использовать этот 16-битный EXR: https://wetransfer.com/downloads/2855df ... 843/0172f8
, Imath, numpy, Pillow) устанавливаются в среде Python Blender или в вашей собственной среде.
< li>Замените '//path_to_your_exr_file.exr' фактическим путем к вашему EXR-файлу.
Запустите скрипт в редакторе сценариев Blender или в вашем собственном редакторе em>.
Проверьте выходное изображение PNG на наличие артефактов.
Ожидаемый результат: >
Плавное и точное представление векторов нормалей без видимых артефактов и искажений. ИЗОБРАЖЕНИЕ: Фактический результат: >
Выходное изображение содержит концентрированные линии красного и синего цвета, нарушающие однородность и плавность обычного сопоставления проходов. ИЗОБРАЖЕНИЕ:
Я попытался внести две изменения в обычную обработку проходов. в скрипте для устранения артефактов:
Сохранение зеленого канала:
Вместо подавления зеленого канал (
), я изменил его, чтобы сохранить компонент 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 без появления артефактов.
Проблема Я работаю над сценарием Python для создания изображений из данных канала EXR для более крупного проекта, требующего точного сопоставления нормальных проходов. Скрипт обрабатывает каналы X, Y и Z из файла EXR и сопоставляет их с каналами RGB полученного изображения. Однако в выходном изображении наблюдаются значительные артефакты и искажения, из-за чего отображение нормального прохода становится неверным по сравнению с ожидаемым результатом. [h4][b]Минимально воспроизводимый пример:[/b][/h4]Вот минимальный пример сценария, демонстрирующий проблему. Этот скрипт предназначен для запуска в среде Python Blender. Он использует OpenEXR для чтения 16-битного файла EXR, обрабатывает обычный проход и сохраняет результат в виде PNG-изображения с помощью Pillow. Вы можете использовать этот 16-битный [b]EXR[/b]: https://wetransfer.com/downloads/2855df23fed4b0c348e1cfa4371bc35020241110001843/0172f8 [code]import bpy import OpenEXR import Imath import numpy as np from PIL import Image import os
# 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) [/code] [b]Зависимости:[/b] [list] [*][code]OpenEXR[/code] [*][code]Imath[/code] [*][code]numpy[/code] [*][code]Pillow[/code] [*]Модуль bpy Blender. Это необязательно, используйте его только в том случае, если вы запускаете пример в блендере, поскольку путь bpy.path.abspath кода [/list] [b]Среда:[/b] [list] [*]Среда Python Blender или ваша собственная. [/list] [b]Инструкции по запуску:[/b] [list] [*]Убедитесь, что установлены необходимые пакеты Python ([code]OpenEXR[/code], Imath, numpy, Pillow) устанавливаются в среде Python Blender или в вашей собственной среде. < li>Замените '//path_to_your_exr_file.exr' фактическим путем к вашему EXR-файлу. [*]Запустите скрипт в редакторе сценариев Blender или в вашем собственном редакторе em>. [*]Проверьте выходное изображение PNG на наличие артефактов. [/list] [b]Ожидаемый результат:[/b] > Плавное и точное представление векторов нормалей без видимых артефактов и искажений. [b]ИЗОБРАЖЕНИЕ[/b]: https://new.imagehostx.com/upload/2024/11/09/normalexr_1731171391.png [b]Фактический результат:[/b] > Выходное изображение содержит концентрированные линии красного и синего цвета, нарушающие однородность и плавность обычного сопоставления проходов. [b]ИЗОБРАЖЕНИЕ[/b]: https://new.imagehostx.com/upload/2024/11/09/putitoREAL_1731171538.png Я попытался внести две изменения в обычную обработку проходов. в скрипте для устранения артефактов: [list] [*][b]Сохранение зеленого канала:[/b] Вместо подавления зеленого канал ([code]g = np.zeros_like(y)[/code]), я изменил его, чтобы сохранить компонент Y, используя g = np.abs(y). Однако в результате результат был в десять раз хуже, а изображение вообще не напоминало ожидаемый нормальный проход. [b]ИЗОБРАЖЕНИЕ[/b]: https://new.imagehostx.com/upload/2024/11/09/vicentesHOY_1731171598.png [code]# 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) [/code]
[*][b]Альтернативный подход к сопоставлению:[/b] Я попробовал переназначить обычные компоненты из диапазона [-1, 1] до [0, 1] по следующим формулам: r = (x + 1,0) * 0,5, g = (y + 1,0) * 0,5 и b = (z + 1,0) * 0,5. Этот подход также привел к нежелательным результатам, поскольку нормальная интерпретация прохода должна осуществляться в мировом пространстве, а не в пространстве камеры или касательном пространстве. [b]ИЗОБРАЖЕНИЕ[/b]: https://new.imagehostx.com/upload/2024/11/09/Basta_1731171625.png [code]# Modification 2 r = (x + 1.0) * 0.5 g = (y + 1.0) * 0.5 b = (z + 1.0) * 0.5 [/code]
[/list] Несмотря на эти попытки, выходные изображения по-прежнему не совсем точно представляют обычный проход, как предполагалось. Мне нужна помощь в определении основной причины этих искажений и поиске надежного решения для правильного сопоставления каналов X, Y и Z с RGB без появления артефактов.