blob: b59e8c551b3e670ac9bef219543471e775dfcd7a [file] [log] [blame]
Parker Schuh0ff777c2017-02-19 15:01:13 -08001#include "aos/vision/blob/transpose.h"
2
3#include <algorithm>
Parker Schuh309dd722017-02-25 11:31:18 -08004#include <limits>
Parker Schuh0ff777c2017-02-19 15:01:13 -08005
Stephan Pleinesf63bde82024-01-13 15:59:33 -08006namespace aos::vision {
Parker Schuh0ff777c2017-02-19 15:01:13 -08007
8RangeImage Transpose(const RangeImage &img) {
9 enum EventT {
10 // Must happen before point adds and deletes.
11 kRangeStart = 0,
12 kRangeEnd = 1,
13 // Non-overlapping
14 kPointAdd = 3,
15 kPointDel = 2,
16 };
Parker Schuh309dd722017-02-25 11:31:18 -080017 int min_y = std::numeric_limits<int>::max();
18 for (const std::vector<ImageRange> &row : img) {
19 if (!row.empty()) min_y = std::min(row[0].st, min_y);
20 }
21
Parker Schuh0ff777c2017-02-19 15:01:13 -080022 std::vector<std::vector<std::pair<int, EventT>>> events;
23 int y = img.min_y();
24 for (const std::vector<ImageRange> &row : img) {
25 for (const ImageRange &range : row) {
Parker Schuh309dd722017-02-25 11:31:18 -080026 if (range.ed - min_y >= static_cast<int>(events.size())) {
27 events.resize(range.ed - min_y + 1);
28 }
29 events[range.st - min_y].emplace_back(y, kPointAdd);
30 events[range.ed - min_y].emplace_back(y, kPointDel);
Parker Schuh0ff777c2017-02-19 15:01:13 -080031 }
32 ++y;
33 }
34
Parker Schuh0ff777c2017-02-19 15:01:13 -080035 std::vector<ImageRange> prev_ranges;
36 std::vector<ImageRange> cur_ranges;
37
38 std::vector<std::vector<ImageRange>> rows;
Parker Schuh309dd722017-02-25 11:31:18 -080039 for (int dy = 0; dy < static_cast<int>(events.size()) - 1; ++dy) {
40 auto row_events = std::move(events[dy]);
Parker Schuh0ff777c2017-02-19 15:01:13 -080041 for (const auto &range : prev_ranges) {
42 row_events.emplace_back(range.st, kRangeStart);
43 row_events.emplace_back(range.ed, kRangeEnd);
44 }
45 std::sort(row_events.begin(), row_events.end());
46 cur_ranges.clear();
47
48 bool has_cur_range = false;
49 ImageRange cur_range{0, 0};
50 auto add_range = [&](ImageRange range) {
51 if (range.st == range.ed) return;
52 if (has_cur_range) {
53 if (cur_range.ed == range.st) {
54 range = ImageRange{cur_range.st, range.ed};
55 } else {
56 cur_ranges.emplace_back(cur_range);
57 }
58 }
59 cur_range = range;
60 has_cur_range = true;
61 };
62
Austin Schuh71f86fb2017-03-15 20:15:41 -070063 int prev_start = 0;
Parker Schuh0ff777c2017-02-19 15:01:13 -080064 for (const auto &pt : row_events) {
65 switch (pt.second) {
66 case kRangeStart:
67 prev_start = pt.first;
68 break;
69 case kPointAdd:
70 add_range(ImageRange{pt.first, pt.first + 1});
71 break;
72 case kRangeEnd:
73 add_range(ImageRange{prev_start, pt.first});
74 break;
75 case kPointDel:
76 add_range(ImageRange{prev_start, pt.first});
77 prev_start = pt.first + 1;
78 break;
79 }
80 }
81
82 if (has_cur_range) cur_ranges.emplace_back(cur_range);
83 rows.emplace_back(cur_ranges);
84 std::swap(cur_ranges, prev_ranges);
85 }
86 return RangeImage(min_y, std::move(rows));
87}
88
Stephan Pleinesf63bde82024-01-13 15:59:33 -080089} // namespace aos::vision