1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.openimaj.image.analysis.algorithm;
31
32 import java.io.File;
33 import java.io.IOException;
34
35 import org.openimaj.image.DisplayUtilities;
36 import org.openimaj.image.FImage;
37 import org.openimaj.image.ImageUtilities;
38 import org.openimaj.image.analyser.ImageAnalyser;
39
40
41
42
43
44
45
46
47
48 public class EuclideanDistanceTransform implements ImageAnalyser<FImage> {
49 FImage distances;
50 int [][] indices;
51
52
53
54
55 @Override
56 public void analyseImage(FImage image) {
57 if (distances == null || distances.height != image.height || distances.width != distances.height) {
58 distances = new FImage(image.width, image.height);
59 indices = new int[image.height][image.width];
60 }
61
62 squaredEuclideanDistance(image, distances, indices);
63 }
64
65
66
67
68 public FImage getDistances() {
69 return distances;
70 }
71
72
73
74
75 public int[][] getIndices() {
76 return indices;
77 }
78
79 protected static void DT1D(float [] f, float [] d, int [] v, int [] l, float [] z) {
80 int k = 0;
81
82 v[0] = 0;
83 z[0] = -Float.MAX_VALUE;
84 z[1] = Float.MAX_VALUE;
85
86 for (int q = 1; q < f.length; q++)
87 {
88 float s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
89
90 while (s <= z[k]) {
91 k--;
92 s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
93 }
94 k++;
95 v[k] = q;
96 z[k] = s;
97 z[k + 1] = Float.MAX_VALUE;
98 }
99
100 k = 0;
101 for (int q = 0; q < f.length; q++)
102 {
103 while (z[k + 1] < q)
104 k++;
105
106 d[q] = (q - v[k]) * (q - v[k]) + f[v[k]];
107 l[q] = v[k];
108 }
109 }
110
111
112
113
114
115
116
117
118 public static void squaredEuclideanDistanceBinary(FImage image, FImage distances, int[][] indices) {
119 float [] f = new float[Math.max(image.height, image.width)];
120 float [] d = new float[f.length];
121 int [] v = new int[f.length];
122 int [] l = new int[f.length];
123 float [] z = new float[f.length + 1];
124
125 for (int x=0; x<image.width; x++) {
126 for (int y=0; y<image.height; y++) {
127 f[y] = image.pixels[y][x] == 0 ? Float.MAX_VALUE : 0;
128 }
129
130 DT1D(f, d, v, l, z);
131 for (int y = 0; y < image.height; y++) {
132 distances.pixels[y][x] = d[y];
133 indices[y][x] = (l[y] * image.width) + x;
134 }
135 }
136
137 for (int y = 0; y < image.height; y++) {
138 DT1D(distances.pixels[y], d, v, l, z);
139
140 for (int x = 0; x < image.width; x++)
141 l[x] = indices[y][l[x]];
142
143 for (int x = 0; x < image.width; x++)
144 {
145 distances.pixels[y][x] = d[x];
146 indices[y][x] = l[x];
147 }
148 }
149 }
150
151
152
153
154
155
156
157
158
159
160 public static void squaredEuclideanDistance(FImage image, FImage distances, int[][] indices) {
161 float [] f = new float[Math.max(image.height, image.width)];
162 float [] d = new float[f.length];
163 int [] v = new int[f.length];
164 int [] l = new int[f.length];
165 float [] z = new float[f.length + 1];
166
167 for (int x=0; x<image.width; x++) {
168 for (int y=0; y<image.height; y++) {
169 f[y] = Float.isInfinite(image.pixels[y][x]) ? (image.pixels[y][x] > 0 ? Float.MAX_VALUE : -Float.MAX_VALUE) : image.pixels[y][x];
170 }
171
172 DT1D(f, d, v, l, z);
173 for (int y = 0; y < image.height; y++) {
174 distances.pixels[y][x] = d[y];
175 indices[y][x] = (l[y] * image.width) + x;
176 }
177 }
178
179 for (int y = 0; y < image.height; y++) {
180 DT1D(distances.pixels[y], d, v, l, z);
181
182 for (int x = 0; x < image.width; x++)
183 l[x] = indices[y][l[x]];
184
185 for (int x = 0; x < image.width; x++)
186 {
187 distances.pixels[y][x] = d[x];
188 indices[y][x] = l[x];
189 }
190 }
191 }
192
193
194
195
196
197
198 public static void main(String args[]) throws IOException{
199 FImage i = ImageUtilities.readF(new File("/Users/ss/Desktop/tache.jpg"));
200 EuclideanDistanceTransform etrans = new EuclideanDistanceTransform();
201
202 i.inverse();
203 for(int x = 0;x < i.width; x++)
204 for(int y = 0; y < i.height; y++)
205 if(i.pixels[y][x] == 1.0f)
206 i.setPixel(x, y, Float.MAX_VALUE);
207 DisplayUtilities.display(i);
208 i.analyseWith(etrans);
209 i = etrans.getDistances();
210 i.normalise();
211 DisplayUtilities.display(i);
212 }
213 }