mlpcascadescan.cc

  1 const char *help = "\
  2 progname: mlpcascadescan.cc\n\
  3 code2html: This program detects objects (such as faces) in an image using a cascade of MLP.\n\
  4 Updades:\n\
  5    version 0.0: basic mlp cascade with mean-stdv pruning\n\
  6    version 1.0: adding edge pruning\n\
  7    version 2.0: correction of default stepx and stepy values\n\
  8 version: Torch3 vision2.1, 2004-2005-2006\n\
  9 (c) Sebastien Marcel (marcel@idiap.ch)\n";
 10 
 11 // image
 12 #include "ImageGray.h"
 13 #include "ImageRgb.h"
 14 #include "Rectangle2D.h"
 15 
 16 // image loader
 17 #include "xtprobeImageDiskXFile.h"
 18 #include "jpegDiskXFile.h"
 19 
 20 // pattern detector
 21 #include "PatternDetect.h"
 22 #include "PyramidPatternDetect.h"
 23 #include "NonOrientedPatternFusion.h"
 24 #include "PatternMerger.h"
 25 #include "ipSWmlpCascade.h"
 26 
 27 // edge
 28 #include "ipIntegralImage.h" 
 29 #include "ipSobel.h"
 30 
 31 //
 32 #include "MTimer.h"
 33 
 34 //
 35 #include "DiskXFile.h"
 36 #include "CmdLine.h"
 37 
 38 using namespace Torch;
 39 
 40 int main(int argc, char **argv)
 41 {
 42 	char *image_filename;
 43 	bool verbose;
 44 	      
 45         int patternWmin;
 46         int patternHmin;
 47         int minWsize;
 48         int maxWsize;
 49         real scale_factor;
 50         real stepx_factor;
 51         real stepy_factor;
 52 
 53         real MeanMin;
 54         real MeanMax;
 55         real StdvMin;
 56         real StdvMax;
 57 
 58 	bool pruning;
 59 
 60 	char *model_filename;
 61 	real model_threshold;
 62  
 63 	real threshold_edges_min;
 64 	real threshold_edges_max;
 65  
 66 	real surfoverlap_fusion;
 67 	real threshold_activation;
 68 
 69 	char *dirname;
 70 
 71 	int nbest;
 72 	bool savepos;
 73 	bool draw;
 74 	bool savejpg;
 75 
 76 
 77 	// Construct the command line.
 78 	// ---------------------------	
 79   	CmdLine cmd;
 80 	cmd.setBOption("write log", false);
 81   	cmd.info(help);
 82   	cmd.addText("\nArguments:");
 83   	cmd.addSCmdArg("image filename", &image_filename, "image filename");
 84   	cmd.addText("\nOptions:");
 85   	cmd.addBCmdOption("-verbose", &verbose, false, "verbose");
 86         cmd.addText("\nScanning Options:");
 87         cmd.addICmdOption("-patternWmin", &patternWmin, 19, "pattern width min");
 88         cmd.addICmdOption("-patternHmin", &patternHmin, 19, "pattern height min");
 89         cmd.addICmdOption("-minWsize", &minWsize, -1, "width min");
 90         cmd.addICmdOption("-maxWsize", &maxWsize, -1, "width max");
 91         cmd.addRCmdOption("-scalefactor", &scale_factor, 0.125, "scale factor");
 92         cmd.addRCmdOption("-stepxfactor", &stepx_factor, 0.1, "step x factor");
 93         cmd.addRCmdOption("-stepyfactor", &stepy_factor, 0.2, "step y factor");
 94 	cmd.addText("\nPruning Options:");
 95 	cmd.addBCmdOption("-pruning", &pruning, false, "use pruning");
 96 	cmd.addRCmdOption("-mmin", &MeanMin, 0.041, "mean min");
 97 	cmd.addRCmdOption("-mmax", &MeanMax, 0.890, "mean max");
 98 	cmd.addRCmdOption("-vmin", &StdvMin, 0.0204354, "variance min");
 99 	cmd.addRCmdOption("-vmax", &StdvMax, 0.382121, "variance max");
100 	cmd.addRCmdOption("-emin", &threshold_edges_min, 0.1, "edge threshold min");
101 	cmd.addRCmdOption("-emax", &threshold_edges_max, 0.5, "edge threshold max");
102 	cmd.addText("\nModel Options:");
103   	cmd.addSCmdOption("-model", &model_filename, "models/mlp-cascade19x19-20-2-110", "MLP cascade model filename");
104 	cmd.addRCmdOption("-threshold", &model_threshold, -0.99, "model threshold");
105 	cmd.addText("\nFusion Options:");
106 	cmd.addRCmdOption("-surfoverlapfusion", &surfoverlap_fusion, 0.6, "threshold for fusion of overlapped patterns");
107 	cmd.addRCmdOption("-threshold_activation", &threshold_activation, 2.0, "threshold after fusion");
108 	cmd.addText("\nMiscellaneous Options:");
109   	cmd.addSCmdOption("-dir", &dirname, ".", "directory to store ouput files");
110         cmd.addBCmdOption("-savepos", &savepos, false, "save pos file");
111         cmd.addBCmdOption("-draw", &draw, false, "draw ppm image with detections");
112         cmd.addBCmdOption("-savejpg", &savejpg, false, "save in jpeg instead of jpeg");
113         cmd.addICmdOption("-nbest", &nbest, -1, "nbest detections (all if -1)");
114 	cmd.read(argc, argv);
115 	
116 	if(strcmp(model_filename, "") == 0)
117 		error("No model specified.");
118 
119 	Allocator *allocator = new Allocator;
120 
121 	
122 	// extract basename from filename
123 	// --------------------------------
124 	char basename[256];
125 	char *extension;
126 	char *separator;
127 	strcpy(basename, image_filename);
128         extension = (char *) strrchr(basename, '.');
129         if(extension != NULL) *extension = '\0';
130 	separator = (char *) rindex(basename, '/');
131 	if(separator != NULL)
132 	{
133 		separator++;
134 		strcpy(basename, separator);
135 	}
136 	
137 	
138 	// load image to scan.
139 	// --------------------
140 	Image *image = NULL;
141 	ImageDiskXFile *image_file = NULL;
142 	image_file = new(allocator) xtprobeImageDiskXFile(image_filename, "r");
143 	image = new(allocator) ImageGray();
144 	image->setBOption("verbose", verbose);
145 	image->loadImageXFile(image_file);
146 	allocator->free(image_file);
147 
148         int width = image->width;
149         int height = image->height;
150 
151 	Sequence *realimage = new(allocator) Sequence(1, width * height);
152 	for(int i = 0 ; i < width * height ; i++) 
153 		realimage->frames[0][i] = image->data[i] / 255.0;
154 
155 	
156 	// pruning.
157 	// ---------
158 	real *pruning_ii = NULL;
159 
160 	if(pruning)
161 	{
162 		ipCore *edges = new(allocator) ipSobel(width, height, "float");
163 		edges->setROption("threshold", 0.4);
164 		Sequence *realedges = new(allocator) Sequence(&edges->seq_out->frames[3], 1, width * height);	
165 		ipCore *integralimagemachine_edges = new(allocator) ipIntegralImage(width, height, "gray");
166 		edges->init();
167 		edges->process(realimage);
168 		integralimagemachine_edges->init();
169 		integralimagemachine_edges->process(realedges);
170 
171 		pruning_ii = integralimagemachine_edges->seq_out->frames[0];
172 	}
173 	
174 	// Detection.
175 	// -----------
176 	PatternDetect *patterndetect;
177 
178 	PatternMerger *merger = new(allocator) meanRectPatternMerger();
179 	PatternFusion *pfusion;
180 	pfusion = new(allocator)NonOrientedPatternFusion(merger, 0, 100);
181 	pfusion->setParams(surfoverlap_fusion, model_threshold, true, threshold_activation);
182 		
183 	ipIntegralImage *ip_ii = new(allocator) ipIntegralImage(width, height, "gray", true);
184 	
185 	ipSubWindow *ip_sw = new(allocator) ipSWmlpCascade(width, height, patternWmin, patternHmin, model_filename, model_threshold, verbose);
186 	
187 	patterndetect = new(allocator) PyramidPatternDetect(
188 			ip_sw, pfusion, ip_ii,
189 	      		width, height, 
190 			patternWmin, patternHmin, 
191 			minWsize, maxWsize, 
192 			stepx_factor, stepy_factor, scale_factor,
193 			MeanMin, MeanMax, StdvMin, StdvMax,
194 			pruning_ii, 
195 			threshold_edges_min, threshold_edges_max,
196 			1000, verbose);
197 	/*
198 	patterndetect = new(allocator) MlpCascadePatternDetect(
199 			model_filename, 
200 	      		model_threshold,
201 	      		width, height, 
202 			patternWmin, patternHmin, 
203 			minWsize, maxWsize, 
204 			stepx_factor, stepy_factor, scale_factor,
205 			MeanMin, MeanMax, StdvMin, StdvMax,
206 			surfoverlap_fusion, threshold_activation, 
207 			integralimagemachine_edges->seq_out->frames[0], 
208 			threshold_edges_min, threshold_edges_max,
209 			1000, verbose);
210 	*/
211 	
212 	// Processing.
213 	// ---------------
214 	MTimer *timer = new(allocator) MTimer();
215         timer->reset();
216         patterndetect->init();
217         patterndetect->process(realimage);
218         patterndetect->stat();
219         timer->stop();
220 	print("processing time: %d' %d'' %dms\n\n", timer->minutes, timer->seconds, timer->mseconds);
221 	
222 	//	
223 	DiskXFile *posoutput = NULL;
224 	char str[250];
225 
226 	if(patterndetect->n_patterns > 0)
227 	{
228 	   	ImageRgb *outputimage = NULL;
229 
230 		if(draw)
231 		{
232 	   		outputimage = new(allocator) ImageRgb(width, height);
233 			outputimage->copyFrom(image);
234 		}
235 		
236 		if(savepos)
237 		{
238 			sprintf(str, "%s/%s.pos", dirname, basename);
239 			posoutput = new(allocator) DiskXFile(str, "w");
240 		}
241 		
242 		Color facecolor = green;
243 		Rectangle2D rect;
244 	
245 		int P = patterndetect->n_patterns;
246 		
247 		if(nbest != -1)
248 		{
249 			if(nbest < P) P = nbest;
250 			print("saving %d-bests\n", P);
251 		}
252 		
253 		if(savepos) posoutput->printf("%d\n", P);
254 		
255 		for(int i = 0 ; i < P ; i++)
256 		{
257 			if(verbose)
258 				print("DETECTION [%02d] %d %d %d %d %g %d %g %g\n", 
259                                         i,
260                                         patterndetect->patterns[i]->x, 
261                                         patterndetect->patterns[i]->y, 
262                                         patterndetect->patterns[i]->w, 
263                                         patterndetect->patterns[i]->h, 
264                                         patterndetect->patterns[i]->scale, 
265                                         patterndetect->patterns[i]->view, 
266                                         patterndetect->patterns[i]->confidence,
267                                         patterndetect->patterns[i]->activation);
268 
269 			rect.reset(	patterndetect->patterns[i]->x, patterndetect->patterns[i]->y, 
270 			      		patterndetect->patterns[i]->w, patterndetect->patterns[i]->h);
271 
272 			if(draw) rect.draw(outputimage, facecolor);
273 
274 			if(savepos)
275 				posoutput->printf("%d %d %d %d\n",
276 				      patterndetect->patterns[i]->x,
277 				      patterndetect->patterns[i]->y,
278 				      patterndetect->patterns[i]->w,
279 				      patterndetect->patterns[i]->h);
280 		}
281 		if(verbose) print("\n");
282 	  
283 		if(draw)
284 		{
285 		   	if(savejpg)
286 			{
287 			   	sprintf(str, "%s/%s-detect.jpg", dirname, basename);
288 				jpegDiskXFile *jpeg_file = new(allocator) jpegDiskXFile(str, "w");
289 				jpeg_file->writeHeader(outputimage->width, outputimage->height);
290 				jpeg_file->writePixmap(outputimage->pixmap);
291 				allocator->free(jpeg_file);
292 			}
293 			else
294 			{
295 				sprintf(str, "%s/%s-detect.ppm", dirname, basename);
296 
297 				outputimage->save(str);
298 			}
299 			allocator->free(outputimage);
300 		}
301 	}
302 	else
303 	{
304 		if(savepos) posoutput->printf("0\n");
305 	}
306 
307 	print("done.\n");
308 
309 	delete allocator;
310 
311 	return(0);
312 }