Blender  V2.93
denoising.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2018 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/denoising.h"
18 
20 
21 #include "util/util_foreach.h"
22 #include "util/util_map.h"
23 #include "util/util_system.h"
24 #include "util/util_task.h"
25 #include "util/util_time.h"
26 
27 #include <OpenImageIO/filesystem.h>
28 
30 
31 /* Utility Functions */
32 
33 static void print_progress(int num, int total, int frame, int num_frames)
34 {
35  const char *label = "Denoise Frame ";
36  int cols = system_console_width();
37 
38  cols -= strlen(label);
39 
40  int len = 1;
41  for (int x = total; x > 9; x /= 10) {
42  len++;
43  }
44 
45  int bars = cols - 2 * len - 6;
46 
47  printf("\r%s", label);
48 
49  if (num_frames > 1) {
50  int frame_len = 1;
51  for (int x = num_frames - 1; x > 9; x /= 10) {
52  frame_len++;
53  }
54  bars -= frame_len + 2;
55  printf("%*d ", frame_len, frame);
56  }
57 
58  int v = int(float(num) * bars / total);
59  printf("[");
60  for (int i = 0; i < v; i++) {
61  printf("=");
62  }
63  if (v < bars) {
64  printf(">");
65  }
66  for (int i = v + 1; i < bars; i++) {
67  printf(" ");
68  }
69  printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
70  fflush(stdout);
71 }
72 
73 /* Splits in at its last dot, setting suffix to the part after the dot and in to the part before
74  * it. Returns whether a dot was found. */
75 static bool split_last_dot(string &in, string &suffix)
76 {
77  size_t pos = in.rfind(".");
78  if (pos == string::npos) {
79  return false;
80  }
81  suffix = in.substr(pos + 1);
82  in = in.substr(0, pos);
83  return true;
84 }
85 
86 /* Separate channel names as generated by Blender.
87  * If views is true:
88  * Inputs are expected in the form RenderLayer.Pass.View.Channel, sets renderlayer to
89  * "RenderLayer.View" Otherwise: Inputs are expected in the form RenderLayer.Pass.Channel */
90 static bool parse_channel_name(
91  string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
92 {
93  if (!split_last_dot(name, channel)) {
94  return false;
95  }
96  string view;
97  if (multiview_channels && !split_last_dot(name, view)) {
98  return false;
99  }
100  if (!split_last_dot(name, pass)) {
101  return false;
102  }
103  renderlayer = name;
104 
105  if (multiview_channels) {
106  renderlayer += "." + view;
107  }
108 
109  return true;
110 }
111 
112 /* Channel Mapping */
113 
115  int channel;
116  string name;
117 };
118 
119 static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, string channels)
120 {
121  for (const char *chan = channels.c_str(); *chan; chan++) {
122  map.push_back({pos++, name + "." + *chan});
123  }
124 }
125 
126 static const int INPUT_NUM_CHANNELS = 15;
127 static const int INPUT_DENOISING_DEPTH = 0;
128 static const int INPUT_DENOISING_NORMAL = 1;
129 static const int INPUT_DENOISING_SHADOWING = 4;
130 static const int INPUT_DENOISING_ALBEDO = 5;
131 static const int INPUT_NOISY_IMAGE = 8;
132 static const int INPUT_DENOISING_VARIANCE = 11;
133 static const int INPUT_DENOISING_INTENSITY = 14;
135 {
137  fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
138  fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
139  fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
140  fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
141  fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
142  fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
143  fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
144  return map;
145 }
146 
147 static const int OUTPUT_NUM_CHANNELS = 3;
149 {
151  fill_mapping(map, 0, "Combined", "RGB");
152  return map;
153 }
154 
155 /* Renderlayer Handling */
156 
158 {
159  /* Map device input to image channels. */
160  input_to_image_channel.clear();
162 
163  foreach (const ChannelMapping &mapping, input_channels()) {
164  vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
165  if (i == channels.end()) {
166  return false;
167  }
168 
169  size_t input_channel = mapping.channel;
170  size_t layer_channel = i - channels.begin();
171  input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
172  }
173 
174  /* Map device output to image channels. */
175  output_to_image_channel.clear();
177 
178  foreach (const ChannelMapping &mapping, output_channels()) {
179  vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
180  if (i == channels.end()) {
181  return false;
182  }
183 
184  size_t output_channel = mapping.channel;
185  size_t layer_channel = i - channels.begin();
186  output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
187  }
188 
189  /* Check that all buffer channels are correctly set. */
190  for (int i = 0; i < INPUT_NUM_CHANNELS; i++) {
191  assert(input_to_image_channel[i] >= 0);
192  }
193  for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
194  assert(output_to_image_channel[i] >= 0);
195  }
196 
197  return true;
198 }
199 
201  const std::vector<string> &channelnames,
202  const std::vector<string> &neighbor_channelnames)
203 {
204  neighbor_input_to_image_channel.resize(neighbor + 1);
205  vector<int> &mapping = neighbor_input_to_image_channel[neighbor];
206 
207  assert(mapping.size() == 0);
208  mapping.resize(input_to_image_channel.size(), -1);
209 
210  for (int i = 0; i < input_to_image_channel.size(); i++) {
211  const string &channel = channelnames[input_to_image_channel[i]];
212  std::vector<string>::const_iterator frame_channel = find(
213  neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
214 
215  if (frame_channel == neighbor_channelnames.end()) {
216  return false;
217  }
218 
219  mapping[i] = frame_channel - neighbor_channelnames.begin();
220  }
221 
222  return true;
223 }
224 
225 /* Denoise Task */
226 
228  Denoiser *denoiser,
229  int frame,
230  const vector<int> &neighbor_frames)
231  : denoiser(denoiser),
232  device(device),
233  frame(frame),
234  neighbor_frames(neighbor_frames),
235  current_layer(0),
236  input_pixels(device, "filter input buffer", MEM_READ_ONLY),
237  num_tiles(0)
238 {
240 }
241 
243 {
244  free();
245 }
246 
247 /* Device callbacks */
248 
249 bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
250 {
251  thread_scoped_lock tile_lock(tiles_mutex);
252 
253  if (tiles.empty()) {
254  return false;
255  }
256 
257  tile = tiles.front();
258  tiles.pop_front();
259 
260  device->map_tile(tile_device, tile);
261 
263 
264  return true;
265 }
266 
267 /* Mapping tiles is required for regular rendering since each tile has its separate memory
268  * which may be allocated on a different device.
269  * For standalone denoising, there is a single memory that is present on all devices, so the only
270  * thing that needs to be done here is to specify the surrounding tile geometry.
271  *
272  * However, since there is only one large memory, the denoised result has to be written to
273  * a different buffer to avoid having to copy an entire horizontal slice of the image. */
275 {
276  RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
277  RenderTile &target_tile = neighbors.target;
278 
279  /* Fill tile information. */
280  for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
281  if (i == RenderTileNeighbors::CENTER) {
282  continue;
283  }
284 
285  RenderTile &tile = neighbors.tiles[i];
286  int dx = (i % 3) - 1;
287  int dy = (i / 3) - 1;
288  tile.x = clamp(center_tile.x + dx * denoiser->tile_size.x, 0, image.width);
289  tile.w = clamp(center_tile.x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tile.x;
290  tile.y = clamp(center_tile.y + dy * denoiser->tile_size.y, 0, image.height);
291  tile.h = clamp(center_tile.y + (dy + 1) * denoiser->tile_size.y, 0, image.height) - tile.y;
292 
293  tile.buffer = center_tile.buffer;
294  tile.offset = center_tile.offset;
295  tile.stride = image.width;
296  }
297 
298  /* Allocate output buffer. */
299  device_vector<float> *output_mem = new device_vector<float>(
300  tile_device, "denoising_output", MEM_READ_WRITE);
301  output_mem->alloc(OUTPUT_NUM_CHANNELS * center_tile.w * center_tile.h);
302 
303  /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
304  * when skipping denoising of some pixels. */
305  float *result = output_mem->data();
306  float *in = &image.pixels[image.num_channels * (center_tile.y * image.width + center_tile.x)];
307 
309  const int *input_to_image_channel = layer.input_to_image_channel.data();
310 
311  for (int y = 0; y < center_tile.h; y++) {
312  for (int x = 0; x < center_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
313  for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
314  result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
315  }
316  }
317  in += image.num_channels * image.width;
318  }
319 
320  output_mem->copy_to_device();
321 
322  /* Fill output tile info. */
323  target_tile = center_tile;
324  target_tile.buffer = output_mem->device_pointer;
325  target_tile.stride = target_tile.w;
326  target_tile.offset -= target_tile.x + target_tile.y * target_tile.stride;
327 
328  thread_scoped_lock output_lock(output_mutex);
329  assert(output_pixels.count(center_tile.tile_index) == 0);
330  output_pixels[target_tile.tile_index] = output_mem;
331 }
332 
334 {
335  RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
336  RenderTile &target_tile = neighbors.target;
337 
338  thread_scoped_lock output_lock(output_mutex);
339  assert(output_pixels.count(center_tile.tile_index) == 1);
340  device_vector<float> *output_mem = output_pixels[target_tile.tile_index];
341  output_pixels.erase(center_tile.tile_index);
342  output_lock.unlock();
343 
344  /* Copy denoised pixels from device. */
345  output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * target_tile.w, target_tile.h);
346 
347  float *result = output_mem->data();
348  float *out = &image.pixels[image.num_channels * (target_tile.y * image.width + target_tile.x)];
349 
351  const int *output_to_image_channel = layer.output_to_image_channel.data();
352 
353  for (int y = 0; y < target_tile.h; y++) {
354  for (int x = 0; x < target_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
355  for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
356  out[image.num_channels * x + output_to_image_channel[i]] = result[i];
357  }
358  }
359  out += image.num_channels * image.width;
360  }
361 
362  /* Free device buffer. */
363  output_mem->free();
364  delete output_mem;
365 }
366 
368 {
369 }
370 
372 {
373  return false;
374 }
375 
377 {
378  /* Callback functions. */
379  task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
380  task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
381  task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
382  task.release_tile = function_bind(&DenoiseTask::release_tile, this);
383  task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
384 
385  /* Denoising parameters. */
386  task.denoising = denoiser->params;
387  task.denoising.type = DENOISER_NLM;
388  task.denoising.use = true;
389  task.denoising.store_passes = false;
390  task.denoising_from_render = false;
391 
392  task.denoising_frames.resize(neighbor_frames.size());
393  for (int i = 0; i < neighbor_frames.size(); i++) {
394  task.denoising_frames[i] = neighbor_frames[i] - frame;
395  }
396 
397  /* Buffer parameters. */
398  task.pass_stride = INPUT_NUM_CHANNELS;
399  task.target_pass_stride = OUTPUT_NUM_CHANNELS;
400  task.pass_denoising_data = 0;
401  task.pass_denoising_clean = -1;
402  task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
403 
404  /* Create tiles. */
405  thread_scoped_lock tile_lock(tiles_mutex);
406  thread_scoped_lock output_lock(output_mutex);
407 
408  tiles.clear();
409  assert(output_pixels.empty());
410  output_pixels.clear();
411 
412  int tiles_x = divide_up(image.width, denoiser->tile_size.x);
413  int tiles_y = divide_up(image.height, denoiser->tile_size.y);
414 
415  for (int ty = 0; ty < tiles_y; ty++) {
416  for (int tx = 0; tx < tiles_x; tx++) {
417  RenderTile tile;
418  tile.x = tx * denoiser->tile_size.x;
419  tile.y = ty * denoiser->tile_size.y;
420  tile.w = min(image.width - tile.x, denoiser->tile_size.x);
421  tile.h = min(image.height - tile.y, denoiser->tile_size.y);
422  tile.start_sample = 0;
423  tile.num_samples = image.layers[current_layer].samples;
424  tile.sample = 0;
425  tile.offset = 0;
426  tile.stride = image.width;
427  tile.tile_index = ty * tiles_x + tx;
428  tile.task = RenderTile::DENOISE;
429  tile.buffers = NULL;
431  tiles.push_back(tile);
432  }
433  }
434 
435  num_tiles = tiles.size();
436 }
437 
438 /* Denoiser Operations */
439 
441 {
442  int w = image.width;
443  int h = image.height;
444  int num_pixels = image.width * image.height;
445  int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
446 
447  /* Load center image */
448  DenoiseImageLayer &image_layer = image.layers[layer];
449 
450  float *buffer_data = input_pixels.data();
451  image.read_pixels(image_layer, buffer_data);
452  buffer_data += frame_stride;
453 
454  /* Load neighbor images */
455  for (int i = 0; i < image.in_neighbors.size(); i++) {
456  if (!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
457  error = "Failed to read neighbor frame pixels";
458  return false;
459  }
460  buffer_data += frame_stride;
461  }
462 
463  /* Preprocess */
464  buffer_data = input_pixels.data();
465  for (int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
466  /* Clamp */
467  if (denoiser->params.clamp_input) {
468  for (int i = 0; i < num_pixels * INPUT_NUM_CHANNELS; i++) {
469  buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
470  }
471  }
472 
473  /* Box blur */
474  int r = 5 * denoiser->params.radius;
475  float *data = buffer_data + 14;
476  array<float> temp(num_pixels);
477 
478  for (int y = 0; y < h; y++) {
479  for (int x = 0; x < w; x++) {
480  int n = 0;
481  float sum = 0.0f;
482  for (int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
483  sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
484  }
485  temp[y * w + x] = sum / n;
486  }
487  }
488 
489  for (int y = 0; y < h; y++) {
490  for (int x = 0; x < w; x++) {
491  int n = 0;
492  float sum = 0.0f;
493 
494  for (int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
495  sum += temp[dy * w + x];
496  }
497 
498  data[INPUT_NUM_CHANNELS * (y * w + x)] = sum / n;
499  }
500  }
501 
502  /* Highlight compression */
503  data = buffer_data + 8;
504  for (int y = 0; y < h; y++) {
505  for (int x = 0; x < w; x++) {
506  int idx = INPUT_NUM_CHANNELS * (y * w + x);
507  float3 color = make_float3(data[idx], data[idx + 1], data[idx + 2]);
508  color = color_highlight_compress(color, NULL);
509  data[idx] = color.x;
510  data[idx + 1] = color.y;
511  data[idx + 2] = color.z;
512  }
513  }
514 
515  buffer_data += frame_stride;
516  }
517 
518  /* Copy to device */
520 
521  return true;
522 }
523 
524 /* Task stages */
525 
527 {
528  string center_filepath = denoiser->input[frame];
529  if (!image.load(center_filepath, error)) {
530  return false;
531  }
532 
534  return false;
535  }
536 
537  if (image.layers.empty()) {
538  error = "No image layers found to denoise in " + center_filepath;
539  return false;
540  }
541 
542  /* Allocate device buffer. */
543  int num_frames = image.in_neighbors.size() + 1;
546 
547  /* Read pixels for first layer. */
548  current_layer = 0;
550  return false;
551  }
552 
553  return true;
554 }
555 
557 {
558  for (current_layer = 0; current_layer < image.layers.size(); current_layer++) {
559  /* Read pixels for secondary layers, first was already loaded. */
560  if (current_layer > 0) {
562  return false;
563  }
564  }
565 
566  /* Run task on device. */
568  create_task(task);
569  device->task_add(task);
570  device->task_wait();
571 
572  printf("\n");
573  }
574 
575  return true;
576 }
577 
579 {
580  bool ok = image.save_output(denoiser->output[frame], error);
581  free();
582  return ok;
583 }
584 
586 {
587  image.free();
588  input_pixels.free();
589  assert(output_pixels.empty());
590 }
591 
592 /* Denoise Image Storage */
593 
595 {
596  width = 0;
597  height = 0;
598  num_channels = 0;
599  samples = 0;
600 }
601 
603 {
604  free();
605 }
606 
608 {
609  in_neighbors.clear();
610 }
611 
613 {
614  close_input();
615  pixels.clear();
616 }
617 
618 bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
619 {
620  const std::vector<string> &channels = in_spec.channelnames;
621  const ParamValue *multiview = in_spec.find_attribute("multiView");
622  const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
623  multiview->type().arraylen >= 2);
624 
625  layers.clear();
626 
627  /* Loop over all the channels in the file, parse their name and sort them
628  * by RenderLayer.
629  * Channels that can't be parsed are directly passed through to the output. */
630  map<string, DenoiseImageLayer> file_layers;
631  for (int i = 0; i < channels.size(); i++) {
632  string layer, pass, channel;
633  if (parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
634  file_layers[layer].channels.push_back(pass + "." + channel);
635  file_layers[layer].layer_to_image_channel.push_back(i);
636  }
637  }
638 
639  /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
640  * Any channels that won't be processed internally are also passed through. */
641  for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
642  ++i) {
643  const string &name = i->first;
644  DenoiseImageLayer &layer = i->second;
645 
646  /* Check for full pass set. */
647  if (!layer.detect_denoising_channels()) {
648  continue;
649  }
650 
651  layer.name = name;
652  layer.samples = samples;
653 
654  /* If the sample value isn't set yet, check if there is a layer-specific one in the input file.
655  */
656  if (layer.samples < 1) {
657  string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
658  if (sample_string != "") {
659  if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
660  error = "Failed to parse samples metadata: " + sample_string;
661  return false;
662  }
663  }
664  }
665 
666  if (layer.samples < 1) {
668  "No sample number specified in the file for layer %s or on the command line",
669  name.c_str());
670  return false;
671  }
672 
673  layers.push_back(layer);
674  }
675 
676  return true;
677 }
678 
679 void DenoiseImage::read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
680 {
681  /* Pixels from center file have already been loaded into pixels.
682  * We copy a subset into the device input buffer with channels reshuffled. */
683  const int *input_to_image_channel = layer.input_to_image_channel.data();
684 
685  for (int i = 0; i < width * height; i++) {
686  for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
687  int image_channel = input_to_image_channel[j];
688  input_pixels[i * INPUT_NUM_CHANNELS + j] =
689  pixels[((size_t)i) * num_channels + image_channel];
690  }
691  }
692 }
693 
695  const DenoiseImageLayer &layer,
696  float *input_pixels)
697 {
698  /* Load pixels from neighboring frames, and copy them into device buffer
699  * with channels reshuffled. */
700  size_t num_pixels = (size_t)width * (size_t)height;
701  array<float> neighbor_pixels(num_pixels * num_channels);
702  if (!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
703  return false;
704  }
705 
706  const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
707 
708  for (int i = 0; i < width * height; i++) {
709  for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
710  int image_channel = input_to_image_channel[j];
711  input_pixels[i * INPUT_NUM_CHANNELS + j] =
712  neighbor_pixels[((size_t)i) * num_channels + image_channel];
713  }
714  }
715 
716  return true;
717 }
718 
719 bool DenoiseImage::load(const string &in_filepath, string &error)
720 {
721  if (!Filesystem::is_regular(in_filepath)) {
722  error = "Couldn't find file: " + in_filepath;
723  return false;
724  }
725 
726  unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
727  if (!in) {
728  error = "Couldn't open file: " + in_filepath;
729  return false;
730  }
731 
732  in_spec = in->spec();
733  width = in_spec.width;
734  height = in_spec.height;
735  num_channels = in_spec.nchannels;
736 
737  if (!parse_channels(in_spec, error)) {
738  return false;
739  }
740 
741  if (layers.size() == 0) {
742  error = "Could not find a render layer containing denoising info";
743  return false;
744  }
745 
746  size_t num_pixels = (size_t)width * (size_t)height;
747  pixels.resize(num_pixels * num_channels);
748 
749  /* Read all channels into buffer. Reading all channels at once is faster
750  * than individually due to interleaved EXR channel storage. */
751  if (!in->read_image(TypeDesc::FLOAT, pixels.data())) {
752  error = "Failed to read image: " + in_filepath;
753  return false;
754  }
755 
756  return true;
757 }
758 
760  const vector<int> &frames,
761  string &error)
762 {
763  if (frames.size() > DENOISE_MAX_FRAMES - 1) {
764  error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
765  return false;
766  }
767 
768  for (int neighbor = 0; neighbor < frames.size(); neighbor++) {
769  int frame = frames[neighbor];
770  const string &filepath = filepaths[frame];
771 
772  if (!Filesystem::is_regular(filepath)) {
773  error = "Couldn't find neighbor frame: " + filepath;
774  return false;
775  }
776 
777  unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
778  if (!in_neighbor) {
779  error = "Couldn't open neighbor frame: " + filepath;
780  return false;
781  }
782 
783  const ImageSpec &neighbor_spec = in_neighbor->spec();
784  if (neighbor_spec.width != width || neighbor_spec.height != height) {
785  error = "Neighbor frame has different dimensions: " + filepath;
786  return false;
787  }
788 
789  foreach (DenoiseImageLayer &layer, layers) {
790  if (!layer.match_channels(neighbor, in_spec.channelnames, neighbor_spec.channelnames)) {
791  error = "Neighbor frame misses denoising data passes: " + filepath;
792  return false;
793  }
794  }
795 
796  in_neighbors.push_back(std::move(in_neighbor));
797  }
798 
799  return true;
800 }
801 
802 bool DenoiseImage::save_output(const string &out_filepath, string &error)
803 {
804  /* Save image with identical dimensions, channels and metadata. */
805  ImageSpec out_spec = in_spec;
806 
807  /* Ensure that the output frame contains sample information even if the input didn't. */
808  for (int i = 0; i < layers.size(); i++) {
809  string name = "cycles." + layers[i].name + ".samples";
810  if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
811  out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
812  }
813  }
814 
815  /* We don't need input anymore at this point, and will possibly
816  * overwrite the same file. */
817  close_input();
818 
819  /* Write to temporary file path, so we denoise images in place and don't
820  * risk destroying files when something goes wrong in file saving. */
821  string extension = OIIO::Filesystem::extension(out_filepath);
822  string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
823  string tmp_filepath = out_filepath + unique_name + extension;
824  unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
825 
826  if (!out) {
827  error = "Failed to open temporary file " + tmp_filepath + " for writing";
828  return false;
829  }
830 
831  /* Open temporary file and write image buffers. */
832  if (!out->open(tmp_filepath, out_spec)) {
833  error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
834  return false;
835  }
836 
837  bool ok = true;
838  if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
839  error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
840  ok = false;
841  }
842 
843  if (!out->close()) {
844  error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
845  ok = false;
846  }
847 
848  out.reset();
849 
850  /* Copy temporary file to output filepath. */
851  string rename_error;
852  if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
853  error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
854  ok = false;
855  }
856 
857  if (!ok) {
858  OIIO::Filesystem::remove(tmp_filepath);
859  }
860 
861  return ok;
862 }
863 
864 /* File pattern handling and outer loop over frames */
865 
867 {
868  samples_override = 0;
869  tile_size = make_int2(64, 64);
870 
871  num_frames = 0;
872 
873  /* Initialize task scheduler. */
875 
876  /* Initialize device. */
877  device = Device::create(device_info, stats, profiler, true);
878 
880  req.use_denoising = true;
881  device->load_kernels(req);
882 }
883 
885 {
886  delete device;
888 }
889 
891 {
892  assert(input.size() == output.size());
893 
894  num_frames = output.size();
895 
896  for (int frame = 0; frame < num_frames; frame++) {
897  /* Skip empty output paths. */
898  if (output[frame].empty()) {
899  continue;
900  }
901 
902  /* Determine neighbor frame numbers that should be used for filtering. */
903  vector<int> neighbor_frames;
904  for (int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
905  if (f >= 0 && f < num_frames && f != frame) {
906  neighbor_frames.push_back(f);
907  }
908  }
909 
910  /* Execute task. */
911  DenoiseTask task(device, this, frame, neighbor_frames);
912  if (!task.load()) {
913  error = task.error;
914  return false;
915  }
916 
917  if (!task.exec()) {
918  error = task.error;
919  return false;
920  }
921 
922  if (!task.save()) {
923  error = task.error;
924  return false;
925  }
926 
927  task.free();
928  }
929 
930  return true;
931 }
932 
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
static float frame_len(const Frame *frame)
Definition: MOD_skin.c:392
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static T sum(const btAlignedObjectArray< T > &items)
vector< unique_ptr< ImageInput > > in_neighbors
Definition: denoising.h:124
bool parse_channels(const ImageSpec &in_spec, string &error)
Definition: denoising.cpp:618
void close_input()
Definition: denoising.cpp:607
bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels)
Definition: denoising.cpp:694
bool load_neighbors(const vector< string > &filepaths, const vector< int > &frames, string &error)
Definition: denoising.cpp:759
array< float > pixels
Definition: denoising.h:120
vector< DenoiseImageLayer > layers
Definition: denoising.h:127
int num_channels
Definition: denoising.h:114
bool load(const string &in_filepath, string &error)
Definition: denoising.cpp:719
bool save_output(const string &out_filepath, string &error)
Definition: denoising.cpp:802
ImageSpec in_spec
Definition: denoising.h:123
void read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
Definition: denoising.cpp:679
int neighbor_frames
Definition: device_task.h:80
bool clamp_input
Definition: device_task.h:82
void release_tile()
Definition: denoising.cpp:367
DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector< int > &neighbor_frames)
Definition: denoising.cpp:227
map< int, device_vector< float > * > output_pixels
Definition: denoising.h:191
bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
Definition: denoising.cpp:249
thread_mutex tiles_mutex
Definition: denoising.h:186
bool get_cancel()
Definition: denoising.cpp:371
bool load()
Definition: denoising.cpp:526
string error
Definition: denoising.h:167
Device * device
Definition: denoising.h:172
int num_tiles
Definition: denoising.h:188
bool exec()
Definition: denoising.cpp:556
Denoiser * denoiser
Definition: denoising.h:171
list< RenderTile > tiles
Definition: denoising.h:187
bool save()
Definition: denoising.cpp:578
bool load_input_pixels(int layer)
Definition: denoising.cpp:440
device_vector< float > input_pixels
Definition: denoising.h:183
int current_layer
Definition: denoising.h:180
void map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
Definition: denoising.cpp:274
void free()
Definition: denoising.cpp:585
vector< int > neighbor_frames
Definition: denoising.h:176
void create_task(DeviceTask &task)
Definition: denoising.cpp:376
DenoiseImage image
Definition: denoising.h:179
void unmap_neighboring_tiles(RenderTileNeighbors &neighbors)
Definition: denoising.cpp:333
thread_mutex output_mutex
Definition: denoising.h:190
Device * device
Definition: denoising.h:67
int samples_override
Definition: denoising.h:55
int num_frames
Definition: denoising.h:69
string error
Definition: denoising.h:45
vector< string > output
Definition: denoising.h:52
bool run()
Definition: denoising.cpp:890
Stats stats
Definition: denoising.h:65
DenoiseParams params
Definition: denoising.h:60
Profiler profiler
Definition: denoising.h:66
vector< string > input
Definition: denoising.h:48
Denoiser(DeviceInfo &device_info)
Definition: denoising.cpp:866
int2 tile_size
Definition: denoising.h:57
Definition: device.h:293
static Device * create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background=true)
Definition: device.cpp:382
virtual void task_wait()=0
virtual void map_tile(Device *, RenderTile &)
Definition: device.h:438
virtual void task_add(DeviceTask &task)=0
virtual bool load_kernels(const DeviceRequestedFeatures &)
Definition: device.h:380
static const int SIZE
Definition: buffers.h:173
RenderTile target
Definition: buffers.h:177
RenderTile tiles[SIZE]
Definition: buffers.h:176
static const int CENTER
Definition: buffers.h:174
int stride
Definition: buffers.h:143
int sample
Definition: buffers.h:140
RenderBuffers * buffers
Definition: buffers.h:152
int num_samples
Definition: buffers.h:139
int tile_index
Definition: buffers.h:144
device_ptr buffer
Definition: buffers.h:146
Task task
Definition: buffers.h:136
int offset
Definition: buffers.h:142
int start_sample
Definition: buffers.h:138
static void exit()
Definition: util_task.cpp:96
static void init(int num_threads=0)
Definition: util_task.cpp:75
T * data()
Definition: util_array.h:208
T * resize(size_t newsize)
Definition: util_array.h:150
void clear()
Definition: util_array.h:188
device_ptr device_pointer
T * alloc(size_t width, size_t height=0, size_t depth=0)
void copy_from_device()
void copy_to_device()
void zero_to_device()
const char * label
static const int INPUT_NOISY_IMAGE
Definition: denoising.cpp:131
static CCL_NAMESPACE_BEGIN void print_progress(int num, int total, int frame, int num_frames)
Definition: denoising.cpp:33
static const int OUTPUT_NUM_CHANNELS
Definition: denoising.cpp:147
static void fill_mapping(vector< ChannelMapping > &map, int pos, string name, string channels)
Definition: denoising.cpp:119
static const int INPUT_DENOISING_DEPTH
Definition: denoising.cpp:127
static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
Definition: denoising.cpp:90
static bool split_last_dot(string &in, string &suffix)
Definition: denoising.cpp:75
static const int INPUT_DENOISING_SHADOWING
Definition: denoising.cpp:129
static vector< ChannelMapping > input_channels()
Definition: denoising.cpp:134
static const int INPUT_DENOISING_ALBEDO
Definition: denoising.cpp:130
static const int INPUT_DENOISING_NORMAL
Definition: denoising.cpp:128
static const int INPUT_NUM_CHANNELS
Definition: denoising.cpp:126
static vector< ChannelMapping > output_channels()
Definition: denoising.cpp:148
static const int INPUT_DENOISING_INTENSITY
Definition: denoising.cpp:133
static const int INPUT_DENOISING_VARIANCE
Definition: denoising.cpp:132
#define function_bind
@ MEM_READ_WRITE
Definition: device_memory.h:37
@ MEM_READ_ONLY
Definition: device_memory.h:36
@ DENOISER_NLM
Definition: device_task.h:36
#define DENOISE_MAX_FRAMES
uint pos
#define CCL_NAMESPACE_END
#define make_int2(x, y)
#define make_float3(x, y, z)
static void error(const char *str)
Definition: meshlaplacian.c:65
struct blender::compositor::@172::@174 task
static void unique_name(bNode *node)
#define min(a, b)
Definition: sort.c:51
vector< int > input_to_image_channel
Definition: denoising.h:85
bool match_channels(int neighbor, const std::vector< string > &channelnames, const std::vector< string > &neighbor_channelnames)
Definition: denoising.cpp:200
bool detect_denoising_channels()
Definition: denoising.cpp:157
vector< int > output_to_image_channel
Definition: denoising.h:92
vector< vector< int > > neighbor_input_to_image_channel
Definition: denoising.h:88
vector< string > channels
Definition: denoising.h:77
vector< int > layer_to_image_channel
Definition: denoising.h:79
float max
ccl_device float3 color_highlight_compress(float3 color, float3 *variance)
Definition: util_color.h:278
ccl_device_inline int clamp(int a, int mn, int mx)
Definition: util_math.h:283
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32
int system_console_width()
std::unique_lock< std::mutex > thread_scoped_lock
Definition: util_thread.h:41
ccl_device_inline size_t divide_up(size_t x, size_t y)
Definition: util_types.h:70
uint len