8 #include <opencv2/opencv.hpp> 9 #include "../cv-helpers.hpp" 10 #include "../../../src/concurrency.h" 24 std::lock_guard<std::mutex>
lock(
_m);
30 return copy[copy.size() / 2];
36 std::lock_guard<std::mutex>
lock(
_m);
44 std::lock_guard<std::mutex>
lock(
_m);
51 std::lock_guard<std::mutex>
lock(
_m);
62 mutable std::mutex
_m;
75 : _digits(digits), _bits(digits, false)
81 std::fill(_bits.begin(), _bits.end(),
false);
88 auto on_bits = std::count_if(_bits.begin() + 2, _bits.end(),
89 [](
bool f) {
return f; });
90 if ((on_bits % 2 == 1) == _bits[0] &&
91 ((on_bits / 2) % 2 == 1) == _bits[1])
94 for (
int i = 2;
i < _digits;
i++)
96 res = res * 2 + _bits[
i];
107 if (number < 1 << (_digits - 2))
112 _bits.push_back(number & 1);
117 while (_bits.size() < _digits) _bits.push_back(
false);
118 reverse(_bits.begin(), _bits.end());
121 auto on_bits = std::count_if(_bits.begin() + 2, _bits.end(),
122 [](
bool f) {
return f; });
123 _bits[0] = (on_bits % 2 == 1);
124 _bits[1] = ((on_bits / 2) % 2 == 1);
132 std::vector<bool>&
get() {
return _bits; }
144 : _digits(digits), _packer(digits),
145 _display_w(display_w),
146 _t([this]() { detect(); }),
147 _preview_size(600, 350),
148 _next_value(0), _next(
false), _alive(
true)
155 _last_preview = Mat::zeros(_preview_size, CV_8UC1);
156 _instructions = Mat::zeros(Size(display_w, 120), CV_8UC1);
158 putText(_instructions,
"Point the camera at the screen. Ensure all white circles are being captured",
159 Point(display_w / 2 - 470, 30), FONT_HERSHEY_SIMPLEX,
160 0.8, Scalar(255, 255, 255), 2, LINE_AA);
162 putText(_instructions,
"Press any key to exit...",
163 Point(display_w / 2 - 160, 70), FONT_HERSHEY_SIMPLEX,
164 0.8, Scalar(255, 255, 255), 2, LINE_AA);
175 _render_time.add(static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).
count()));
187 record frame_for_processing;
189 frame_for_processing.
f =
f;
196 _processing_time.add(static_cast<int>(
rs2_get_time(&e) - toa));
199 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).
count();
200 frame_for_processing.
ms = ms;
202 _queue.enqueue(
std::move(frame_for_processing));
211 if (_next.exchange(
false))
214 auto duration =
now - _start_time;
215 auto ms =
static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).
count());
216 auto next = ms % (1 << (_digits - 2));
226 std::lock_guard<std::mutex>
lock(_preview_mutex);
227 cv::Rect roi(
cv::Point(_display_w / 2 - _preview_size.width / 2, 200), _last_preview.size());
228 _last_preview.copyTo(
display(roi));
230 cv::Rect text_roi(
cv::Point(0, 580), _instructions.size());
231 _instructions.copyTo(
display(text_roi));
244 while (_queue.try_dequeue(&r));
265 std::lock_guard<std::mutex>
lock(_preview_mutex);
266 _instructions = Mat::zeros(Size(_display_w, 120), CV_8UC1);
268 std::stringstream ss;
270 ss <<
"Total Collected Samples: " << _latency.total();
272 putText(_instructions, ss.str().c_str(),
273 Point(80, 20), FONT_HERSHEY_SIMPLEX,
274 0.8, Scalar(255, 255, 255), 2, LINE_AA);
277 ss <<
"Estimated Latency: (Rolling-Median)" << _latency.median() <<
"ms, ";
278 ss <<
"(Average)" << _latency.avg() <<
"ms";
280 putText(_instructions, ss.str().c_str(),
281 Point(80, 60), FONT_HERSHEY_SIMPLEX,
282 0.8, Scalar(255, 255, 255), 2, LINE_AA);
285 ss <<
"Software Processing: " << _processing_time.median() <<
"ms";
287 putText(_instructions, ss.str().c_str(),
288 Point(80, 100), FONT_HERSHEY_SIMPLEX,
289 0.8, Scalar(255, 255, 255), 2, LINE_AA);
299 std::this_thread::sleep_for(std::chrono::milliseconds(1));
301 if (_queue.try_dequeue(&r))
309 if (color_mat.channels() > 1)
310 cvtColor(color_mat, color_mat, COLOR_BGR2GRAY);
311 medianBlur(color_mat, color_mat, 5);
313 std::vector<Vec3f> circles;
314 cv::Rect roi(
Point(0, 0), Size(color_mat.size().width, color_mat.size().height / 4));
315 HoughCircles(color_mat(roi), circles, HOUGH_GRADIENT, 1, 10, 100, 30, 1, 100);
316 for (
size_t i = 0;
i < circles.size();
i++)
318 Vec3i
c = circles[
i];
319 Rect
r(c[0] - c[2] - 5, c[1] - c[2] - 5, 2 * c[2] + 10, 2 * c[2] + 10);
320 rectangle(color_mat, r, Scalar(0, 100, 100), -1, LINE_AA);
323 cv::resize(color_mat, color_mat, _preview_size);
325 std::lock_guard<std::mutex>
lock(_preview_mutex);
326 _last_preview = color_mat;
329 sort(circles.begin(), circles.end(),
330 [](
const Vec3f&
a,
const Vec3f&
b) ->
bool 334 if (circles.size() > 1)
336 int min_x =
static_cast<int>(circles[0][0]);
337 int max_x =
static_cast<int>(circles[circles.size() - 1][0]);
339 int circle_est_size = (max_x - min_x) / (_digits + 1);
340 min_x += circle_est_size / 2;
341 max_x -= circle_est_size / 2;
344 for (
int i = 1;
i < circles.size() - 1;
i++)
346 const int x =
static_cast<int>(circles[
i][0]);
347 const int idx =
static_cast<int>(_digits * ((float)(x - min_x) / (max_x - min_x)));
348 if (idx >= 0 && idx < _packer.get().size())
349 _packer.get()[
idx] =
true;
353 if (_packer.try_unpack(&res))
355 if (res == _next_value)
357 auto cropped =
static_cast<int>(r.
ms) % (1 << (_digits - 2));
360 auto avg_render_time = _render_time.avg();
361 _latency.add(static_cast<int>((cropped - res) - avg_render_time));
362 update_instructions();
369 flush_queue_after.
abort();
static const textual_icon lock
GLboolean GLboolean GLboolean b
measurement< int > _processing_time
detector_lock(detector *owner)
rs2_metadata_type get_frame_metadata(rs2_frame_metadata_value frame_metadata) const
bool try_pack(int number)
std::chrono::high_resolution_clock::time_point _render_start
measurement< int > _latency
Exposes RealSense internal functionality for C compilers.
std::mutex _preview_mutex
void sort(sort_type m_sort_type, const std::string &in, const std::string &out)
GLboolean GLboolean GLboolean GLboolean a
void update_instructions()
rs2_time_t rs2_get_time(rs2_error **error)
std::vector< bool > _bits
single_consumer_queue< record > _queue
std::chrono::high_resolution_clock::time_point _start_time
detector(int digits, int display_w)
void submit_frame(rs2::frame f)
const cv::Size _preview_size
measurement< int > _render_time
void next(auto_any_t cur, type2type< T, C > *)
bool try_unpack(int *number)
std::atomic< int > _next_value
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
static cv::Mat frame_to_mat(const rs2::frame &f)
void copy(void *dst, void const *src, size_t size)
void copy_preview_to(cv::Mat &display)
::geometry_msgs::Point_< std::allocator< void > > Point