OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ImageProcessingThread.cpp
Go to the documentation of this file.
1 
11 // Copyright 2016 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 // Internal Includes
26 #include "ImageProcessingThread.h"
27 #include "TrackerThread.h"
28 #include "TrackingSystem.h"
29 
31 
32 // Library/third-party includes
33 #include <osvr/Util/Finally.h>
34 
35 // Standard includes
36 #include <iostream>
37 
38 namespace osvr {
39 namespace vbtracker {
40  ImageProcessingThread::ImageProcessingThread(
41  TrackingSystem &trackingSystem, ImageSource &cam,
42  TrackerThread &trackerThread, CameraParameters const &camParams,
43  std::int32_t cameraUsecOffset)
44  : trackingSystem_(trackingSystem), cam_(cam),
45  trackerThreadObj_(trackerThread), camParams_(camParams),
46  cameraUsecOffset_(cameraUsecOffset),
47  logBlobs_(trackingSystem_.getParams().logRawBlobs) {
48  if (logBlobs_) {
49  blobFile_.open("blobs.csv");
50  if (blobFile_) {
51  blobFile_ << "sec,usec,x,y,size" << std::endl;
52  } else {
53  warn() << "Could not open blob file!" << std::endl;
54  logBlobs_ = false;
55  }
56  }
57  }
58 
60  {
61  std::lock_guard<std::mutex> lock{stateMutex_};
62  next_ = NextOp::DoFrame;
63  }
64  stateCondVar_.notify_all();
65  }
66 
68  {
69  std::lock_guard<std::mutex> lock{stateMutex_};
70  next_ = NextOp::Exit;
71  }
72  stateCondVar_.notify_all();
73  }
74 
76  while (1) {
77  {
78  std::unique_lock<std::mutex> lock(stateMutex_);
79 
80  if (NextOp::Waiting == next_) {
82  stateCondVar_.wait(
83  lock, [&] { return next_ != NextOp::Waiting; });
84  }
85 
87  if (NextOp::Exit == next_) {
88  // we are all done.
89  exiting_ = true;
90  return;
91  }
94  next_ = NextOp::Waiting;
95  }
96  doFrame();
97  }
98  }
99 
100  void ImageProcessingThread::doFrame() {
101  ImageOutputDataPtr data;
104  auto signalCompletion = util::finally([&] {
105  trackerThreadObj_.signalImageProcessingComplete(std::move(data),
106  frame_, gray_);
107  });
108 
109  // Pull the image into an OpenCV matrix named m_frame.
110  util::time::TimeValue frameTime;
111  cam_.retrieve(frame_, gray_, frameTime);
112  if (!frame_.data || !gray_.data) {
113  // let the tracker thread warn if it wants to, we'll just get
114  // out.
115  return;
116  }
117 
119 
122 
123  if (cameraUsecOffset_ != 0) {
124  // apply offset, if non-zero.
125  const util::time::TimeValue offset{0, cameraUsecOffset_};
126  osvrTimeValueSum(&frameTime, &offset);
127  }
128 
129  // Do the slow, but intentionally async-able part of the image
130  // processing.
131  data = trackingSystem_.performInitialImageProcessing(frameTime, frame_,
132  gray_, camParams_);
133  // Log blobs, if applicable
134  if (logBlobs_) {
135  if (!blobFile_) {
136  // Oh dear, the file went bad.
137  logBlobs_ = false;
138  return;
139  }
140  blobFile_ << data->tv.seconds << "," << data->tv.microseconds;
141  for (auto &measurement : data->ledMeasurements) {
142  blobFile_ << "," << measurement.loc.x << ","
143  << measurement.loc.y << "," << measurement.diameter;
144  }
145  blobFile_ << "\n";
146  }
147 
148  // On return, we'll automatically notify the tracker thread that its
149  // results are ready for pickup at the second window.
150  }
151 
152  std::ostream &ImageProcessingThread::msg() const {
153  return std::cout << "[UnifiedTracker:ImgProcThread] ";
154  }
155 
156  std::ostream &ImageProcessingThread::warn() const {
157  return msg() << "Warning: ";
158  }
159 
160 } // namespace vbtracker
161 } // namespace osvr
Header declaring a C++11 finally or "scope-guard" construct.
void threadAction()
Entry point for the thread dedicated to this object.
void signalExit()
called by TrackerThread
::OSVR_TimeValue TimeValue
C++-friendly typedef for the OSVR_TimeValue structure.
Definition: TimeValue.h:48
void signalDoFrame()
called by TrackerThread
FinalTask< F > finally(F &&f)
Definition: Finally.h:87
virtual void retrieve(cv::Mat &color, cv::Mat &gray, osvr::util::time::TimeValue &timestamp)
Call after grab() to get the actual image data.
Definition: ImageSource.cpp:37
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
Definition: TimeValueC.h:81
void osvrTimeValueSum(OSVR_TimeValue *tvA, const OSVR_TimeValue *tvB)
Sums two time values, replacing the first with the result.
Definition: TimeValueC.cpp:65
void signalImageProcessingComplete(ImageOutputDataPtr &&imageData, cv::Mat const &frame, cv::Mat const &frameGray)