Kuwahara hydra
From Adobe Labs
Kuwahara source code
/*****************************************************************************
*
* Author: Joa Ebert
* http://blog.je2050.de
* Contact: j -at- je2050.de
*
*****************************************************************************/
kernel Kuwahara
< nameSpace: "popforge::ImageProcessing";
vendor: "Joa Ebert";
version: 1;
description: "Kuwahara filter with a kernal size of k = 2";
>
{
#define HANDLE_SQUARE(mean,variance) \
v = float3(0.0); \
vv = float3(0.0); \
mean += (val=sampleNearest(source, float2(x + 0.0, y + 0.0))); \
v += val; \
vv += val * val; \
\
mean += (val=sampleNearest(source, float2(x + 1.0, y + 0.0))); \
v += val; \
vv += val * val; \
\
mean += (val=sampleNearest(source, float2(x + 0.0, y + 1.0))); \
v += val; \
vv += val * val; \
\
mean += (val=sampleNearest(source, float2(x + 1.0, y + 1.0))); \
v += val; \
vv += val * val; \
\
variance = ((k2 * vv - v * v) / k2); \
mean = mean * ik2;
const float k = 2.0;
const float k2 = k * k;
const float ik2 = 1.0 / k2;
void evaluatePixel(in image3 source, out pixel3 sampled)
{
float2 pos = outCoord();
float3 v0, v1, v2, v3;
float x, y;
float3 v, vv;
float oldV = 1.0;
float bestV = 1.0;
pixel3 m0, m1, m2, m3;
pixel3 val;
pixel3 bestM;
// reset mean values;
m0 = m1 = m2 = m3 = pixel3(0.0);
// top left
x = pos.x - k;
y = pos.y - k;
HANDLE_SQUARE(m0, v0);
// top right
x = pos.x;
y = pos.y - k;
HANDLE_SQUARE(m1, v1);
// bottom left
x = pos.x - k;
y = pos.y;
HANDLE_SQUARE(m2, v2);
// bottom right
x = pos.x;
y = pos.y;
HANDLE_SQUARE(m3, v3);
/* local variance minimum for red channel */
bestV = (v0.r < bestV) ? v0.r : bestV;
bestM.r = (oldV != bestV) ? m0.r : bestM.r;
oldV = bestV;
bestV = (v1.r < bestV) ? v1.r : bestV;
bestM.r = (oldV != bestV) ? m1.r : bestM.r;
oldV = bestV;
bestV = (v2.r < bestV) ? v2.r : bestV;
bestM.r = (oldV != bestV) ? m2.r : bestM.r;
oldV = bestV;
bestV = (v3.r < bestV) ? v3.r : bestV;
bestM.r = (oldV != bestV) ? m3.r : bestM.r;
oldV = bestV;
/* reset local minimum */
bestV = 1.0;
oldV = 1.0;
/* local variance minimum for green channel */
bestV = (v0.g < bestV) ? v0.g : bestV;
bestM.g = (oldV != bestV) ? m0.g : bestM.g;
oldV = bestV;
bestV = (v1.g < bestV) ? v1.g : bestV;
bestM.g = (oldV != bestV) ? m1.g : bestM.g;
oldV = bestV;
bestV = (v2.g < bestV) ? v2.g : bestV;
bestM.g = (oldV != bestV) ? m2.g : bestM.g;
oldV = bestV;
bestV = (v3.g < bestV) ? v3.g : bestV;
bestM.g = (oldV != bestV) ? m3.g : bestM.g;
oldV = bestV;
/* reset local minimum */
bestV = 1.0;
oldV = 1.0;
/* local variance minimum for blue channel */
bestV = (v0.b < bestV) ? v0.b : bestV;
bestM.b = (oldV != bestV) ? m0.b : bestM.b;
oldV = bestV;
bestV = (v1.b < bestV) ? v1.b : bestV;
bestM.b = (oldV != bestV) ? m1.b : bestM.b;
oldV = bestV;
bestV = (v2.b < bestV) ? v2.b : bestV;
bestM.b = (oldV != bestV) ? m2.b : bestM.b;
oldV = bestV;
bestV = (v3.b < bestV) ? v3.b : bestV;
bestM.b = (oldV != bestV) ? m3.b : bestM.b;
oldV = bestV;
/* finally */
sampled = bestM;
}
}