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.analysis.algorithm.TemplateMatcher;
34  import org.openimaj.image.analysis.algorithm.TemplateMatcher.Mode;
35  import org.openimaj.image.pixel.FValuePixel;
36  import org.openimaj.math.geometry.point.Point2d;
37  import org.openimaj.math.geometry.point.PointList;
38  import org.openimaj.math.geometry.shape.Rectangle;
39  import org.openimaj.util.pair.ObjectFloatPair;
40  
41  
42  
43  
44  
45  
46  
47  public class FPatchLandmarkModel implements LandmarkModel<FImage> {
48  	
49  
50  
51  
52  
53  	public static class Factory implements LandmarkModelFactory<FImage> {
54  		@Override
55  		public LandmarkModel<FImage> createLandmarkModel() {
56  			return new FPatchLandmarkModel();
57  		}
58  
59  		@Override
60  		public LandmarkModel<FImage> createLandmarkModel(float scaleFactor) {
61  			return new FPatchLandmarkModel();
62  		}
63  	}
64  	
65  	int blockSize = 11;
66  	int searchSize = 31;
67  	
68  	FImage average;
69  	int n = 0;
70  	TemplateMatcher matcher;
71  	
72  	protected Rectangle getROI(int x, int y, int w, int h) {
73  		if(w % 2 == 0 ) w+=1;
74  		if(h % 2 == 0 ) h+=1;
75  		
76  		int roiX = Math.max(0,x-(int)(w/2.0));
77  		int roiY = Math.max(0,y-(int)(h/2.0));
78  		
79  		int newWidth = (int)(w / 2.0) + 1 + (x - roiX);
80  		int newHeight = (int)(h / 2.0) + 1 + (y - roiY);
81  		
82  		return new Rectangle(roiX, roiY, newWidth, newHeight);
83  	}
84  	
85  	protected FImage extractBlock(FImage image, Point2d pt, int sz) {
86  		return image.extractROI(getROI((int)pt.getX(), (int)pt.getY(), sz, sz));
87  	}
88  
89  	@Override
90  	public void updateModel(FImage image, Point2d point, PointList pointList) {
91  		FImage extracted = extractBlock(image, point, blockSize);
92  		
93  		n++;
94  		if (average == null) {
95  			average = extracted; 
96  		} else {
97  			average.addInplace( extracted.subtractInplace(average).divide((float)n) );
98  		}
99  		matcher = null;
100 	}
101 
102 	@Override
103 	public float computeCost(FImage image, Point2d point, PointList pointList) {
104 		FImage extracted = extractBlock(image, point, blockSize);
105 		
106 		if (matcher == null)
107 			matcher = new TemplateMatcher(average, Mode.NORM_SUM_SQUARED_DIFFERENCE);
108 		
109 		matcher.setSearchBounds(null);
110 		extracted.analyseWith(matcher);
111 		
112 		return matcher.getResponseMap().pixels[0][0];
113 	}
114 
115 	@Override
116 	public ObjectFloatPair<Point2d> updatePosition(FImage image, Point2d initial, PointList pointList) {
117 		Rectangle roi = getROI((int)initial.getX(), (int)initial.getY(), searchSize, searchSize);
118 		
119 		if (matcher == null)
120 			matcher = new TemplateMatcher(average, Mode.NORM_SUM_SQUARED_DIFFERENCE);
121 		
122 		matcher.setSearchBounds(roi);
123 		image.analyseWith(matcher);
124 		FValuePixel p = matcher.getBestResponses(1)[0];
125 		
126 		return new ObjectFloatPair<Point2d>(p, 0);
127 	}
128 }