1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package org.openimaj.image.saliency;
31
32 import org.openimaj.citation.annotation.Reference;
33 import org.openimaj.citation.annotation.ReferenceType;
34 import org.openimaj.image.FImage;
35 import org.openimaj.image.analysis.algorithm.HorizontalProjection;
36 import org.openimaj.image.analysis.algorithm.VerticalProjection;
37 import org.openimaj.math.geometry.shape.Rectangle;
38
39 /**
40 * Extract the subject region of an image based on the
41 * part that is least blurred (most in-focus).
42 * <p>
43 * Algorithm based on:
44 * Yiwen Luo and Xiaoou Tang. 2008.
45 * Photo and Video Quality Evaluation: Focusing on the Subject.
46 * In Proceedings of the 10th European Conference on Computer Vision:
47 * Part III (ECCV '08), David Forsyth, Philip Torr, and Andrew Zisserman (Eds.).
48 * Springer-Verlag, Berlin, Heidelberg, 386-399. DOI=10.1007/978-3-540-88690-7_29
49 * http://dx.doi.org/10.1007/978-3-540-88690-7_29
50 * <p>
51 * Note that this is not scale invariant - you will get different results with
52 * different sized images...
53 *
54 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
55 */
56 @Reference(
57 type = ReferenceType.Inproceedings,
58 author = { "Luo, Yiwen", "Tang, Xiaoou" },
59 title = "Photo and Video Quality Evaluation: Focusing on the Subject",
60 year = "2008",
61 booktitle = "Proceedings of the 10th European Conference on Computer Vision: Part III",
62 pages = { "386", "", "399" },
63 url = "http://dx.doi.org/10.1007/978-3-540-88690-7_29",
64 publisher = "Springer-Verlag",
65 series = "ECCV '08",
66 customData = {
67 "isbn", "978-3-540-88689-1",
68 "location", "Marseille, France",
69 "numpages", "14",
70 "doi", "10.1007/978-3-540-88690-7_29",
71 "acmid", "1478204",
72 "address", "Berlin, Heidelberg"
73 }
74 )
75 public class LuoTangSubjectRegion implements SaliencyMapGenerator<FImage> {
76 DepthOfFieldEstimator dofEstimator;
77
78 Rectangle roi;
79 private FImage dofMap;
80 private float alpha = 0.9f;
81
82 /**
83 * Construct with default values for the {@link DepthOfFieldEstimator}
84 * and an alpha parameter of 0.9.
85 */
86 public LuoTangSubjectRegion() {
87 dofEstimator = new DepthOfFieldEstimator();
88 }
89
90 /**
91 * Construct with the given parameters.
92 * @param alpha the alpha value.
93 * @param maxKernelSize Maximum kernel size for the {@link DepthOfFieldEstimator}.
94 * @param kernelSizeStep Kernel step size for the {@link DepthOfFieldEstimator}.
95 * @param nbins Number of bins for the {@link DepthOfFieldEstimator}.
96 * @param windowSize window size for the {@link DepthOfFieldEstimator}.
97 */
98 public LuoTangSubjectRegion(float alpha, int maxKernelSize, int kernelSizeStep, int nbins, int windowSize) {
99 this.dofEstimator = new DepthOfFieldEstimator(maxKernelSize, kernelSizeStep, nbins, windowSize);
100 this.alpha = alpha;
101 }
102
103 /* (non-Javadoc)
104 * @see org.openimaj.image.analyser.ImageAnalyser#analyseImage(org.openimaj.image.Image)
105 */
106 @Override
107 public void analyseImage(FImage image) {
108 image.analyseWith(dofEstimator);
109 dofMap = dofEstimator.getSaliencyMap();
110
111 for (int y=0; y<dofMap.height; y++) {
112 for (int x=0; x<dofMap.width; x++) {
113 if (dofMap.pixels[y][x] == 0)
114 dofMap.pixels[y][x] = 1;
115 else
116 dofMap.pixels[y][x] = 0;
117 }
118 }
119 }
120
121 /**
122 * @return the estimated rectangular region of interest
123 */
124 public Rectangle calculateROI() {
125 float [] pUx = HorizontalProjection.project(dofMap);
126 float [] pUy = VerticalProjection.project(dofMap);
127
128 float energy = 0;
129 for (float f : pUx) energy += f;
130 float thresh = energy * ((1 - alpha) / 2);
131
132 int x1 = 0;
133 float tmp = pUx[x1];
134 while (tmp < thresh) {
135 x1++;
136 tmp += pUx[x1];
137 }
138
139 int y1 = 0;
140 tmp = pUy[y1];
141 while (tmp < thresh) {
142 y1++;
143 tmp += pUy[y1];
144 }
145
146 int x2 = pUx.length - 1;
147 tmp = pUx[x2];
148 while (tmp < thresh) {
149 x2--;
150 tmp += pUx[x2];
151 }
152
153 int y2 = pUy.length - 1;
154 tmp = pUy[y2];
155 while (tmp < thresh) {
156 y2--;
157 tmp += pUy[y2];
158 }
159
160 return new Rectangle(x1, y1, x2-x1, y2-y1);
161 }
162
163 @Override
164 public FImage getSaliencyMap() {
165 return dofMap;
166 }
167
168 /**
169 * @return a mask image showing the region of interest.
170 */
171 public FImage getROIMap() {
172 FImage image = new FImage(dofMap.width, dofMap.height);
173 image.drawShapeFilled(calculateROI(), 1f);
174 return image;
175 }
176 }