Visual Servoing Platform  version 3.6.1 under development (2025-02-19)
tutorial-face-detector-live.cpp
1 #include <iostream>
3 
4 #include <visp3/core/vpConfig.h>
5 
7 // Comment / uncomment following lines to use the specific 3rd party compatible with your camera
8 // #undef VISP_HAVE_V4L2
9 // #undef HAVE_OPENCV_HIGHGUI
10 // #undef HAVE_OPENCV_VIDEOIO
12 
13 #if defined(HAVE_OPENCV_IMGPROC) \
14  && (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_OBJDETECT)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_XOBJDETECT))) \
15  && (defined(VISP_HAVE_V4L2) || (((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI)) || ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))))
16 
17 #include <visp3/detection/vpDetectorFace.h>
18 #include <visp3/gui/vpDisplayFactory.h>
19 #ifdef VISP_HAVE_MODULE_SENSOR
20 #include <visp3/sensor/vpV4l2Grabber.h>
21 #endif
22 
23 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI)
24 #include <opencv2/highgui/highgui.hpp> // for cv::VideoCapture
25 #elif (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO)
26 #include <opencv2/videoio/videoio.hpp>
27 #endif
28 
29 int main(int argc, const char *argv[])
30 {
31 #ifdef ENABLE_VISP_NAMESPACE
32  using namespace VISP_NAMESPACE_NAME;
33 #endif
34 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
35  std::shared_ptr<vpDisplay> display;
36 #else
37  vpDisplay *display = nullptr;
38 #endif
39  try {
40  std::string opt_face_cascade_name = "./haarcascade_frontalface_alt.xml";
41  unsigned int opt_device = 0;
42  unsigned int opt_scale = 2; // Default value is 2 in the constructor. Turn
43  // it to 1 to avoid subsampling
44 
45  for (int i = 1; i < argc; i++) {
46  if (std::string(argv[i]) == "--haar" && i + 1 < argc) {
47  opt_face_cascade_name = std::string(argv[++i]);
48  }
49  else if (std::string(argv[i]) == "--device" && i + 1 < argc) {
50  opt_device = (unsigned int)atoi(argv[++i]);
51  }
52  else if (std::string(argv[i]) == "--scale" && i + 1 < argc) {
53  opt_scale = (unsigned int)atoi(argv[++i]);
54  }
55  else if ((std::string(argv[i]) == "--help") || (std::string(argv[i]) == "-h")) {
56  std::cout << "Usage: " << argv[0]
57  << " [--haar <haarcascade xml filename>]"
58  << " [--device <camera device>]"
59  << " [--scale <subsampling factor>]"
60  << " [--help] [-h]"
61  << std::endl;
62  return EXIT_SUCCESS;
63  }
64  }
65 
66  vpImage<unsigned char> I; // for gray images
67 
69 #if defined(VISP_HAVE_V4L2)
70  vpV4l2Grabber g;
71  std::ostringstream device;
72  device << "/dev/video" << opt_device;
73  g.setDevice(device.str());
74  g.setScale(opt_scale); // Default value is 2 in the constructor. Turn it
75  // to 1 to avoid subsampling
76  g.acquire(I);
77 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
78  cv::VideoCapture cap(opt_device); // open the default camera
79 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
80  int width = (int)cap.get(cv::CAP_PROP_FRAME_WIDTH);
81  int height = (int)cap.get(cv::CAP_PROP_FRAME_HEIGHT);
82  cap.set(cv::CAP_PROP_FRAME_WIDTH, width / opt_scale);
83  cap.set(cv::CAP_PROP_FRAME_HEIGHT, height / opt_scale);
84 #else
85  int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
86  int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
87  cap.set(CV_CAP_PROP_FRAME_WIDTH, width / opt_scale);
88  cap.set(CV_CAP_PROP_FRAME_HEIGHT, height / opt_scale);
89 #endif
90  if (!cap.isOpened()) { // check if we succeeded
91  std::cout << "Failed to open the camera" << std::endl;
92  return EXIT_FAILURE;
93  }
94  cv::Mat frame;
95  cap >> frame; // get a new frame from camera
96  vpImageConvert::convert(frame, I);
97 #endif
99 
100 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
101  display = vpDisplayFactory::createDisplay(I);
102 #else
104 #endif
105  vpDisplay::setTitle(I, "ViSP viewer");
106 
107  vpDetectorFace face_detector;
108  face_detector.setCascadeClassifierFile(opt_face_cascade_name);
109 
110  while (1) {
111  double t = vpTime::measureTimeMs();
113 #if defined(VISP_HAVE_V4L2)
114  g.acquire(I);
115  bool face_found = face_detector.detect(I);
116 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
117  cap >> frame; // get a new frame from camera
118  vpImageConvert::convert(frame, I);
119  bool face_found = face_detector.detect(frame); // We pass frame to avoid an internal image conversion
120 #endif
122 
124 
125  if (face_found) {
126  std::ostringstream text;
127  text << "Found " << face_detector.getNbObjects() << " face(s)";
128  vpDisplay::displayText(I, 10, 10, text.str(), vpColor::red);
129  for (size_t i = 0; i < face_detector.getNbObjects(); i++) {
130  vpRect bbox = face_detector.getBBox(i);
131  vpDisplay::displayRectangle(I, bbox, vpColor::green, false, 4);
132  vpDisplay::displayText(I, (int)bbox.getTop() - 10, (int)bbox.getLeft(),
133  "Message: \"" + face_detector.getMessage(i) + "\"", vpColor::red);
134  }
135  }
136  vpDisplay::displayText(I, (int)I.getHeight() - 25, 10, "Click to quit...", vpColor::red);
137  vpDisplay::flush(I);
138  if (vpDisplay::getClick(I, false)) // a click to exit
139  break;
140 
141  std::cout << "Loop time: " << vpTime::measureTimeMs() - t << " ms" << std::endl;
142  }
143  }
144  catch (const vpException &e) {
145  std::cout << e.getMessage() << std::endl;
146  }
147 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
148  if (display != nullptr) {
149  delete display;
150  }
151 #endif
152 }
153 
154 #else
155 
156 int main()
157 {
158 #if !defined(HAVE_OPENCV_IMGPROC)
159  std::cout << "This tutorial needs OpenCV imgproc module that is missing." << std::endl;
160 #endif
161 #if (VISP_HAVE_OPENCV_VERSION < 0x050000) && !defined(HAVE_OPENCV_OBJDETECT)
162  std::cout << "This tutorial needs OpenCV objdetect module that is missing." << std::endl;
163 #endif
164 #if ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && !defined(HAVE_OPENCV_XOBJDETECT))
165  std::cout << "This tutorial needs OpenCV xobjdetect module that is missing." << std::endl;
166 #endif
167  }
168 
169 #endif
static const vpColor red
Definition: vpColor.h:198
static const vpColor green
Definition: vpColor.h:201
vpRect getBBox(size_t i) const
size_t getNbObjects() const
std::vector< std::string > & getMessage()
void setCascadeClassifierFile(const std::string &filename)
bool detect(const vpImage< unsigned char > &I) VP_OVERRIDE
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
const char * getMessage() const
Definition: vpException.cpp:65
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
unsigned int getHeight() const
Definition: vpImage.h:181
Defines a rectangle in the plane.
Definition: vpRect.h:79
double getLeft() const
Definition: vpRect.h:173
double getTop() const
Definition: vpRect.h:192
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT double measureTimeMs()