blob: 81a8c4830f9a8bc4f15cc68ab322acbbb1fc871a [file] [log] [blame]
Parker Schuh6691f192017-01-14 17:01:02 -08001#include "aos/vision/blob/range_image.h"
2
3#include <math.h>
4#include <algorithm>
5
6namespace aos {
7namespace vision {
Brian Silverman93897f32019-03-10 16:19:19 -07008namespace {
Parker Schuh6691f192017-01-14 17:01:02 -08009
Brian Silverman93897f32019-03-10 16:19:19 -070010// Merge sort of multiple range images into a single range image.
11// They must not overlap.
Parker Schuh6691f192017-01-14 17:01:02 -080012RangeImage MergeRangeImage(const BlobList &blobl) {
13 if (blobl.size() == 1) return blobl[0];
14
15 int min_y = blobl[0].min_y();
16 for (const RangeImage &subrimg : blobl) {
17 if (min_y > subrimg.min_y()) min_y = subrimg.min_y();
18 }
19 std::vector<std::vector<ImageRange>> ranges;
20 int i = min_y;
21 while (true) {
22 std::vector<ImageRange> range_lst;
23 int n_missing = 0;
24 for (const RangeImage &subrimg : blobl) {
25 if (subrimg.min_y() > i) continue;
26 int ri = i - subrimg.min_y();
27 if (ri < (int)subrimg.ranges().size()) {
28 for (const auto &span : subrimg.ranges()[ri]) {
29 range_lst.emplace_back(span);
30 }
31 } else {
32 ++n_missing;
33 }
34 }
35 std::sort(range_lst.begin(), range_lst.end());
36 ranges.emplace_back(std::move(range_lst));
37 if (n_missing == static_cast<int>(blobl.size()))
38 return RangeImage(min_y, std::move(ranges));
39 ++i;
40 }
41}
42
Brian Silverman93897f32019-03-10 16:19:19 -070043} // namespace
44
Parker Schuh6691f192017-01-14 17:01:02 -080045std::string ShortDebugPrint(const BlobList &blobl) {
46 RangeImage rimg = MergeRangeImage(blobl);
47 std::string out;
48 out += "{";
49 out += "min_y: " + std::to_string(rimg.min_y());
50 for (const auto &line : rimg) {
51 out += "{";
52 for (const auto &span : line) {
53 out +=
54 "{" + std::to_string(span.st) + ", " + std::to_string(span.ed) + "},";
55 }
56 out += "},";
57 }
58 out += "}";
59 return out;
60}
61
62void DebugPrint(const BlobList &blobl) {
63 RangeImage rimg = MergeRangeImage(blobl);
64 int minx = rimg.ranges()[0][0].st;
65 int maxx = 0;
Austin Schuh335eef12019-03-02 17:04:17 -080066 for (const std::vector<ImageRange> &range : rimg.ranges()) {
67 for (const ImageRange &span : range) {
Parker Schuh6691f192017-01-14 17:01:02 -080068 if (span.st < minx) minx = span.st;
69 if (span.ed > maxx) maxx = span.ed;
70 }
71 }
Parker Schuh309dd722017-02-25 11:31:18 -080072 printf("maxx: %d minx: %d\n", maxx, minx);
Parker Schuh6691f192017-01-14 17:01:02 -080073 char buf[maxx - minx];
Austin Schuh335eef12019-03-02 17:04:17 -080074 for (const std::vector<ImageRange> &range : rimg.ranges()) {
Parker Schuh6691f192017-01-14 17:01:02 -080075 int i = minx;
Austin Schuh335eef12019-03-02 17:04:17 -080076 for (const ImageRange &span : range) {
Parker Schuh6691f192017-01-14 17:01:02 -080077 for (; i < span.st; ++i) buf[i - minx] = ' ';
78 for (; i < span.ed; ++i) buf[i - minx] = '#';
79 }
80 for (; i < maxx; ++i) buf[i - minx] = ' ';
Parker Schuh309dd722017-02-25 11:31:18 -080081 printf("%.*s\n", maxx - minx, buf);
Parker Schuh6691f192017-01-14 17:01:02 -080082 }
83}
84
Brian Silverman5eec8b92019-03-10 15:14:31 -070085void PrintTo(const ImageRange &range, std::ostream *os) {
86 *os << "{" << range.st << ", " << range.ed << "}";
87}
88
Parker Schuh6691f192017-01-14 17:01:02 -080089void RangeImage::Flip(int image_width, int image_height) {
90 std::reverse(ranges_.begin(), ranges_.end());
91 for (std::vector<ImageRange> &range : ranges_) {
92 std::reverse(range.begin(), range.end());
93 for (ImageRange &interval : range) {
94 int tmp = image_width - interval.ed;
95 interval.ed = image_width - interval.st;
96 interval.st = tmp;
97 }
98 }
99
100 min_y_ = image_height - static_cast<int>(ranges_.size()) - min_y_;
101}
102
Brian Silverman5eec8b92019-03-10 15:14:31 -0700103void PrintTo(const RangeImage &range, std::ostream *os) {
104 *os << "{min_y=" << range.min_y()
105 << ", ranges={";
106 bool first_row = true;
107 for (const auto &row : range) {
108 if (first_row) {
109 first_row = false;
110 } else {
111 *os << ", ";
112 }
113 *os << "{";
114 bool first_value = true;
115 for (const auto &value : row) {
116 if (first_value) {
117 first_value = false;
118 } else {
119 *os << ", ";
120 }
121 *os << "{" << value.st << ", " << value.ed << "}";
122 }
123 *os << "}";
124 }
125 *os << "}}";
126}
127
Parker Schuh6691f192017-01-14 17:01:02 -0800128int RangeImage::npixels() {
129 if (npixelsc_ > 0) {
130 return npixelsc_;
131 }
132 npixelsc_ = calc_area();
133 return npixelsc_;
134}
135
136int RangeImage::calc_area() const {
137 int area = 0;
138 for (auto &range : ranges_) {
139 for (auto &interval : range) {
140 area += interval.calc_width();
141 }
142 }
143 return area;
144}
145
146} // namespace vision
147} // namespace aos