Skip to content

Commit

Permalink
Implement NFOR denoiser
Browse files Browse the repository at this point in the history
  • Loading branch information
tunabrain committed Jun 6, 2017
1 parent 63648a8 commit 0cf990f
Show file tree
Hide file tree
Showing 13 changed files with 962 additions and 167 deletions.
41 changes: 41 additions & 0 deletions src/core/Logging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <tinyformat/tinyformat.hpp>

#include <iostream>
#include <string>
#include <ctime>

namespace Tungsten {

void printProgressBar(int tick, int maxTicks)
{
const int numCols = 80;
const int numTicks = numCols - 19;

int numFilledPrev = ((tick - 1)*numTicks)/maxTicks;
int numFilledCur = ((tick + 0)*numTicks)/maxTicks;
if (tick != 0 && numFilledPrev == numFilledCur)
return;

std::string bar(numTicks, ' ');
for (int i = 0; i < numFilledCur; ++i)
bar[i] = '#';

std::cout << tfm::format("\r [%s] %3d%%", bar, (100*tick)/maxTicks);
std::cout.flush();

if (tick == maxTicks) {
std::cout << '\r' << std::string(numCols, ' ') << '\r';
std::cout.flush();
}
}

void printTimestampedLog(const std::string &s)
{
std::time_t t = std::time(NULL);
char mbstr[100];
std::strftime(mbstr, sizeof(mbstr), "[%H:%M:%S] ", std::localtime(&t));
std::cout << mbstr << s << '\n';
std::cout.flush();
}

}
13 changes: 13 additions & 0 deletions src/core/Logging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef LOGGING_HPP_
#define LOGGING_HPP_

#include <string>

namespace Tungsten {

void printProgressBar(int tick, int maxTicks);
void printTimestampedLog(const std::string &s);

}

#endif /* LOGGING_HPP_ */
45 changes: 45 additions & 0 deletions src/core/Memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
#include <cstring>
#include <memory>

#ifdef __APPLE__
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif

namespace Tungsten {

template<typename T>
Expand All @@ -14,6 +20,45 @@ inline std::unique_ptr<T[]> zeroAlloc(size_t size)
return std::move(result);
}

template<class T>
struct AlignedDeleter
{
void operator()(T *p) const
{
#ifdef _WIN32
_aligned_free(p);
#else
free(p);
#endif
}
};

template<class T>
using aligned_unique_ptr = std::unique_ptr<T[], AlignedDeleter<T>>;

template<typename T>
inline aligned_unique_ptr<T> alignedAlloc(size_t size, int alignment)
{
void *ptr;
#ifdef _WIN32
ptr = _aligned_malloc(size*sizeof(T), alignment);
#else
if (posix_memalign(&ptr, alignment, size*sizeof(T)))
ptr = NULL;
#endif
if (!ptr)
return nullptr;
return aligned_unique_ptr<T>(static_cast<T *>(ptr));
}

template<typename T>
inline aligned_unique_ptr<T> alignedZeroAlloc(size_t size, int alignment)
{
auto result = alignedAlloc<T>(size, alignment);
std::memset(result.get(), 0, size*sizeof(T));
return std::move(result);
}

}

