View Javadoc

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.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   * An {@link FPatchLandmarkModel} is a landmark represented by the 
43   * local patch of pixels around of a point in an {@link FImage}. 
44   * 
45   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
46   */
47  public class FPatchLandmarkModel implements LandmarkModel<FImage> {
48  	/**
49  	 * A factory for producing {@link FPatchLandmarkModel}s
50  	 * 
51  	 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
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 }