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.feature.global;
31
32 import org.openimaj.citation.annotation.Reference;
33 import org.openimaj.citation.annotation.ReferenceType;
34 import org.openimaj.feature.DoubleFV;
35 import org.openimaj.feature.FeatureVectorProvider;
36 import org.openimaj.image.FImage;
37 import org.openimaj.image.MBFImage;
38 import org.openimaj.image.analyser.ImageAnalyser;
39 import org.openimaj.image.colour.Transforms;
40 import org.openimaj.image.mask.AbstractMaskedObject;
41
42
43
44
45
46
47
48
49
50 @Reference(
51 type = ReferenceType.Article,
52 author = { "Huang, Kai-Qi", "Wang, Qiao", "Wu, Zhen-Yang" },
53 title = "Natural color image enhancement and evaluation algorithm based on human visual system",
54 year = "2006",
55 journal = "Comput. Vis. Image Underst.",
56 pages = { "52", "", "63" },
57 url = "http://dx.doi.org/10.1016/j.cviu.2006.02.007",
58 month = "jul",
59 number = "1",
60 publisher = "Elsevier Science Inc.",
61 volume = "103")
62 public class Naturalness extends AbstractMaskedObject<FImage>
63 implements
64 ImageAnalyser<MBFImage>,
65 FeatureVectorProvider<DoubleFV>
66 {
67 private final static double grassLower = 95.0 / 360.0;
68 private final static double grassUpper = 135.0 / 360.0;
69 private final static double skinLower = 25.0 / 360.0;
70 private final static double skinUpper = 70.0 / 360.0;
71 private final static double skyLower = 185.0 / 360.0;
72 private final static double skyUpper = 260.0 / 360.0;
73
74 private final static double satLower = 0.1;
75
76 private final static double lightnessLower = 20.0 / 100.0;
77 private final static double lightnessUpper = 80.0 / 100.0;
78
79 private double skyMean = 0;
80 private int skyN = 0;
81
82 private double skinMean = 0;
83 private int skinN = 0;
84
85 private double grassMean = 0;
86 private int grassN = 0;
87
88
89
90
91 public Naturalness() {
92 super();
93 }
94
95
96
97
98
99
100
101 public Naturalness(FImage mask) {
102 super(mask);
103 }
104
105 @Override
106 public void analyseImage(MBFImage image) {
107
108 skyMean = 0;
109 skyN = 0;
110 skinMean = 0;
111 skinN = 0;
112 grassMean = 0;
113 grassN = 0;
114
115 final MBFImage hsl = Transforms.RGB_TO_HSL(image);
116
117 final FImage H = (hsl).getBand(0);
118 final FImage S = (hsl).getBand(1);
119 final FImage L = (hsl).getBand(2);
120
121 for (int y = 0; y < H.height; y++) {
122 for (int x = 0; x < H.width; x++) {
123 if (mask != null && mask.pixels[y][x] == 0)
124 continue;
125
126 if (lightnessLower <= L.pixels[y][x] && L.pixels[y][x] <= lightnessUpper && S.pixels[y][x] > satLower) {
127 final double hue = H.pixels[y][x];
128 final double sat = S.pixels[y][x];
129
130 if (skyLower <= hue && hue <= skyUpper) {
131 skyMean += sat;
132 skyN++;
133 }
134
135 if (skinLower <= hue && hue <= skinUpper) {
136 skinMean += sat;
137 skinN++;
138 }
139
140 if (grassLower <= hue && hue <= grassUpper) {
141 grassMean += sat;
142 grassN++;
143 }
144 }
145 }
146 }
147
148 if (skyN != 0)
149 skyMean /= skyN;
150 if (skinN != 0)
151 skinMean /= skinN;
152 if (grassN != 0)
153 grassMean /= grassN;
154 }
155
156
157
158
159
160
161
162 public double getNaturalness() {
163 final double NSkin = Math.exp(-0.5 * Math.pow((skinMean - 0.76) / (0.52), 2));
164 final double NGrass = Math.exp(-0.5 * Math.pow((grassMean - 0.81) / (0.53), 2));
165 final double NSky = Math.exp(-0.5 * Math.pow((skyMean - 0.43) / (0.22), 2));
166
167 final double nPixels = skinN + grassN + skyN;
168
169 if (nPixels == 0)
170 return 0;
171
172 final double wSkin = skinN / nPixels;
173 final double wGrass = grassN / nPixels;
174 final double wSky = skyN / nPixels;
175
176 return wSkin * NSkin + wGrass * NGrass + wSky * NSky;
177 }
178
179 @Override
180 public DoubleFV getFeatureVector() {
181 return new DoubleFV(new double[] { getNaturalness() });
182 }
183 }