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