blob: 19ac965c8743f74c96164da1e1ff02d8e44b4b9e [file] [log] [blame]
Parker Schuh0ff777c2017-02-19 15:01:13 -08001#include "aos/vision/blob/transpose.h"
2
3#include <algorithm>
4
5namespace aos {
6namespace vision {
7
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 };
17 std::vector<std::vector<std::pair<int, EventT>>> events;
18 int y = img.min_y();
19 for (const std::vector<ImageRange> &row : img) {
20 for (const ImageRange &range : row) {
21 if (range.ed >= static_cast<int>(events.size()))
22 events.resize(range.ed + 1);
23 events[range.st].emplace_back(y, kPointAdd);
24 events[range.ed].emplace_back(y, kPointDel);
25 }
26 ++y;
27 }
28
29 int min_y = 0;
30 while (min_y < (int)events.size() && events[min_y].empty()) ++min_y;
31
32 std::vector<ImageRange> prev_ranges;
33 std::vector<ImageRange> cur_ranges;
34
35 std::vector<std::vector<ImageRange>> rows;
36 for (int y = min_y; y < static_cast<int>(events.size()) - 1; ++y) {
37 auto row_events = std::move(events[y]);
38 for (const auto &range : prev_ranges) {
39 row_events.emplace_back(range.st, kRangeStart);
40 row_events.emplace_back(range.ed, kRangeEnd);
41 }
42 std::sort(row_events.begin(), row_events.end());
43 cur_ranges.clear();
44
45 bool has_cur_range = false;
46 ImageRange cur_range{0, 0};
47 auto add_range = [&](ImageRange range) {
48 if (range.st == range.ed) return;
49 if (has_cur_range) {
50 if (cur_range.ed == range.st) {
51 range = ImageRange{cur_range.st, range.ed};
52 } else {
53 cur_ranges.emplace_back(cur_range);
54 }
55 }
56 cur_range = range;
57 has_cur_range = true;
58 };
59
60 int prev_start;
61 for (const auto &pt : row_events) {
62 switch (pt.second) {
63 case kRangeStart:
64 prev_start = pt.first;
65 break;
66 case kPointAdd:
67 add_range(ImageRange{pt.first, pt.first + 1});
68 break;
69 case kRangeEnd:
70 add_range(ImageRange{prev_start, pt.first});
71 break;
72 case kPointDel:
73 add_range(ImageRange{prev_start, pt.first});
74 prev_start = pt.first + 1;
75 break;
76 }
77 }
78
79 if (has_cur_range) cur_ranges.emplace_back(cur_range);
80 rows.emplace_back(cur_ranges);
81 std::swap(cur_ranges, prev_ranges);
82 }
83 return RangeImage(min_y, std::move(rows));
84}
85
86} // namespace vision
87} // namespace aos