blob: 92f77cceac295711a19fc348221b20f352d89f6b [file] [log] [blame]
Parker Schuh6691f192017-01-14 17:01:02 -08001#include "aos/vision/blob/range_image.h"
2
Parker Schuh6691f192017-01-14 17:01:02 -08003#include <algorithm>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07004#include <cmath>
Parker Schuh6691f192017-01-14 17:01:02 -08005
Stephan Pleinesf63bde82024-01-13 15:59:33 -08006namespace aos::vision {
Brian Silverman93897f32019-03-10 16:19:19 -07007namespace {
Parker Schuh6691f192017-01-14 17:01:02 -08008
Brian Silverman93897f32019-03-10 16:19:19 -07009// Merge sort of multiple range images into a single range image.
10// They must not overlap.
Parker Schuh6691f192017-01-14 17:01:02 -080011RangeImage MergeRangeImage(const BlobList &blobl) {
12 if (blobl.size() == 1) return blobl[0];
13
14 int min_y = blobl[0].min_y();
15 for (const RangeImage &subrimg : blobl) {
16 if (min_y > subrimg.min_y()) min_y = subrimg.min_y();
17 }
18 std::vector<std::vector<ImageRange>> ranges;
19 int i = min_y;
20 while (true) {
21 std::vector<ImageRange> range_lst;
22 int n_missing = 0;
23 for (const RangeImage &subrimg : blobl) {
24 if (subrimg.min_y() > i) continue;
25 int ri = i - subrimg.min_y();
26 if (ri < (int)subrimg.ranges().size()) {
27 for (const auto &span : subrimg.ranges()[ri]) {
28 range_lst.emplace_back(span);
29 }
30 } else {
31 ++n_missing;
32 }
33 }
34 std::sort(range_lst.begin(), range_lst.end());
35 ranges.emplace_back(std::move(range_lst));
36 if (n_missing == static_cast<int>(blobl.size()))
37 return RangeImage(min_y, std::move(ranges));
38 ++i;
39 }
40}
41
Brian Silverman93897f32019-03-10 16:19:19 -070042} // namespace
43
Parker Schuh6691f192017-01-14 17:01:02 -080044std::string ShortDebugPrint(const BlobList &blobl) {
45 RangeImage rimg = MergeRangeImage(blobl);
46 std::string out;
47 out += "{";
48 out += "min_y: " + std::to_string(rimg.min_y());
49 for (const auto &line : rimg) {
50 out += "{";
51 for (const auto &span : line) {
52 out +=
53 "{" + std::to_string(span.st) + ", " + std::to_string(span.ed) + "},";
54 }
55 out += "},";
56 }
57 out += "}";
58 return out;
59}
60
61void DebugPrint(const BlobList &blobl) {
62 RangeImage rimg = MergeRangeImage(blobl);
63 int minx = rimg.ranges()[0][0].st;
64 int maxx = 0;
Austin Schuh335eef12019-03-02 17:04:17 -080065 for (const std::vector<ImageRange> &range : rimg.ranges()) {
66 for (const ImageRange &span : range) {
Parker Schuh6691f192017-01-14 17:01:02 -080067 if (span.st < minx) minx = span.st;
68 if (span.ed > maxx) maxx = span.ed;
69 }
70 }
Parker Schuh309dd722017-02-25 11:31:18 -080071 printf("maxx: %d minx: %d\n", maxx, minx);
Parker Schuh6691f192017-01-14 17:01:02 -080072 char buf[maxx - minx];
Austin Schuh335eef12019-03-02 17:04:17 -080073 for (const std::vector<ImageRange> &range : rimg.ranges()) {
Parker Schuh6691f192017-01-14 17:01:02 -080074 int i = minx;
Austin Schuh335eef12019-03-02 17:04:17 -080075 for (const ImageRange &span : range) {
Parker Schuh6691f192017-01-14 17:01:02 -080076 for (; i < span.st; ++i) buf[i - minx] = ' ';
77 for (; i < span.ed; ++i) buf[i - minx] = '#';
78 }
79 for (; i < maxx; ++i) buf[i - minx] = ' ';
Parker Schuh309dd722017-02-25 11:31:18 -080080 printf("%.*s\n", maxx - minx, buf);
Parker Schuh6691f192017-01-14 17:01:02 -080081 }
82}
83
Brian Silverman5eec8b92019-03-10 15:14:31 -070084void PrintTo(const ImageRange &range, std::ostream *os) {
85 *os << "{" << range.st << ", " << range.ed << "}";
86}
87
Parker Schuh6691f192017-01-14 17:01:02 -080088void RangeImage::Flip(int image_width, int image_height) {
89 std::reverse(ranges_.begin(), ranges_.end());
90 for (std::vector<ImageRange> &range : ranges_) {
91 std::reverse(range.begin(), range.end());
92 for (ImageRange &interval : range) {
93 int tmp = image_width - interval.ed;
94 interval.ed = image_width - interval.st;
95 interval.st = tmp;
96 }
97 }
98
99 min_y_ = image_height - static_cast<int>(ranges_.size()) - min_y_;
100}
101
Brian Silverman5eec8b92019-03-10 15:14:31 -0700102void PrintTo(const RangeImage &range, std::ostream *os) {
Tyler Chatowbf0609c2021-07-31 16:13:27 -0700103 *os << "{min_y=" << range.min_y() << ", ranges={";
Brian Silverman5eec8b92019-03-10 15:14:31 -0700104 bool first_row = true;
105 for (const auto &row : range) {
106 if (first_row) {
107 first_row = false;
108 } else {
109 *os << ", ";
110 }
111 *os << "{";
112 bool first_value = true;
113 for (const auto &value : row) {
114 if (first_value) {
115 first_value = false;
116 } else {
117 *os << ", ";
118 }
119 *os << "{" << value.st << ", " << value.ed << "}";
120 }
121 *os << "}";
122 }
123 *os << "}}";
124}
125
Parker Schuh6691f192017-01-14 17:01:02 -0800126int RangeImage::npixels() {
127 if (npixelsc_ > 0) {
128 return npixelsc_;
129 }
130 npixelsc_ = calc_area();
131 return npixelsc_;
132}
133
134int RangeImage::calc_area() const {
135 int area = 0;
136 for (auto &range : ranges_) {
137 for (auto &interval : range) {
138 area += interval.calc_width();
139 }
140 }
141 return area;
142}
143
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800144} // namespace aos::vision