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 gnu.trove.map.hash.TObjectFloatHashMap;
33 import gnu.trove.procedure.TObjectFloatProcedure;
34
35 import org.openimaj.citation.annotation.Reference;
36 import org.openimaj.citation.annotation.ReferenceType;
37 import org.openimaj.feature.DoubleFV;
38 import org.openimaj.feature.FeatureVectorProvider;
39 import org.openimaj.image.MBFImage;
40 import org.openimaj.image.analyser.ImageAnalyser;
41 import org.openimaj.image.pixel.ConnectedComponent;
42 import org.openimaj.image.pixel.PixelSet;
43 import org.openimaj.image.saliency.AchantaSaliency;
44 import org.openimaj.image.saliency.YehSaliency;
45 import org.openimaj.image.segmentation.FelzenszwalbHuttenlocherSegmenter;
46 import org.openimaj.math.geometry.point.Point2dImpl;
47
48
49
50
51
52
53
54
55
56
57 @Reference(
58 type = ReferenceType.Inproceedings,
59 author = { "Che-Hua Yeh", "Yuan-Chen Ho", "Brian A. Barsky", "Ming Ouhyoung" },
60 title = "Personalized Photograph Ranking and Selection System",
61 year = "2010",
62 booktitle = "Proceedings of ACM Multimedia",
63 pages = { "211", "220" },
64 month = "October",
65 customData = { "location", "Florence, Italy" })
66 public class RuleOfThirds implements ImageAnalyser<MBFImage>, FeatureVectorProvider<DoubleFV> {
67 private static final double SIGMA = 0.17;
68 private static final Point2dImpl[] powerPoints = getPowerPoints();
69
70 YehSaliency saliencyGenerator;
71 private double asSum;
72 private double aseSum;
73
74
75
76
77
78 public RuleOfThirds() {
79 saliencyGenerator = new YehSaliency();
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public RuleOfThirds(float saliencySigma, float segmenterSigma, float k, int minSize) {
97 saliencyGenerator = new YehSaliency(saliencySigma, segmenterSigma, k, minSize);
98 }
99
100 @Override
101 public DoubleFV getFeatureVector() {
102 if (asSum == 0)
103 new DoubleFV(new double[] { 0 });
104 return new DoubleFV(new double[] { aseSum / asSum });
105 }
106
107
108
109
110
111
112
113
114 @Override
115 public void analyseImage(MBFImage image) {
116 final int width = image.getWidth();
117 final int height = image.getHeight();
118
119 image.analyseWith(saliencyGenerator);
120 final TObjectFloatHashMap<ConnectedComponent> componentMap = saliencyGenerator.getSaliencyComponents();
121
122 asSum = 0;
123 aseSum = 0;
124 componentMap.forEachEntry(new TObjectFloatProcedure<ConnectedComponent>() {
125 @Override
126 public boolean execute(ConnectedComponent c, float s) {
127 final double as = c.calculateArea() * s;
128
129 final double D = closestDistance(c, width, height);
130
131 asSum += as;
132 aseSum += as * Math.exp(-(D * D) / (2 * SIGMA));
133
134 return true;
135 }
136 });
137 }
138
139 private double closestDistance(PixelSet cc, int width, int height) {
140 final double centroid[] = cc.calculateCentroid();
141 double minDistance = Double.MAX_VALUE;
142
143 for (final Point2dImpl pt : powerPoints) {
144 final double dx = (centroid[0] / width) - pt.x;
145 final double dy = (centroid[1] / width) - pt.y;
146 final double d = dx * dx + dy * dy;
147
148 if (d < minDistance)
149 minDistance = d;
150 }
151
152 return Math.sqrt(minDistance);
153 }
154
155 private static Point2dImpl[] getPowerPoints() {
156 return new Point2dImpl[] {
157 new Point2dImpl(1 / 3f, 1 / 3f),
158 new Point2dImpl(2 / 3f, 1 / 3f),
159 new Point2dImpl(1 / 3f, 2 / 3f),
160 new Point2dImpl(2 / 3f, 2 / 3f) };
161 }
162 }