algo.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 
4 #include "algo.h"
5 #include "option.h"
6 
7 using namespace librealsense;
8 
10 {
11  return is_auto_exposure;
12 }
13 
15 {
16  return mode;
17 }
18 
20 {
21  return rate;
22 }
23 
25 {
26  return step;
27 }
28 
30 {
31  is_auto_exposure = value;
32 }
33 
35 {
36  mode = value;
37 }
38 
40 {
41  rate = value;
42 }
43 
45 {
46  step = value;
47 }
48 
50  : _gain_option(gain_option), _exposure_option(exposure_option),
51  _auto_exposure_algo(auto_exposure_state),
52  _keep_alive(true), _data_queue(queue_size), _frames_counter(0),
53  _skip_frames(auto_exposure_state.skip_frames)
54 {
55  _exposure_thread = std::make_shared<std::thread>(
56  [this]()
57  {
58  while (_keep_alive)
59  {
60  std::unique_lock<std::mutex> lk(_queue_mtx);
61  _cv.wait(lk, [&] {return (_data_queue.size() || !_keep_alive); });
62 
63  if (!_keep_alive)
64  return;
65 
66  frame_holder f_holder;
67  auto frame_sts = _data_queue.dequeue(&f_holder, RS2_DEFAULT_TIMEOUT);
68 
69  lk.unlock();
70 
71  if (!frame_sts)
72  {
73  LOG_ERROR("After waiting on data_queue signalled there are no frames on queue");
74  continue;
75  }
76  try
77  {
78  auto frame = std::move(f_holder);
79 
80  double values[2] = {};
81 
86 
87  values[0] /= 1000.; // Fisheye exposure value by extension control-
88  // is in units of MicroSeconds, from FW version 5.6.3.0
89 
90  auto exposure_value = static_cast<float>(values[0]);
91  auto gain_value = static_cast<float>(2. + (values[1] - 15.) / 8.);
92 
94  if (sts)
95  {
96  bool modify_exposure, modify_gain;
97  _auto_exposure_algo.modify_exposure(exposure_value, modify_exposure, gain_value, modify_gain);
98 
99  if (modify_exposure)
100  {
101  auto value = exposure_value * 1000.f;
102  if (value < 1)
103  value = 1;
104 
106  }
107 
108  if (modify_gain)
109  {
110  auto value = (gain_value - 2.f) * 8.f + 15.f;
112  }
113  }
114  }
115  catch (const std::exception& ex)
116  {
117  LOG_ERROR("Error during Auto-Exposure loop: " << ex.what());
118  }
119  catch (...)
120  {
121  LOG_ERROR("Unknown error during Auto-Exposure loop!");
122  }
123  }
124  });
125 }
126 
128 {
129  {
130  std::lock_guard<std::mutex> lk(_queue_mtx);
131  _keep_alive = false;
132  }
133  _cv.notify_one();
134  _exposure_thread->join();
135 }
136 
138 {
139  std::lock_guard<std::mutex> lk(_queue_mtx);
140  _skip_frames = auto_exposure_state.skip_frames;
141  _auto_exposure_algo.update_options(auto_exposure_state);
142 }
143 
145 {
146  std::lock_guard<std::mutex> lk(_queue_mtx);
148 }
149 
151 {
152 
154  {
155  return;
156  }
157 
158  _frames_counter = 0;
159 
160  {
161  std::lock_guard<std::mutex> lk(_queue_mtx);
162  _data_queue.enqueue(std::move(frame));
163  }
164  _cv.notify_one();
165 }
166 
168  : exposure_step(ae_step_default_value)
169 {
170  update_options(auto_exposure_state);
171 }
172 
173 void auto_exposure_algorithm::modify_exposure(float& exposure_value, bool& exp_modified, float& gain_value, bool& gain_modified)
174 {
175  float total_exposure = exposure * gain;
176  LOG_DEBUG("TotalExposure " << total_exposure << ", target_exposure " << target_exposure);
177  if (fabs(target_exposure - total_exposure) > eps)
178  {
179  rounding_mode_type RoundingMode;
180 
181  if (target_exposure > total_exposure)
182  {
183  float target_exposure0 = total_exposure * (1.0f + exposure_step);
184 
185  target_exposure0 = std::min(target_exposure0, target_exposure);
186  increase_exposure_gain(target_exposure0, target_exposure0, exposure, gain);
187  RoundingMode = rounding_mode_type::ceil;
188  LOG_DEBUG(" ModifyExposure: IncreaseExposureGain: ");
189  LOG_DEBUG(" target_exposure0 " << target_exposure0);
190  }
191  else
192  {
193  float target_exposure0 = total_exposure / (1.0f + exposure_step);
194 
195  target_exposure0 = std::max(target_exposure0, target_exposure);
196  decrease_exposure_gain(target_exposure0, target_exposure0, exposure, gain);
197  RoundingMode = rounding_mode_type::floor;
198  LOG_DEBUG(" ModifyExposure: DecreaseExposureGain: ");
199  LOG_DEBUG(" target_exposure0 " << target_exposure0);
200  }
201  LOG_DEBUG(" exposure " << exposure << ", gain " << gain);
202  if (exposure_value != exposure)
203  {
204  exp_modified = true;
205  exposure_value = exposure;
206  exposure_value = exposure_to_value(exposure_value, RoundingMode);
207  LOG_DEBUG("output exposure by algo = " << exposure_value);
208  }
209  if (gain_value != gain)
210  {
211  gain_modified = true;
212  gain_value = gain;
213  LOG_DEBUG("GainModified: gain = " << gain);
214  gain_value = gain_to_value(gain_value, RoundingMode);
215  LOG_DEBUG(" rounded to: " << gain);
216  }
217  }
218 }
219 
221 {
222  region_of_interest image_roi = roi;
223  auto number_of_pixels = (image_roi.max_x - image_roi.min_x + 1)*(image_roi.max_y - image_roi.min_y + 1);
224  if (number_of_pixels == 0)
225  return false; // empty image
226 
227  auto frame = ((video_frame*)image);
228 
229  if (!is_roi_initialized)
230  {
231  auto width = frame->get_width();
232  auto height = frame->get_height();
233  image_roi.min_x = 0;
234  image_roi.min_y = 0;
235  image_roi.max_x = width - 1;
236  image_roi.max_y = height - 1;
237  number_of_pixels = width * height;
238  }
239 
240  std::vector<int> H(256);
241  auto total_weight = number_of_pixels;
242 
243  auto cols = frame->get_width();
244  im_hist((uint8_t*)frame->get_frame_data(), image_roi, frame->get_bpp() / 8 * cols, &H[0]);
245 
246  histogram_metric score = {};
247  histogram_score(H, total_weight, score);
248  // int EffectiveDynamicRange = (score.highlight_limit - score.shadow_limit);
250  float s1 = (score.main_mean - 128.0f) / 255.0f;
251  float s2 = 0;
252 
253  s2 = (score.over_exposure_count - score.under_exposure_count) / (float)total_weight;
254 
255  float s = -0.3f * (s1 + 5.0f * s2);
256  LOG_DEBUG(" AnalyzeImage Score: " << s);
257 
258  if (s > 0)
259  {
260  direction = +1;
262  }
263  else
264  {
265  LOG_DEBUG(" AnalyzeImage: DecreaseExposure");
266  direction = -1;
268  }
269 
270  if (fabs(1.0f - (exposure * gain) / target_exposure) < hysteresis)
271  {
272  LOG_DEBUG(" AnalyzeImage: Don't Modify (Hysteresis): " << target_exposure << " " << exposure * gain);
273  return false;
274  }
275 
277  LOG_DEBUG(" AnalyzeImage: Modify");
278  return true;
279 }
280 
282 {
283  std::lock_guard<std::recursive_mutex> lock(state_mutex);
284 
285  state = options;
286  flicker_cycle = 1000.0f / (state.get_auto_exposure_antiflicker_rate() * 2.0f);
287  exposure_step = state.get_auto_exposure_step();
288 }
289 
291 {
292  std::lock_guard<std::recursive_mutex> lock(state_mutex);
293  roi = ae_roi;
294  is_roi_initialized = true;
295 }
296 
297 void auto_exposure_algorithm::im_hist(const uint8_t* data, const region_of_interest& image_roi, const int rowStep, int h[])
298 {
299  std::lock_guard<std::recursive_mutex> lock(state_mutex);
300 
301  for (int i = 0; i < 256; ++i)
302  h[i] = 0;
303 
304  const uint8_t* rowData = data + (image_roi.min_y * rowStep);
305  for (int i = image_roi.min_y; i < image_roi.max_y; ++i, rowData += rowStep)
306  for (int j = image_roi.min_x; j < image_roi.max_x; j+=state.sample_rate)
307  ++h[rowData[j]];
308 }
309 
311 {
312  target_exposure = std::min((exposure * gain) * (1.0f + mult), maximal_exposure * gain_limit);
313 }
316 {
317  target_exposure = std::max((exposure * gain) * (1.0f + mult), minimal_exposure * base_gain);
318 }
319 
320 void auto_exposure_algorithm::increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain)
321 {
322  std::lock_guard<std::recursive_mutex> lock(state_mutex);
323 
324  switch ((int)(state.get_auto_exposure_mode()))
325  {
326  case int(auto_exposure_modes::static_auto_exposure): static_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
327  case int(auto_exposure_modes::auto_exposure_anti_flicker): anti_flicker_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
328  case int(auto_exposure_modes::auto_exposure_hybrid): hybrid_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
329  }
330 }
331 void auto_exposure_algorithm::decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain)
332 {
333  std::lock_guard<std::recursive_mutex> lock(state_mutex);
334 
335  switch ((int)(state.get_auto_exposure_mode()))
336  {
337  case int(auto_exposure_modes::static_auto_exposure): static_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
338  case int(auto_exposure_modes::auto_exposure_anti_flicker): anti_flicker_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
339  case int(auto_exposure_modes::auto_exposure_hybrid): hybrid_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain); break;
340  }
341 }
342 void auto_exposure_algorithm::static_increase_exposure_gain(const float& /*target_exposure*/, const float& target_exposure0, float& exposure, float& gain)
343 {
344  exposure = std::max(minimal_exposure, std::min(target_exposure0 / base_gain, maximal_exposure));
345  gain = std::min(gain_limit, std::max(target_exposure0 / exposure, base_gain));
346 }
347 void auto_exposure_algorithm::static_decrease_exposure_gain(const float& /*target_exposure*/, const float& target_exposure0, float& exposure, float& gain)
348 {
349  exposure = std::max(minimal_exposure, std::min(target_exposure0 / base_gain, maximal_exposure));
350  gain = std::min(gain_limit, std::max(target_exposure0 / exposure, base_gain));
351 }
352 void auto_exposure_algorithm::anti_flicker_increase_exposure_gain(const float& target_exposure, const float& /*target_exposure0*/, float& exposure, float& gain)
353 {
354  std::vector< std::tuple<float, float, float> > exposure_gain_score;
355 
356  for (int i = 1; i < 4; ++i)
357  {
359  {
360  continue;
361  }
362  float exposure1 = std::max(std::min(i * flicker_cycle, maximal_exposure), flicker_cycle);
363  float gain1 = base_gain;
364 
365  if ((exposure1 * gain1) != target_exposure)
366  {
367  gain1 = std::min(std::max(target_exposure / exposure1, base_gain), gain_limit);
368  }
369  float score1 = fabs(target_exposure - exposure1 * gain1);
370  exposure_gain_score.push_back(std::tuple<float, float, float>(score1, exposure1, gain1));
371  }
372 
373  std::sort(exposure_gain_score.begin(), exposure_gain_score.end());
374 
375  exposure = std::get<1>(exposure_gain_score.front());
376  gain = std::get<2>(exposure_gain_score.front());
377 }
378 void auto_exposure_algorithm::anti_flicker_decrease_exposure_gain(const float& target_exposure, const float& /*target_exposure0*/, float& exposure, float& gain)
379 {
380  std::vector< std::tuple<float, float, float> > exposure_gain_score;
381 
382  for (int i = 1; i < 4; ++i)
383  {
385  {
386  continue;
387  }
388  float exposure1 = std::max(std::min(i * flicker_cycle, maximal_exposure), flicker_cycle);
389  float gain1 = base_gain;
390  if ((exposure1 * gain1) != target_exposure)
391  {
392  gain1 = std::min(std::max(target_exposure / exposure1, base_gain), gain_limit);
393  }
394  float score1 = fabs(target_exposure - exposure1 * gain1);
395  exposure_gain_score.push_back(std::tuple<float, float, float>(score1, exposure1, gain1));
396  }
397 
398  std::sort(exposure_gain_score.begin(), exposure_gain_score.end());
399 
400  exposure = std::get<1>(exposure_gain_score.front());
401  gain = std::get<2>(exposure_gain_score.front());
402 }
403 void auto_exposure_algorithm::hybrid_increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain)
404 {
405  if (anti_flicker_mode)
406  {
407  anti_flicker_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain);
408  }
409  else
410  {
411  static_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain);
412  LOG_DEBUG("HybridAutoExposure::IncreaseExposureGain: " << exposure * gain << " " << flicker_cycle * base_gain << " " << base_gain);
413  if (target_exposure > 0.99 * flicker_cycle * base_gain)
414  {
415  anti_flicker_mode = true;
416  anti_flicker_increase_exposure_gain(target_exposure, target_exposure0, exposure, gain);
417  LOG_DEBUG("anti_flicker_mode = true");
418  }
419  }
420 }
421 void auto_exposure_algorithm::hybrid_decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain)
422 {
423  if (anti_flicker_mode)
424  {
425  LOG_DEBUG("HybridAutoExposure::DecreaseExposureGain: " << exposure << " " << flicker_cycle << " " << gain << " " << base_gain);
426  if ((target_exposure) <= 0.99 * (flicker_cycle * base_gain))
427  {
428  anti_flicker_mode = false;
429  static_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain);
430  LOG_DEBUG("anti_flicker_mode = false");
431  }
432  else
433  {
434  anti_flicker_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain);
435  }
436  }
437  else
438  {
439  static_decrease_exposure_gain(target_exposure, target_exposure0, exposure, gain);
440  }
441 }
442 
444 {
445  const float line_period_us = 19.33333333f;
446 
447  float ExposureTimeLine = (exp_ms * 1000.0f / line_period_us);
448  if (rounding_mode == rounding_mode_type::ceil) ExposureTimeLine = std::ceil(ExposureTimeLine);
449  else if (rounding_mode == rounding_mode_type::floor) ExposureTimeLine = std::floor(ExposureTimeLine);
450  else ExposureTimeLine = round(ExposureTimeLine);
451  return ((float)ExposureTimeLine * line_period_us) / 1000.0f;
452 }
453 
455 {
456 
457  if (gain < base_gain) { return base_gain; }
458  else if (gain > 16.0f) { return 16.0f; }
459  else {
460  if (rounding_mode == rounding_mode_type::ceil) return std::ceil(gain * 8.0f) / 8.0f;
461  else if (rounding_mode == rounding_mode_type::floor) return std::floor(gain * 8.0f) / 8.0f;
462  else return round(gain * 8.0f) / 8.0f;
463  }
464 }
465 
466 template <typename T> inline T sqr(const T& x) { return (x*x); }
467 void auto_exposure_algorithm::histogram_score(std::vector<int>& h, const int total_weight, histogram_metric& score)
468 {
469  score.under_exposure_count = 0;
470  score.over_exposure_count = 0;
471 
472  for (size_t i = 0; i <= under_exposure_limit; ++i)
473  {
474  score.under_exposure_count += h[i];
475  }
476  score.shadow_limit = 0;
477  //if (Score.UnderExposureCount < UnderExposureNoiseLimit)
478  {
480  for (size_t i = under_exposure_limit + 1; i <= over_exposure_limit; ++i)
481  {
482  if (h[i] > under_exposure_noise_limit)
483  {
484  break;
485  }
486  score.shadow_limit++;
487  }
488  int lower_q = 0;
489  score.lower_q = 0;
490  for (size_t i = under_exposure_limit + 1; i <= over_exposure_limit; ++i)
491  {
492  lower_q += h[i];
493  if (lower_q > total_weight / 4)
494  {
495  break;
496  }
497  score.lower_q++;
498  }
499  }
500 
501  for (size_t i = over_exposure_limit; i <= 255; ++i)
502  {
503  score.over_exposure_count += h[i];
504  }
505 
506  score.highlight_limit = 255;
507  //if (Score.OverExposureCount < OverExposureNoiseLimit)
508  {
510  for (size_t i = over_exposure_limit; i >= under_exposure_limit; --i)
511  {
512  if (h[i] > over_exposure_noise_limit)
513  {
514  break;
515  }
516  score.highlight_limit--;
517  }
518  int upper_q = 0;
520  for (size_t i = over_exposure_limit; i >= under_exposure_limit; --i)
521  {
522  upper_q += h[i];
523  if (upper_q > total_weight / 4)
524  {
525  break;
526  }
527  score.upper_q--;
528  }
529 
530  }
531  int32_t m1 = 0;
532  int64_t m2 = 0;
533 
534  double nn = (double)total_weight - score.under_exposure_count - score.over_exposure_count;
535  if (nn == 0)
536  {
537  nn = (double)total_weight;
538  for (int i = 0; i <= 255; ++i)
539  {
540  m1 += h[i] * i;
541  m2 += h[i] * sqr(i);
542  }
543  }
544  else
545  {
546  for (int i = under_exposure_limit + 1; i < over_exposure_limit; ++i)
547  {
548  m1 += h[i] * i;
549  m2 += h[i] * sqr(i);
550  }
551  }
552  score.main_mean = (float)((double)m1 / nn);
553  double Var = (double)m2 / nn - sqr((double)m1 / nn);
554  if (Var > 0)
555  {
556  score.main_std = (float)sqrt(Var);
557  }
558  else
559  {
560  score.main_std = 0.0f;
561  }
562 }
563 
564 rect_gaussian_dots_target_calculator::rect_gaussian_dots_target_calculator(int width, int height, int roi_start_x, int roi_start_y, int roi_width, int roi_height)
565  : _full_width(width), _full_height(height), _roi_start_x(roi_start_x), _roi_start_y(roi_start_y), _width(roi_width), _height(roi_height)
566 {
567  _wt = _width - _tsize;
568  _ht = _height - _tsize;
569  _size = _width * _height;
570 
571  _hwidth = _width >> 1;
572  _hheight = _height >> 1;
573 
574  _imgt.resize(_tsize2);
575  _img.resize(_size);
576  _ncc.resize(_size);
577  memset(_ncc.data(), 0, _size * sizeof(double));
578 
579  _buf.resize(_patch_size);
580 }
581 
583 {
584 }
585 
586 bool rect_gaussian_dots_target_calculator::calculate(const uint8_t* img, float* target_dims, unsigned int target_dims_size)
587 {
588  bool ret = false;
589  if (target_dims_size < 4)
590  return ret;
591 
592  normalize(img);
593  calculate_ncc();
594 
595  if (find_corners())
596  ret = validate_corners(img);
597 
598  if (ret)
599  {
600  if (target_dims_size == 4)
601  calculate_rect_sides(target_dims);
602  else if (target_dims_size == 8)
603  {
604  int j = 0;
605  for (int i = 0; i < 4; ++i)
606  {
607  target_dims[j++] = static_cast<float>(_corners[i].x + _roi_start_x);
608  target_dims[j++] = static_cast<float>(_corners[i].y + _roi_start_y);
609  }
610  }
611  }
612 
613  return ret;
614 }
615 
617 {
618  uint8_t min_val = 255;
619  uint8_t max_val = 0;
620 
621  int jumper = _full_width - _width;
622  const uint8_t* p = img + _roi_start_y * _full_width + _roi_start_x;
623  for (int j = 0; j < _height; ++j)
624  {
625  for (int i = 0; i < _width; ++i)
626  {
627  if (*p < min_val)
628  min_val = *p;
629 
630  if (*p > max_val)
631  max_val = *p;
632 
633  ++p;
634  }
635 
636  p += jumper;
637  }
638 
639  if (max_val > min_val)
640  {
641  double factor = 1.0 / (max_val - min_val);
642 
643  p = img;
644  double* q = _img.data();
645  p = img + _roi_start_y * _full_width + _roi_start_x;
646  for (int j = 0; j < _height; ++j)
647  {
648  for (int i = 0; i < _width; ++i)
649  *q++ = 1.0f - (*p++ - min_val) * factor;
650 
651  p += jumper;
652  }
653  }
654 }
655 
657 {
658  double* pncc = _ncc.data() + (_htsize * _width + _htsize);
659  double* pi = _img.data();
660  double* pit = _imgt.data();
661 
662  const double* pt = nullptr;
663  const double* qi = nullptr;
664 
665  double sum = 0.0;
666  double mean = 0.0;
667  double norm = 0.0;
668 
669  double min_val = 2.0;
670  double max_val = -2.0;
671  double tmp = 0.0;
672 
673  for (int j = 0; j < _ht; ++j)
674  {
675  for (int i = 0; i < _wt; ++i)
676  {
677  qi = pi;
678  sum = 0.0f;
679  for (int m = 0; m < _tsize; ++m)
680  {
681  for (int n = 0; n < _tsize; ++n)
682  sum += *qi++;
683 
684  qi += _wt;
685  }
686 
687  mean = sum / _tsize2;
688 
689  qi = pi;
690  sum = 0.0f;
691  pit = _imgt.data();
692  for (int m = 0; m < _tsize; ++m)
693  {
694  for (int n = 0; n < _tsize; ++n)
695  {
696  *pit = *qi++ - mean;
697  sum += *pit * *pit;
698  ++pit;
699  }
700  qi += _wt;
701  }
702 
703  norm = sqrt(sum);
704 
705  pt = _template.data();
706  pit = _imgt.data();
707  sum = 0.0;
708  for (int k = 0; k < _tsize2; ++k)
709  sum += *pit++ * *pt++;
710 
711  tmp = sum / norm;
712  if (tmp < min_val)
713  min_val = tmp;
714 
715  if (tmp > max_val)
716  max_val = tmp;
717 
718  *pncc++ = tmp;
719  ++pi;
720  }
721 
722  pncc += _tsize;
723  pi += _tsize;
724  }
725 
726  if (max_val > min_val)
727  {
728  double factor = 1.0 / (max_val - min_val);
729  double div = 1.0 - _thresh;
730  pncc = _ncc.data();
731  for (int i = 0; i < _size; ++i)
732  {
733  tmp = (*pncc - min_val) * factor;
734  *pncc++ = (tmp < _thresh ? 0 : (tmp - _thresh) / div);
735  }
736  }
737 }
738 
740 {
741  static const int edge = 20;
742 
743  // upper left
744  _pts[0].x = 0;
745  _pts[0].y = 0;
746  double peak = 0.0f;
747  double* p = _ncc.data() + _htsize * _width;
748  for (int j = _htsize; j < _hheight; ++j)
749  {
750  p += _htsize;
751  for (int i = _htsize; i < _hwidth; ++i)
752  {
753  if (*p > peak)
754  {
755  peak = *p;
756  _pts[0].x = i;
757  _pts[0].y = j;
758  }
759  ++p;
760  }
761  p += _hwidth;
762  }
763 
764  if (peak < _thresh || _pts[0].x < edge || _pts[0].y < edge)
765  return false;
766 
767  // upper right
768  _pts[1].x = 0;
769  _pts[1].y = 0;
770  peak = 0.0f;
771  p = _ncc.data() + (_htsize * _width);
772  for (int j = _htsize; j < _hheight; ++j)
773  {
774  p += _hwidth;
775  for (int i = _hwidth; i < _width - _htsize; ++i)
776  {
777  if (*p > peak)
778  {
779  peak = *p;
780  _pts[1].x = i;
781  _pts[1].y = j;
782  }
783  ++p;
784  }
785  p += _htsize;
786  }
787 
788  if (peak < _thresh || _pts[1].x + edge > _width || _pts[1].y < edge || _pts[1].x - _pts[0].x < edge)
789  return false;
790 
791  // lower left
792  _pts[2].x = 0;
793  _pts[2].y = 0;
794  peak = 0.0f;
795  p = _ncc.data() + (_hheight * _width);
796  for (int j = _hheight; j < _height - _htsize; ++j)
797  {
798  p += _htsize;
799  for (int i = _htsize; i < _hwidth; ++i)
800  {
801  if (*p > peak)
802  {
803  peak = *p;
804  _pts[2].x = i;
805  _pts[2].y = j;
806  }
807  ++p;
808  }
809  p += _hwidth;
810  }
811 
812  if (peak < _thresh || _pts[2].x < edge || _pts[2].y + edge > _height || _pts[2].y - _pts[1].y < edge)
813  return false;
814 
815  // lower right
816  _pts[3].x = 0;
817  _pts[3].y = 0;
818  peak = 0.0f;
819  p = _ncc.data() + (_hheight * _width);
820  for (int j = _hheight; j < _height - _htsize; ++j)
821  {
822  p += _hwidth;
823  for (int i = _hwidth; i < _width - _htsize; ++i)
824  {
825  if (*p > peak)
826  {
827  peak = *p;
828  _pts[3].x = i;
829  _pts[3].y = j;
830  }
831  ++p;
832  }
833  p += _htsize;
834  }
835 
836  if (peak < _thresh || _pts[3].x + edge > _width || _pts[3].y + edge > _height || _pts[3].x - _pts[2].x < edge || _pts[3].y - _pts[1].y < edge)
837  return false;
838  else
839  refine_corners();
840 
841  return true;
842 }
843 
845 {
846  double* f = _buf.data();
847  int hs = _patch_size >> 1;
848 
849  // upper left
850  int pos = (_pts[0].y - hs) * _width + _pts[0].x - hs;
851 
852  _corners[0].x = static_cast<double>(_pts[0].x) - hs;
853  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[0].x);
854 
855  _corners[0].y = static_cast<double>(_pts[0].y) - hs;
856  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[0].y);
857 
858  // upper right
859  pos = (_pts[1].y - hs) * _width + _pts[1].x - hs;
860 
861  _corners[1].x = static_cast<double>(_pts[1].x) - hs;
862  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[1].x);
863 
864  _corners[1].y = static_cast<double>(_pts[1].y) - hs;
865  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[1].y);
866 
867  // lower left
868  pos = (_pts[2].y - hs) * _width + _pts[2].x - hs;
869 
870  _corners[2].x = static_cast<double>(_pts[2].x) - hs;
871  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[2].x);
872 
873  _corners[2].y = static_cast<double>(_pts[2].y) - hs;
874  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[2].y);
875 
876  // lower right
877  pos = (_pts[3].y - hs) * _width + _pts[3].x - hs;
878 
879  _corners[3].x = static_cast<double>(_pts[3].x) - hs;
880  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[3].x);
881 
882  _corners[3].y = static_cast<double>(_pts[3].y) - hs;
883  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[3].y);
884 }
885 
887 {
888  bool ok = true;
889 
890  static const int pos_diff_threshold = 4;
891  if (abs(_corners[0].x - _corners[2].x) > pos_diff_threshold ||
892  abs(_corners[1].x - _corners[3].x) > pos_diff_threshold ||
893  abs(_corners[0].y - _corners[1].y) > pos_diff_threshold ||
894  abs(_corners[2].y - _corners[3].y) > pos_diff_threshold)
895  {
896  ok = false;
897  }
898 
899  return ok;
900 }
901 
903 {
904  double lx = _corners[1].x - _corners[0].x;
905  double ly = _corners[1].y - _corners[0].y;
906  rect_sides[0] = static_cast<float>(sqrt(lx * lx + ly * ly)); // uppper
907 
908  lx = _corners[3].x - _corners[2].x;
909  ly = _corners[3].y - _corners[2].y;
910  rect_sides[1] = static_cast<float>(sqrt(lx * lx + ly * ly)); // lower
911 
912  lx = _corners[2].x - _corners[0].x;
913  ly = _corners[2].y - _corners[0].y;
914  rect_sides[2] = static_cast<float>(sqrt(lx * lx + ly * ly)); // left
915 
916  lx = _corners[3].x - _corners[1].x;
917  ly = _corners[3].y - _corners[1].y;
918  rect_sides[3] = static_cast<float>(sqrt(lx * lx + ly * ly)); // right
919 }
920 
921 void rect_gaussian_dots_target_calculator::minimize_x(const double* p, int s, double* f, double& x)
922 {
923  int ws = _width - s;
924 
925  for (int i = 0; i < s; ++i)
926  f[i] = 0;
927 
928  for (int j = 0; j < s; ++j)
929  {
930  for (int i = 0; i < s; ++i)
931  f[i] += *p++;
932  p += ws;
933  }
934 
935  x += subpixel_agj(f, s);
936 }
937 
938 void rect_gaussian_dots_target_calculator::minimize_y(const double* p, int s, double* f, double& y)
939 {
940  int ws = _width - s;
941 
942  for (int i = 0; i < s; ++i)
943  f[i] = 0;
944 
945  for (int j = 0; j < s; ++j)
946  {
947  for (int i = 0; i < s; ++i)
948  f[j] += *p++;
949  p += ws;
950  }
951 
952  y += subpixel_agj(f, s);
953 }
954 
956 {
957  int mi = 0;
958  double mv = f[mi];
959  for (int i = 1; i < s; ++i)
960  {
961  if (f[i] > mv)
962  {
963  mi = i;
964  mv = f[mi];
965  }
966  }
967 
968  double half_mv = 0.5f * mv;
969 
970  int x_0 = 0;
971  int x_1 = 0;
972  for (int i = 0; i < s; ++i)
973  {
974  if (f[i] > half_mv)
975  {
976  x_1 = i;
977  break;
978  }
979  }
980 
981  double left_mv = 0.0f;
982  if (x_1 > 0)
983  {
984  x_0 = x_1 - 1;
985  left_mv = x_0 + (half_mv - f[x_0]) / (f[x_1] - f[x_0]);
986  }
987  else
988  left_mv = static_cast<double>(0);
989 
990  x_0 = s - 1;
991  for (int i = s - 1; i >= 0; --i)
992  {
993  if (f[i] > half_mv)
994  {
995  x_0 = i;
996  break;
997  }
998  }
999 
1000  double right_mv = 0.0f;
1001  if (x_0 == s - 1)
1002  right_mv = static_cast<double>(s) - 1;
1003  else
1004  {
1005  x_1 = x_0 + 1;
1006  right_mv = x_0 + (half_mv - f[x_0]) / (f[x_1] - f[x_0]);
1007  }
1008 
1009  return (left_mv + right_mv) / 2;
1010 }
1011 
1012 // return 1 if target pattern is found and its location is calculated, zero otherwise.
1013 int rect_calculator::extract_target_dims(const rs2_frame* frame_ref, float4& rect_sides)
1014 {
1015  int ret = 0;
1016  rs2_error* e = nullptr;
1017 
1018  //Target dimension array size is predefined. 4 for RS2_CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES and 8 for RS2_CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES.
1019  int dim_size = _roi ? 4 : 8;
1021  rs2_extract_target_dimensions(frame_ref, tgt_type, reinterpret_cast<float*>(&rect_sides), dim_size, &e);
1022  if (e == nullptr)
1023  {
1024  ret = 1;
1025  }
1026 
1027  return ret;
1028 }
static const textual_icon lock
Definition: model-views.h:219
bool supports_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: frame.cpp:132
std::shared_ptr< std::thread > _exposure_thread
Definition: algo.h:131
float3 mult(const float3x3 &a, const float3 &b)
Definition: test-pose.cpp:72
#define LOG_ERROR(...)
Definition: easyloggingpp.h:58
void set_enable_auto_exposure(bool value)
Definition: algo.cpp:29
rect_gaussian_dots_target_calculator(int width, int height, int roi_start_x, int roi_start_y, int roi_width, int roi_height)
Definition: algo.cpp:564
void hybrid_decrease_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:421
GLint y
std::atomic< unsigned > _frames_counter
Definition: algo.h:136
unsigned get_auto_exposure_antiflicker_rate() const
Definition: algo.cpp:19
static const unsigned skip_frames
Definition: algo.h:47
bool analyze_image(const frame_interface *image)
Definition: algo.cpp:220
int extract_target_dims(const rs2_frame *frame_ref, float4 &rect_sides)
Definition: algo.cpp:1013
std::recursive_mutex state_mutex
Definition: algo.h:102
auto_exposure_modes
Definition: algo.h:20
const std::vector< double > _template
Definition: algo.h:188
float exposure_to_value(float exp_ms, rounding_mode_type rounding_mode)
Definition: algo.cpp:443
void update_auto_exposure_state(const auto_exposure_state &auto_exposure_state)
Definition: algo.cpp:137
GLdouble s
void increase_exposure_target(float mult, float &target_exposure)
Definition: algo.cpp:310
void calculate_rect_sides(float *rect_sides)
Definition: algo.cpp:902
virtual void set(float value)=0
static const float ae_step_default_value
Definition: algo.h:18
std::mutex m
GLfloat value
rs2_calib_target_type
Calibration target type.
Definition: rs_frame.h:84
void static_increase_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:342
std::atomic< float > exposure_step
Definition: algo.h:98
void set_auto_exposure_mode(auto_exposure_modes value)
Definition: algo.cpp:34
unsigned char uint8_t
Definition: stdint.h:78
#define LOG_DEBUG(...)
Definition: easyloggingpp.h:55
e
Definition: rmse.py:177
auto_exposure_algorithm _auto_exposure_algo
Definition: algo.h:130
virtual float query() const =0
void minimize_y(const double *p, int s, double *f, double &y)
Definition: algo.cpp:938
void sort(sort_type m_sort_type, const std::string &in, const std::string &out)
direction
Definition: rs-align.cpp:25
void add_frame(frame_holder frame)
Definition: algo.cpp:150
const int _patch_size
Definition: algo.h:152
const int H
GLenum mode
std::atomic< bool > _keep_alive
Definition: algo.h:133
void anti_flicker_increase_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:352
GLenum GLenum GLsizei void * image
void set_auto_exposure_antiflicker_rate(unsigned value)
Definition: algo.cpp:39
std::atomic< unsigned > _skip_frames
Definition: algo.h:137
double p[GRIDW][GRIDH]
Definition: wave.c:109
bool calculate(const uint8_t *img, float *target_dims, unsigned int target_dims_size) override
Definition: algo.cpp:586
Definition: lz4.c:1706
GLdouble x
void update_options(const auto_exposure_state &options)
Definition: algo.cpp:281
void static_decrease_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:347
void set_auto_exposure_step(float value)
Definition: algo.cpp:44
auto_exposure_modes mode
Definition: algo.h:51
float gain_to_value(float gain, rounding_mode_type rounding_mode)
Definition: algo.cpp:454
GLint GLsizei GLsizei height
void increase_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:320
auto_exposure_modes get_auto_exposure_mode() const
Definition: algo.cpp:14
GLint j
auto_exposure_mechanism(option &gain_option, option &exposure_option, const auto_exposure_state &auto_exposure_state)
Definition: algo.cpp:49
#define RS2_DEFAULT_TIMEOUT
Definition: rs_config.h:13
GLint void * img
auto_exposure_algorithm(const auto_exposure_state &auto_exposure_state)
Definition: algo.cpp:167
void rs2_extract_target_dimensions(const rs2_frame *frame, rs2_calib_target_type calib_type, float *target_dims, unsigned int target_dims_size, rs2_error **error)
Definition: rs.cpp:2466
single_consumer_queue< frame_holder > _data_queue
Definition: algo.h:134
GLsizei const GLfloat * values
void hybrid_increase_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:403
GLdouble GLdouble GLdouble q
void anti_flicker_decrease_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:378
int min(int a, int b)
Definition: lz4s.c:73
void decrease_exposure_target(float mult, float &target_exposure)
Definition: algo.cpp:315
signed __int64 int64_t
Definition: stdint.h:89
GLdouble f
float get_auto_exposure_step() const
Definition: algo.cpp:24
static const double pi
Definition: src/types.h:45
typename ::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
bool get_enable_auto_exposure() const
Definition: algo.cpp:9
float rs2_vector::* pos
void update_roi(const region_of_interest &ae_roi)
Definition: algo.cpp:290
int i
void histogram_score(std::vector< int > &h, const int total_weight, histogram_metric &score)
Definition: algo.cpp:467
signed int int32_t
Definition: stdint.h:77
const byte * get_frame_data() const override
Definition: frame.cpp:158
int h
Definition: sw.py:17
void modify_exposure(float &exposure_value, bool &exp_modified, float &gain_value, bool &gain_modified)
Definition: algo.cpp:173
void update_auto_exposure_roi(const region_of_interest &roi)
Definition: algo.cpp:144
void decrease_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:331
void minimize_x(const double *p, int s, double *f, double &x)
Definition: algo.cpp:921
Definition: parser.hpp:153
rs2_metadata_type get_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: frame.cpp:95
struct rs2_frame rs2_frame
Definition: rs_types.h:262
GLint GLsizei width
std::condition_variable _cv
Definition: algo.h:132
void im_hist(const uint8_t *data, const region_of_interest &image_roi, const int rowStep, int h[])
Definition: algo.cpp:297


librealsense2
Author(s): LibRealSense ROS Team
autogenerated on Thu Dec 22 2022 03:41:41