OpenPose  1.0.0rc2
OpenPose: A Real-Time Multi-Person Key-Point Detection And Multi-Threading C++ Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
datumProducer.hpp
Go to the documentation of this file.
1 #ifndef OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP
2 #define OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP
3 
4 #include <atomic>
5 #include <limits> // std::numeric_limits
6 #include <tuple>
11 
12 namespace op
13 {
14  template<typename TDatumsNoPtr>
16  {
17  public:
18  explicit DatumProducer(const std::shared_ptr<Producer>& producerSharedPtr,
19  const unsigned long long frameFirst = 0, const unsigned long long frameStep = 1,
20  const unsigned long long frameLast = std::numeric_limits<unsigned long long>::max(),
21  const std::shared_ptr<std::pair<std::atomic<bool>,
22  std::atomic<int>>>& videoSeekSharedPtr = nullptr);
23 
24  virtual ~DatumProducer();
25 
26  std::pair<bool, std::shared_ptr<TDatumsNoPtr>> checkIfRunningAndGetDatum();
27 
28  private:
29  const unsigned long long mNumberFramesToProcess;
30  std::shared_ptr<Producer> spProducer;
31  unsigned long long mGlobalCounter;
32  unsigned long long mFrameStep;
33  unsigned int mNumberConsecutiveEmptyFrames;
34  std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>> spVideoSeek;
35 
36  void checkIfTooManyConsecutiveEmptyFrames(unsigned int& numberConsecutiveEmptyFrames,
37  const bool emptyFrame) const;
38 
39  DELETE_COPY(DatumProducer);
40  };
41 }
42 
43 
44 
45 
46 
47 // Implementation
48 #include <opencv2/imgproc/imgproc.hpp> // cv::cvtColor
50 namespace op
51 {
52  template<typename TDatumsNoPtr>
53  DatumProducer<TDatumsNoPtr>::DatumProducer(const std::shared_ptr<Producer>& producerSharedPtr,
54  const unsigned long long frameFirst, const unsigned long long frameStep,
55  const unsigned long long frameLast,
56  const std::shared_ptr<std::pair<std::atomic<bool>,
57  std::atomic<int>>>& videoSeekSharedPtr) :
58  mNumberFramesToProcess{(frameLast != std::numeric_limits<unsigned long long>::max()
59  ? frameLast - frameFirst : frameLast)},
60  spProducer{producerSharedPtr},
61  mGlobalCounter{0ll},
62  mFrameStep{frameStep},
63  mNumberConsecutiveEmptyFrames{0u},
64  spVideoSeek{videoSeekSharedPtr}
65  {
66  try
67  {
68  // Sanity check
69  if (frameLast < frameFirst)
70  error("The desired initial frame must be lower than the last one (flags `--frame_first` vs."
71  " `--frame_last`). Current: " + std::to_string(frameFirst) + " vs. " + std::to_string(frameLast)
72  + ".", __LINE__, __FUNCTION__, __FILE__);
73  if (frameLast != std::numeric_limits<unsigned long long>::max()
74  && frameLast > spProducer->get(CV_CAP_PROP_FRAME_COUNT)-1)
75  error("The desired last frame must be lower than the length of the video or the number of images."
76  " Current: " + std::to_string(frameLast) + " vs. "
77  + std::to_string(intRound(spProducer->get(CV_CAP_PROP_FRAME_COUNT))-1) + ".",
78  __LINE__, __FUNCTION__, __FILE__);
79  // Set frame first and step
80  if (spProducer->getType() != ProducerType::FlirCamera && spProducer->getType() != ProducerType::IPCamera
81  && spProducer->getType() != ProducerType::Webcam)
82  {
83  // Frame first
84  spProducer->set(CV_CAP_PROP_POS_FRAMES, (double)frameFirst);
85  // Frame step
86  spProducer->set(ProducerProperty::FrameStep, (double)frameStep);
87  }
88  }
89  catch (const std::exception& e)
90  {
91  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
92  }
93  }
94 
95  template<typename TDatumsNoPtr>
97  {
98  }
99 
100  template<typename TDatumsNoPtr>
101  std::pair<bool, std::shared_ptr<TDatumsNoPtr>> DatumProducer<TDatumsNoPtr>::checkIfRunningAndGetDatum()
102  {
103  try
104  {
105  auto datums = std::make_shared<TDatumsNoPtr>();
106  // Check last desired frame has not been reached
107  if (mNumberFramesToProcess != std::numeric_limits<unsigned long long>::max()
108  && mGlobalCounter > mNumberFramesToProcess)
109  {
110  spProducer->release();
111  }
112  // If producer released -> it sends an empty cv::Mat + a datumProducerRunning signal
113  const bool datumProducerRunning = spProducer->isOpened();
114  // If device is open
115  if (datumProducerRunning)
116  {
117  // Fast forward/backward - Seek to specific frame index desired
118  if (spVideoSeek != nullptr)
119  {
120  // Fake pause vs. normal mode
121  const auto increment = spVideoSeek->second - (spVideoSeek->first ? 1 : 0);
122  // Normal mode
123  if (increment != 0)
124  spProducer->set(CV_CAP_PROP_POS_FRAMES, spProducer->get(CV_CAP_PROP_POS_FRAMES) + increment);
125  // It must be always reset or bug in fake pause
126  spVideoSeek->second = 0;
127  }
128  auto nextFrameName = spProducer->getNextFrameName();
129  const auto nextFrameNumber = (unsigned long long)spProducer->get(CV_CAP_PROP_POS_FRAMES);
130  const auto cvMats = spProducer->getFrames();
131  const auto cameraMatrices = spProducer->getCameraMatrices();
132  auto cameraExtrinsics = spProducer->getCameraExtrinsics();
133  auto cameraIntrinsics = spProducer->getCameraIntrinsics();
134  // Check frames are not empty
135  checkIfTooManyConsecutiveEmptyFrames(mNumberConsecutiveEmptyFrames, cvMats.empty() || cvMats[0].empty());
136  if (!cvMats.empty())
137  {
138  datums->resize(cvMats.size());
139  // Datum cannot be assigned before resize()
140  auto& datum = (*datums)[0];
141  // Filling first element
142  std::swap(datum.name, nextFrameName);
143  datum.frameNumber = nextFrameNumber;
144  datum.cvInputData = cvMats[0];
145  if (!cameraMatrices.empty())
146  {
147  datum.cameraMatrix = cameraMatrices[0];
148  datum.cameraExtrinsics = cameraExtrinsics[0];
149  datum.cameraIntrinsics = cameraIntrinsics[0];
150  }
151  // Image integrity
152  if (datum.cvInputData.channels() != 3)
153  {
154  const std::string commonMessage{"Input images must be 3-channel BGR."};
155  // Grey to RGB if required
156  if (datum.cvInputData.channels() == 1)
157  {
158  log(commonMessage + " Converting grey image into BGR.", Priority::High);
159  cv::cvtColor(datum.cvInputData, datum.cvInputData, CV_GRAY2BGR);
160  }
161  else
162  error(commonMessage, __LINE__, __FUNCTION__, __FILE__);
163  }
164  datum.cvOutputData = datum.cvInputData;
165  // Resize if it's stereo-system
166  if (datums->size() > 1)
167  {
168  // Stereo-system: Assign all cv::Mat
169  for (auto i = 1u ; i < datums->size() ; i++)
170  {
171  auto& datumI = (*datums)[i];
172  datumI.name = datum.name;
173  datumI.frameNumber = datum.frameNumber;
174  datumI.cvInputData = cvMats[i];
175  datumI.cvOutputData = datumI.cvInputData;
176  if (cameraMatrices.size() > i)
177  {
178  datumI.cameraMatrix = cameraMatrices[i];
179  datumI.cameraExtrinsics = cameraExtrinsics[i];
180  datumI.cameraIntrinsics = cameraIntrinsics[i];
181  }
182  }
183  }
184  // Check producer is running
185  if (!datumProducerRunning || (*datums)[0].cvInputData.empty())
186  datums = nullptr;
187  // Increase counter if successful image
188  if (datums != nullptr)
189  mGlobalCounter += mFrameStep;
190  }
191  }
192  // Return result
193  return std::make_pair(datumProducerRunning, datums);
194  }
195  catch (const std::exception& e)
196  {
197  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
198  return std::make_pair(false, std::make_shared<TDatumsNoPtr>());
199  }
200  }
201 
202  template<typename TDatumsNoPtr>
203  void DatumProducer<TDatumsNoPtr>::checkIfTooManyConsecutiveEmptyFrames(unsigned int& numberConsecutiveEmptyFrames,
204  const bool emptyFrame) const
205  {
206  numberConsecutiveEmptyFrames = (emptyFrame ? numberConsecutiveEmptyFrames+1 : 0);
207  const auto threshold = 500u;
208  if (numberConsecutiveEmptyFrames >= threshold)
209  error("Detected too many (" + std::to_string(numberConsecutiveEmptyFrames) + ") empty frames in a row.",
210  __LINE__, __FUNCTION__, __FILE__);
211  }
212 
213  extern template class DatumProducer<DATUM_BASE_NO_PTR>;
214 }
215 
216 
217 #endif // OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP
std::pair< bool, std::shared_ptr< TDatumsNoPtr > > checkIfRunningAndGetDatum()
Definition: datumProducer.hpp:101
OP_API void error(const std::string &message, const int line=-1, const std::string &function="", const std::string &file="")
virtual ~DatumProducer()
Definition: datumProducer.hpp:96
OP_API void log(const std::string &message, const Priority priority=Priority::Max, const int line=-1, const std::string &function="", const std::string &file="")
Definition: datumProducer.hpp:15
int intRound(const T a)
Definition: fastMath.hpp:26
DatumProducer(const std::shared_ptr< Producer > &producerSharedPtr, const unsigned long long frameFirst=0, const unsigned long long frameStep=1, const unsigned long long frameLast=std::numeric_limits< unsigned long long >::max(), const std::shared_ptr< std::pair< std::atomic< bool >, std::atomic< int >>> &videoSeekSharedPtr=nullptr)
Definition: datumProducer.hpp:53
std::string string
Definition: cl2.hpp:574