Не получается конвертировать карту глубины в карту нормалей
Я пытаюсь конвертировать карту глубины полученную от графического инжектора 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}")


