Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
distance_transform.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2021 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/*
20 eucledian distance transform for darktable Hanno Schwalm (hanno@schwalm-bremen.de) 2021/09
21 - adopted to C
22 - omp support
23 - reduced alloc/free using dt_alloc_align variants for better debug support
24 - tuned for performance in collaboration with Ingo Weyrich (heckflosse67@gmx.de) from rawtherapee
25
26 The original code is from:
27
28 *** Original copyright note ***
29 Implementation of the distance transform algorithm described in:
30
31 Distance Transforms of Sampled Functions
32 Pedro F. Felzenszwalb and Daniel P. Huttenlocher
33 Cornell Computing and Information Science TR2004-1963
34 Copyright (C) 2006 Pedro Felzenszwalb
35
36 This program is free software; you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation; either version 2 of the License, or
39 (at your option) any later version.
40*/
41
42/* Howto
43 float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height,
44 const float clip, const dt_distance_transform_t mode)
45 writes data to an 1-ch image at 'out' with dimensions given. 'out' must be aligned as by dt_alloc_align_float.
46 You may either
47 - prepare the 'out' image before calling the distance transform, in this case use DT_DISTANCE_TRANSFORM_NONE as mode.
48 you should have filled 'out' with either 0.0f or DT_DISTANCE_TRANSFORM_MAX marking the positions as on/off
49 - use DT_DISTANCE_TRANSFORM_MASK, in this case data found in src is checked vs clip, dt_image_distance_transform
50 will fill in the zeros / DT_DISTANCE_TRANSFORM_MAX
51 The returned float of this function is the maximum calculated distance
52*/
53
54#include "common/imagebuf.h"
55
61
62#define DT_DISTANCE_TRANSFORM_MAX (1e20)
63
64static void _image_distance_transform(const float *f, float *z, float *d, int *v, const int n)
65{
66 int k = 0;
67 v[0] = 0;
70 for(int q = 1; q <= n-1; q++)
71 {
72 float s = (f[q] + sqf((float)q)) - (f[v[k]] + sqf((float)v[k]));
73 while(s <= z[k] * (float)(2*q - 2*v[k]))
74 {
75 k--;
76 s = (f[q] + sqf((float)q)) - (f[v[k]] + sqf((float)v[k]));
77 }
78 s /= (float)(2*q - 2*v[k]);
79 k++;
80 v[k] = q;
81 z[k] = s;
83 }
84
85 k = 0;
86 for(int q = 0; q <= n-1; q++)
87 {
88 while(z[k+1] < (float)q)
89 k++;
90 d[q] = sqf((float)(q-v[k])) + f[v[k]];
91 }
92}
93
94float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height, const float clip, const dt_distance_transform_t mode)
95{
96 switch(mode)
97 {
99 break;
101#ifdef _OPENMP
102 #pragma omp parallel for simd default(none) \
103 dt_omp_firstprivate(src, out) \
104 dt_omp_sharedconst(clip, width, height) \
105 schedule(static) aligned(src, out : 64)
106#endif
107 for(size_t i = 0; i < width * height; i++)
108 out[i] = (src[i] < clip) ? 0.0f : DT_DISTANCE_TRANSFORM_MAX;
109 break;
110 default:
111 dt_iop_image_fill(out, 0.0f, width, height, 1);
112 fprintf(stderr,"[dt_image_distance_transform] called with unsupported mode %i\n", mode);
113 return 0.0f;
114 }
115
116 const size_t maxdim = MAX(width, height);
117 float max_distance = 0.0f;
118#ifdef _OPENMP
119 #pragma omp parallel \
120 reduction(max : max_distance) \
121 dt_omp_firstprivate(out) \
122 dt_omp_sharedconst(maxdim, width, height)
123#endif
124 {
125 float *f = dt_alloc_align_float(maxdim);
126 float *z = dt_alloc_align_float(maxdim + 1);
127 float *d = dt_alloc_align_float(maxdim);
128 int *v = dt_alloc_align(maxdim * sizeof(int));
129
130 // transform along columns
131#ifdef _OPENMP
132 #pragma omp for schedule(simd:static)
133#endif
134 for(size_t x = 0; x < width; x++)
135 {
136 for(size_t y = 0; y < height; y++)
137 f[y] = out[y*width + x];
139 for(size_t y = 0; y < height; y++)
140 out[y*width + x] = d[y];
141 }
142 // implicit barrier :-)
143 // transform along rows
144#ifdef _OPENMP
145 #pragma omp for schedule(simd:static) nowait
146#endif
147 for(size_t y = 0; y < height; y++)
148 {
149 _image_distance_transform(&out[y*width], z, d, v, width);
150 for(size_t x = 0; x < width; x++)
151 {
152 const float val = sqrtf(d[x]);
153 out[y*width + x] = val;
154 max_distance = fmaxf(max_distance, val);
155 }
156 }
158 dt_free_align(d);
159 dt_free_align(z);
160 dt_free_align(v);
161 }
162 return max_distance;
163}
164
165// clang-format off
166// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
167// vim: shiftwidth=2 expandtab tabstop=2 cindent
168// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
169// clang-format on
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:345
#define dt_free_align(A)
Definition darktable.h:334
dt_distance_transform_t
Definition distance_transform.h:57
@ DT_DISTANCE_TRANSFORM_NONE
Definition distance_transform.h:58
@ DT_DISTANCE_TRANSFORM_MASK
Definition distance_transform.h:59
float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height, const float clip, const dt_distance_transform_t mode)
Definition distance_transform.h:94
#define DT_DISTANCE_TRANSFORM_MAX
Definition distance_transform.h:62
static void _image_distance_transform(const float *f, float *z, float *d, int *v, const int n)
Definition distance_transform.h:64
static float f(const float t, const float c, const float x)
Definition graduatednd.c:173
void dt_iop_image_fill(float *const buf, const float fill_value, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.c:210
static float sqf(const float x)
Definition math.h:215
#define dt_alloc_align(B)
Definition tests/cache.c:22
#define MAX(a, b)
Definition thinplate.c:20