-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAnalyze_Pixels.java
368 lines (284 loc) · 15.4 KB
/
Analyze_Pixels.java
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.Point;
public class Analyze_Pixels {
private static final int[] max_sameness_values_ = new int[]{ 1, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91,
105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300 };
private static final int RED_INDEX_VALUE = 0;
private static final int GREEN_VALUE_INDEX = 1;
private static final int BLUE_VALUE_INDEX = 2;
private static final int LUMINOSITY_VALUE_INDEX = 3;
// returns value in (0,1) representing how good point in given picture is good
// for changing its value
public static double usability_point_calculation( BufferedImage img, Point p ) {
double _similarity_ = Analyze_Pixels.similarity_calculation( img, p );
double _smoothness_ = Analyze_Pixels.Smoothness_Calculation( img, p );
_similarity_ *= _similarity_;
_similarity_ *= 1.5;
_smoothness_ *= _smoothness_;
double answer = ( _similarity_ + _smoothness_ ) / 2.5;
answer = Math.sqrt( answer );
return answer;
}
// compare RGB and luminosity values
public static double similarity_calculation( BufferedImage img, Point p ) {
int start_x = p.x - 2;
int end_x = p.x + 2;
int start_y = p.y - 2;
int end_y = p.y + 2;
int width_comparison;
int height_comparison;
int comparison_area_;
int matches_of_red = 0;
int matches_of_green = 0;
int matches_of_blue = 0;
int matches_of_luminosity = 0;
int matches_of_distance = 0;
Color[] colour_array;
if ( start_x < 0 ) {
start_x = 0;
}
if ( end_x >= img.getWidth() ) {
end_x = img.getWidth() - 1;
}
if ( start_y < 0 ) {
start_y = 0;
}
if ( end_y >= img.getHeight() ) {
end_y = img.getHeight() - 1;
}
width_comparison = ( 1 + end_x - start_x );
height_comparison = ( 1 + end_y - start_y );
comparison_area_ = width_comparison * height_comparison; //Should be 25 unless we're near an edge
colour_array = new Color[comparison_area_];
int i = 0;
for( int y = 0; ( y < height_comparison ) && ( i < comparison_area_ ); y++ ) {
for( int x = 0; ( x < width_comparison ) && ( i < comparison_area_ ); x++ ) {
colour_array[i] = new Color( img.getRGB( x + start_x, y + start_y ) );
i++;
}
}
for( int j = 0; j < comparison_area_; j++ ) {
for( int k = j + 1; k < comparison_area_; k++ ) {
if ( colour_array[j].getRed() == colour_array[k].getRed() ) {
matches_of_red++;
}
if ( colour_array[j].getGreen() == colour_array[k].getGreen() ) {
matches_of_green++;
}
if ( colour_array[j].getBlue() == colour_array[k].getBlue() ) {
matches_of_blue++;
}
if ( Analyze_Pixels.Colour_Distance_Calculation( colour_array[j], colour_array[k] ) < 2.1 ) {
matches_of_distance++;
}
double startLum = Analyze_Pixels.Luminosity_calculation( colour_array[j] );
double endLum = Analyze_Pixels.Luminosity_calculation( colour_array[k] );
if ( Math.abs( startLum - endLum ) < 1 ) {
matches_of_luminosity++;
}
} //End internal loop k
} //End loop j
//Each of following values is in range (0,1)
double redMatchValue = ( (double) matches_of_red ) / ( (double) max_sameness_values_[comparison_area_ - 1] );
double greenMatchValue = ( (double) matches_of_green ) / ( (double) max_sameness_values_[comparison_area_ - 1] );
double blueMatchValue = ( (double) matches_of_blue ) / ( (double) max_sameness_values_[comparison_area_ - 1] );
double luminosityMatchValue = ( (double) matches_of_luminosity ) / ( (double) max_sameness_values_[comparison_area_ - 1] );
double distanceMatchValue = ( (double) matches_of_distance ) / ( (double) max_sameness_values_[comparison_area_ - 1] );
//Take the mean square average
redMatchValue *= redMatchValue;
greenMatchValue *= greenMatchValue;
blueMatchValue *= blueMatchValue;
luminosityMatchValue *= luminosityMatchValue;
distanceMatchValue *= distanceMatchValue;
//DistanceMatchValue is weighted double
double answer = redMatchValue + greenMatchValue + blueMatchValue + luminosityMatchValue + distanceMatchValue + distanceMatchValue;
answer /= 6;
answer = Math.sqrt( answer );
return answer;
}
// compares all the pixels to see variation of values in a paritcular
// direction. Examines in all the four directions
public static double Smoothness_Calculation( BufferedImage img, Point p ) {
int start_x = p.x - 2;
int end_x = p.x + 2;
int start_y = p.y - 2;
int end_y = p.y + 2;
int width_comparison;
int height_comparison;
int[] tally_for_one_direction = new int[4];
double[] total_runnings = new double[4];
int num_of_directions_compared = 0;
if ( start_x < 0 ) {
start_x = 0;
}
if ( end_x >= img.getWidth() ) {
end_x = img.getWidth() - 1;
}
if ( start_y < 0 ) {
start_y = 0;
}
if ( end_y >= img.getHeight() ) {
end_y = img.getHeight() - 1;
}
width_comparison = ( 1 + end_x - start_x );
height_comparison = ( 1 + end_y - start_y );
Color[][] colour_array = new Color[width_comparison][height_comparison];
//Feed values in the colour array
for( int y = 0; ( y < height_comparison ); y++ ) {
for( int x = 0; ( x < width_comparison ); x++ ) {
colour_array[x][y] = new Color( img.getRGB( x + start_x, y + start_y ) );
}
}
if ( width_comparison > 2 ) {
// horizontal comparison
for( int y = 0; y < height_comparison; y++ ) {
for ( int x = 0; ( x + 1 ) < width_comparison; x++ ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[x][y], colour_array[x+1][y] );
}
}
// log the results
Analyze_Pixels.Average_smoothness_and_add_squares( total_runnings, tally_for_one_direction, ( width_comparison - 1 ) * height_comparison );
num_of_directions_compared++;
}
if ( height_comparison > 2 ) {
// Vertical Comparison
for( int x = 0; x < width_comparison; x++ ) {
for ( int y = 0; ( y + 1 ) < height_comparison; y++ ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[x][y], colour_array[x][y+1] );
}
}
//Log results
Analyze_Pixels.Average_smoothness_and_add_squares( total_runnings, tally_for_one_direction, ( height_comparison - 1 ) * width_comparison );
num_of_directions_compared++;
}
if ( height_comparison > 3 && width_comparison > 3 ) {
// diagonal comparisons
int num_of_comparisons = 0; //number of comparisons for averaging purposes
for( int x = 0; ( x + 2 ) < width_comparison; x++ ) {
//Down-right comparisons on the top horizontal
int temp_x = x;
for ( int y = 0; ( y + 1 ) < height_comparison && ( temp_x + 1 ) < width_comparison; ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[temp_x][y], colour_array[temp_x+1][y+1] );
y++; //down
temp_x++; //right
num_of_comparisons++;
}
}
//Down-right comparisons on the left vertical, but not on the top horizontal
for( int y = 1; ( y + 2 ) < height_comparison; y++ ) {
int tempY = y;
int temp_x = 0;
for( ; (temp_x+1) < width_comparison && (tempY+1) < height_comparison; ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[temp_x][tempY], colour_array[temp_x+1][tempY+1] );
//System.out.print( "Compare ( " + temp_x + ", " + tempY + " ):( " + (temp_x+1) + ", " + (tempY+1) + " )\t" );
num_of_comparisons++;
tempY++;
temp_x++;
}
}
Analyze_Pixels.Average_smoothness_and_add_squares( total_runnings, tally_for_one_direction, num_of_comparisons );
num_of_directions_compared++;
num_of_comparisons = 0;
for( int x = 0; ( x + 2 ) < width_comparison; x++ ) {
int temp_x = x;
for ( int y = height_comparison - 1; y > 0 && ( temp_x + 1 ) < width_comparison; ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[temp_x][y], colour_array[temp_x+1][y-1] );
y--;
temp_x++;
num_of_comparisons++;
}
}
//Up-right comparisons on the left vertical, but not on the top horizontal
for( int y = height_comparison -2; ( y - 2 ) >= 0; y-- ) {
int tempY = y;
int temp_x = 0;
for( ; (temp_x+1) < width_comparison && (tempY-1) >= 0; ) {
Analyze_Pixels.Compare_Two_Pixels_For_smoothness( tally_for_one_direction, colour_array[temp_x][tempY], colour_array[temp_x+1][tempY-1] );
num_of_comparisons++;
tempY--;
temp_x++;
}
}
Analyze_Pixels.Average_smoothness_and_add_squares( total_runnings, tally_for_one_direction, num_of_comparisons );
num_of_directions_compared++;
}
//average the values then square root
total_runnings[RED_INDEX_VALUE] /= num_of_directions_compared;
total_runnings[GREEN_VALUE_INDEX] /= num_of_directions_compared;
total_runnings[BLUE_VALUE_INDEX] /= num_of_directions_compared;
total_runnings[LUMINOSITY_VALUE_INDEX] /= num_of_directions_compared;
double finalAnswer = total_runnings[RED_INDEX_VALUE] + total_runnings[GREEN_VALUE_INDEX] +
total_runnings[BLUE_VALUE_INDEX] + total_runnings[LUMINOSITY_VALUE_INDEX];
finalAnswer /= 4;
finalAnswer = Math.sqrt( finalAnswer );
return finalAnswer;
}
// returns true if pixel is close to white or black
public static boolean Pixel_colour_is_near_extreme( int intColor ) {
Color _colour_ = new Color( intColor );
boolean answer = false;
if ( _colour_.getRed() >= 250 && _colour_.getGreen() >= 250 && _colour_.getBlue() >= 250 ) {
if ( Colour_Distance_Calculation( _colour_, Color.WHITE ) <= 5 ) {
answer = true;
}
} else if ( _colour_.getRed() <= 5 && _colour_.getGreen() <= 5 && _colour_.getBlue() <= 5 ) { //If we're near black
if ( Colour_Distance_Calculation( _colour_, Color.BLACK ) <= 5 ) {
answer = true;
}
}
return answer;
}
// calculates the luminosity of given colour range is [0,255]
public static double Luminosity_calculation( Color c ) {
double answer = 0;
//Values taken from http://jscience.org/experimental/javadoc/org/jscience/computing/ai/vision/GreyscaleFilter.html
answer += 0.2125 * ( (double) c.getRed() );
answer += 0.7154 * ( (double) c.getGreen() );
answer += 0.0721 * ( (double) c.getBlue() );
return answer;
}
// use eucledian distance to calculate distance b/w RGB values
public static double Colour_Distance_Calculation( Color a, Color b ) {
double red = a.getRed() - b.getRed();
double green = a.getGreen() - b.getGreen();
double blue = a.getBlue() - b.getBlue();
return Math.sqrt( (red*red) + (green*green) + (blue*blue) );
}
// compare RGB and luminosity values of two pixels and changes counter accordingly
private static void Compare_Two_Pixels_For_smoothness( int[] tally_for_one_direction, Color a, Color b ) {
if ( a.getRed() < b.getRed() ) { //Red channel increasing
tally_for_one_direction[RED_INDEX_VALUE]++;
} else if ( a.getRed() > b.getRed() ) { //Red channel decreasing
tally_for_one_direction[RED_INDEX_VALUE]--;
}
if ( a.getGreen() < b.getGreen() ) { //Green channel increasing
tally_for_one_direction[GREEN_VALUE_INDEX]++;
} else if ( a.getGreen() > b.getGreen() ) { //Green channel decreasing
tally_for_one_direction[GREEN_VALUE_INDEX]--;
}
if ( a.getBlue() < b.getBlue() ) { //Blue channel increasing
tally_for_one_direction[BLUE_VALUE_INDEX]++;
} else if ( a.getBlue() > b.getBlue() ) { //Blue channel decreasing
tally_for_one_direction[BLUE_VALUE_INDEX]--;
}
double luminosity_start = Analyze_Pixels.Luminosity_calculation( a );
double luminosity_end = Analyze_Pixels.Luminosity_calculation( b );
if ( luminosity_start < luminosity_end ) { //Luminosity increasing
tally_for_one_direction[LUMINOSITY_VALUE_INDEX]++;
} else if ( luminosity_start > luminosity_end ) { //Luminosity channel decreasing
tally_for_one_direction[LUMINOSITY_VALUE_INDEX]--;
}
}
// average the squares then adds into running total
private static void Average_smoothness_and_add_squares( double[] total_runnings, int[] tally_for_one_direction, int num_of_comparisons ) {
total_runnings[RED_INDEX_VALUE] += Math.pow( ( ( (double) tally_for_one_direction[RED_INDEX_VALUE] ) / ( (double) num_of_comparisons ) ), 2 );
total_runnings[GREEN_VALUE_INDEX] += Math.pow( ( ( (double) tally_for_one_direction[GREEN_VALUE_INDEX] ) / ( (double) num_of_comparisons ) ), 2 );
total_runnings[BLUE_VALUE_INDEX] += Math.pow( ( ( (double) tally_for_one_direction[BLUE_VALUE_INDEX] ) / ( (double) num_of_comparisons ) ), 2 );
total_runnings[LUMINOSITY_VALUE_INDEX] += Math.pow( ( ( (double) tally_for_one_direction[LUMINOSITY_VALUE_INDEX] ) / ( (double) num_of_comparisons ) ), 2 );
tally_for_one_direction[RED_INDEX_VALUE] = 0;
tally_for_one_direction[GREEN_VALUE_INDEX] = 0;
tally_for_one_direction[BLUE_VALUE_INDEX] = 0;
tally_for_one_direction[LUMINOSITY_VALUE_INDEX] = 0;
}
}