50 std::span<const float> mask, uint32_t w, uint32_t
h)
52 const size_t n =
static_cast<size_t>(w) *
h;
54 std::vector<uint32_t> labels(n, 0);
56 uint32_t next_label = 1;
58 for (uint32_t
py = 0;
py <
h; ++
py) {
59 for (uint32_t
px = 0;
px < w; ++
px) {
60 const size_t idx =
static_cast<size_t>(
py) * w +
px;
62 if (!is_fg(mask[idx]))
65 const std::array<uint32_t, 4> neighbors {
66 px > 0 ? labels[idx - 1] : 0U,
67 py > 0 &&
px > 0 ? labels[idx - w - 1] : 0U,
68 py > 0 ? labels[idx - w] : 0U,
69 py > 0 &&
px + 1 < w ? labels[idx - w + 1] : 0U,
73 for (uint32_t neighbor : neighbors) {
79 uf.unite(
label, neighbor);
82 labels[idx] =
label != 0 ?
label : next_label++;
86 std::vector<uint32_t> remap(next_label, 0);
88 for (uint32_t i = 1; i < next_label; ++i) {
89 const uint32_t root = uf.find(i);
91 remap[root] = ++compact;
92 remap[i] = remap[root];
96 uint32_t x_min, y_min, x_max, y_max;
100 std::vector<Extent> extents(compact + 1,
101 Extent { .x_min = w, .y_min =
h, .x_max = 0, .y_max = 0, .pixel_count = 0 });
103 for (uint32_t
py = 0;
py <
h; ++
py) {
104 for (uint32_t
px = 0;
px < w; ++
px) {
105 const size_t idx =
static_cast<size_t>(
py) * w +
px;
106 if (labels[idx] == 0)
109 const uint32_t lbl = remap[labels[idx]];
112 auto& e = extents[lbl];
113 e.x_min = std::min(e.x_min,
px);
114 e.y_min = std::min(e.y_min,
py);
115 e.x_max = std::max(e.x_max,
px);
116 e.y_max = std::max(e.y_max,
py);
121 const float inv_w = 1.0F /
static_cast<float>(w);
122 const float inv_h = 1.0F /
static_cast<float>(
h);
124 std::vector<BoundingBox> boxes;
125 boxes.reserve(compact);
127 for (uint32_t i = 1; i <= compact; ++i) {
128 const auto& e = extents[i];
129 const float x =
static_cast<float>(e.x_min) * inv_w;
130 const float y =
static_cast<float>(e.y_min) * inv_h;
131 const float bw =
static_cast<float>(e.x_max - e.x_min + 1) * inv_w;
132 const float bh =
static_cast<float>(e.y_max - e.y_min + 1) * inv_h;
133 boxes.push_back({ .x = x, .y = y, .w = bw, .h = bh, .confidence = 1.0F, .label_id = i });
136 return { .label_map = std::move(labels), .boxes = std::move(boxes), .count = compact };