27 #include <OpenImageIO/filesystem.h>
35 const char *
label =
"Denoise Frame ";
38 cols -= strlen(
label);
41 for (
int x = total;
x > 9;
x /= 10) {
45 int bars = cols - 2 *
len - 6;
47 printf(
"\r%s",
label);
51 for (
int x = num_frames - 1;
x > 9;
x /= 10) {
58 int v = int(
float(num) * bars / total);
60 for (
int i = 0; i <
v; i++) {
66 for (
int i =
v + 1; i < bars; i++) {
77 size_t pos = in.rfind(
".");
78 if (
pos == string::npos) {
81 suffix = in.substr(
pos + 1);
82 in = in.substr(0,
pos);
91 string name,
string &renderlayer,
string &pass,
string &channel,
bool multiview_channels)
105 if (multiview_channels) {
106 renderlayer +=
"." +
view;
121 for (
const char *chan = channels.c_str(); *chan; chan++) {
122 map.push_back({
pos++, name +
"." + *chan});
169 size_t input_channel = mapping.
channel;
170 size_t layer_channel = i -
channels.begin();
184 size_t output_channel = mapping.
channel;
185 size_t layer_channel = i -
channels.begin();
201 const std::vector<string> &channelnames,
202 const std::vector<string> &neighbor_channelnames)
207 assert(mapping.size() == 0);
212 std::vector<string>::const_iterator frame_channel = find(
213 neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
215 if (frame_channel == neighbor_channelnames.end()) {
219 mapping[i] = frame_channel - neighbor_channelnames.begin();
231 : denoiser(denoiser),
234 neighbor_frames(neighbor_frames),
257 tile =
tiles.front();
286 int dx = (i % 3) - 1;
287 int dy = (i / 3) - 1;
311 for (
int y = 0;
y < center_tile.
h;
y++) {
323 target_tile = center_tile;
325 target_tile.
stride = target_tile.
w;
326 target_tile.
offset -= target_tile.
x + target_tile.
y * target_tile.
stride;
342 output_lock.unlock();
353 for (
int y = 0;
y < target_tile.
h;
y++) {
388 task.denoising.use =
true;
389 task.denoising.store_passes =
false;
390 task.denoising_from_render =
false;
400 task.pass_denoising_data = 0;
401 task.pass_denoising_clean = -1;
415 for (
int ty = 0; ty < tiles_y; ty++) {
416 for (
int tx = 0; tx < tiles_x; tx++) {
431 tiles.push_back(tile);
452 buffer_data += frame_stride;
457 error =
"Failed to read neighbor frame pixels";
460 buffer_data += frame_stride;
469 buffer_data[i] =
clamp(buffer_data[i], -1e8f, 1e8f);
475 float *
data = buffer_data + 14;
478 for (
int y = 0;
y < h;
y++) {
479 for (
int x = 0;
x <
w;
x++) {
482 for (
int dx =
max(
x -
r, 0); dx <
min(
x +
r + 1,
w); dx++, n++) {
485 temp[
y *
w +
x] =
sum / n;
489 for (
int y = 0;
y < h;
y++) {
490 for (
int x = 0;
x <
w;
x++) {
494 for (
int dy =
max(
y -
r, 0); dy <
min(
y +
r + 1, h); dy++, n++) {
495 sum += temp[dy *
w +
x];
503 data = buffer_data + 8;
504 for (
int y = 0;
y < h;
y++) {
505 for (
int x = 0;
x <
w;
x++) {
510 data[idx + 1] = color.y;
511 data[idx + 2] = color.z;
515 buffer_data += frame_stride;
538 error =
"No image layers found to denoise in " + center_filepath;
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);
630 map<string, DenoiseImageLayer> file_layers;
631 for (
int i = 0; i < channels.size(); i++) {
632 string layer, pass, channel;
634 file_layers[layer].channels.push_back(pass +
"." + channel);
635 file_layers[layer].layer_to_image_channel.push_back(i);
641 for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
643 const string &name = i->first;
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;
668 "No sample number specified in the file for layer %s or on the command line",
687 int image_channel = input_to_image_channel[j];
700 size_t num_pixels = (size_t)
width * (
size_t)
height;
702 if (!
in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.
data())) {
710 int image_channel = input_to_image_channel[j];
712 neighbor_pixels[((size_t)i) *
num_channels + image_channel];
721 if (!Filesystem::is_regular(in_filepath)) {
722 error =
"Couldn't find file: " + in_filepath;
726 unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
728 error =
"Couldn't open file: " + in_filepath;
742 error =
"Could not find a render layer containing denoising info";
746 size_t num_pixels = (size_t)
width * (
size_t)
height;
751 if (!in->read_image(TypeDesc::FLOAT,
pixels.
data())) {
752 error =
"Failed to read image: " + in_filepath;
768 for (
int neighbor = 0; neighbor < frames.size(); neighbor++) {
769 int frame = frames[neighbor];
770 const string &filepath = filepaths[frame];
772 if (!Filesystem::is_regular(filepath)) {
773 error =
"Couldn't find neighbor frame: " + filepath;
777 unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
779 error =
"Couldn't open neighbor frame: " + filepath;
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;
791 error =
"Neighbor frame misses denoising data passes: " + filepath;
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)) {
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));
827 error =
"Failed to open temporary file " + tmp_filepath +
" for writing";
832 if (!out->open(tmp_filepath, out_spec)) {
833 error =
"Failed to open file " + tmp_filepath +
" for writing: " + out->geterror();
838 if (!out->write_image(TypeDesc::FLOAT,
pixels.
data())) {
839 error =
"Failed to write to file " + tmp_filepath +
": " + out->geterror();
844 error =
"Failed to save to file " + tmp_filepath +
": " + out->geterror();
852 if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
853 error =
"Failed to move denoised image to " + out_filepath +
": " + rename_error;
858 OIIO::Filesystem::remove(tmp_filepath);
896 for (
int frame = 0; frame <
num_frames; frame++) {
898 if (
output[frame].empty()) {
906 neighbor_frames.push_back(f);
_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)
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static T sum(const btAlignedObjectArray< T > &items)
vector< unique_ptr< ImageInput > > in_neighbors
bool parse_channels(const ImageSpec &in_spec, string &error)
bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels)
bool load_neighbors(const vector< string > &filepaths, const vector< int > &frames, string &error)
vector< DenoiseImageLayer > layers
bool load(const string &in_filepath, string &error)
bool save_output(const string &out_filepath, string &error)
void read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector< int > &neighbor_frames)
map< int, device_vector< float > * > output_pixels
bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
bool load_input_pixels(int layer)
device_vector< float > input_pixels
void map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
vector< int > neighbor_frames
void create_task(DeviceTask &task)
void unmap_neighboring_tiles(RenderTileNeighbors &neighbors)
thread_mutex output_mutex
Denoiser(DeviceInfo &device_info)
static Device * create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background=true)
virtual void task_wait()=0
virtual void map_tile(Device *, RenderTile &)
virtual void task_add(DeviceTask &task)=0
virtual bool load_kernels(const DeviceRequestedFeatures &)
static void init(int num_threads=0)
T * resize(size_t newsize)
device_ptr device_pointer
T * alloc(size_t width, size_t height=0, size_t depth=0)
static const int INPUT_NOISY_IMAGE
static CCL_NAMESPACE_BEGIN void print_progress(int num, int total, int frame, int num_frames)
static const int OUTPUT_NUM_CHANNELS
static void fill_mapping(vector< ChannelMapping > &map, int pos, string name, string channels)
static const int INPUT_DENOISING_DEPTH
static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
static bool split_last_dot(string &in, string &suffix)
static const int INPUT_DENOISING_SHADOWING
static vector< ChannelMapping > input_channels()
static const int INPUT_DENOISING_ALBEDO
static const int INPUT_DENOISING_NORMAL
static const int INPUT_NUM_CHANNELS
static vector< ChannelMapping > output_channels()
static const int INPUT_DENOISING_INTENSITY
static const int INPUT_DENOISING_VARIANCE
#define DENOISE_MAX_FRAMES
#define CCL_NAMESPACE_END
#define make_float3(x, y, z)
static void error(const char *str)
struct blender::compositor::@172::@174 task
static void unique_name(bNode *node)
vector< int > input_to_image_channel
bool match_channels(int neighbor, const std::vector< string > &channelnames, const std::vector< string > &neighbor_channelnames)
bool detect_denoising_channels()
vector< int > output_to_image_channel
vector< vector< int > > neighbor_input_to_image_channel
vector< string > channels
vector< int > layer_to_image_channel
ccl_device float3 color_highlight_compress(float3 color, float3 *variance)
ccl_device_inline int clamp(int a, int mn, int mx)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
int system_console_width()
std::unique_lock< std::mutex > thread_scoped_lock
ccl_device_inline size_t divide_up(size_t x, size_t y)