Fawkes API  Fawkes Development Version
qa_facesclassifier.cpp
1 
2 /***************************************************************************
3  * qa_camargp.h - QA for camera argument parser
4  *
5  * Generated: Wed Apr 11 16:02:33 2007
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  * 2009 Daniel Beck
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 /// @cond QA
26 
27 #include <cams/factory.h>
28 #include <classifiers/faces.h>
29 #include <filters/roidraw.h>
30 #include <fvutils/adapters/iplimage.h>
31 #include <fvutils/color/colorspaces.h>
32 #include <fvutils/draw/drawer.h>
33 #include <fvutils/readers/jpeg.h>
34 #include <fvwidgets/image_display.h>
35 #include <opencv/cv.h>
36 #include <utils/system/argparser.h>
37 #include <utils/time/tracker.h>
38 
39 #include <SDL.h>
40 #include <cstdio>
41 #include <cstdlib>
42 
43 using namespace fawkes;
44 
45 int
46 main(int argc, char **argv)
47 {
48  ArgumentParser *argp = new ArgumentParser(argc, argv, "h:f:c:");
49 
50  if (argp->has_arg("h") && argp->has_arg("f"))
51  // read image from file
52  {
53  const char *cascade_file = argp->arg("h");
54  const char *image_file = argp->arg("f");
55 
56  JpegReader * reader = new JpegReader(image_file);
57  unsigned char *buffer =
58  malloc_buffer(YUV422_PLANAR, reader->pixel_width(), reader->pixel_height());
59 
60  reader->set_buffer(buffer);
61  reader->read();
62 
63  FacesClassifier *classifier =
64  new FacesClassifier(cascade_file, reader->pixel_width(), reader->pixel_height());
65 
66  classifier->set_src_buffer(buffer, reader->pixel_width(), reader->pixel_height());
67  std::list<ROI> *rois = classifier->classify();
68 
69  FilterROIDraw *roi_draw = new FilterROIDraw();
70  for (std::list<ROI>::iterator i = rois->begin(); i != rois->end(); ++i) {
71  printf("ROI: start (%u, %u) extent %u x %u\n",
72  (*i).start.x,
73  (*i).start.y,
74  (*i).width,
75  (*i).height);
76 
77  roi_draw->set_dst_buffer(buffer, &(*i));
78  roi_draw->apply();
79  }
80 
81  ImageDisplay *display = new ImageDisplay(reader->pixel_width(), reader->pixel_height());
82  display->show(buffer);
83 
84  display->loop_until_quit();
85 
86  delete display;
87 
88  delete rois;
89  free(buffer);
90  delete reader;
91  delete classifier;
92  }
93 
94  else if (argp->has_arg("h") && argp->has_arg("c"))
95  // get images from camera
96  {
97  const char *cascade_file = argp->arg("h");
98 
99  Camera *camera = NULL;
100  try {
101  camera = CameraFactory::instance(argp->arg("c"));
102  camera->open();
103  camera->start();
104  } catch (Exception &e) {
105  printf("Failed to open camera.\n");
106  delete camera;
107  return (-1);
108  }
109 
110  printf("successfully opened camera: w=%d h=%d\n",
111  camera->pixel_width(),
112  camera->pixel_height());
113 
114  TimeTracker *tt = new TimeTracker();
115  unsigned int ttc_recognition = tt->add_class("Face recognition");
116  unsigned int loop_count = 0;
117 
118  IplImage *image =
119  cvCreateImage(cvSize(camera->pixel_width(), camera->pixel_height()), IPL_DEPTH_8U, 3);
120 
121  IplImage *scaled_image =
122  cvCreateImage(cvSize(camera->pixel_width() / 2, camera->pixel_height() / 2), IPL_DEPTH_8U, 3);
123 
124  FacesClassifier *classifier = new FacesClassifier(cascade_file,
125  camera->pixel_width(),
126  camera->pixel_height(),
127  scaled_image,
128  1.2 /* scale factor */,
129  2 /* min neighbours */,
130  CV_HAAR_DO_CANNY_PRUNING);
131 
132  unsigned char *display_buffer = (unsigned char *)malloc(camera->buffer_size());
133 
134  ImageDisplay *display =
135  new ImageDisplay(camera->pixel_width(), camera->pixel_height(), "QA Faces Classifier");
136 
137  Drawer *drawer = new Drawer();
138  drawer->set_buffer(display_buffer, camera->pixel_width(), camera->pixel_height());
139 
140  SDL_Event redraw_event;
141  redraw_event.type = SDL_KEYUP;
142  redraw_event.key.keysym.sym = SDLK_SPACE;
143 
144  SDL_PushEvent(&redraw_event);
145 
146  bool quit = false;
147  while (!quit) {
148  SDL_Event event;
149  if (SDL_WaitEvent(&event)) {
150  switch (event.type) {
151  case SDL_QUIT: quit = true; break;
152 
153  case SDL_KEYUP:
154  if (event.key.keysym.sym == SDLK_SPACE) {
155  camera->capture();
156 
157  if (camera->buffer() != NULL) {
158  IplImageAdapter::convert_image_bgr(camera->buffer(), image);
159  cvResize(image, scaled_image, CV_INTER_LINEAR);
160  memcpy(display_buffer, camera->buffer(), camera->buffer_size());
161 
162  tt->ping_start(ttc_recognition);
163  std::list<ROI> *rois = classifier->classify();
164  tt->ping_end(ttc_recognition);
165 
166  camera->dispose_buffer();
167 
168  bool first = true;
169  for (std::list<ROI>::reverse_iterator i = rois->rbegin(); i != rois->rend(); ++i) {
170  if (first) {
171  drawer->set_color(127, 70, 200);
172  }
173  drawer->draw_rectangle(2 * i->start.x, 2 * i->start.y, 2 * i->width, 2 * i->height);
174  if (first) {
175  drawer->set_color(30, 30, 30);
176  first = false;
177  }
178  }
179 
180  if (++loop_count % 15 == 0) {
181  tt->print_to_stdout();
182  }
183 
184  display->show(display_buffer);
185  }
186 
187  SDL_PushEvent(&redraw_event);
188  }
189 
190  else if (event.key.keysym.sym == SDLK_ESCAPE) {
191  quit = true;
192  }
193 
194  break;
195 
196  default: break;
197  }
198  }
199  }
200 
201  camera->stop();
202  camera->close();
203  delete camera;
204  delete display;
205  delete drawer;
206  free(display_buffer);
207  cvReleaseImage(&image);
208  cvReleaseImage(&scaled_image);
209  delete tt;
210  }
211 
212  else {
213  printf("Usage: %s -h <Haar cascade file> -f <Image file as JPEG>\n", argv[0]);
214  printf(" or %s -h <Haar cascade file> -c <Camera argument string>\n", argv[0]);
215  exit(-1);
216  }
217 
218  delete argp;
219 }
220 
221 /// @endcond
Parse command line arguments.
Definition: argparser.h:64
const char * arg(const char *argn)
Get argument value.
Definition: argparser.cpp:177
bool has_arg(const char *argn)
Check if argument has been supplied.
Definition: argparser.cpp:165
Base class for exceptions in Fawkes.
Definition: exception.h:36
Time tracking utility.
Definition: tracker.h:37
void print_to_stdout()
Print results to stdout.
Definition: tracker.cpp:307
unsigned int add_class(std::string name)
Add a new class.
Definition: tracker.cpp:149
void ping_end(unsigned int cls)
End of given class task.
Definition: tracker.cpp:243
void ping_start(unsigned int cls)
Start of given class task.
Definition: tracker.cpp:218
Fawkes library namespace.