blob: 72e1cc16dca97624a4133810b36de3fbc3261ac6 [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
6namespace aos {
7namespace vision {
8
9RangeImage Transpose(const RangeImage &img) {
10 enum EventT {
11 // Must happen before point adds and deletes.
12 kRangeStart = 0,
13 kRangeEnd = 1,
14 // Non-overlapping
15 kPointAdd = 3,
16 kPointDel = 2,
17 };
Parker Schuh309dd722017-02-25 11:31:18 -080018 int min_y = std::numeric_limits<int>::max();
19 for (const std::vector<ImageRange> &row : img) {
20 if (!row.empty()) min_y = std::min(row[0].st, min_y);
21 }
22
Parker Schuh0ff777c2017-02-19 15:01:13 -080023 std::vector<std::vector<std::pair<int, EventT>>> events;
24 int y = img.min_y();
25 for (const std::vector<ImageRange> &row : img) {
26 for (const ImageRange &range : row) {
Parker Schuh309dd722017-02-25 11:31:18 -080027 if (range.ed - min_y >= static_cast<int>(events.size())) {
28 events.resize(range.ed - min_y + 1);
29 }
30 events[range.st - min_y].emplace_back(y, kPointAdd);
31 events[range.ed - min_y].emplace_back(y, kPointDel);
Parker Schuh0ff777c2017-02-19 15:01:13 -080032 }
33 ++y;
34 }
35
Parker Schuh0ff777c2017-02-19 15:01:13 -080036 std::vector<ImageRange> prev_ranges;
37 std::vector<ImageRange> cur_ranges;
38
39 std::vector<std::vector<ImageRange>> rows;
Parker Schuh309dd722017-02-25 11:31:18 -080040 for (int dy = 0; dy < static_cast<int>(events.size()) - 1; ++dy) {
41 auto row_events = std::move(events[dy]);
Parker Schuh0ff777c2017-02-19 15:01:13 -080042 for (const auto &range : prev_ranges) {
43 row_events.emplace_back(range.st, kRangeStart);
44 row_events.emplace_back(range.ed, kRangeEnd);
45 }
46 std::sort(row_events.begin(), row_events.end());
47 cur_ranges.clear();
48
49 bool has_cur_range = false;
50 ImageRange cur_range{0, 0};
51 auto add_range = [&](ImageRange range) {
52 if (range.st == range.ed) return;
53 if (has_cur_range) {
54 if (cur_range.ed == range.st) {
55 range = ImageRange{cur_range.st, range.ed};
56 } else {
57 cur_ranges.emplace_back(cur_range);
58 }
59 }
60 cur_range = range;
61 has_cur_range = true;
62 };
63
64 int prev_start;
65 for (const auto &pt : row_events) {
66 switch (pt.second) {
67 case kRangeStart:
68 prev_start = pt.first;
69 break;
70 case kPointAdd:
71 add_range(ImageRange{pt.first, pt.first + 1});
72 break;
73 case kRangeEnd:
74 add_range(ImageRange{prev_start, pt.first});
75 break;
76 case kPointDel:
77 add_range(ImageRange{prev_start, pt.first});
78 prev_start = pt.first + 1;
79 break;
80 }
81 }
82
83 if (has_cur_range) cur_ranges.emplace_back(cur_range);
84 rows.emplace_back(cur_ranges);
85 std::swap(cur_ranges, prev_ranges);
86 }
87 return RangeImage(min_y, std::move(rows));
88}
89
90} // namespace vision
91} // namespace aos