#endif /* MEMORY_HPP_ */
2 changes: 1 addition & 1 deletion src/core/cameras/OutputBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class OutputBuffer
if (!hdrFile.empty()) {
ImageIO::saveHdr(hdrFile, elementPointer(hdr.get()), _res.x(), _res.y(), elementCount(hdr[0]));
ImageIO::saveHdr(hdrFileA, elementPointer(_bufferA.get()), _res.x(), _res.y(), elementCount(_bufferA[0]));
ImageIO::saveHdr(hdrFileB, elementPointer(_bufferA.get()), _res.x(), _res.y(), elementCount(_bufferB[0]));
ImageIO::saveHdr(hdrFileB, elementPointer(_bufferB.get()), _res.x(), _res.y(), elementCount(_bufferB[0]));
}
if (!ldrFile.empty()) {
saveLdr(hdr.get(), ldrFile, true);
Expand Down
6 changes: 6 additions & 0 deletions src/core/math/Box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "IntTypes.hpp"
#include "MathUtil.hpp"
#include "Range.hpp"

#include "sse/SimdUtils.hpp"

Expand Down Expand Up @@ -121,6 +122,11 @@ class Box {
_max = Tungsten::min(_max, box._max);
}

Range<ElementType> range(int dimension) const
{
return Range<ElementType>(_min[dimension], _max[dimension]);
}

friend std::ostream &operator<< (std::ostream &stream, const Box &box) {
stream << '(' << box.min() << " - " << box.max() << ')';
return stream;
Expand Down
51 changes: 51 additions & 0 deletions src/core/math/Range.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef RANGE_HPP_
#define RANGE_HPP_

namespace Tungsten {

template<typename T> class RangeIterator;

template<typename T>
class Range
{
T _start, _end, _step;

public:
Range(T start, T end, T step = T(1))
: _start(start), _end(end), _step(step)
{
}

RangeIterator<T> begin() const;
RangeIterator<T> end() const;
};

template<typename T>
Range<T> range(T start, T end, T step = T(1))
{
return Range<T>(start, end, step);
}

template<typename T>
class RangeIterator
{
T _pos, _step;

public:
RangeIterator(T pos, T step) : _pos(pos), _step(step) {}

bool operator!=(const RangeIterator &o) const { return _pos < o._pos; }
RangeIterator &operator++() { _pos += _step; return *this; }
RangeIterator operator++(int) { RangeIterator copy(*this); operator++(); return copy; }
T operator*() const { return _pos; }
};

template<typename T>
RangeIterator<T> Range<T>::begin() const { return RangeIterator<T>(_start, _step); }

template<typename T>
RangeIterator<T> Range<T>::end() const { return RangeIterator<T>(_end, _step); }

}

#endif /* RANGE_HPP_ */
94 changes: 94 additions & 0 deletions src/denoiser/BoxFilter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#ifndef BOXFILTER_HPP_
#define BOXFILTER_HPP_

#include "math/Box.hpp"

#include "Pixmap.hpp"

namespace Tungsten {

template<typename Texel>
void boxFilterSlow(const Pixmap<Texel> &src, Pixmap<Texel> &result, int R, Box2i subImage = Box2i())
{
if (subImage.empty())
subImage = Box2i(Vec2i(0), Vec2i(src.w(), src.h()));

int x0 = subImage.min().x(), x1 = subImage.max().x();
int y0 = subImage.min().y(), y1 = subImage.max().y();

for (int y = y0; y < y1; ++y) {
for (int x = x0; x < x1; ++x) {
Texel sum(0.0f);
int pixelCount = 0;
for (int dy = -R; dy <= R; ++dy) {
for (int dx = -R; dx <= R; ++dx) {
int xp = x + dx;
int yp = y + dy;
if (xp >= x0 && xp < x1 && yp >= y0 && yp < y1) {
sum += src(xp, yp);
pixelCount++;
}
}
}

result(x, y) = sum/pixelCount;
}
}
}

template<typename Texel>
void boxFilter(const Pixmap<Texel> &src, Pixmap<Texel> &tmp, Pixmap<Texel> &result, int R, Box2i subImage = Box2i())
{
if (subImage.empty())
subImage = Box2i(Vec2i(0), Vec2i(src.w(), src.h()));

int x0 = subImage.min().x(), x1 = subImage.max().x();
int y0 = subImage.min().y(), y1 = subImage.max().y();

if (x1 - x0 < 2*R || y1 - y0 < 2*R) {
boxFilterSlow(src, result, R, subImage);
return;
}

float factor = 1.0f/(2*R + 1);

for (int y = y0; y < y1; ++y) {
Texel sumL(0.0f);
Texel sumR(0.0f);
for (int x = 0; x < 2*R; ++x) {
sumL += src(x0 + x, y);
sumR += src(x1 - 1 - x, y);
if (x >= R) {
tmp(x0 + x - R , y) = sumL/(x + 1);
tmp(x1 - 1 - (x - R), y) = sumR/(x + 1);
}
}
for (int x = x0 + R; x < x1 - R; ++x) {
sumL += src(x + R, y);
tmp(x, y) = sumL*factor;
sumL -= src(x - R, y);
}
}

for (int x = x0; x < x1; ++x) {
Texel sumL(0.0f);
Texel sumR(0.0f);
for (int y = 0; y < 2*R; ++y) {
sumL += tmp(x, y0 + y);
sumR += tmp(x, y1 - 1 - y);
if (y >= R) {
result(x, y0 + y - R) = sumL/(y + 1);
result(x, y1 - 1 - (y - R)) = sumR/(y + 1);
}
}
for (int y = y0 + R; y < y1 - R; ++y) {
sumL += tmp(x, y + R);
result(x, y) = sumL*factor;
sumL -= tmp(x, y - R);
}
}
}

}

#endif /* BOXFILTER_HPP_ */
Loading

0 comments on commit 0cf990f

Please sign in to comment.