forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,80 @@
|
||||
import bpy, os
|
||||
|
||||
class TLM_Integrated_Denoise:
|
||||
|
||||
image_array = []
|
||||
image_output_destination = ""
|
||||
|
||||
def load(self, images):
|
||||
self.image_array = images
|
||||
|
||||
self.cull_undefined()
|
||||
|
||||
def setOutputDir(self, dir):
|
||||
self.image_output_destination = dir
|
||||
|
||||
def cull_undefined(self):
|
||||
|
||||
#Do a validation check before denoising
|
||||
|
||||
cam = bpy.context.scene.camera
|
||||
if not cam:
|
||||
bpy.ops.object.camera_add()
|
||||
|
||||
#Just select the first camera we find, needed for the compositor
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "CAMERA":
|
||||
bpy.context.scene.camera = obj
|
||||
return
|
||||
|
||||
def denoise(self):
|
||||
|
||||
if not bpy.context.scene.use_nodes:
|
||||
bpy.context.scene.use_nodes = True
|
||||
|
||||
tree = bpy.context.scene.node_tree
|
||||
|
||||
for image in self.image_array:
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Image...: " + image)
|
||||
|
||||
img = bpy.data.images.load(self.image_output_destination + "/" + image)
|
||||
|
||||
image_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node.image = img
|
||||
image_node.location = 0, 0
|
||||
|
||||
denoise_node = tree.nodes.new(type='CompositorNodeDenoise')
|
||||
denoise_node.location = 300, 0
|
||||
|
||||
comp_node = tree.nodes.new('CompositorNodeComposite')
|
||||
comp_node.location = 600, 0
|
||||
|
||||
links = tree.links
|
||||
links.new(image_node.outputs[0], denoise_node.inputs[0])
|
||||
links.new(denoise_node.outputs[0], comp_node.inputs[0])
|
||||
|
||||
# set output resolution to image res
|
||||
bpy.context.scene.render.resolution_x = img.size[0]
|
||||
bpy.context.scene.render.resolution_y = img.size[1]
|
||||
bpy.context.scene.render.resolution_percentage = 100
|
||||
|
||||
filePath = bpy.data.filepath
|
||||
path = os.path.dirname(filePath)
|
||||
|
||||
base = os.path.basename(image)
|
||||
filename, file_extension = os.path.splitext(image)
|
||||
filename = filename[:-6]
|
||||
|
||||
bpy.context.scene.render.filepath = self.image_output_destination + "/" + filename + "_denoised" + file_extension
|
||||
|
||||
denoised_image_path = self.image_output_destination
|
||||
bpy.context.scene.render.image_settings.file_format = "HDR"
|
||||
|
||||
bpy.ops.render.render(write_still=True)
|
||||
|
||||
#Cleanup
|
||||
comp_nodes = [image_node, denoise_node, comp_node]
|
||||
for node in comp_nodes:
|
||||
tree.nodes.remove(node)
|
207
leenkx/blender/lnx/lightmapper/utility/denoiser/oidn.py
Normal file
207
leenkx/blender/lnx/lightmapper/utility/denoiser/oidn.py
Normal file
@ -0,0 +1,207 @@
|
||||
import bpy, os, sys, re, platform, subprocess
|
||||
import numpy as np
|
||||
|
||||
class TLM_OIDN_Denoise:
|
||||
|
||||
image_array = []
|
||||
|
||||
image_output_destination = ""
|
||||
|
||||
denoised_array = []
|
||||
|
||||
def __init__(self, oidnProperties, img_array, dirpath):
|
||||
|
||||
self.oidnProperties = oidnProperties
|
||||
|
||||
self.image_array = img_array
|
||||
|
||||
self.image_output_destination = dirpath
|
||||
|
||||
self.check_binary()
|
||||
|
||||
def check_binary(self):
|
||||
|
||||
oidnPath = self.oidnProperties.tlm_oidn_path
|
||||
|
||||
if oidnPath != "":
|
||||
|
||||
file = oidnPath
|
||||
filename, file_extension = os.path.splitext(file)
|
||||
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
|
||||
if(file_extension == ".exe"):
|
||||
|
||||
pass
|
||||
|
||||
else:
|
||||
|
||||
self.oidnProperties.tlm_oidn_path = os.path.join(self.oidnProperties.tlm_oidn_path,"oidnDenoise.exe")
|
||||
|
||||
else:
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Please provide OIDN path")
|
||||
|
||||
def denoise(self):
|
||||
|
||||
for image in self.image_array:
|
||||
|
||||
if image not in self.denoised_array:
|
||||
|
||||
image_path = os.path.join(self.image_output_destination, image)
|
||||
|
||||
#Save to pfm
|
||||
loaded_image = bpy.data.images.load(image_path, check_existing=False)
|
||||
|
||||
width = loaded_image.size[0]
|
||||
height = loaded_image.size[1]
|
||||
|
||||
image_output_array = np.zeros([width, height, 3], dtype="float32")
|
||||
image_output_array = np.array(loaded_image.pixels)
|
||||
image_output_array = image_output_array.reshape(height, width, 4)
|
||||
image_output_array = np.float32(image_output_array[:,:,:3])
|
||||
|
||||
image_output_denoise_destination = image_path[:-4] + ".pfm"
|
||||
|
||||
image_output_denoise_result_destination = image_path[:-4] + "_denoised.pfm"
|
||||
|
||||
with open(image_output_denoise_destination, "wb") as fileWritePFM:
|
||||
self.save_pfm(fileWritePFM, image_output_array)
|
||||
|
||||
#Denoise
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Loaded image: " + str(loaded_image))
|
||||
|
||||
verbose = self.oidnProperties.tlm_oidn_verbose
|
||||
affinity = self.oidnProperties.tlm_oidn_affinity
|
||||
|
||||
if verbose:
|
||||
print("Denoiser search: " + bpy.path.abspath(self.oidnProperties.tlm_oidn_path))
|
||||
v = "3"
|
||||
else:
|
||||
v = "0"
|
||||
|
||||
if affinity:
|
||||
a = "1"
|
||||
else:
|
||||
a = "0"
|
||||
|
||||
threads = str(self.oidnProperties.tlm_oidn_threads)
|
||||
maxmem = str(self.oidnProperties.tlm_oidn_maxmem)
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
oidnPath = bpy.path.abspath(self.oidnProperties.tlm_oidn_path)
|
||||
pipePath = [oidnPath, '-f', 'RTLightmap', '-hdr', image_output_denoise_destination, '-o', image_output_denoise_result_destination, '-verbose', v, '-threads', threads, '-affinity', a, '-maxmem', maxmem]
|
||||
elif platform.system() == 'Darwin':
|
||||
oidnPath = bpy.path.abspath(self.oidnProperties.tlm_oidn_path)
|
||||
pipePath = [oidnPath + ' -f ' + ' RTLightmap ' + ' -hdr ' + image_output_denoise_destination + ' -o ' + image_output_denoise_result_destination + ' -verbose ' + v]
|
||||
else:
|
||||
oidnPath = bpy.path.abspath(self.oidnProperties.tlm_oidn_path)
|
||||
oidnPath = oidnPath.replace(' ', '\\ ')
|
||||
image_output_denoise_destination = image_output_denoise_destination.replace(' ', '\\ ')
|
||||
image_output_denoise_result_destination = image_output_denoise_result_destination.replace(' ', '\\ ')
|
||||
pipePath = [oidnPath + ' -f ' + ' RTLightmap ' + ' -hdr ' + image_output_denoise_destination + ' -o ' + image_output_denoise_result_destination + ' -verbose ' + v]
|
||||
|
||||
if not verbose:
|
||||
denoisePipe = subprocess.Popen(pipePath, stdout=subprocess.PIPE, stderr=None, shell=True)
|
||||
else:
|
||||
denoisePipe = subprocess.Popen(pipePath, shell=True)
|
||||
|
||||
denoisePipe.communicate()[0]
|
||||
|
||||
if platform.system() != 'Windows':
|
||||
image_output_denoise_result_destination = image_output_denoise_result_destination.replace('\\', '')
|
||||
|
||||
with open(image_output_denoise_result_destination, "rb") as f:
|
||||
denoise_data, scale = self.load_pfm(f)
|
||||
|
||||
ndata = np.array(denoise_data)
|
||||
ndata2 = np.dstack((ndata, np.ones((width,height))))
|
||||
img_array = ndata2.ravel()
|
||||
|
||||
loaded_image.pixels = img_array
|
||||
loaded_image.filepath_raw = image_output_denoise_result_destination = image_path[:-10] + "_denoised.hdr"
|
||||
loaded_image.file_format = "HDR"
|
||||
loaded_image.save()
|
||||
|
||||
self.denoised_array.append(image)
|
||||
|
||||
print(image_path)
|
||||
|
||||
def clean(self):
|
||||
|
||||
self.denoised_array.clear()
|
||||
self.image_array.clear()
|
||||
|
||||
for file in self.image_output_destination:
|
||||
if file.endswith("_baked.hdr"):
|
||||
baked_image_array.append(file)
|
||||
|
||||
#self.image_output_destination
|
||||
|
||||
#Clean temporary files here..
|
||||
#...pfm
|
||||
#...denoised.hdr
|
||||
|
||||
|
||||
def load_pfm(self, file, as_flat_list=False):
|
||||
#start = time()
|
||||
|
||||
header = file.readline().decode("utf-8").rstrip()
|
||||
if header == "PF":
|
||||
color = True
|
||||
elif header == "Pf":
|
||||
color = False
|
||||
else:
|
||||
raise Exception("Not a PFM file.")
|
||||
|
||||
dim_match = re.match(r"^(\d+)\s(\d+)\s$", file.readline().decode("utf-8"))
|
||||
if dim_match:
|
||||
width, height = map(int, dim_match.groups())
|
||||
else:
|
||||
raise Exception("Malformed PFM header.")
|
||||
|
||||
scale = float(file.readline().decode("utf-8").rstrip())
|
||||
if scale < 0: # little-endian
|
||||
endian = "<"
|
||||
scale = -scale
|
||||
else:
|
||||
endian = ">" # big-endian
|
||||
|
||||
data = np.fromfile(file, endian + "f")
|
||||
shape = (height, width, 3) if color else (height, width)
|
||||
if as_flat_list:
|
||||
result = data
|
||||
else:
|
||||
result = np.reshape(data, shape)
|
||||
#print("PFM import took %.3f s" % (time() - start))
|
||||
return result, scale
|
||||
|
||||
def save_pfm(self, file, image, scale=1):
|
||||
#start = time()
|
||||
|
||||
if image.dtype.name != "float32":
|
||||
raise Exception("Image dtype must be float32 (got %s)" % image.dtype.name)
|
||||
|
||||
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
||||
color = True
|
||||
elif len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1: # greyscale
|
||||
color = False
|
||||
else:
|
||||
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
||||
|
||||
file.write(b"PF\n" if color else b"Pf\n")
|
||||
file.write(b"%d %d\n" % (image.shape[1], image.shape[0]))
|
||||
|
||||
endian = image.dtype.byteorder
|
||||
|
||||
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
||||
scale = -scale
|
||||
|
||||
file.write(b"%f\n" % scale)
|
||||
|
||||
image.tofile(file)
|
||||
|
||||
#print("PFM export took %.3f s" % (time() - start))
|
92
leenkx/blender/lnx/lightmapper/utility/denoiser/optix.py
Normal file
92
leenkx/blender/lnx/lightmapper/utility/denoiser/optix.py
Normal file
@ -0,0 +1,92 @@
|
||||
import bpy, os, platform, subprocess
|
||||
|
||||
class TLM_Optix_Denoise:
|
||||
|
||||
image_array = []
|
||||
|
||||
image_output_destination = ""
|
||||
|
||||
denoised_array = []
|
||||
|
||||
def __init__(self, optixProperties, img_array, dirpath):
|
||||
|
||||
self.optixProperties = optixProperties
|
||||
|
||||
self.image_array = img_array
|
||||
|
||||
self.image_output_destination = dirpath
|
||||
|
||||
self.check_binary()
|
||||
|
||||
def check_binary(self):
|
||||
|
||||
optixPath = self.optixProperties.tlm_optix_path
|
||||
|
||||
if optixPath != "":
|
||||
|
||||
file = optixPath
|
||||
filename, file_extension = os.path.splitext(file)
|
||||
|
||||
if(file_extension == ".exe"):
|
||||
|
||||
#if file exists optixDenoise or denoise
|
||||
|
||||
pass
|
||||
|
||||
else:
|
||||
|
||||
#if file exists optixDenoise or denoise
|
||||
|
||||
self.optixProperties.tlm_optix_path = os.path.join(self.optixProperties.tlm_optix_path,"Denoiser.exe")
|
||||
|
||||
else:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Please provide Optix path")
|
||||
|
||||
def denoise(self):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Optix: Denoising")
|
||||
for image in self.image_array:
|
||||
|
||||
if image not in self.denoised_array:
|
||||
|
||||
image_path = os.path.join(self.image_output_destination, image)
|
||||
|
||||
denoise_output_destination = image_path[:-10] + "_denoised.hdr"
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
optixPath = bpy.path.abspath(self.optixProperties.tlm_optix_path)
|
||||
pipePath = [optixPath, '-i', image_path, '-o', denoise_output_destination]
|
||||
elif platform.system() == 'Darwin':
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Mac for Optix is still unsupported")
|
||||
else:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Linux for Optix is still unsupported")
|
||||
|
||||
if self.optixProperties.tlm_optix_verbose:
|
||||
denoisePipe = subprocess.Popen(pipePath, shell=True)
|
||||
else:
|
||||
denoisePipe = subprocess.Popen(pipePath, stdout=subprocess.PIPE, stderr=None, shell=True)
|
||||
|
||||
denoisePipe.communicate()[0]
|
||||
|
||||
image = bpy.data.images.load(image_path, check_existing=False)
|
||||
bpy.data.images[image.name].filepath_raw = bpy.data.images[image.name].filepath_raw[:-4] + "_denoised.hdr"
|
||||
bpy.data.images[image.name].reload()
|
||||
|
||||
def clean(self):
|
||||
|
||||
self.denoised_array.clear()
|
||||
self.image_array.clear()
|
||||
|
||||
for file in self.image_output_destination:
|
||||
if file.endswith("_baked.hdr"):
|
||||
baked_image_array.append(file)
|
||||
|
||||
#self.image_output_destination
|
||||
|
||||
#Clean temporary files here..
|
||||
#...pfm
|
||||
#...denoised.hdr
|
Reference in New Issue
Block a user