13#include <OpenImageIO/filesystem.h>
23 size_t pos = in.rfind(
".");
24 if (
pos == string::npos) {
27 suffix = in.substr(
pos + 1);
28 in = in.substr(0,
pos);
37 string name,
string &renderlayer,
string &pass,
string &channel,
bool multiview_channels)
51 if (multiview_channels) {
52 renderlayer +=
"." +
view;
67 for (
const char *chan =
channels.c_str(); *chan; chan++) {
68 map.push_back({
pos++, name +
"." + *chan});
109 size_t input_channel = mapping.channel;
110 size_t layer_channel = i -
channels.begin();
124 size_t output_channel = mapping.channel;
125 size_t layer_channel = i -
channels.begin();
141 const std::vector<string> &neighbor_channelnames)
145 assert(mapping.size() == 0);
150 std::vector<string>::const_iterator frame_channel = find(
151 neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
153 if (frame_channel == neighbor_channelnames.end()) {
157 mapping[i] = frame_channel - neighbor_channelnames.begin();
182 float *buffer_data =
buffers.buffer.data();
183 image.read_pixels(image_layer,
buffers.params, buffer_data);
186 if (
frame > 0 && !
image.read_previous_pixels(image_layer,
buffers.params, buffer_data)) {
187 error =
"Failed to read neighbor frame pixels";
192 buffers.buffer.copy_to_device();
202 pass->set_type(type);
203 pass->set_mode(mode);
205 passes.push_back(pass);
220 if (
image.layers.empty()) {
221 error =
"No image layers found to denoise in " + center_filepath;
233 add_pass(passes, PassType::PASS_COMBINED);
234 add_pass(passes, PassType::PASS_DENOISING_ALBEDO);
235 add_pass(passes, PassType::PASS_DENOISING_NORMAL);
236 add_pass(passes, PassType::PASS_MOTION);
237 add_pass(passes, PassType::PASS_DENOISING_PREVIOUS);
249 for (
Pass *pass : passes) {
278 buffers.buffer.copy_from_device();
285 for (
int y = 0;
y <
image.height;
y++) {
289 int image_channel = output_to_image_channel[j];
290 out[
image.num_channels *
x + image_channel] =
result[offset + j];
344 const ParamValue *multiview =
in_spec.find_attribute(
"multiView");
345 const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
346 multiview->type().arraylen >= 2);
353 map<string, DenoiseImageLayer> file_layers;
354 for (
int i = 0; i <
channels.size(); i++) {
355 string layer, pass, channel;
357 file_layers[layer].channels.push_back(pass +
"." + channel);
358 file_layers[layer].layer_to_image_channel.push_back(i);
364 for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
367 const string &name = i->first;
381 string sample_string =
in_spec.get_string_attribute(
"cycles." + name +
".samples",
"");
382 if (sample_string !=
"") {
383 if (!sscanf(sample_string.c_str(),
"%d", &layer.
samples)) {
384 error =
"Failed to parse samples metadata: " + sample_string;
392 "No sample number specified in the file for layer %s or on the command line",
412 for (
int j = 0; j < 3; ++j) {
415 input_pixels[i *
params.pass_stride + offset + j] =
418 for (
int j = 0; j < 3; ++j) {
421 input_pixels[i *
params.pass_stride + offset + j] =
424 for (
int j = 0; j < 3; ++j) {
427 input_pixels[i *
params.pass_stride + offset + j] =
430 for (
int j = 0; j < 4; ++j) {
432 int image_channel = input_to_image_channel[
INPUT_MOTION + j];
433 input_pixels[i *
params.pass_stride + offset + j] =
445 const size_t num_pixels = (size_t)
width * (
size_t)
height;
457 for (
int j = 0; j < 3; ++j) {
459 int image_channel = output_to_image_channel[j];
460 input_pixels[i *
params.pass_stride + offset + j] =
461 neighbor_pixels[((size_t)i) *
num_channels + image_channel];
470 if (!Filesystem::is_regular(in_filepath)) {
471 error =
"Couldn't find file: " + in_filepath;
477 error =
"Couldn't open file: " + in_filepath;
491 error =
"Could not find a render layer containing denoising data and motion vector passes";
495 size_t num_pixels = (size_t)
width * (
size_t)
height;
501 error =
"Failed to read image: " + in_filepath;
510 if (!Filesystem::is_regular(filepath)) {
511 error =
"Couldn't find neighbor frame: " + filepath;
517 error =
"Couldn't open neighbor frame: " + filepath;
521 const ImageSpec &neighbor_spec = in_neighbor->spec();
522 if (neighbor_spec.width !=
width || neighbor_spec.height !=
height) {
523 error =
"Neighbor frame has different dimensions: " + filepath;
528 if (!layer.match_channels(
in_spec.channelnames, neighbor_spec.channelnames)) {
529 error =
"Neighbor frame misses denoising data passes: " + filepath;
545 for (
int i = 0; i <
layers.size(); i++) {
546 string name =
"cycles." +
layers[i].name +
".samples";
547 if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
558 string extension = OIIO::Filesystem::extension(out_filepath);
559 string unique_name =
".denoise-tmp-" + OIIO::Filesystem::unique_path();
560 string tmp_filepath = out_filepath +
unique_name + extension;
564 error =
"Failed to open temporary file " + tmp_filepath +
" for writing";
569 if (!out->open(tmp_filepath, out_spec)) {
570 error =
"Failed to open file " + tmp_filepath +
" for writing: " + out->geterror();
575 if (!out->write_image(TypeDesc::FLOAT,
pixels.data())) {
576 error =
"Failed to write to file " + tmp_filepath +
": " + out->geterror();
581 error =
"Failed to save to file " + tmp_filepath +
": " + out->geterror();
589 if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
590 error =
"Failed to move denoised image to " + out_filepath +
": " + rename_error;
595 OIIO::Filesystem::remove(tmp_filepath);
631 int num_frames =
output.size();
633 for (
int frame = 0; frame < num_frames; frame++) {
635 if (
output[frame].empty()) {
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
void read_pixels(const DenoiseImageLayer &layer, const BufferParams ¶ms, float *input_pixels)
bool parse_channels(const ImageSpec &in_spec, string &error)
vector< DenoiseImageLayer > layers
bool read_previous_pixels(const DenoiseImageLayer &layer, const BufferParams ¶ms, float *input_pixels)
bool load(const string &in_filepath, string &error)
unique_ptr< ImageInput > in_previous
bool load_previous(const string &in_filepath, string &error)
bool save_output(const string &out_filepath, string &error)
DenoiserPipeline * denoiser
DenoiseTask(Device *device, DenoiserPipeline *denoiser, int frame)
bool load_input_pixels(int layer)
std::unique_ptr< Denoiser > denoiser
DenoiserPipeline(DeviceInfo &denoiser_device_info, const DenoiseParams ¶ms)
static unique_ptr< Denoiser > create(Device *denoise_device, Device *cpu_fallback_device, const DenoiseParams ¶ms)
static Device * create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
static void init(int num_threads=0)
static const int INPUT_NOISY_IMAGE
static const int OUTPUT_NUM_CHANNELS
static void fill_mapping(vector< ChannelMapping > &map, int pos, string name, string channels)
static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
static CCL_NAMESPACE_BEGIN bool split_last_dot(string &in, string &suffix)
static const int INPUT_DENOISING_ALBEDO
static vector< ChannelMapping > output_channels()
static const int INPUT_DENOISING_NORMAL
static const int INPUT_NUM_CHANNELS
static const int INPUT_MOTION
static void add_pass(vector< Pass * > &passes, PassType type, PassMode mode=PassMode::NOISY)
static vector< ChannelMapping > input_channels()
CCL_NAMESPACE_BEGIN Device * device_cpu_create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
void device_cpu_info(vector< DeviceInfo > &devices)
#define CCL_NAMESPACE_END
@ PASS_DENOISING_PREVIOUS
#define KERNEL_FEATURE_DENOISING
static void error(const char *str)
static void unique_name(bNode *node)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
vector< int > previous_output_to_image_channel
vector< int > input_to_image_channel
bool match_channels(const std::vector< string > &channelnames, const std::vector< string > &neighbor_channelnames)
bool detect_denoising_channels()
vector< int > output_to_image_channel
vector< string > channels
vector< int > layer_to_image_channel