47 if (params !=
nullptr) {
54 memset(hist_.data(), 0,
sizeof(uint32_t) * nr_bins);
55 GenerateHat(hist_hat_.data(), nr_bins);
65 uint32_t *hist = hist_.data();
66 uint32_t *hist_smoothed = hist_buffer_.data();
68 Smooth(hist, nr_bins, hist_smoothed);
70 SaveHist(
"input_hist", hist, nr_bins);
71 SaveHist(
"smoothed_hist", hist_smoothed, nr_bins);
75 GetPeakIndexAndMass(hist_smoothed, nr_bins, &max_index, &mass);
77 AERROR <<
"Fail: lack enough samples.";
81 if (!IsGoodShape(hist, nr_bins, max_index)) {
82 AERROR <<
"Fail: distribution is not good.";
86 val_estimation_ = GetValFromIndex(max_index);
92void HistogramEstimator::Smooth(
const uint32_t *hist_input,
int nr_bins,
93 uint32_t *hist_output) {
97 if (filter_radius * 2 > nr_bins) {
101 float weight_sum_kernel = 0.0f;
102 for (
auto &w : params_.smooth_kernel) {
103 weight_sum_kernel +=
static_cast<float>(w);
110 for (
int i = 0; i < filter_radius; ++i) {
113 ep = i + filter_radius;
114 float kernel_sum = 0.0f;
115 for (
int j = sp; j <= ep; ++j) {
116 sum += hist_input[j] * params_.
smooth_kernel[j - i + filter_radius];
117 kernel_sum +=
static_cast<float>(params_.
smooth_kernel[j - sp]);
120 hist_output[i] =
static_cast<uint32_t
>(
static_cast<float>(sum) * scale);
124 for (
int i = filter_radius; i < nr_bins - filter_radius; ++i) {
126 sp = i - filter_radius;
127 ep = i + filter_radius;
128 for (
int j = sp; j <= ep; ++j) {
132 static_cast<uint32_t
>(
static_cast<float>(sum) * norm_reversed);
136 for (
int i = nr_bins - filter_radius; i < nr_bins; ++i) {
138 sp = i - filter_radius;
140 float kernel_sum = 0.0f;
141 for (
int j = sp; j <= ep; ++j) {
143 kernel_sum +=
static_cast<float>(params_.
smooth_kernel[j - sp]);
146 hist_output[i] =
static_cast<uint32_t
>(
static_cast<float>(sum) * scale);
150void HistogramEstimator::GenerateHat(
float *hist_hat,
int nr_bins) {
158 int nr_bins_half = nr_bins >> 1;
159 for (
int i = 0; i < nr_bins; ++i) {
160 float val =
static_cast<float>(i - nr_bins_half) / hat_std_allowed;
161 hist_hat_[i] = expf(-val * val * 0.5f) + hat_min_allowed;
165bool HistogramEstimator::IsGoodShape(
const uint32_t *hist,
int nr_bins,
169 assert(max_index >= 0);
171 uint32_t max_value = hist[max_index];
172 int nr_bins_half = nr_bins >> 1;
174 int offset = max_index - nr_bins_half;
175 int sp = std::max(offset, 0);
176 int ep = std::min(offset + nr_bins, nr_bins);
178 for (
int i = sp; i < ep; ++i) {
179 float hat_val = hist_hat_[i - offset];
180 if (
static_cast<float>(hist[i]) >
static_cast<float>(max_value) * hat_val) {
187void HistogramEstimator::GetPeakIndexAndMass(
const uint32_t *hist,
int nr_bins,
188 int *index, uint32_t *mass) {
190 assert(hist !=
nullptr);
191 assert(index !=
nullptr);
192 assert(mass !=
nullptr);
195 uint32_t max_value = hist[0];
196 for (
int i = 1; i < nr_bins; ++i) {
197 if (hist[i] > max_value) {
static const int kMaxNrBins
void Init(const HistogramEstimatorParams *params=nullptr)
std::vector< uint32_t > smooth_kernel
uint32_t histogram_mass_limit