Apollo 11.0
自动驾驶开放平台
histogram_estimator.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
17
19
20namespace apollo {
21namespace perception {
22namespace camera {
23
24void HistogramEstimatorParams::Init() { // set default value
26 data_sp = 0;
27 data_ep = 255;
28 assert(nr_bins_in_histogram > 0);
29 assert(data_ep > data_sp);
30
31 step_bin = (data_ep - data_sp) / static_cast<float>(nr_bins_in_histogram);
32
33 smooth_kernel.clear();
34 smooth_kernel.push_back(1);
35 smooth_kernel.push_back(2);
36 smooth_kernel.push_back(1);
37 smooth_kernel_width = static_cast<int>(smooth_kernel.size());
39
40 hat_min_allowed = 0.2f;
41 hat_std_allowed = 6.0f;
43 decay_factor = 0.9f;
44}
45
47 if (params != nullptr) {
48 params_ = *params;
49 }
50 step_bin_reversed_ = algorithm::IRec(params_.step_bin);
51 assert(params_.nr_bins_in_histogram > 0);
52 assert(params_.nr_bins_in_histogram <= kMaxNrBins);
53 int nr_bins = params_.nr_bins_in_histogram;
54 memset(hist_.data(), 0, sizeof(uint32_t) * nr_bins);
55 GenerateHat(hist_hat_.data(), nr_bins);
56}
57
59 // smooth histogram - >
60 // get peak & check mass ->
61 // shape anlysisi ->
62 // update estimates - >
63 // final decay
64
65 uint32_t *hist = hist_.data();
66 uint32_t *hist_smoothed = hist_buffer_.data();
67 int nr_bins = params_.nr_bins_in_histogram;
68 Smooth(hist, nr_bins, hist_smoothed);
69#if 0
70 SaveHist("input_hist", hist, nr_bins);
71 SaveHist("smoothed_hist", hist_smoothed, nr_bins);
72#endif
73 int max_index = 0;
74 uint32_t mass = 0;
75 GetPeakIndexAndMass(hist_smoothed, nr_bins, &max_index, &mass);
76 if (mass < params_.histogram_mass_limit) {
77 AERROR << "Fail: lack enough samples.";
78 return false;
79 }
80
81 if (!IsGoodShape(hist, nr_bins, max_index)) {
82 AERROR << "Fail: distribution is not good.";
83 return false;
84 }
85
86 val_estimation_ = GetValFromIndex(max_index);
87 Decay(hist, nr_bins);
88
89 return true;
90}
91
92void HistogramEstimator::Smooth(const uint32_t *hist_input, int nr_bins,
93 uint32_t *hist_output) {
94 assert(nr_bins == params_.nr_bins_in_histogram);
95
96 int filter_radius = params_.smooth_kernel_radius;
97 if (filter_radius * 2 > nr_bins) {
98 return;
99 }
100
101 float weight_sum_kernel = 0.0f;
102 for (auto &w : params_.smooth_kernel) {
103 weight_sum_kernel += static_cast<float>(w);
104 }
105 float norm_reversed = algorithm::IRec(weight_sum_kernel);
106 int sp = 0;
107 int ep = 0;
108
109 // left boundary part
110 for (int i = 0; i < filter_radius; ++i) {
111 uint32_t sum = 0;
112 sp = 0;
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]);
118 }
119 float scale = algorithm::IRec(kernel_sum);
120 hist_output[i] = static_cast<uint32_t>(static_cast<float>(sum) * scale);
121 }
122
123 // mid part
124 for (int i = filter_radius; i < nr_bins - filter_radius; ++i) {
125 uint32_t sum = 0;
126 sp = i - filter_radius;
127 ep = i + filter_radius;
128 for (int j = sp; j <= ep; ++j) {
129 sum += hist_input[j] * params_.smooth_kernel[j - sp];
130 }
131 hist_output[i] =
132 static_cast<uint32_t>(static_cast<float>(sum) * norm_reversed);
133 }
134
135 // right boundary part
136 for (int i = nr_bins - filter_radius; i < nr_bins; ++i) {
137 uint32_t sum = 0;
138 sp = i - filter_radius;
139 ep = nr_bins - 1;
140 float kernel_sum = 0.0f;
141 for (int j = sp; j <= ep; ++j) {
142 sum += hist_input[j] * params_.smooth_kernel[j - sp];
143 kernel_sum += static_cast<float>(params_.smooth_kernel[j - sp]);
144 }
145 float scale = algorithm::IRec(kernel_sum);
146 hist_output[i] = static_cast<uint32_t>(static_cast<float>(sum) * scale);
147 }
148}
149
150void HistogramEstimator::GenerateHat(float *hist_hat, int nr_bins) {
151 assert(nr_bins == params_.nr_bins_in_histogram);
152 // Equation: e^(-(x^2 / (2 * a^2)) + b
153 // a -> hat_std_allowed
154 // b -> hat_min_allowed
155 // max: 1 + hat_min_allowed
156 float hat_std_allowed = params_.hat_std_allowed;
157 float hat_min_allowed = params_.hat_min_allowed;
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;
162 }
163}
164
165bool HistogramEstimator::IsGoodShape(const uint32_t *hist, int nr_bins,
166 int max_index) {
167 assert(nr_bins == params_.nr_bins_in_histogram);
168 assert(max_index < params_.nr_bins_in_histogram);
169 assert(max_index >= 0);
170
171 uint32_t max_value = hist[max_index];
172 int nr_bins_half = nr_bins >> 1;
173
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);
177
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) {
181 return false;
182 }
183 }
184 return true;
185}
186
187void HistogramEstimator::GetPeakIndexAndMass(const uint32_t *hist, int nr_bins,
188 int *index, uint32_t *mass) {
189 assert(nr_bins == params_.nr_bins_in_histogram);
190 assert(hist != nullptr);
191 assert(index != nullptr);
192 assert(mass != nullptr);
193 *index = 0;
194 *mass = hist[0];
195 uint32_t max_value = hist[0];
196 for (int i = 1; i < nr_bins; ++i) {
197 if (hist[i] > max_value) {
198 *index = i;
199 max_value = hist[i];
200 }
201 *mass += hist[i];
202 }
203}
204
205// bool HistogramEstimator::SaveHist(const std::string &filename,
206// const uint32_t *hist, int nr_bins) {
207// if (nr_bins < 1) {
208// return false;
209// }
210// std::ofstream fout;
211// fout.open(filename.c_str());
212// if (!fout) {
213// std::cerr << "Fail to save the hist: " << filename << std::endl;
214// return false;
215// }
216// for (int i = 0; i < nr_bins; ++i) {
217// fout << hist[i] << std::endl;
218// }
219// fout.close();
220// return true;
221// }
222
223} // namespace camera
224} // namespace perception
225} // namespace apollo
void Init(const HistogramEstimatorParams *params=nullptr)
#define AERROR
Definition log.h:44
class register implement
Definition arena_queue.h:37