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.landmark;
31
32 import org.openimaj.image.FImage;
33 import org.openimaj.image.pixel.sampling.FLineSampler;
34 import org.openimaj.image.pixel.statistics.FStatisticalPixelProfileModel;
35 import org.openimaj.image.pixel.statistics.PixelProfileModel;
36 import org.openimaj.math.geometry.line.Line2d;
37 import org.openimaj.math.geometry.point.Point2d;
38 import org.openimaj.math.geometry.point.PointList;
39 import org.openimaj.math.geometry.point.PointListConnections;
40 import org.openimaj.util.pair.ObjectFloatPair;
41
42
43
44
45
46
47
48
49 public class FNormalLandmarkModel implements LandmarkModel<FImage> {
50
51
52
53
54
55 public static class Factory implements LandmarkModelFactory<FImage> {
56 private PointListConnections connections;
57 private float normalLength;
58 private int numSearchSamples;
59 private FLineSampler sampler;
60 private int numModelSamples;
61
62
63
64
65
66
67
68
69
70 public Factory(PointListConnections connections, FLineSampler sampler, int numModelSamples, int numSearchSamples, float normalLength) {
71 this.connections = connections;
72 this.sampler = sampler;
73 this.numModelSamples = numModelSamples;
74 this.normalLength = normalLength;
75 this.numSearchSamples = numSearchSamples;
76 }
77
78 @Override
79 public FNormalLandmarkModel createLandmarkModel() {
80 return new FNormalLandmarkModel(connections, sampler, numModelSamples, numSearchSamples, normalLength);
81 }
82
83 @Override
84 public FNormalLandmarkModel createLandmarkModel(float scaleFactor) {
85 return new FNormalLandmarkModel(connections, sampler, numModelSamples, numSearchSamples, scaleFactor * normalLength);
86 }
87 }
88
89 private PointListConnections connections;
90 private PixelProfileModel<FImage> model;
91 private float normalLength;
92 private int numModelSamples;
93 private int numSearchSamples;
94
95
96
97
98
99
100
101
102
103
104 public FNormalLandmarkModel(PointListConnections connections, FLineSampler sampler, int numModelSamples, int numSearchSamples, float normalLength) {
105 this.connections = connections;
106 this.model = new FStatisticalPixelProfileModel(numModelSamples, sampler);
107 this.normalLength = normalLength;
108 this.numModelSamples = numModelSamples;
109 this.numSearchSamples = numSearchSamples;
110 }
111
112 @Override
113 public void updateModel(FImage image, Point2d point, PointList pointList) {
114 float lineScale = normalLength * pointList.computeIntrinsicScale();
115 Line2d line = connections.calculateNormalLine(point, pointList, lineScale);
116
117 model.updateModel(image, line);
118 }
119
120 @Override
121 public float computeCost(FImage image, Point2d point, PointList pointList) {
122 float lineScale = normalLength * pointList.computeIntrinsicScale();
123 Line2d line = connections.calculateNormalLine(point, pointList, lineScale);
124
125 return model.computeCost(image, line);
126 }
127
128 @Override
129 public ObjectFloatPair<Point2d> updatePosition(FImage image, Point2d initial, PointList pointList) {
130 float scale = numSearchSamples * normalLength * pointList.computeIntrinsicScale() / (float) numModelSamples;
131 Line2d line = connections.calculateNormalLine(initial, pointList, scale);
132
133 Point2d newBest = model.computeNewBest(image, line, numSearchSamples);
134 float distance = model.computeMovementDistance(image, line, numSearchSamples, newBest);
135
136 return new ObjectFloatPair<Point2d>(newBest, distance);
137 }
138 }