blob: 4fc58eb273cd2e8b96e8d4e7270d77bf408daf76 [file] [log] [blame]
Brian Silverman37b15b32019-03-10 13:30:18 -07001#include "aos/vision/blob/threshold.h"
2
3namespace aos {
4namespace vision {
5
6#define MASH(v0, v1, v2, v3, v4) \
7 ((uint8_t(v0) << 4) | (uint8_t(v1) << 3) | (uint8_t(v2) << 2) | \
8 (uint8_t(v3) << 1) | (uint8_t(v4)))
9
10RangeImage FastYuyvYThreshold(ImageFormat fmt, const char *data,
11 uint8_t value) {
12 std::vector<std::vector<ImageRange>> ranges;
13 ranges.reserve(fmt.h);
14 for (int y = 0; y < fmt.h; ++y) {
15 const char *row = fmt.w * y * 2 + data;
16 bool p_score = false;
17 int pstart = -1;
18 std::vector<ImageRange> rngs;
19 for (int x = 0; x < fmt.w / 4; ++x) {
20 uint8_t v[8];
21 memcpy(&v[0], row + x * 4 * 2, 8);
22 uint8_t pattern =
23 MASH(p_score, v[0] > value, v[2] > value, v[4] > value, v[6] > value);
24 switch (pattern) {
25 /*
26# Ruby code to generate the below code:
2732.times do |v|
28 puts "case MASH(#{[v[4], v[3], v[2], v[1], v[0]].join(", ")}):"
29 p_score = v[4]
30 pstart = "pstart"
31 4.times do |i|
32 if v[3 - i] != p_score
33 if (p_score == 1)
34 puts " rngs.emplace_back(ImageRange(#{pstart},
35x * 4 + #{i}));"
36 else
37 pstart = "x * 4 + #{i}"
38 end
39 p_score = v[3 - i]
40 end
41 end
42 if (pstart != "pstart")
43 puts " pstart = #{pstart};"
44 end
45 if (p_score != v[4])
46 puts " p_score = #{["false", "true"][v[0]]};"
47 end
48 puts " break;"
49end
50*/
51 case MASH(0, 0, 0, 0, 0):
52 break;
53 case MASH(0, 0, 0, 0, 1):
54 pstart = x * 4 + 3;
55 p_score = true;
56 break;
57 case MASH(0, 0, 0, 1, 0):
58 rngs.emplace_back(ImageRange(x * 4 + 2, x * 4 + 3));
59 pstart = x * 4 + 2;
60 break;
61 case MASH(0, 0, 0, 1, 1):
62 pstart = x * 4 + 2;
63 p_score = true;
64 break;
65 case MASH(0, 0, 1, 0, 0):
66 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 2));
67 pstart = x * 4 + 1;
68 break;
69 case MASH(0, 0, 1, 0, 1):
70 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 2));
71 pstart = x * 4 + 3;
72 p_score = true;
73 break;
74 case MASH(0, 0, 1, 1, 0):
75 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 3));
76 pstart = x * 4 + 1;
77 break;
78 case MASH(0, 0, 1, 1, 1):
79 pstart = x * 4 + 1;
80 p_score = true;
81 break;
82 case MASH(0, 1, 0, 0, 0):
83 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 1));
84 pstart = x * 4 + 0;
85 break;
86 case MASH(0, 1, 0, 0, 1):
87 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 1));
88 pstart = x * 4 + 3;
89 p_score = true;
90 break;
91 case MASH(0, 1, 0, 1, 0):
92 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 1));
93 rngs.emplace_back(ImageRange(x * 4 + 2, x * 4 + 3));
94 pstart = x * 4 + 2;
95 break;
96 case MASH(0, 1, 0, 1, 1):
97 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 1));
98 pstart = x * 4 + 2;
99 p_score = true;
100 break;
101 case MASH(0, 1, 1, 0, 0):
102 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 2));
103 pstart = x * 4 + 0;
104 break;
105 case MASH(0, 1, 1, 0, 1):
106 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 2));
107 pstart = x * 4 + 3;
108 p_score = true;
109 break;
110 case MASH(0, 1, 1, 1, 0):
111 rngs.emplace_back(ImageRange(x * 4 + 0, x * 4 + 3));
112 pstart = x * 4 + 0;
113 break;
114 case MASH(0, 1, 1, 1, 1):
115 pstart = x * 4 + 0;
116 p_score = true;
117 break;
118 case MASH(1, 0, 0, 0, 0):
119 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
120 p_score = false;
121 break;
122 case MASH(1, 0, 0, 0, 1):
123 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
124 pstart = x * 4 + 3;
125 break;
126 case MASH(1, 0, 0, 1, 0):
127 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
128 rngs.emplace_back(ImageRange(x * 4 + 2, x * 4 + 3));
129 pstart = x * 4 + 2;
130 p_score = false;
131 break;
132 case MASH(1, 0, 0, 1, 1):
133 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
134 pstart = x * 4 + 2;
135 break;
136 case MASH(1, 0, 1, 0, 0):
137 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
138 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 2));
139 pstart = x * 4 + 1;
140 p_score = false;
141 break;
142 case MASH(1, 0, 1, 0, 1):
143 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
144 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 2));
145 pstart = x * 4 + 3;
146 break;
147 case MASH(1, 0, 1, 1, 0):
148 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
149 rngs.emplace_back(ImageRange(x * 4 + 1, x * 4 + 3));
150 pstart = x * 4 + 1;
151 p_score = false;
152 break;
153 case MASH(1, 0, 1, 1, 1):
154 rngs.emplace_back(ImageRange(pstart, x * 4 + 0));
155 pstart = x * 4 + 1;
156 break;
157 case MASH(1, 1, 0, 0, 0):
158 rngs.emplace_back(ImageRange(pstart, x * 4 + 1));
159 p_score = false;
160 break;
161 case MASH(1, 1, 0, 0, 1):
162 rngs.emplace_back(ImageRange(pstart, x * 4 + 1));
163 pstart = x * 4 + 3;
164 break;
165 case MASH(1, 1, 0, 1, 0):
166 rngs.emplace_back(ImageRange(pstart, x * 4 + 1));
167 rngs.emplace_back(ImageRange(x * 4 + 2, x * 4 + 3));
168 pstart = x * 4 + 2;
169 p_score = false;
170 break;
171 case MASH(1, 1, 0, 1, 1):
172 rngs.emplace_back(ImageRange(pstart, x * 4 + 1));
173 pstart = x * 4 + 2;
174 break;
175 case MASH(1, 1, 1, 0, 0):
176 rngs.emplace_back(ImageRange(pstart, x * 4 + 2));
177 p_score = false;
178 break;
179 case MASH(1, 1, 1, 0, 1):
180 rngs.emplace_back(ImageRange(pstart, x * 4 + 2));
181 pstart = x * 4 + 3;
182 break;
183 case MASH(1, 1, 1, 1, 0):
184 rngs.emplace_back(ImageRange(pstart, x * 4 + 3));
185 p_score = false;
186 break;
187 case MASH(1, 1, 1, 1, 1):
188 break;
189 }
190
191 for (int i = 0; i < 4; ++i) {
192 if ((v[i * 2] > value) != p_score) {
193 if (p_score) {
194 rngs.emplace_back(ImageRange(pstart, x * 4 + i));
195 } else {
196 pstart = x * 4 + i;
197 }
198 p_score = !p_score;
199 }
200 }
201 }
202 if (p_score) {
203 rngs.emplace_back(ImageRange(pstart, fmt.w));
204 }
205 ranges.push_back(rngs);
206 }
207 return RangeImage(0, std::move(ranges));
208}
209
210#undef MASH
211
212} // namespace vision
213} // namespace aos