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.demos;
31  
32  import java.io.BufferedWriter;
33  import java.io.DataInput;
34  import java.io.DataOutput;
35  import java.io.File;
36  import java.io.FileWriter;
37  import java.io.IOException;
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  import org.apache.commons.io.IOUtils;
42  import org.openimaj.image.FImage;
43  import org.openimaj.image.ImageUtilities;
44  import org.openimaj.image.processing.face.alignment.AffineAligner;
45  import org.openimaj.image.processing.face.alignment.FaceAligner;
46  import org.openimaj.image.processing.face.detection.DetectedFace;
47  import org.openimaj.image.processing.face.detection.FaceDetector;
48  import org.openimaj.image.processing.face.detection.keypoints.FKEFaceDetector;
49  import org.openimaj.image.processing.face.detection.keypoints.KEDetectedFace;
50  import org.openimaj.math.geometry.shape.Rectangle;
51  import org.openimaj.util.function.Operation;
52  import org.openimaj.util.parallel.Parallel;
53  
54  import scala.actors.threadpool.Arrays;
55  
56  public class FVFWDetectAlign {
57  	static interface FDFactory {
58  		FKEFaceDetector create();
59  	}
60  
61  	@SuppressWarnings("unchecked")
62  	private static void extractFaces(final File indir, final File outDir, final FDFactory factory,
63  			final FaceAligner<KEDetectedFace> aligner) throws IOException
64  	{
65  		final List<String> skipped = new ArrayList<String>();
66  
67  		Parallel.forEach(Arrays.asList(indir.listFiles()), new Operation<File>() {
68  
69  			@Override
70  			public void perform(File dir) {
71  				try {
72  					if (!dir.isDirectory())
73  						return;
74  
75  					final FKEFaceDetector detector = factory.create();
76  
77  					for (final File imgfile : dir.listFiles()) {
78  						if (!imgfile.getName().endsWith(".jpg"))
79  							continue;
80  
81  						System.out.println(imgfile);
82  						final File outfile = new File(outDir, imgfile.getAbsolutePath().replace(indir.getAbsolutePath(),
83  								""));
84  						outfile.getParentFile().mkdirs();
85  
86  						final FImage aligned = extractAndAlignFace(ImageUtilities.readF(imgfile), detector, aligner);
87  
88  						if (aligned == null) {
89  							synchronized (skipped) {
90  								skipped.add(imgfile.toString());
91  							}
92  						} else {
93  							ImageUtilities.write(aligned, outfile);
94  						}
95  					}
96  				} catch (final Exception e) {
97  					e.printStackTrace();
98  					System.err.println(e);
99  				}
100 			}
101 		});
102 
103 		final BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outDir, "skipped.txt")));
104 		IOUtils.writeLines(skipped, "\n", writer);
105 		writer.close();
106 	}
107 
108 	private static FImage
109 			extractAndAlignFace(FImage img, FKEFaceDetector detector, FaceAligner<KEDetectedFace> aligner)
110 	{
111 		final List<KEDetectedFace> faces = detector.detectFaces(img);
112 
113 		if (faces.size() == 1)
114 			return aligner.align(faces.get(0));
115 
116 		return null;
117 	}
118 
119 	/**
120 	 * @param args
121 	 * @throws IOException
122 	 */
123 	public static void main(String[] args) throws IOException {
124 		final FDFactory factory = new FDFactory() {
125 			@Override
126 			public FKEFaceDetector create() {
127 				final FaceDetector<DetectedFace, FImage> inner = new FaceDetector<DetectedFace, FImage>() {
128 					@Override
129 					public void readBinary(DataInput in) throws IOException {
130 						// do nothing
131 					}
132 
133 					@Override
134 					public byte[] binaryHeader() {
135 						return null;
136 					}
137 
138 					@Override
139 					public void writeBinary(DataOutput out) throws IOException {
140 						// do nothing
141 					}
142 
143 					@Override
144 					public List<DetectedFace> detectFaces(FImage image) {
145 						final List<DetectedFace> faces = new ArrayList<DetectedFace>();
146 
147 						final int dw = Math.round(image.width / 2.2f);
148 						final int dh = Math.round(image.height / 2.2f);
149 						final int x = (image.width - dw) / 2;
150 						final int y = (image.height - dh) / 2;
151 						final Rectangle bounds = new Rectangle(x, y, dw, dh);
152 
153 						faces.add(new DetectedFace(bounds, image.extractROI(bounds), 1f));
154 
155 						return faces;
156 					}
157 				};
158 
159 				return new FKEFaceDetector(inner, 1.5f);
160 			}
161 		};
162 
163 		final AffineAligner aligner = new AffineAligner(125, 160, 0.1f);
164 
165 		extractFaces(new File("/Volumes/Raid/face_databases/lfw"), new File(
166 				"/Volumes/Raid/face_databases/lfw-centre-affine/"), factory, aligner);
167 	}
168 }