[gegl] noise-reduction: use 2nd order derivative for diffusion condition
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] noise-reduction: use 2nd order derivative for diffusion condition
- Date: Tue, 14 Jun 2011 13:06:46 +0000 (UTC)
commit 28b9154afd4054b085816f987538477f47e41d89
Author: �yvind Kolås <pippin gimp org>
Date: Tue Jun 14 11:04:35 2011 +0100
noise-reduction: use 2nd order derivative for diffusion condition
Removing the edge-preservation/lambda argument, as well as diffusion arguments from op
making the configuration of the operation simpler.
operations/common/noise-reduction.c | 77 +++++++++++++---------------------
1 files changed, 30 insertions(+), 47 deletions(-)
---
diff --git a/operations/common/noise-reduction.c b/operations/common/noise-reduction.c
index 0f8707f..26e8e37 100644
--- a/operations/common/noise-reduction.c
+++ b/operations/common/noise-reduction.c
@@ -18,9 +18,7 @@
#ifdef GEGL_CHANT_PROPERTIES
-gegl_chant_double (edge_preservation, "Smoothing", 0.0, 0.075, 0.005, "Amount of smoothing to do")
-gegl_chant_double (diffusion, "Diffusion", 0.0, 1.0, 0.5, "Amount of diffusion to do per iteration, 1.0 is max")
-gegl_chant_int (iterations, "Iterations", 1, 50, 10, "Number of iterations")
+gegl_chant_int (iterations, "Iterations", 1, 50, 5, "Number of iterations, more iterations takes longer time but might also make the image less noisy.")
#else
@@ -34,9 +32,7 @@ static void
noise_reduction (GeglBuffer *src,
const GeglRectangle *src_rect,
GeglBuffer *dst,
- const GeglRectangle *dst_rect,
- gdouble edge_preservation,
- gdouble diffusion);
+ const GeglRectangle *dst_rect);
static void prepare (GeglOperation *operation)
{
@@ -92,7 +88,7 @@ process (GeglOperation *operation,
source = input;
if (iteration == o->iterations-1)
target = output;
- noise_reduction (source, &source_rect, target, &target_rect, o->edge_preservation, o->diffusion);
+ noise_reduction (source, &source_rect, target, &target_rect);
}
if (temp[0])
@@ -107,9 +103,7 @@ static void
noise_reduction (GeglBuffer *src,
const GeglRectangle *src_rect,
GeglBuffer *dst,
- const GeglRectangle *dst_rect,
- gdouble edge_preservation,
- gdouble diffusion)
+ const GeglRectangle *dst_rect)
{
int c;
int x,y;
@@ -118,11 +112,14 @@ noise_reduction (GeglBuffer *src,
float *dst_buf;
int src_width = src_rect->width;
-#define DIRECTIONS 8
- int offsets2[DIRECTIONS][2] = {{ -1, -1}, {0, -1},{1, -1},
- { -1, 0}, {1, 0},
- { -1, 1}, {0, 1}, {1, 1}};
- int offsets[DIRECTIONS]; /* sizeof(float) offsets for neighbours */
+ int rel_offsets[8][2] = {{ -1, -1}, {0, -1},{1, -1},
+ { -1, 0}, {1, 0},
+ { -1, 1}, {0, 1}, {1, 1}};
+ int offsets[8]; /* sizeof(float) offsets for neighbours */
+
+ /* initialize offsets, dependent on source buffer width */
+ for (c = 0; c < 8; c++)
+ offsets[c] = ((rel_offsets[c][0])+((rel_offsets[c][1]) * src_width)) * 4;
src_buf = g_new0 (float, src_rect->width * src_rect->height * 4);
dst_buf = g_new0 (float, dst_rect->width * dst_rect->height * 4);
@@ -130,8 +127,6 @@ noise_reduction (GeglBuffer *src,
gegl_buffer_get (src, 1.0, src_rect, babl_format ("R'G'B'A float"), src_buf,
GEGL_AUTO_ROWSTRIDE);
- for (c = 0; c < DIRECTIONS; c++)
- offsets[c] = ((offsets2[c][0])+((offsets2[c][1]) * src_width)) * 4;
offset = 0;
for (y=0; y<dst_rect->height; y++)
@@ -142,50 +137,38 @@ noise_reduction (GeglBuffer *src,
for (c=0; c<3; c++)
{
float result_sum = 0.0;
- float original_gradient[DIRECTIONS];
+ float original_gradient[4];
int dir;
- float max = -100.0;
- float min = 100.0;
- float lambda;
- for (dir = 0; dir < DIRECTIONS; dir++)
+ for (dir = 0; dir < 4; dir++)
{ /* initialize original gradients */
- float *neighbour_pix = center_pix + offsets[dir];
- original_gradient[dir] = center_pix[c] - neighbour_pix[c];
- original_gradient[dir] *= original_gradient[dir];
-
- if (neighbour_pix[c] > max)
- max = neighbour_pix[c];
- if (neighbour_pix[c] < min)
- min = neighbour_pix[c];
+ float *pix = center_pix + offsets[dir];
+ float *pix_opposite = center_pix + offsets[(dir+4)%8];
+#define POW2(a) ((a)*(a))
+ original_gradient[dir] = POW2(center_pix[c] - pix[c]) +
+ POW2(center_pix[c] - pix_opposite[c]);
}
- lambda = edge_preservation * (max-min); /* scale lambda based on
- neighbourhood range */
-
- for (dir = 0; dir < DIRECTIONS; dir++)
+ for (dir = 0; dir < 8; dir++)
{
- float *neighbour_pix = center_pix + offsets[dir];
- float result = (center_pix[c] * (1.0-diffusion) + neighbour_pix[c] * diffusion);
- int comparing_dir;
- for (comparing_dir = 0; comparing_dir < DIRECTIONS; comparing_dir++)
- if (G_LIKELY (comparing_dir != dir))
+ float *pix = center_pix + offsets[dir];
+ float result = (pix[c] + center_pix[c]) /2;
+ int comparison_dir;
+ for (comparison_dir = 0; comparison_dir < 4; comparison_dir++)
+ if (G_LIKELY (comparison_dir != dir))
{
- float *pix2 = center_pix + offsets[comparing_dir];
- float new_gradient = (result - pix2[c]);
- new_gradient *= new_gradient;
- if (G_UNLIKELY (new_gradient > original_gradient[comparing_dir] + lambda))
+ float *pix2 = center_pix + offsets[comparison_dir];
+ float *pix2b = center_pix + offsets[(comparison_dir+4)%8];
+ float new_gradient = POW2(result - pix2[c]) + POW2(result - pix2b[c]);
+ if (G_UNLIKELY (new_gradient > original_gradient[comparison_dir]))
{
- /* if influencing the center pixel by a smooth
- in this direction, skip it in the summed average
- of smoothing directions */
result = center_pix[c];
break;
}
}
result_sum += result;
}
- dst_buf[offset*4+c] = result_sum / DIRECTIONS;
+ dst_buf[offset*4+c] = result_sum / 8;
}
dst_buf[offset*4+3] = center_pix[3]; /* copy alpha */
offset++;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]