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 __OMP_FOR_SIMD__(aligned(src, out : 64))
106 for(size_t i = 0; i < width * height; i++)
107 out[i] = (src[i] < clip) ? 0.0f : DT_DISTANCE_TRANSFORM_MAX;
108 break;
109 default:
110 dt_iop_image_fill(out, 0.0f, width, height, 1);
111 fprintf(stderr,"[dt_image_distance_transform] called with unsupported mode %i\n", mode);
112 return 0.0f;
113 }
114
115 const size_t maxdim = MAX(width, height);
116 float max_distance = 0.0f;
117#ifdef _OPENMP
118 #pragma omp parallel \
119 reduction(max : max_distance)
120#endif
121 {
123 float *z = dt_pixelpipe_cache_alloc_align_float_cache(maxdim + 1, 0);
125 int *v = dt_pixelpipe_cache_alloc_align_cache(maxdim * sizeof(int), 0);
126
127 // transform along columns
128#ifdef _OPENMP
129 #pragma omp for
130#endif
131 for(size_t x = 0; x < width; x++)
132 {
133 for(size_t y = 0; y < height; y++)
134 f[y] = out[y*width + x];
136 for(size_t y = 0; y < height; y++)
137 out[y*width + x] = d[y];
138 }
139 // implicit barrier :-)
140 // transform along rows
141#ifdef _OPENMP
142 #pragma omp for nowait
143#endif
144 for(size_t y = 0; y < height; y++)
145 {
147 for(size_t x = 0; x < width; x++)
148 {
149 const float val = sqrtf(d[x]);
150 out[y*width + x] = val;
151 max_distance = fmaxf(max_distance, val);
152 }
153 }
158 }
159 return max_distance;
160}
161
162// clang-format off
163// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
164// vim: shiftwidth=2 expandtab tabstop=2 cindent
165// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
166// clang-format on
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
const float i
Definition colorspaces_inline_conversions.h:440
const dt_aligned_pixel_t f
Definition colorspaces_inline_conversions.h:102
const float d
Definition colorspaces_inline_conversions.h:680
const dt_colormatrix_t dt_aligned_pixel_t out
Definition colorspaces_inline_conversions.h:42
const float n
Definition colorspaces_inline_conversions.h:678
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
Definition darktable.h:447
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
Definition darktable.h:433
#define dt_pixelpipe_cache_free_align(mem)
Definition darktable.h:453
#define __OMP_FOR_SIMD__(...)
Definition darktable.h:260
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:214
static const float x
Definition iop_profile.h:235
const float v
Definition iop_profile.h:221
float *const restrict const size_t k
Definition luminance_mask.h:78
#define MAX(a, b)
Definition thinplate.c:29