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.model.asm;
31
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.openimaj.citation.annotation.Reference;
36 import org.openimaj.citation.annotation.ReferenceType;
37 import org.openimaj.citation.annotation.References;
38 import org.openimaj.image.FImage;
39 import org.openimaj.image.Image;
40 import org.openimaj.image.analysis.pyramid.SimplePyramid;
41 import org.openimaj.image.model.asm.ActiveShapeModel.IterationResult;
42 import org.openimaj.image.model.landmark.LandmarkModel;
43 import org.openimaj.image.model.landmark.LandmarkModelFactory;
44 import org.openimaj.image.processor.SinglebandImageProcessor;
45 import org.openimaj.math.geometry.point.PointList;
46 import org.openimaj.math.geometry.shape.PointDistributionModel;
47 import org.openimaj.math.geometry.shape.PointDistributionModel.Constraint;
48 import org.openimaj.math.geometry.transforms.TransformUtilities;
49 import org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis.ComponentSelector;
50 import org.openimaj.util.pair.IndependentPair;
51
52 import Jama.Matrix;
53
54
55
56
57
58
59
60
61
62
63 @References(references = {
64 @Reference(
65 author = { "Cootes, T. F.", "Taylor, C. J." },
66 title = "Statistical Models of Appearance for Computer Vision",
67 type = ReferenceType.Unpublished,
68 month = "October",
69 year = "2001",
70 url = "http://isbe.man.ac.uk/~bim/Models/app_model.ps.gz"
71 ),
72 @Reference(
73 type = ReferenceType.Inproceedings,
74 author = { "Cootes, T F", "Taylor, C J", "Lanitis, A" },
75 title = "Active shape models: Evaluation of a multi-resolution method for improving image search",
76 year = "1994",
77 booktitle = "Proc British Machine Vision Conference",
78 pages = { "327", "", "336" },
79 url = "http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.141.4937&rep=rep1&type=pdf",
80 editor = { "Hancock, E" },
81 publisher = "BMVA Press",
82 volume = "1"
83 )
84 })
85 public class MultiResolutionActiveShapeModel<I extends Image<?, I> & SinglebandImageProcessor.Processable<Float,FImage,I>> {
86 private int numLevels;
87 private ActiveShapeModel<I>[] asms;
88 private static float sigma = 0.5f;
89
90
91
92
93
94
95
96
97 public MultiResolutionActiveShapeModel(ActiveShapeModel<I>[] asms) {
98 this.numLevels = asms.length;
99 this.asms = asms;
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114 public static <I extends Image<?, I> & SinglebandImageProcessor.Processable<Float,FImage,I>> MultiResolutionActiveShapeModel<I>
115 trainModel(int numLevels, ComponentSelector selector, List<IndependentPair<PointList, I>> data, Constraint constraint, LandmarkModelFactory<I> factory) {
116 int nPoints = data.get(0).firstObject().size();
117
118 @SuppressWarnings("unchecked")
119 LandmarkModel<I>[][] ppms = new LandmarkModel[numLevels][nPoints];
120
121 for (int i=0; i<data.size(); i++) {
122 SimplePyramid<I> pyr = SimplePyramid.createGaussianPyramid(data.get(i).secondObject(), sigma, numLevels);
123 PointList pl = data.get(i).firstObject();
124
125 for (int level=0; level<numLevels; level++) {
126 Matrix scaling = TransformUtilities.scaleMatrix(1.0/Math.pow(2, level), 1.0/Math.pow(2, level));
127 PointList tfpl = pl.transform(scaling);
128 I image = pyr.pyramid[level];
129
130 for (int j=0; j<nPoints; j++) {
131 if (ppms[level][j] == null) {
132
133
134
135
136 ppms[level][j] = factory.createLandmarkModel((float) Math.pow(2, level));
137 }
138
139 ppms[level][j].updateModel(image, tfpl.get(j), tfpl);
140 }
141 }
142 }
143
144 List<PointList> pls = new ArrayList<PointList>();
145 for (IndependentPair<PointList, I> i : data)
146 pls.add(i.firstObject());
147
148 PointDistributionModel pdm = new PointDistributionModel(constraint, pls);
149 pdm.setNumComponents(selector);
150
151 @SuppressWarnings("unchecked")
152 ActiveShapeModel<I> [] asms = new ActiveShapeModel[numLevels];
153 for (int level=0; level<numLevels; level++) {
154 asms[level] = new ActiveShapeModel<I>(pdm, ppms[level]);
155 }
156
157 return new MultiResolutionActiveShapeModel<I>(asms);
158 }
159
160
161
162
163
164
165
166
167
168 public IterationResult fit(I initialImage, PointList initialShape) {
169 SimplePyramid<I> pyr = SimplePyramid.createGaussianPyramid(initialImage, sigma, numLevels);
170
171 Matrix scaling = TransformUtilities.scaleMatrix(1.0/Math.pow(2, numLevels-1), 1.0/Math.pow(2, numLevels-1));
172
173 PointList shape = initialShape.transform(scaling);
174 Matrix pose = null;
175 double [] parameters = null;
176
177 double fit = 0;
178 for (int level=numLevels-1; level>=0; level--) {
179 I image = pyr.pyramid[level];
180
181 ActiveShapeModel<I> asm = asms[level];
182
183 IterationResult newData = asm.fit(image, shape);
184
185 if (level == 0)
186 scaling = Matrix.identity(3, 3);
187 else
188 scaling = TransformUtilities.scaleMatrix(2, 2);
189
190 shape = newData.shape.transform(scaling);
191 pose = newData.pose.times(scaling);
192 fit = newData.fit;
193 parameters = newData.parameters;
194 }
195
196 return new IterationResult(pose, shape, fit, parameters);
197 }
198
199
200
201
202 public PointDistributionModel getPDM() {
203 return asms[0].getPDM();
204 }
205 }