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.HashSet;
33 import java.util.Set;
34
35 import org.openimaj.image.FImage;
36 import org.openimaj.image.pixel.ConnectedComponent;
37 import org.openimaj.image.pixel.Pixel;
38 import org.openimaj.image.processing.algorithm.MinFilter;
39 import org.openimaj.image.processor.KernelProcessor;
40 import org.openimaj.image.processor.connectedcomponent.ConnectedComponentProcessor;
41 import org.openimaj.math.geometry.shape.Rectangle;
42
43
44
45
46
47
48
49 public class Erode implements ConnectedComponentProcessor, KernelProcessor<Float, FImage> {
50 protected StructuringElement element;
51 protected int cx;
52 protected int cy;
53 protected int sw;
54 protected int sh;
55
56
57
58
59
60
61
62 public Erode(StructuringElement se) {
63 this.element = se;
64
65 final int[] sz = se.size();
66 sw = sz[0];
67 sh = sz[1];
68 cx = sw / 2;
69 cy = sh / 2;
70 }
71
72
73
74
75 public Erode() {
76 this(StructuringElement.BOX);
77 }
78
79 @Override
80 public void process(ConnectedComponent cc) {
81
82 final Set<Pixel> retain = new HashSet<Pixel>();
83 final Set<Pixel> pixels = cc.getPixels();
84 final int[] se_size = element.size();
85 final Rectangle cc_bb = cc.calculateRegularBoundingBox();
86 for (int j = (int) (cc_bb.y - se_size[1]); j <= cc_bb.y + se_size[1] + cc_bb.height; j++) {
87 for (int i = (int) (cc_bb.x - se_size[0]); i <= cc_bb.x + se_size[0] + cc_bb.width; i++) {
88 final Pixel p = new Pixel(i, j);
89
90 if (element.matches(p, pixels)) {
91 retain.add(p);
92 }
93 }
94 }
95
96 cc.getPixels().retainAll(retain);
97 }
98
99 @Override
100 public int getKernelHeight() {
101 return sh;
102 }
103
104 @Override
105 public int getKernelWidth() {
106 return sw;
107 }
108
109 @Override
110 public Float processKernel(FImage patch) {
111 int count = 0;
112
113 for (final Pixel p : element.positive) {
114 final int px = cx - p.x;
115 final int py = cy - p.y;
116 if (px >= 0 && py >= 0 && px < sw && py < sh && patch.pixels[py][px] == 1)
117 count++;
118 }
119
120 for (final Pixel p : element.negative) {
121 final int px = cx - p.x;
122 final int py = cy - p.y;
123 if (px >= 0 && py >= 0 && px < sw && py < sh && patch.pixels[py][px] == 0)
124 count++;
125 }
126
127 return (count == element.positive.size() + element.negative.size() ? patch.pixels[cy][cx] : 0);
128 }
129
130
131
132
133
134
135
136
137
138
139 public static void erode(FImage img, int times) {
140 final Erode e = new Erode();
141 for (int i = 0; i < times; i++)
142 img.processInplace(e);
143 }
144 }