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
31
32
33 package org.openimaj.image.processing.mask;
34
35 import org.openimaj.image.FImage;
36 import org.openimaj.image.MBFImage;
37 import org.openimaj.math.geometry.line.Line2d;
38 import org.openimaj.math.geometry.point.Point2d;
39 import org.openimaj.math.geometry.point.Point2dImpl;
40
41
42
43
44
45
46
47
48 public class MatteGenerator
49 {
50
51
52
53
54
55
56
57 public enum MatteType
58 {
59
60
61
62
63
64 LINEAR_VERTICAL_GRADIENT
65 {
66 @Override
67 public void generateMatte( final FImage img, final Object... args )
68 {
69 boolean whiteAtTop = false;
70 if( args.length == 0 || ((args[0] instanceof Boolean) && !((Boolean)args[0]).booleanValue()) )
71 whiteAtTop = true;
72
73 final double g = (whiteAtTop?1:0);
74 final double scalar = (whiteAtTop?-1d/img.getHeight():1d/img.getHeight());
75
76 for( int y = 0; y < img.getHeight(); y++ )
77 for( int x = 0; x < img.getWidth(); x++ )
78 img.pixels[y][x] = (float)(g + y*scalar);
79 }
80 },
81
82
83
84
85
86 LINEAR_HORIZONTAL_GRADIENT
87 {
88 @Override
89 public void generateMatte( final FImage img, final Object... args )
90 {
91 boolean whiteAtLeft = false;
92 if( args.length == 0 || ((args[0] instanceof Boolean) && !((Boolean)args[0]).booleanValue()) )
93 whiteAtLeft = true;
94
95 final double g = (whiteAtLeft?1:0);
96 final double scalar = (whiteAtLeft?-1d/img.getWidth():1d/img.getWidth());
97
98 for( int y = 0; y < img.getHeight(); y++ )
99 for( int x = 0; x < img.getWidth(); x++ )
100 img.pixels[y][x] = (float)(g + x*scalar);
101 }
102 },
103
104
105
106
107
108 RADIAL_GRADIENT
109 {
110 @Override
111 public void generateMatte( final FImage img, final Object... args )
112 {
113 boolean whiteInCentre = false;
114 if( args.length > 0 && args[0] instanceof Boolean && ((Boolean)args[0]).booleanValue())
115 whiteInCentre = true;
116
117
118 final int cx = img.getWidth() /2;
119 final int cy = img.getHeight() /2;
120
121
122 final int maxDist = Math.max(
123 Math.max( img.getWidth() - cx, cx ),
124 Math.max( img.getHeight() - cy, cy )
125 );
126 final double scale = maxDist;
127
128 for( int y = 0; y < img.getHeight(); y++ )
129 for( int x = 0; x < img.getWidth(); x++ )
130 img.pixels[y][x] = whiteInCentre?
131 1f-(float)this.distanceFromCentre( cx, cy, x, y, scale ):
132 (float)this.distanceFromCentre( cx, cy, x, y, scale );
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 private double distanceFromCentre( final int cx, final int cy, final int x, final int y,
147 final double scale )
148 {
149 final double b = cx - x;
150 final double c = cy - y;
151 double v = Math.abs( Math.sqrt( b*b + c*c ) )/scale;
152 if( v > 1 ) v = 1;
153 if( v < 0 ) v = 0;
154 return v;
155 }
156 },
157
158
159
160
161
162
163
164 ANGLED_LINEAR_GRADIENT
165 {
166
167 @Override
168 public void generateMatte( final FImage img, final Object... args )
169 {
170
171 double angle = 0;
172 double lx = 0;
173 double ly = 0;
174
175
176 if( args.length > 0 && args[0] instanceof Double )
177 angle = ((Double)args[0]).doubleValue();
178 if( args.length > 1 && args[1] instanceof Double )
179 lx = ((Double)args[1]).doubleValue();
180 if( args.length > 2 && args[2] instanceof Double )
181 ly = ((Double)args[2]).doubleValue();
182
183
184 final double scalar = Math.max(
185 Math.max( img.getWidth() - lx, lx ),
186 Math.max( img.getHeight() - ly, ly )
187 );
188
189 for( int y = 0; y < img.getHeight(); y++ )
190 for( int x = 0; x < img.getWidth(); x++ )
191 img.pixels[y][x] = (float)this.distanceFromAxis( lx, ly, angle, x, y, scalar );
192 }
193
194
195
196
197
198
199
200
201
202
203
204 private double distanceFromAxis( final double lx, final double ly, final double angle,
205 final double x, final double y, final double scalar )
206 {
207
208 final Line2d line = Line2d.lineFromRotation( (int)lx, (int)ly, angle, 1 );
209 final Point2d A = line.begin;
210 final Point2d B = line.end;
211 final Point2dImpl P = new Point2dImpl( (float)x, (float)y );
212 final double normalLength = Math.hypot(B.getX() - A.getX(), B.getY() - A.getY());
213 double grad = Math.abs((P.x - A.getX()) * (B.getY() - A.getY()) - (P.y - A.getY()) *
214 (B.getX() - A.getX())) / normalLength / scalar;
215 if( grad < 0 ) grad = 0;
216 if( grad > 1 ) grad = 1;
217 return grad;
218 }
219 }
220 ;
221
222
223
224
225
226
227 public abstract void generateMatte( FImage img, Object... args );
228 }
229
230
231
232
233
234
235
236
237
238
239 public static FImage generateMatte( final MBFImage image, final int band,
240 final MatteType type, final Object... args )
241 {
242 return MatteGenerator.generateMatte( image.getBand( band ), type, args );
243 }
244
245
246
247
248
249
250
251
252
253 public static FImage generateMatte( final FImage image, final MatteType type, final Object... args )
254 {
255 type.generateMatte( image, args );
256 return image;
257 }
258 }