Visual Servoing Platform  version 3.6.1 under development (2024-10-15)
vpImageQueue.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Image queue for storage helper.
32  */
33 
34 #ifndef vpImageQueue_h
35 #define vpImageQueue_h
36 
37 #include <visp3/core/vpConfig.h>
38 
39 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) && defined(VISP_HAVE_THREADS)
40 
41 #include <condition_variable>
42 #include <mutex>
43 #include <queue>
44 #include <string>
45 #include <thread>
46 
47 #include <visp3/core/vpDisplay.h>
48 #include <visp3/core/vpIoTools.h>
49 
50 BEGIN_VISP_NAMESPACE
51 
52 #ifndef DOXYGEN_SHOULD_SKIP_THIS
64 template <class Type> class vpImageQueue
65 {
66 public:
67  struct vpCancelled_t
68  { };
69 
77  vpImageQueue(const std::string &seqname, int record_mode)
78  : m_cancelled(false), m_cond(), m_queue_image(), m_queue_data(), m_maxQueueSize(1024 * 8), m_mutex(),
79  m_seqname(seqname), m_recording_mode(record_mode), m_start_recording(false), m_directory_to_create(false),
80  m_recording_trigger(false)
81  {
82  m_directory = vpIoTools::getParent(seqname);
83  if (!m_directory.empty()) {
84  if (!vpIoTools::checkDirectory(m_directory)) {
85  m_directory_to_create = true;
86  }
87  }
88  m_text_record_mode =
89  std::string("Record mode: ") + (m_recording_mode ? std::string("single") : std::string("continuous"));
90  }
91 
95  void cancel()
96  {
97  std::lock_guard<std::mutex> lock(m_mutex);
98  std::cout << "Wait to finish saving images..." << std::endl;
99  m_cancelled = true;
100  m_cond.notify_all();
101  }
102 
106  int getRecordingMode() const { return m_recording_mode; }
107 
111  bool getRecordingTrigger() const { return m_recording_trigger; }
112 
116  std::string getSeqName() const { return m_seqname; }
117 
125  void pop(vpImage<Type> &I, std::string &data)
126  {
127  std::unique_lock<std::mutex> lock(m_mutex);
128 
129  while (m_queue_image.empty()) {
130  if (m_cancelled) {
131  throw vpCancelled_t();
132  }
133 
134  m_cond.wait(lock);
135 
136  if (m_cancelled) {
137  throw vpCancelled_t();
138  }
139  }
140 
141  I = m_queue_image.front();
142 
143  m_queue_image.pop();
144 
145  if (!m_queue_data.empty()) {
146  data = m_queue_data.front();
147  m_queue_data.pop();
148  }
149  }
150 
157  void push(const vpImage<Type> &I, std::string *data)
158  {
159  std::lock_guard<std::mutex> lock(m_mutex);
160 
161  m_queue_image.push(I);
162 
163  if (data != nullptr) {
164  m_queue_data.push(*data);
165  }
166 
167  // Pop extra data in the queue
168  while (m_queue_image.size() > m_maxQueueSize) {
169  m_queue_image.pop();
170  }
171 
172  if (data != nullptr) {
173  while (m_queue_data.size() > m_maxQueueSize) {
174  m_queue_data.pop();
175  }
176  }
177 
178  m_cond.notify_one();
179  }
180 
190  bool record(const vpImage<Type> &I, std::string *data = nullptr, bool trigger_recording = false,
191  bool disable_left_click = false)
192  {
193  if (I.display) {
194  if (!m_seqname.empty()) {
195  if (!disable_left_click) {
196  if (!m_recording_mode) { // continuous
197  if (m_start_recording) {
199  10 * vpDisplay::getDownScalingFactor(I), "Left click: stop recording",
200  vpColor::red);
201  }
202  else {
204  10 * vpDisplay::getDownScalingFactor(I), "Left click: start recording",
205  vpColor::red);
206  }
207  }
208  else {
210  "Left click: record image", vpColor::red);
211  }
212  }
214  "Right click: quit", vpColor::red);
215  }
216  else {
218  "Click to quit", vpColor::red);
219  }
220 
221  if (!m_seqname.empty()) {
223  m_text_record_mode, vpColor::red);
224  }
226  if (vpDisplay::getClick(I, button, false)) {
227  if (!m_seqname.empty()) { // Recording requested
228  if (button == vpMouseButton::button1 && !disable_left_click) { // enable/disable recording
229  m_start_recording = !m_start_recording;
230  }
231  else if (button == vpMouseButton::button3) { // quit
232  return true;
233  }
234  }
235  else { // any button to quit
236  return true;
237  }
238  }
239  }
240  else if (!m_seqname.empty()) {
241  m_start_recording = true;
242  }
243 
244  if (trigger_recording) {
245  m_start_recording = true;
246  }
247 
248  m_recording_trigger = m_start_recording;
249 
250  if (m_start_recording) {
251 
252  if (m_directory_to_create) {
253  std::cout << "Create directory \"" << m_directory << "\"" << std::endl;
254  vpIoTools::makeDirectory(m_directory);
255  m_directory_to_create = false;
256  }
257 
258  push(I, data);
259 
260  if (m_recording_mode == 1) { // single shot mode
261  m_start_recording = false;
262  }
263  }
264  return false;
265  }
266 
271  void setMaxQueueSize(const size_t max_queue_size) { m_maxQueueSize = max_queue_size; }
272 
273 private:
274  bool m_cancelled;
275  std::condition_variable m_cond;
276  std::queue<vpImage<Type> > m_queue_image;
277  std::queue<std::string> m_queue_data;
278  size_t m_maxQueueSize;
279  std::mutex m_mutex;
280  std::string m_seqname;
281  std::string m_directory;
282  int m_recording_mode;
283  bool m_start_recording;
284  std::string m_text_record_mode;
285  bool m_directory_to_create;
286  bool m_recording_trigger;
287 };
288 
289 #endif // DOXYGEN_SHOULD_SKIP_THIS
290 END_VISP_NAMESPACE
291 #endif
292 #endif
static const vpColor red
Definition: vpColor.h:217
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
unsigned int getDownScalingFactor()
Definition: vpDisplay.h:221
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition of the vpImage class member functions.
Definition: vpImage.h:131
vpDisplay * display
Definition: vpImage.h:136
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:396
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:550
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1314