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.restoration.inpainting;
31
32 import java.util.Set;
33
34 import org.openimaj.citation.annotation.Reference;
35 import org.openimaj.citation.annotation.ReferenceType;
36 import org.openimaj.image.FImage;
37 import org.openimaj.image.Image;
38 import org.openimaj.image.MBFImage;
39 import org.openimaj.image.pixel.Pixel;
40 import org.openimaj.image.processing.morphology.StructuringElement;
41 import org.openimaj.image.processor.SinglebandImageProcessor;
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @Reference(
56 type = ReferenceType.Article,
57 author = { "Telea, Alexandru" },
58 title = "An Image Inpainting Technique Based on the Fast Marching Method.",
59 year = "2004",
60 journal = "J. Graphics, GPU, & Game Tools",
61 pages = { "23", "34" },
62 url = "http://dblp.uni-trier.de/db/journals/jgtools/jgtools9.html#Telea04",
63 number = "1",
64 volume = "9",
65 customData = {
66 "biburl", "http://www.bibsonomy.org/bibtex/2b0bf54e265d011a8e1fe256e6fcf556b/dblp",
67 "doi", "http://dx.doi.org/10.1080/10867651.2004.10487596",
68 "keywords", "dblp"
69 })
70 public class TeleaInpainting<IMAGE extends Image<?, IMAGE> & SinglebandImageProcessor.Processable<Float, FImage, IMAGE>>
71 extends
72 AbstractFMMInpainter<IMAGE>
73 {
74 protected Set<Pixel> region;
75
76
77
78
79
80
81
82
83 public TeleaInpainting(int radius) {
84 region = StructuringElement.disk(radius).positive;
85 }
86
87 @Override
88 protected void inpaint(int x, int y, IMAGE image) {
89 if (image instanceof FImage)
90 inpaint(x, y, (FImage) image);
91 else if (image instanceof MBFImage)
92 inpaint(x, y, (MBFImage) image);
93 else
94 throw new UnsupportedOperationException("Image type not supported!");
95 }
96
97 protected void inpaint(int x, int y, FImage input) {
98 final int width = input.getWidth();
99 final int height = input.getHeight();
100 final float gradx_u = gradX(timeMap.pixels, x, y);
101 final float grady_u = gradY(timeMap.pixels, x, y);
102
103 float accum = 0;
104 float norm = 0;
105
106 for (final Pixel p : region) {
107 final int xx = p.x + x;
108 final int yy = p.y + y;
109
110 if (xx <= 1 || xx >= width - 1 || yy <= 1 || yy >= height - 1)
111 continue;
112 if (flag[yy][xx] != KNOWN)
113 continue;
114
115 final int rx = x - xx;
116 final int ry = y - yy;
117
118
119 final float geometricDistance = (float) (1. / ((rx * rx + ry * ry) * Math.sqrt((rx * rx + ry * ry))));
120
121
122 final float levelsetDistance = (float) (1. / (1 + Math.abs(timeMap.pixels[yy][xx] - timeMap.pixels[y][x])));
123
124
125 float direction = Math.abs(rx * gradx_u + ry * grady_u);
126 if (direction < 0.000001f)
127 direction = 0.000001f;
128
129 final float weight = geometricDistance * levelsetDistance * direction;
130
131 accum += weight * input.pixels[yy][xx];
132 norm += weight;
133 }
134
135 input.pixels[y][x] = accum / norm;
136 }
137
138 protected void inpaint(int x, int y, MBFImage input) {
139 final int width = input.getWidth();
140 final int height = input.getHeight();
141 final float gradx_u = gradX(timeMap.pixels, x, y);
142 final float grady_u = gradY(timeMap.pixels, x, y);
143
144 final int nbands = input.numBands();
145 final float accum[] = new float[nbands];
146 float norm = 0;
147
148 for (final Pixel p : region) {
149 final int xx = p.x + x;
150 final int yy = p.y + y;
151
152 if (xx <= 1 || xx >= width - 1 || yy <= 1 || yy >= height - 1)
153 continue;
154 if (flag[yy][xx] != KNOWN)
155 continue;
156
157 final int rx = x - xx;
158 final int ry = y - yy;
159
160
161 final float geometricDistance = (float) (1. / ((rx * rx + ry * ry) * Math.sqrt((rx * rx + ry * ry))));
162
163
164 final float levelsetDistance = (float) (1. / (1 + Math.abs(timeMap.pixels[yy][xx] - timeMap.pixels[y][x])));
165
166
167 float direction = Math.abs(rx * gradx_u + ry * grady_u);
168 if (direction < 0.000001f)
169 direction = 0.000001f;
170
171 final float weight = geometricDistance * levelsetDistance * direction;
172
173 for (int i = 0; i < nbands; i++)
174 accum[i] += weight * input.getBand(i).pixels[yy][xx];
175 norm += weight;
176 }
177
178 for (int i = 0; i < nbands; i++)
179 input.getBand(i).pixels[y][x] = accum[i] / norm;
180 }
181
182 private float gradX(float[][] img, int x, int y) {
183 float grad;
184
185 if (flag[y][x + 1] != UNKNOWN) {
186 if (flag[y][x - 1] != UNKNOWN)
187 grad = (img[y][x + 1] - img[y][x - 1]) * 0.5f;
188 else
189 grad = (img[y][x + 1] - img[y][x]);
190 } else {
191 if (flag[y][x - 1] != UNKNOWN)
192 grad = (img[y][x] - img[y][x - 1]);
193 else
194 grad = 0;
195 }
196
197 return grad;
198 }
199
200 private float gradY(float[][] img, int x, int y) {
201 float grad;
202
203 if (flag[y + 1][x] != UNKNOWN) {
204 if (flag[y - 1][x] != UNKNOWN)
205 grad = (img[y + 1][x] - img[y - 1][x]) * 0.5f;
206 else
207 grad = (img[y + 1][x] - img[y][x]);
208 } else {
209 if (flag[y - 1][x] != UNKNOWN)
210 grad = (img[y][x] - img[y - 1][x]);
211 else
212 grad = 0;
213 }
214
215 return grad;
216 }
217 }