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.processing.morphology;
31
32 import java.util.Arrays;
33 import java.util.HashSet;
34 import java.util.Set;
35
36 import org.openimaj.image.pixel.Pixel;
37
38
39
40
41
42
43
44
45
46 public class StructuringElement {
47
48
49
50 public final static StructuringElement BOX;
51
52
53
54
55 public final static StructuringElement CROSS;
56
57
58
59
60 public final static StructuringElement HPIT;
61
62
63 static {
64 BOX = new StructuringElement();
65 BOX.positive.add(new Pixel(-1, -1));
66 BOX.positive.add(new Pixel(0, -1));
67 BOX.positive.add(new Pixel(1, -1));
68 BOX.positive.add(new Pixel(-1, 0));
69 BOX.positive.add(new Pixel(0, 0));
70 BOX.positive.add(new Pixel(1, 0));
71 BOX.positive.add(new Pixel(-1, 1));
72 BOX.positive.add(new Pixel(0, 1));
73 BOX.positive.add(new Pixel(1, 1));
74
75 CROSS = new StructuringElement();
76 CROSS.positive.add(new Pixel(0, -1));
77 CROSS.positive.add(new Pixel(-1, 0));
78 CROSS.positive.add(new Pixel(0, 0));
79 CROSS.positive.add(new Pixel(1, 0));
80 CROSS.positive.add(new Pixel(0, 1));
81
82 HPIT = new StructuringElement();
83 HPIT.positive.add(new Pixel(-1, 0));
84 HPIT.positive.add(new Pixel(1, 0));
85 }
86
87
88
89
90 public Set<Pixel> positive = new HashSet<Pixel>();
91
92
93
94
95 public Set<Pixel> negative = new HashSet<Pixel>();
96
97
98
99
100 public StructuringElement() {
101
102 }
103
104
105
106
107
108
109
110
111
112
113 public StructuringElement(Set<Pixel> positive, Set<Pixel> negative) {
114 if (positive != null)
115 this.positive.addAll(positive);
116 if (negative != null)
117 this.negative.addAll(negative);
118 }
119
120
121
122
123
124
125
126
127
128
129 public StructuringElement(Pixel[] positive, Pixel[] negative) {
130 if (positive != null)
131 this.positive.addAll(Arrays.asList(positive));
132 if (negative != null)
133 this.negative.addAll(Arrays.asList(negative));
134 }
135
136
137
138
139
140
141 public int[] size() {
142 int xmin = Integer.MAX_VALUE;
143 int xmax = -Integer.MAX_VALUE;
144 int ymin = Integer.MAX_VALUE;
145 int ymax = -Integer.MAX_VALUE;
146
147 for (final Pixel p : positive) {
148 if (p.x < xmin)
149 xmin = p.x;
150 if (p.x > xmax)
151 xmax = p.x;
152 if (p.y < ymin)
153 ymin = p.y;
154 if (p.y > ymax)
155 ymax = p.y;
156 }
157 for (final Pixel p : negative) {
158 if (p.x < xmin)
159 xmin = p.x;
160 if (p.x > xmax)
161 xmax = p.x;
162 if (p.y < ymin)
163 ymin = p.y;
164 if (p.y > ymax)
165 ymax = p.y;
166 }
167
168 return new int[] { 1 + xmax - xmin, 1 + ymax - ymin, xmin, ymin };
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public static StructuringElement parseElement(String ele, int cx, int cy) {
186 final String[] lines = ele.split("\\n");
187 final int height = lines.length;
188 final int width = lines[0].length();
189
190 final StructuringElement se = new StructuringElement();
191
192 for (int j = 0; j < height; j++) {
193 for (int i = 0; i < width; i++) {
194 final char c = lines[j].charAt(i);
195
196 if (c == '*') {
197 se.positive.add(new Pixel(i - cx, j - cy));
198 } else if (c == 'o') {
199 se.negative.add(new Pixel(i - cx, j - cy));
200 }
201 }
202 }
203
204 return se;
205 }
206
207 @Override
208 public String toString() {
209 final int[] sz = size();
210 String s = "";
211
212 for (int j = 0; j < sz[1]; j++) {
213 for (int i = 0; i < sz[0]; i++) {
214 final Pixel p = new Pixel(i + sz[2], j + sz[3]);
215
216 if (positive.contains(p))
217 s += "*";
218 else if (negative.contains(p))
219 s += "o";
220 else
221 s += ".";
222 }
223 s += "\n";
224 }
225
226 return s;
227 }
228
229
230
231
232
233
234
235
236
237
238
239 public boolean matches(Pixel p, Set<Pixel> pixels) {
240
241 return (intersect(p, pixels).size() == countActive());
242 }
243
244 Set<Pixel> intersect(Pixel p, Set<Pixel> pixels) {
245 final Set<Pixel> intersect = new HashSet<Pixel>();
246
247
248 for (final Pixel sep : positive) {
249 final Pixel imp = new Pixel(p.x + sep.x, p.y + sep.y);
250
251 if (pixels.contains(imp))
252 intersect.add(imp);
253 }
254
255
256 for (final Pixel sep : negative) {
257 final Pixel imp = new Pixel(p.x + sep.x, p.y + sep.y);
258
259 if (!pixels.contains(imp))
260 intersect.add(imp);
261 }
262
263 return intersect;
264 }
265
266
267
268
269
270
271
272 public int countActive() {
273 return positive.size() + negative.size();
274 }
275
276
277
278
279
280
281
282
283 public static StructuringElement disk(int radius) {
284 final StructuringElement se = new StructuringElement();
285 final int r2 = radius * radius;
286
287 for (int j = -radius; j <= radius; j++) {
288 final int j2 = j * j;
289 for (int i = -radius; i <= radius; i++) {
290 if ((i * i + j2) <= r2) {
291 se.positive.add(new Pixel(i, j));
292 }
293 }
294 }
295
296 return se;
297 }
298 }