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 {
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 
565  : _width(width), _height(height)
566 {
567  if (width != 256 || height != 144)
568  throw std::runtime_error(to_string() << "Only 256x144 resolution is supported!");
569 
570  _wt = _width - _tsize;
571  _ht = _height - _tsize;
572  _size = _width * _height;
573 
574  _hwidth = _width >> 1;
575  _hheight = _height >> 1;
576 
577  _imgt.resize(_tsize2);
578  _img.resize(_size);
579  _ncc.resize(_size);
580  memset(_ncc.data(), 0, _size * sizeof(double));
581 
582  _buf.resize(_patch_size * _patch_size);
583 }
584 
586 {
587 }
588 
589 bool rect_gaussian_dots_target_calculator::calculate(const uint8_t* img, float* target_dims, unsigned int target_dims_size)
590 {
591  bool ret = false;
592  if (target_dims_size < 4)
593  return ret;
594 
595  normalize(img);
596  calculate_ncc();
597 
598  if (find_corners())
599  ret = validate_corners(img);
600 
601  if (ret)
602  calculate_rect_sides(target_dims);
603 
604  return ret;
605 }
606 
608 {
609  uint8_t min_val = 255;
610  uint8_t max_val = 0;
611  const uint8_t* p = img;
612  for (int i = 0; i < _size; ++i)
613  {
614  if (*p < min_val)
615  min_val = *p;
616 
617  if (*p > max_val)
618  max_val = *p;
619 
620  ++p;
621  }
622 
623  if (max_val > min_val)
624  {
625  double factor = 1.0f / (max_val - min_val);
626 
627  p = img;
628  double* q = _img.data();
629  for (int i = 0; i < _size; ++i)
630  *q++ = 1.0f - (*p++ - min_val) * factor;
631  }
632 }
633 
635 {
636  double* pncc = _ncc.data() + (_htsize * _width + _htsize);
637  double* pi = _img.data();
638  double* pit = _imgt.data();
639 
640  const double* pt = nullptr;
641  const double* qi = nullptr;
642 
643  double sum = 0.0f;
644  double mean = 0.0f;
645  double norm = 0.0f;
646 
647  double min_val = 2.0;
648  double max_val = -2.0;
649  double tmp = 0.0;
650 
651  for (int j = 0; j < _ht; ++j)
652  {
653  for (int i = 0; i < _wt; ++i)
654  {
655  qi = pi;
656  sum = 0.0f;
657  for (int m = 0; m < _tsize; ++m)
658  {
659  for (int n = 0; n < _tsize; ++n)
660  sum += *qi++;
661 
662  qi += _wt;
663  }
664 
665  mean = sum / _tsize2;
666 
667  qi = pi;
668  sum = 0.0f;
669  pit = _imgt.data();
670  for (int m = 0; m < _tsize; ++m)
671  {
672  for (int n = 0; n < _tsize; ++n)
673  {
674  *pit = *qi++ - mean;
675  sum += *pit * *pit;
676  ++pit;
677  }
678  qi += _wt;
679  }
680 
681  norm = sqrt(sum);
682 
683  pt = _template.data();
684  pit = _imgt.data();
685  sum = 0.0f;
686  for (int k = 0; k < _tsize2; ++k)
687  sum += *pit++ * *pt++;
688 
689  tmp = sum / norm;
690  if (tmp < min_val)
691  min_val = tmp;
692 
693  if (tmp > max_val)
694  max_val = tmp;
695 
696  *pncc++ = tmp;
697  ++pi;
698  }
699 
700  pncc += _tsize;
701  pi += _tsize;
702  }
703 
704  if (max_val > min_val)
705  {
706  double factor = 1.0f / (max_val - min_val);
707  double div = 1.0 - _thresh;
708  pncc = _ncc.data();
709  for (int i = 0; i < _size; ++i)
710  {
711  tmp = (*pncc - min_val) * factor;
712  *pncc++ = (tmp < _thresh ? 0 : (tmp - _thresh) / div);
713  }
714  }
715 }
716 
718 {
719  static const int edge = 20;
720 
721  // upper left
722  _pts[0].x = 0;
723  _pts[0].y = 0;
724  double peak = 0.0f;
725  double* p = _ncc.data() + _htsize * _width;
726  for (int j = _htsize; j < _hheight; ++j)
727  {
728  p += _htsize;
729  for (int i = _htsize; i < _hwidth; ++i)
730  {
731  if (*p > peak)
732  {
733  peak = *p;
734  _pts[0].x = i;
735  _pts[0].y = j;
736  }
737  ++p;
738  }
739  p += _hwidth;
740  }
741 
742  if (peak < _thresh || _pts[0].x < edge || _pts[0].y < edge)
743  return false;
744 
745  // upper right
746  _pts[1].x = 0;
747  _pts[1].y = 0;
748  peak = 0.0f;
749  p = _ncc.data() + _htsize * _width;
750  for (int j = _htsize; j < _hheight; ++j)
751  {
752  p += _hwidth;
753  for (int i = _hwidth; i < _width - _htsize; ++i)
754  {
755  if (*p > peak)
756  {
757  peak = *p;
758  _pts[1].x = i;
759  _pts[1].y = j;
760  }
761  ++p;
762  }
763  p += _htsize;
764  }
765 
766  if (peak < _thresh || _pts[1].x + edge > _width || _pts[1].y < edge || _pts[1].x - _pts[0].x < edge)
767  return false;
768 
769  // lower left
770  _pts[2].x = 0;
771  _pts[2].y = 0;
772  peak = 0.0f;
773  p = _ncc.data() + _hheight * _width;
774  for (int j = _hheight; j < _height - _htsize; ++j)
775  {
776  p += _htsize;
777  for (int i = _htsize; i < _hwidth; ++i)
778  {
779  if (*p > peak)
780  {
781  peak = *p;
782  _pts[2].x = i;
783  _pts[2].y = j;
784  }
785  ++p;
786  }
787  p += _hwidth;
788  }
789 
790  if (peak < _thresh || _pts[2].x < edge || _pts[2].y + edge > _height || _pts[2].y - _pts[1].y < edge)
791  return false;
792 
793  // lower right
794  _pts[3].x = 0;
795  _pts[3].y = 0;
796  peak = 0.0f;
797  p = _ncc.data() + _hheight * _width;
798  for (int j = _hheight; j < _height - _htsize; ++j)
799  {
800  p += _hwidth;
801  for (int i = _hwidth; i < _width - _htsize; ++i)
802  {
803  if (*p > peak)
804  {
805  peak = *p;
806  _pts[3].x = i;
807  _pts[3].y = j;
808  }
809  ++p;
810  }
811  p += _htsize;
812  }
813 
814  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)
815  return false;
816  else
817  refine_corners();
818 
819  return true;
820 }
821 
823 {
824  double* f = _buf.data();
825  int hs = _patch_size >> 1;
826 
827  // upper left
828  int pos = (_pts[0].y - hs) * _width + _pts[0].x - hs;
829 
830  _corners[0].x = static_cast<double>(_pts[0].x - hs);
831  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[0].x);
832 
833  _corners[0].y = static_cast<double>(_pts[0].y - hs);
834  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[0].y);
835 
836  // upper right
837  pos = (_pts[1].y - hs) * _width + _pts[1].x - hs;
838 
839  _corners[1].x = static_cast<double>(_pts[1].x - hs);
840  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[1].x);
841 
842  _corners[1].y = static_cast<double>(_pts[1].y - hs);
843  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[1].y);
844 
845  // lower left
846  pos = (_pts[2].y - hs) * _width + _pts[2].x - hs;
847 
848  _corners[2].x = static_cast<double>(_pts[2].x - hs);
849  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[2].x);
850 
851  _corners[2].y = static_cast<double>(_pts[2].y - hs);
852  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[2].y);
853 
854  // lower right
855  pos = (_pts[3].y - hs) * _width + _pts[3].x - hs;
856 
857  _corners[3].x = static_cast<double>(_pts[3].x - hs);
858  minimize_x(_ncc.data() + pos, _patch_size, f, _corners[3].x);
859 
860  _corners[3].y = static_cast<double>(_pts[3].y - hs);
861  minimize_y(_ncc.data() + pos, _patch_size, f, _corners[3].y);
862 }
863 
865 {
866  uint8_t peaks[4] = { 0 };
867  int idx = 0;
868  int x = 0;
869  int y = 0;
870  for (int i = 0; i < 4; ++i)
871  {
872  y = static_cast<int>(_corners[i].y + 0.5f);
873  x = static_cast<int>(_corners[i].x + 0.5f);
874  idx = y * _width + x;
875  peaks[i] = img[idx];
876  }
877 
878  static const int peak_diff_thresh = 12;
879  bool ok = true;
880  for (int j = 0; j < 4; ++j)
881  {
882  for (int i = 0; i < 4; ++i)
883  {
884  if (std::abs(peaks[i] - peaks[j]) > peak_diff_thresh)
885  {
886  ok = false;
887  break;
888  }
889 
890  if (!ok)
891  break;
892  }
893  }
894 
895  return ok;
896 }
897 
899 {
900  double lx = _corners[1].x - _corners[0].x;
901  double ly = _corners[1].y - _corners[0].y;
902  rect_sides[0] = static_cast<float>(sqrt(lx * lx + ly * ly)); // uppper
903 
904  lx = _corners[3].x - _corners[2].x;
905  ly = _corners[3].y - _corners[2].y;
906  rect_sides[1] = static_cast<float>(sqrt(lx * lx + ly * ly)); // lower
907 
908  lx = _corners[2].x - _corners[0].x;
909  ly = _corners[2].y - _corners[0].y;
910  rect_sides[2] = static_cast<float>(sqrt(lx * lx + ly * ly)); // left
911 
912  lx = _corners[3].x - _corners[1].x;
913  ly = _corners[3].y - _corners[1].y;
914  rect_sides[3] = static_cast<float>(sqrt(lx * lx + ly * ly)); // right
915 }
916 
917 void rect_gaussian_dots_target_calculator::minimize_x(const double* p, int s, double* f, double& x)
918 {
919  int ws = _width - s;
920 
921  for (int i = 0; i < s; ++i)
922  f[i] = 0;
923 
924  for (int j = 0; j < s; ++j)
925  {
926  for (int i = 0; i < s; ++i)
927  f[i] += *p++;
928  p += ws;
929  }
930 
931  x += subpixel_agj(f, s);
932 }
933 
934 void rect_gaussian_dots_target_calculator::minimize_y(const double* p, int s, double* f, double& y)
935 {
936  int ws = _width - s;
937 
938  for (int i = 0; i < s; ++i)
939  f[i] = 0;
940 
941  for (int j = 0; j < s; ++j)
942  {
943  for (int i = 0; i < s; ++i)
944  f[j] += *p++;
945  p += ws;
946  }
947 
948  y += subpixel_agj(f, s);
949 }
950 
952 {
953  int mi = 0;
954  double mv = f[mi];
955  for (int i = 1; i < s; ++i)
956  {
957  if (f[i] > mv)
958  {
959  mi = i;
960  mv = f[mi];
961  }
962  }
963 
964  double half_mv = 0.5f * mv;
965 
966  int x_0 = 0;
967  int x_1 = 0;
968  for (int i = 0; i < s; ++i)
969  {
970  if (f[i] > half_mv)
971  {
972  x_1 = i;
973  break;
974  }
975  }
976 
977  double left_mv = 0.0f;
978  if (x_1 > 0)
979  {
980  x_0 = x_1 - 1;
981  left_mv = x_0 + (half_mv - f[x_0]) / (f[x_1] - f[x_0]);
982  }
983  else
984  left_mv = static_cast<double>(0);
985 
986  x_0 = s - 1;
987  for (int i = s - 1; i >= 0; --i)
988  {
989  if (f[i] > half_mv)
990  {
991  x_0 = i;
992  break;
993  }
994  }
995 
996  double right_mv = 0.0f;
997  if (x_0 == s - 1)
998  right_mv = static_cast<double>(s - 1);
999  else
1000  {
1001  x_1 = x_0 + 1;
1002  right_mv = x_0 + (half_mv - f[x_0]) / (f[x_1] - f[x_0]);
1003  }
1004 
1005  return (left_mv + right_mv) / 2;
1006 }
static const textual_icon lock
Definition: model-views.h:218
bool supports_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: archive.cpp:250
std::shared_ptr< std::thread > _exposure_thread
Definition: algo.h:131
float3 mult(const float3x3 &a, const float3 &b)
Definition: test-pose.cpp:78
void set_enable_auto_exposure(bool value)
Definition: algo.cpp:29
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
static const unsigned skip_frames
Definition: algo.h:47
bool analyze_image(const frame_interface *image)
Definition: algo.cpp:220
std::recursive_mutex state_mutex
Definition: algo.h:102
auto_exposure_modes
Definition: algo.h:20
const std::vector< double > _template
Definition: algo.h:185
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:898
virtual void set(float value)=0
static const float ae_step_default_value
Definition: algo.h:18
GLfloat GLfloat p
Definition: glext.h:12687
const GLfloat * m
Definition: glext.h:6814
float get_auto_exposure_step() const
Definition: algo.cpp:24
GLfloat value
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
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
GLdouble n
Definition: glext.h:1966
unsigned char uint8_t
Definition: stdint.h:78
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:934
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
GLenum GLenum GLsizei void * image
const int H
GLdouble f
GLenum mode
std::atomic< bool > _keep_alive
Definition: algo.h:133
GLuint GLenum * rate
Definition: glext.h:10991
void anti_flicker_increase_exposure_gain(const float &target_exposure, const float &target_exposure0, float &exposure, float &gain)
Definition: algo.cpp:352
void set_auto_exposure_antiflicker_rate(unsigned value)
Definition: algo.cpp:39
std::atomic< unsigned > _skip_frames
Definition: algo.h:137
bool calculate(const uint8_t *img, float *target_dims, unsigned int target_dims_size) override
Definition: algo.cpp:589
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
unsigned get_auto_exposure_antiflicker_rate() const
Definition: algo.cpp:19
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
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
#define LOG_ERROR(...)
Definition: src/types.h:242
auto_exposure_algorithm(const auto_exposure_state &auto_exposure_state)
Definition: algo.cpp:167
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
rect_gaussian_dots_target_calculator(int width, int height)
Definition: algo.cpp:564
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
bool get_enable_auto_exposure() const
Definition: algo.cpp:9
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
static const double pi
Definition: src/types.h:57
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
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
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glext.h:9721
signed int int32_t
Definition: stdint.h:77
#define LOG_DEBUG(...)
Definition: src/types.h:239
const byte * get_frame_data() const override
Definition: archive.cpp:276
auto_exposure_modes get_auto_exposure_mode() const
Definition: algo.cpp:14
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:917
Definition: parser.hpp:150
rs2_metadata_type get_frame_metadata(const rs2_frame_metadata_value &frame_metadata) const override
Definition: archive.cpp:216
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
std::string to_string(T value)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:45:06