Apollo 11.0
自动驾驶开放平台
spp_label_image.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
18#include <algorithm>
19#include <utility>
20
24
25namespace apollo {
26namespace perception {
27namespace lidar {
28
29void SppLabelImage::Init(size_t width, size_t height,
30 const std::string& sensor_name) {
31 // simply release the last memory and allocate new one
32 if (labels_) {
33 algorithm::IFree2(&labels_);
34 }
35 width_ = width;
36 height_ = height;
37 sensor_name_ = sensor_name;
38 labels_ = algorithm::IAlloc2<uint16_t>(static_cast<int>(height_),
39 static_cast<int>(width_));
40 memset(labels_[0], 0, sizeof(uint16_t) * width_ * height_);
41 clusters_.clear();
42}
43
44void SppLabelImage::InitRangeMask(float range, float boundary_distance) {
45 if (range_mask_) {
46 algorithm::IFree2(&range_mask_);
47 }
48 range_mask_ = algorithm::IAlloc2<char>(static_cast<int>(height_),
49 static_cast<int>(width_));
50 memset(range_mask_[0], 0, sizeof(char) * width_ * height_);
51 float meter_per_pixel = range * 2.0f / static_cast<float>(width_);
52 size_t half_width = width_ / 2;
53 size_t half_height = height_ / 2;
54 for (size_t r = 0; r < height_; ++r) {
55 for (size_t c = 0; c < width_; ++c) {
56 float distance = sqrtf(
57 powf((static_cast<float>(r) - static_cast<float>(half_height)), 2.f) +
58 powf((static_cast<float>(c) - static_cast<float>(half_width)), 2.f));
59 distance *= meter_per_pixel;
60 if (distance <= boundary_distance) {
61 range_mask_[r][c] = 1;
62 }
63 }
64 }
65}
66
68 size_t size = width_ * height_;
69 // find max label
70 uint16_t max_label = *(std::max_element(labels_[0], labels_[0] + size));
71 clusters_.clear();
72 SppClusterPool::Instance(sensor_name_).BatchGet(max_label, &clusters_);
73 for (size_t y = 0; y < height_; ++y) {
74 for (size_t x = 0; x < width_; ++x) {
75 uint16_t& label = labels_[y][x];
76 // label 0 is invalid, will be ignored
77 if (label) {
78 clusters_[label - 1]->pixels.push_back(
79 static_cast<unsigned int>(y * width_ + x));
80 }
81 }
82 }
83}
84
86 memset(labels_[0], 0, sizeof(uint16_t) * width_ * height_);
87 for (size_t n = 0; n < clusters_.size(); ++n) {
88 auto& cluster = clusters_[n];
89 for (auto& pixel : cluster->pixels) {
90 labels_[0][pixel] = static_cast<uint16_t>(n + 1);
91 }
92 }
93}
94
95void SppLabelImage::FilterClusters(const float* confidence_map,
96 float threshold) {
97 for (auto& cluster : clusters_) {
98 float sum = 0.f;
99 for (auto& pixel : cluster->pixels) {
100 sum += confidence_map[pixel];
101 }
102 sum = cluster->pixels.size() > 0
103 ? sum / static_cast<float>(cluster->pixels.size())
104 : sum;
105 cluster->confidence = sum;
106 }
107 size_t current = 0;
108 for (size_t n = 0; n < clusters_.size(); ++n) {
109 if (clusters_[n]->confidence >= threshold) {
110 if (current != n) {
111 clusters_[current] = clusters_[n];
112 for (auto& pixel : clusters_[current]->pixels) {
113 labels_[0][pixel] = static_cast<uint16_t>(current + 1);
114 }
115 }
116 ++current;
117 } else {
118 for (auto& pixel : clusters_[n]->pixels) {
119 labels_[0][pixel] = 0;
120 }
121 }
122 }
123 clusters_.resize(current);
124}
125
126void SppLabelImage::FilterClusters(const float* confidence_map,
127 const float* category_map,
128 float confidence_threshold,
129 float category_threshold) {
130 std::vector<bool> is_valid;
131 is_valid.reserve(clusters_.size());
132 for (auto& cluster : clusters_) {
133 char mask = 1;
134 for (auto& pixel : cluster->pixels) {
135 mask &= range_mask_[0][pixel];
136 }
137 float sum_confidence = 0.f;
138 for (auto& pixel : cluster->pixels) {
139 sum_confidence += confidence_map[pixel];
140 }
141 sum_confidence =
142 cluster->pixels.size() > 0
143 ? sum_confidence / static_cast<float>(cluster->pixels.size())
144 : sum_confidence;
145 cluster->confidence = sum_confidence;
146 if (mask) { // in range, use confidence estimation
147 is_valid.push_back(cluster->confidence >= confidence_threshold);
148 } else { // out of range, use category estimation
149 float sum_category = 0.f;
150 for (auto& pixel : cluster->pixels) {
151 sum_category += category_map[pixel];
152 }
153 sum_category =
154 cluster->pixels.size() > 0
155 ? sum_category / static_cast<float>(cluster->pixels.size())
156 : sum_category;
157 is_valid.push_back(sum_category >= category_threshold);
158 // category is not stable, here we hack the confidence
159 cluster->confidence =
160 std::max(sum_confidence, confidence_threshold + 0.01f);
161 }
162 }
163 size_t current = 0;
164 for (size_t n = 0; n < clusters_.size(); ++n) {
165 if (is_valid[n]) {
166 if (current != n) {
167 clusters_[current] = clusters_[n];
168 for (auto& pixel : clusters_[current]->pixels) {
169 labels_[0][pixel] = static_cast<uint16_t>(current + 1);
170 }
171 }
172 ++current;
173 } else {
174 for (auto& pixel : clusters_[n]->pixels) {
175 labels_[0][pixel] = 0;
176 }
177 }
178 }
179 clusters_.resize(current);
180}
181
182void SppLabelImage::CalculateClusterClass(const float* class_map,
183 size_t class_num) {
184 for (auto& cluster : clusters_) {
185 cluster->class_prob.assign(class_num, 0.f);
186 }
187 size_t size = width_ * height_;
188 for (size_t c = 0; c < class_num; ++c) {
189 const float* class_map_ptr = class_map + c * size;
190 for (auto& cluster : clusters_) {
191 auto& probs = cluster->class_prob;
192 for (auto& pixel : cluster->pixels) {
193 probs[c] += class_map_ptr[pixel];
194 }
195 }
196 }
197 for (auto& cluster : clusters_) {
198 auto& probs = cluster->class_prob;
199 float sum = std::accumulate(probs.begin(), probs.end(), 0.f);
200 if (sum > 1e-9) {
201 for (auto& value : probs) {
202 value /= sum;
203 }
204 }
205 cluster->type = static_cast<SppClassType>(std::distance(
206 probs.begin(), std::max_element(probs.begin(), probs.end())));
207 }
208}
209
210void SppLabelImage::CalculateClusterHeading(const float* heading_map) {
211 const float* heading_map_x_ptr = heading_map;
212 const float* heading_map_y_ptr = heading_map + width_ * height_;
213
214 for (size_t n = 0; n < clusters_.size(); ++n) {
215 float heading_x = 0.f, heading_y = 0.f;
216 for (auto pixel : clusters_[n]->pixels) {
217 heading_x += heading_map_x_ptr[pixel];
218 heading_y += heading_map_y_ptr[pixel];
219 }
220 clusters_[n]->yaw = std::atan2(heading_y, heading_x) * 0.5f;
221 }
222}
223
224void SppLabelImage::CalculateClusterTopZ(const float* top_z_map) {
225 for (auto& cluster : clusters_) {
226 float sum = 0.f;
227 for (auto& pixel : cluster->pixels) {
228 sum += top_z_map[pixel];
229 }
230 sum = cluster->pixels.size() > 0
231 ? sum / static_cast<float>(cluster->pixels.size())
232 : sum;
233 cluster->top_z = sum;
234 }
235}
236
237void SppLabelImage::AddPixelSample(size_t id, uint32_t pixel) {
238 if (clusters_.size() <= id) {
239 SppClusterPool::Instance(sensor_name_)
240 .BatchGet(id + 1 - clusters_.size(), &clusters_);
241 }
242 clusters_[id]->pixels.push_back(pixel);
243}
244
246 if (size > clusters_.size()) {
247 SppClusterPool::Instance(sensor_name_)
248 .BatchGet(size - clusters_.size(), &clusters_);
249 } else {
250 clusters_.resize(size);
251 }
252}
253
255 size_t reset_pos = std::min(clusters_.size(), size);
256 ResizeClusters(size);
257 for (size_t i = 0; i < reset_pos; ++i) {
258 clusters_[i]->clear();
259 }
260}
261
262} // namespace lidar
263} // namespace perception
264} // namespace apollo
void BatchGet(size_t num, std::vector< std::shared_ptr< ObjectType > > *data) override
static LightObjectPool & Instance(const std::string &sensor_name="velodyne64")
void CalculateClusterTopZ(const float *top_z_map)
void CalculateClusterClass(const float *class_map, size_t class_num)
void CalculateClusterHeading(const float *heading_map)
void Init(size_t width, size_t height, const std::string &sensor_name="velodyne64")
void AddPixelSample(size_t id, uint16_t x, uint16_t y)
void FilterClusters(const float *confidence_map, float threshold)
void InitRangeMask(float range, float boundary_distance)
Image< uchar > * threshold(Image< T > *src, int t)
Threshold image
Definition imutil.h:79
class register implement
Definition arena_queue.h:37