View Javadoc

1   /**
2    * FaceTracker Licence
3    * -------------------
4    * (Academic, non-commercial, not-for-profit licence)
5    *
6    * Copyright (c) 2010 Jason Mora Saragih
7    * All rights reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions are met:
11   *
12   *     * The software is provided under the terms of this licence stricly for
13   *       academic, non-commercial, not-for-profit purposes.
14   *     * Redistributions of source code must retain the above copyright notice,
15   *       this list of conditions (licence) and the following disclaimer.
16   *     * Redistributions in binary form must reproduce the above copyright
17   *       notice, this list of conditions (licence) and the following disclaimer
18   *       in the documentation and/or other materials provided with the
19   *       distribution.
20   *     * The name of the author may not be used to endorse or promote products
21   *       derived from this software without specific prior written permission.
22   *     * As this software depends on other libraries, the user must adhere to and
23   *       keep in place any licencing terms of those libraries.
24   *     * Any publications arising from the use of this software, including but
25   *       not limited to academic journal and conference publications, technical
26   *       reports and manuals, must cite the following work:
27   *
28   *       J. M. Saragih, S. Lucey, and J. F. Cohn. Face Alignment through Subspace
29   *       Constrained Mean-Shifts. International Journal of Computer Vision
30   *       (ICCV), September, 2009.
31   *
32   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
33   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
35   * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
37   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
39   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
41   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package com.jsaragih;
44  
45  import java.io.BufferedReader;
46  import java.io.BufferedWriter;
47  import java.io.FileNotFoundException;
48  import java.io.FileReader;
49  import java.io.FileWriter;
50  import java.io.IOException;
51  import java.util.Scanner;
52  
53  import org.openimaj.image.FImage;
54  
55  /**
56   * Multiple patches
57   * 
58   * @author Jason Mora Saragih
59   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
60   */
61  public class MPatch {
62  	static { Tracker.init(); }
63  	
64  	/** Width of patch */
65  	public int _w;
66  
67  	/** Height of patch */
68  	public int _h;
69  
70  	/** List of patches */
71  	public Patch[] _p;
72  
73  	private FImage res_;
74  
75  	MPatch(Patch[] p) {
76  		_w = p[0].matcher.getTemplate().width;
77  		_h = p[0].matcher.getTemplate().height;
78  
79  		for (int i = 1; i < p.length; i++) {
80  			if ((p[i].matcher.getTemplate().width != _w)
81  					|| (p[i].matcher.getTemplate().height != _h)) {
82  				throw new IllegalArgumentException(
83  						"Patches must all have the same size");
84  			}
85  		}
86  
87  		_p = p;
88  		res_ = new FImage(0, 0);
89  	}
90  
91  	MPatch() {
92  	}
93  
94  	static MPatch load(final String fname) throws FileNotFoundException {
95  		BufferedReader br = null;
96  		try {
97  			br = new BufferedReader(new FileReader(fname));
98  			Scanner sc = new Scanner(br);
99  			return read(sc, true);
100 		} finally {
101 			try {
102 				br.close();
103 			} catch (IOException e) {
104 			}
105 		}
106 	}
107 
108 	void save(final String fname) throws IOException {
109 		BufferedWriter bw = null;
110 		try {
111 			bw = new BufferedWriter(new FileWriter(fname));
112 
113 			write(bw);
114 		} finally {
115 			try {
116 				if (bw != null)
117 					bw.close();
118 			} catch (IOException e) {
119 			}
120 		}
121 	}
122 
123 	void write(BufferedWriter s) throws IOException {
124 		s.write(IO.Types.MPATCH.ordinal() + " " + _w + " " + _h + " "
125 				+ _p.length + " ");
126 
127 		for (int i = 0; i < _p.length; i++)
128 			_p[i].write(s);
129 	}
130 
131 	static MPatch read(Scanner s, boolean readType) {
132 		if (readType) {
133 			int type = s.nextInt();
134 			assert (type == IO.Types.MPATCH.ordinal());
135 		}
136 
137 		MPatch mpatch = new MPatch();
138 
139 		mpatch._w = s.nextInt();
140 		mpatch._h = s.nextInt();
141 		int n = s.nextInt();
142 
143 		mpatch._p = new Patch[n];
144 		for (int i = 0; i < n; i++)
145 			mpatch._p[i] = Patch.read(s, true);
146 
147 		return mpatch;
148 	}
149 
150 	final void sum2one(FImage M) {
151 		M.divideInplace(M.sum());
152 	}
153 
154 	void response(FImage im, FImage resp) {
155 		assert ((im.height >= _h) && (im.width >= _w));
156 
157 		int h = im.height - _h + 1, w = im.width - _w + 1;
158 
159 		if (resp.height != h || resp.width != w)
160 			resp.internalAssign(new FImage(w, h));
161 
162 		if (res_ == null)
163 			res_ = new FImage(w, h);
164 		if (res_.height != h || res_.width != w)
165 			res_.internalAssign(new FImage(w, h));
166 
167 		if (_p.length == 1) {
168 			_p[0].response(im, resp);
169 			sum2one(resp);
170 		} else {
171 			resp.fill(1);
172 
173 			for (int i = 0; i < _p.length; i++) {
174 				_p[i].response(im, res_);
175 				sum2one(res_);
176 				resp.multiplyInplace(res_);
177 			}
178 
179 			sum2one(resp);
180 		}
181 	}
182 
183 	/**
184 	 * Returns a copy of this MPatch
185 	 * 
186 	 * @return A copy of this object
187 	 */
188 	public MPatch copy() {
189 		MPatch m = new MPatch();
190 		m._w = _w;
191 		m._h = _h;
192 		m.res_ = res_;
193 		m._p = new Patch[_p.length];
194 		for (int i = 0; i < _p.length; i++)
195 			m._p[i] = _p[i].copy();
196 		return m;
197 	}
198 }