Add support for alpha weighting to float image.
This commit is contained in:
parent
2411f3f5db
commit
4f576d5539
@ -12,6 +12,10 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
// This value is to prevent division by zero when weighting kernels by alpha.
|
||||||
|
#define ALPHA_EPSILON (1.0f / 256.0f)
|
||||||
|
|
||||||
|
|
||||||
using namespace nv;
|
using namespace nv;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -601,6 +605,15 @@ FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm) const
|
|||||||
return resize(filter, w, h, wm);
|
return resize(filter, w, h, wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Downsample applying a 1D kernel separately in each dimension.
|
||||||
|
FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm, uint alpha) const
|
||||||
|
{
|
||||||
|
const uint w = max(1, m_width / 2);
|
||||||
|
const uint h = max(1, m_height / 2);
|
||||||
|
|
||||||
|
return resize(filter, w, h, wm, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Downsample applying a 1D kernel separately in each dimension.
|
/// Downsample applying a 1D kernel separately in each dimension.
|
||||||
FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm) const
|
FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm) const
|
||||||
@ -672,10 +685,51 @@ FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode
|
|||||||
return dst_image.release();
|
return dst_image.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Downsample applying a 1D kernel separately in each dimension.
|
||||||
|
FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const
|
||||||
|
{
|
||||||
|
nvCheck(alpha < m_componentNum);
|
||||||
|
|
||||||
|
AutoPtr<FloatImage> tmp_image( new FloatImage() );
|
||||||
|
AutoPtr<FloatImage> dst_image( new FloatImage() );
|
||||||
|
|
||||||
|
PolyphaseKernel xkernel(filter, m_width, w, 32);
|
||||||
|
PolyphaseKernel ykernel(filter, m_height, h, 32);
|
||||||
|
|
||||||
|
{
|
||||||
|
tmp_image->allocate(m_componentNum, w, m_height);
|
||||||
|
dst_image->allocate(m_componentNum, w, h);
|
||||||
|
|
||||||
|
Array<float> tmp_column(h);
|
||||||
|
tmp_column.resize(h);
|
||||||
|
|
||||||
|
for (uint c = 0; c < m_componentNum; c++)
|
||||||
|
{
|
||||||
|
float * tmp_channel = tmp_image->channel(c);
|
||||||
|
|
||||||
|
for (uint y = 0; y < m_height; y++) {
|
||||||
|
this->applyKernelHorizontal(xkernel, y, c, alpha, wm, tmp_channel + y * w);
|
||||||
|
}
|
||||||
|
|
||||||
|
float * dst_channel = dst_image->channel(c);
|
||||||
|
|
||||||
|
for (uint x = 0; x < w; x++) {
|
||||||
|
tmp_image->applyKernelVertical(ykernel, x, c, alpha, wm, tmp_column.mutableBuffer());
|
||||||
|
|
||||||
|
for (uint y = 0; y < h; y++) {
|
||||||
|
dst_channel[y * w + x] = tmp_column[y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst_image.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Apply 2D kernel at the given coordinates and return result.
|
/// Apply 2D kernel at the given coordinates and return result.
|
||||||
float FloatImage::applyKernel(const Kernel2 * k, int x, int y, int c, WrapMode wm) const
|
float FloatImage::applyKernel(const Kernel2 * k, int x, int y, uint c, WrapMode wm) const
|
||||||
{
|
{
|
||||||
nvDebugCheck(k != NULL);
|
nvDebugCheck(k != NULL);
|
||||||
|
|
||||||
@ -704,7 +758,7 @@ float FloatImage::applyKernel(const Kernel2 * k, int x, int y, int c, WrapMode w
|
|||||||
|
|
||||||
|
|
||||||
/// Apply 1D vertical kernel at the given coordinates and return result.
|
/// Apply 1D vertical kernel at the given coordinates and return result.
|
||||||
float FloatImage::applyKernelVertical(const Kernel1 * k, int x, int y, int c, WrapMode wm) const
|
float FloatImage::applyKernelVertical(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const
|
||||||
{
|
{
|
||||||
nvDebugCheck(k != NULL);
|
nvDebugCheck(k != NULL);
|
||||||
|
|
||||||
@ -726,7 +780,7 @@ float FloatImage::applyKernelVertical(const Kernel1 * k, int x, int y, int c, Wr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
||||||
float FloatImage::applyKernelHorizontal(const Kernel1 * k, int x, int y, int c, WrapMode wm) const
|
float FloatImage::applyKernelHorizontal(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const
|
||||||
{
|
{
|
||||||
nvDebugCheck(k != NULL);
|
nvDebugCheck(k != NULL);
|
||||||
|
|
||||||
@ -749,7 +803,7 @@ float FloatImage::applyKernelHorizontal(const Kernel1 * k, int x, int y, int c,
|
|||||||
|
|
||||||
|
|
||||||
/// Apply 1D vertical kernel at the given coordinates and return result.
|
/// Apply 1D vertical kernel at the given coordinates and return result.
|
||||||
void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, WrapMode wm, float * output) const
|
void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, uint c, WrapMode wm, float * output) const
|
||||||
{
|
{
|
||||||
const uint length = k.length();
|
const uint length = k.length();
|
||||||
const float scale = float(length) / float(m_height);
|
const float scale = float(length) / float(m_height);
|
||||||
@ -781,7 +835,7 @@ void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, int c, Wr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
||||||
void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c, WrapMode wm, float * output) const
|
void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, WrapMode wm, float * output) const
|
||||||
{
|
{
|
||||||
const uint length = k.length();
|
const uint length = k.length();
|
||||||
const float scale = float(length) / float(m_width);
|
const float scale = float(length) / float(m_width);
|
||||||
@ -812,6 +866,79 @@ void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, int c,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Apply 1D vertical kernel at the given coordinates and return result.
|
||||||
|
void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, uint c, uint a, WrapMode wm, float * output) const
|
||||||
|
{
|
||||||
|
const uint length = k.length();
|
||||||
|
const float scale = float(length) / float(m_height);
|
||||||
|
const float iscale = 1.0f / scale;
|
||||||
|
|
||||||
|
const float width = k.width();
|
||||||
|
const int windowSize = k.windowSize();
|
||||||
|
|
||||||
|
const float * channel = this->channel(c);
|
||||||
|
const float * alpha = this->channel(a);
|
||||||
|
|
||||||
|
for (uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
const float center = (0.5f + i) * iscale;
|
||||||
|
|
||||||
|
const int left = (int)floorf(center - width);
|
||||||
|
const int right = (int)ceilf(center + width);
|
||||||
|
nvCheck(right - left <= windowSize);
|
||||||
|
|
||||||
|
float alphaSum = 0;
|
||||||
|
float sum = 0;
|
||||||
|
for (int j = 0; j < windowSize; ++j)
|
||||||
|
{
|
||||||
|
const int idx = this->index(x, j+left, wm);
|
||||||
|
|
||||||
|
float alphaFactor = alpha[idx] + ALPHA_EPSILON;
|
||||||
|
alphaSum += alphaFactor;
|
||||||
|
sum += k.valueAt(i, j) * channel[idx] * alphaFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[i] = sum / alphaSum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply 1D horizontal kernel at the given coordinates and return result.
|
||||||
|
void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * output) const
|
||||||
|
{
|
||||||
|
const uint length = k.length();
|
||||||
|
const float scale = float(length) / float(m_width);
|
||||||
|
const float iscale = 1.0f / scale;
|
||||||
|
|
||||||
|
const float width = k.width();
|
||||||
|
const int windowSize = k.windowSize();
|
||||||
|
|
||||||
|
const float * channel = this->channel(c);
|
||||||
|
const float * alpha = this->channel(a);
|
||||||
|
|
||||||
|
for (uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
const float center = (0.5f + i) * iscale;
|
||||||
|
|
||||||
|
const int left = (int)floorf(center - width);
|
||||||
|
const int right = (int)ceilf(center + width);
|
||||||
|
nvDebugCheck(right - left <= windowSize);
|
||||||
|
|
||||||
|
float alphaSum = 0.0f;
|
||||||
|
float sum = 0;
|
||||||
|
for (int j = 0; j < windowSize; ++j)
|
||||||
|
{
|
||||||
|
const int idx = this->index(left + j, y, wm);
|
||||||
|
|
||||||
|
float alphaFactor = alpha[idx] + ALPHA_EPSILON;
|
||||||
|
alphaSum += alphaFactor;
|
||||||
|
sum += k.valueAt(i, j) * channel[idx] * alphaFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[i] = sum / alphaSum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FloatImage* FloatImage::clone() const
|
FloatImage* FloatImage::clone() const
|
||||||
{
|
{
|
||||||
FloatImage* copy = new FloatImage();
|
FloatImage* copy = new FloatImage();
|
||||||
|
@ -73,17 +73,21 @@ public:
|
|||||||
|
|
||||||
NVIMAGE_API FloatImage * fastDownSample() const;
|
NVIMAGE_API FloatImage * fastDownSample() const;
|
||||||
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const;
|
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const;
|
||||||
|
NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const;
|
||||||
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const;
|
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const;
|
||||||
|
NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const;
|
||||||
|
|
||||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
|
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
|
||||||
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
|
//NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
NVIMAGE_API float applyKernel(const Kernel2 * k, int x, int y, int c, WrapMode wm) const;
|
NVIMAGE_API float applyKernel(const Kernel2 * k, int x, int y, uint c, WrapMode wm) const;
|
||||||
NVIMAGE_API float applyKernelVertical(const Kernel1 * k, int x, int y, int c, WrapMode wm) const;
|
NVIMAGE_API float applyKernelVertical(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const;
|
||||||
NVIMAGE_API float applyKernelHorizontal(const Kernel1 * k, int x, int y, int c, WrapMode wm) const;
|
NVIMAGE_API float applyKernelHorizontal(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const;
|
||||||
NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, int c, WrapMode wm, float * output) const;
|
NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, WrapMode wm, float * output) const;
|
||||||
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, int c, WrapMode wm, float * output) const;
|
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, WrapMode wm, float * output) const;
|
||||||
|
NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, uint a, WrapMode wm, float * output) const;
|
||||||
|
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * output) const;
|
||||||
|
|
||||||
|
|
||||||
uint width() const { return m_width; }
|
uint width() const { return m_width; }
|
||||||
|
Loading…
Reference in New Issue
Block a user