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;
31
32 import java.io.DataInput;
33 import java.io.DataOutput;
34 import java.io.IOException;
35 import java.util.List;
36
37 import org.openimaj.citation.annotation.Reference;
38 import org.openimaj.citation.annotation.ReferenceType;
39 import org.openimaj.feature.DoubleFV;
40 import org.openimaj.feature.FeatureExtractor;
41 import org.openimaj.image.FImage;
42 import org.openimaj.image.feature.DoubleFV2FImage;
43 import org.openimaj.image.feature.FImage2DoubleFV;
44 import org.openimaj.io.IOUtils;
45 import org.openimaj.io.ReadWriteableBinary;
46 import org.openimaj.math.matrix.algorithm.pca.ThinSvdPrincipalComponentAnalysis;
47 import org.openimaj.ml.pca.FeatureVectorPCA;
48 import org.openimaj.ml.training.BatchTrainer;
49 import org.openimaj.util.array.ArrayUtils;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 @Reference(
71 type = ReferenceType.Inproceedings,
72 author = { "Turk, M.A.", "Pentland, A.P." },
73 title = "Face recognition using eigenfaces",
74 year = "1991",
75 booktitle = "Computer Vision and Pattern Recognition, 1991. Proceedings CVPR '91., IEEE Computer Society Conference on",
76 pages = { "586 ", "591" },
77 month = "jun",
78 number = "",
79 volume = "",
80 customData = {
81 "keywords",
82 "eigenfaces;eigenvectors;face images;face recognition system;face space;feature space;human faces;two-dimensional recognition;unsupervised learning;computerised pattern recognition;eigenvalues and eigenfunctions;",
83 "doi", "10.1109/CVPR.1991.139758"
84 })
85 public class EigenImages implements BatchTrainer<FImage>, FeatureExtractor<DoubleFV, FImage>, ReadWriteableBinary {
86 private FeatureVectorPCA pca;
87 private int width;
88 private int height;
89 private int numComponents;
90
91
92
93
94 protected EigenImages() {
95 }
96
97
98
99
100
101
102
103 public EigenImages(int numComponents) {
104 this.numComponents = numComponents;
105 pca = new FeatureVectorPCA(new ThinSvdPrincipalComponentAnalysis(numComponents));
106 }
107
108 @Override
109 public DoubleFV extractFeature(FImage img) {
110 final DoubleFV feature = FImage2DoubleFV.INSTANCE.extractFeature(img);
111
112 return pca.project(feature);
113 }
114
115 @Override
116 public void train(List<? extends FImage> data) {
117 final double[][] features = new double[data.size()][];
118
119 width = data.get(0).width;
120 height = data.get(0).height;
121
122 for (int i = 0; i < features.length; i++)
123 features[i] = FImage2DoubleFV.INSTANCE.extractFeature(data.get(i)).values;
124
125 pca.learnBasis(features);
126 }
127
128
129
130
131
132
133
134
135 public FImage reconstruct(DoubleFV weights) {
136 return DoubleFV2FImage.extractFeature(pca.generate(weights), width, height);
137 }
138
139
140
141
142
143
144
145
146 public FImage reconstruct(double[] weights) {
147 return new FImage(ArrayUtils.reshapeFloat(pca.generate(weights), width, height));
148 }
149
150
151
152
153
154
155
156
157
158 public FImage visualisePC(int pc) {
159 return new FImage(ArrayUtils.reshapeFloat(pca.getPrincipalComponent(pc), width, height)).normalise();
160 }
161
162 @Override
163 public void readBinary(DataInput in) throws IOException {
164 width = in.readInt();
165 height = in.readInt();
166 numComponents = in.readInt();
167 pca = IOUtils.read(in);
168 }
169
170 @Override
171 public byte[] binaryHeader() {
172 return "EigI".getBytes();
173 }
174
175 @Override
176 public void writeBinary(DataOutput out) throws IOException {
177 out.writeInt(width);
178 out.writeInt(height);
179 out.writeInt(numComponents);
180 IOUtils.write(pca, out);
181 }
182
183 @Override
184 public String toString() {
185 return String.format("EigenImages[width=%d; height=%d; pca=%s]", width, height, pca);
186 }
187
188
189
190
191
192
193
194 public int getNumComponents() {
195 return numComponents;
196 }
197 }