Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tutorial-grabber-opencv-threaded.cpp
1 #include <iostream>
4 
5 #include <visp3/core/vpImageConvert.h>
6 #include <visp3/core/vpMutex.h>
7 #include <visp3/core/vpThread.h>
8 #include <visp3/core/vpTime.h>
9 #include <visp3/gui/vpDisplayX.h>
10 #include <visp3/gui/vpDisplayGDI.h>
11 
12 #if (VISP_HAVE_OPENCV_VERSION >= 0x020100) && (defined(VISP_HAVE_PTHREAD) || defined(_WIN32))
13 
14 #include <opencv2/highgui/highgui.hpp>
15 
16 // Shared vars
17 typedef enum {
18  capture_waiting,
19  capture_started,
20  capture_stopped
21 } t_CaptureState;
22 t_CaptureState s_capture_state = capture_waiting;
23 cv::Mat s_frame;
24 vpMutex s_mutex_capture;
26 
28 vpThread::Return captureFunction(vpThread::Args args)
29 {
30  cv::VideoCapture cap = *((cv::VideoCapture *) args);
31 
32  if(!cap.isOpened()) { // check if we succeeded
33  std::cout << "Unable to start capture" << std::endl;
34  return 0;
35  }
36 
37  cv::Mat frame_;
38  int i=0;
39  while ((i++ < 100) && !cap.read(frame_)) {}; // warm up camera by skiping unread frames
40 
41  bool stop_capture_ = false;
42 
43  double start_time = vpTime::measureTimeSecond();
44  while ((vpTime::measureTimeSecond() - start_time) < 30 && !stop_capture_) {
45  // Capture in progress
46  cap >> frame_; // get a new frame from camera
47 
48  // Update shared data
49  {
50  vpMutex::vpScopedLock lock(s_mutex_capture);
51  if (s_capture_state == capture_stopped)
52  stop_capture_ = true;
53  else
54  s_capture_state = capture_started;
55  s_frame = frame_;
56  }
57  }
58 
59  {
60  vpMutex::vpScopedLock lock(s_mutex_capture);
61  s_capture_state = capture_stopped;
62  }
63 
64  std::cout << "End of capture thread" << std::endl;
65  return 0;
66 }
68 
70 vpThread::Return displayFunction(vpThread::Args args)
71 {
72  (void)args; // Avoid warning: unused parameter args
74 
75  t_CaptureState capture_state_;
76  bool display_initialized_ = false;
77 #if defined(VISP_HAVE_X11)
78  vpDisplayX *d_ = NULL;
79 #elif defined(VISP_HAVE_GDI)
80  vpDisplayGDI *d_ = NULL;
81 #endif
82 
83  do {
84  s_mutex_capture.lock();
85  capture_state_ = s_capture_state;
86  s_mutex_capture.unlock();
87 
88  // Check if a frame is available
89  if (capture_state_ == capture_started) {
90  // Get the frame and convert it to a ViSP image used by the display class
91  {
92  vpMutex::vpScopedLock lock(s_mutex_capture);
93  vpImageConvert::convert(s_frame, I_);
94  }
95 
96  // Check if we need to initialize the display with the first frame
97  if (! display_initialized_) {
98  // Initialize the display
99 #if defined(VISP_HAVE_X11)
100  d_ = new vpDisplayX(I_);
101  display_initialized_ = true;
102 #elif defined(VISP_HAVE_GDI)
103  d_ = new vpDisplayGDI(I_);
104  display_initialized_ = true;
105 #endif
106  }
107 
108  // Display the image
109  vpDisplay::display(I_);
110 
111  // Trigger end of acquisition with a mouse click
112  vpDisplay::displayText(I_, 10, 10, "Click to exit...", vpColor::red);
113  if (vpDisplay::getClick(I_, false)) {
114  vpMutex::vpScopedLock lock(s_mutex_capture);
115  s_capture_state = capture_stopped;
116  }
117 
118  // Update the display
119  vpDisplay::flush(I_);
120  }
121  else {
122  vpTime::wait(2); // Sleep 2ms
123  }
124  } while(capture_state_ != capture_stopped);
125 
126 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)
127  delete d_;
128 #endif
129 
130  std::cout << "End of display thread" << std::endl;
131  return 0;
132 }
134 
136 int main(int argc, const char* argv[])
137 {
138  int opt_device = 0;
139 
140  // Command line options
141  for (int i=0; i<argc; i++) {
142  if (std::string(argv[i]) == "--device")
143  opt_device = atoi(argv[i+1]);
144  else if (std::string(argv[i]) == "--help") {
145  std::cout << "Usage: " << argv[0] << " [--device <camera device>] [--help]" << std::endl;
146  return 0;
147  }
148  }
149 
150  // Instanciate the capture
151  cv::VideoCapture cap;
152  cap.open(opt_device);
153 
154  // Start the threads
155  vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&cap);
156  vpThread thread_display((vpThread::Fn)displayFunction);
157 
158  // Wait until thread ends up
159  thread_capture.join();
160  thread_display.join();
161 
162  return 0;
163 }
165 
166 #else
167 int main()
168 {
169 # ifndef VISP_HAVE_OPENCV
170  std::cout << "You should install OpenCV to make this example working..." << std::endl;
171 # elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
172  std::cout << "You should enable pthread usage and rebuild ViSP..." << std::endl;
173 # else
174  std::cout << "Multi-threading seems not supported on this platform" << std::endl;
175 # endif
176 }
177 
178 #endif
Class that allows protection by mutex.
Definition: vpMutex.h:163
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:157
void lock()
Definition: vpMutex.h:90
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void * Return
Definition: vpThread.h:36
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
VISP_EXPORT double measureTimeSecond()
Definition: vpTime.cpp:255
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
void unlock()
Definition: vpMutex.h:106
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:153
static void flush(const vpImage< unsigned char > &I)
void *(* Fn)(Args)
Definition: vpThread.h:37
static const vpColor red
Definition: vpColor.h:163
void * Args
Definition: vpThread.h:35
static void display(const vpImage< unsigned char > &I)