Не получается конвертировать карту глубины в карту нормалей

Я пытаюсь конвертировать карту глубины полученную от графического инжектора reshade в карту нормалей. Reshade сам по себе умеет строить normalmap, но не умеет экспортировать глубину и нормали одновременно. Причем я точно знаю что он получает нормали не на прямую а из глубины, так что я подумал что раз он может, то смогу и я. Я погуглил как это делается, но почему-то почти все нормали на выходе смотрят в одну сторону. Как это исправить? (Карта глубины и правильных и неправильных нормалей прилагаются.)

import cv2
import tensorflow as tf
from google.colab import drive
from google.colab.patches import cv2_imshow
import numpy as np

def unpack_zBuffer(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    arr = np.asarray([256.0, 256.0*256.0, 256.0*256.0*256.0])
    arr = (1.0 / arr)
    img = img.astype(np.float32)
    depth_map = (img.dot(arr)) * (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0)
    # Invert the depth map
    depth_map = 1.0 - depth_map
    min_depth = np.min(depth_map)
    max_depth = np.max(depth_map)
    scaled_depth_map = 255 * (depth_map - min_depth) / (max_depth - min_depth)
    return scaled_depth_map


def depth2normal(y_pred):
    y_pred = tf.convert_to_tensor(y_pred, dtype=tf.float32)
    y_pred = y_pred[tf.newaxis, :, :, tf.newaxis]
    zy, zx = tf.image.image_gradients(y_pred)
    zx = tf.squeeze(zx, axis=0)
    zy = tf.squeeze(zy, axis=0)
    y_pred_sq = tf.squeeze(y_pred, axis=0)
    normal_ori = tf.concat([-zx, -zy, tf.ones_like(y_pred_sq)], axis=-1)
    new_normal = tf.sqrt(tf.square(zx) +  tf.square(zy) + 1)
    normal = normal_ori/new_normal
    normal += 1
    normal /= 2
    return normal

drive.mount('/content/drive/')
img_path = '/content/drive/MyDrive/BlGrDMap.webp'
img = cv2.imread(img_path, cv2.IMREAD_COLOR)

if img is not None:
    cv2_imshow(img)
    #Originaly depthmap stored in bmp image, and to fit 32bit gray color in it
    #the depth info splited in blue and green color chanels, this func convert it back
    #and works fine
    depth_map = unpack_zBuffer(img)
    cv2.imwrite('/content/drive/MyDrive/32bit_depth.webp', depth_map, [cv2.IMWRITE_WEBP_QUALITY, 100])
    cv2_imshow(depth_map)
    #But this func works wierd, even thow it copy-pasted from eng stackoverflow
    normal_map = depth2normal(depth_map)
    normal_map_np = normal_map.numpy()
    normal_map_np = cv2.cvtColor(normal_map_np, cv2.COLOR_RGB2BGR)
    imgshow = normal_map_np * 255
    cv2_imshow(imgshow)

    cv2.imwrite('/content/drive/MyDrive/32bit_normal.webp', imgshow, [cv2.IMWRITE_WEBP_QUALITY, 100])

else:
    print(f"Error loading image from {img_path}")

Глубина

Правильные нормали

Мои


Ответы (0 шт):