blob: 36dcafef329ed1ca8c399506caf8afb51b13c81a [file] [log] [blame]
Brian Silverman37b15b32019-03-10 13:30:18 -07001#include "aos/vision/blob/threshold.h"
2
Brian Silverman4482db52019-03-10 16:14:48 -07003#include "aos/logging/logging.h"
4
Brian Silverman37b15b32019-03-10 13:30:18 -07005namespace aos {
6namespace vision {
Brian Silvermanefde9522019-03-23 22:02:40 -07007namespace {
Brian Silverman37b15b32019-03-10 13:30:18 -07008
Brian Silvermanefde9522019-03-23 22:02:40 -07009constexpr int kChunkSize = 8;
10
11} // namespace
Brian Silverman37b15b32019-03-10 13:30:18 -070012
Brian Silverman4482db52019-03-10 16:14:48 -070013// At a high level, the algorithm is the same as the slow thresholding, except
Brian Silvermanefde9522019-03-23 22:02:40 -070014// it operates in kChunkSize-pixel chunks.
Brian Silverman37b15b32019-03-10 13:30:18 -070015RangeImage FastYuyvYThreshold(ImageFormat fmt, const char *data,
16 uint8_t value) {
Brian Silvermanefde9522019-03-23 22:02:40 -070017 CHECK_EQ(0, fmt.w % kChunkSize);
Brian Silverman4482db52019-03-10 16:14:48 -070018 std::vector<std::vector<ImageRange>> result;
19 result.reserve(fmt.h);
20
21 // Iterate through each row.
Brian Silverman37b15b32019-03-10 13:30:18 -070022 for (int y = 0; y < fmt.h; ++y) {
Brian Silverman4482db52019-03-10 16:14:48 -070023 // The start of the data for the current row.
24 const char *const current_row = fmt.w * y * 2 + data;
25 bool in_range = false;
26 int current_range_start = -1;
27 std::vector<ImageRange> current_row_ranges;
Brian Silvermanefde9522019-03-23 22:02:40 -070028 // Iterate through each kChunkSize-pixel chunk
29 for (int x = 0; x < fmt.w / kChunkSize; ++x) {
Brian Silverman4482db52019-03-10 16:14:48 -070030 // The per-channel (YUYV) values in the current chunk.
Brian Silvermanefde9522019-03-23 22:02:40 -070031 uint8_t chunk_channels[2 * kChunkSize];
32 memcpy(&chunk_channels[0], current_row + x * kChunkSize * 2, 2 * kChunkSize);
33
34 for (int i = 0; i < kChunkSize; ++i) {
35 if ((chunk_channels[i * 2] > value) != in_range) {
36 const int here = x * kChunkSize + i;
37 if (in_range) {
38 current_row_ranges.emplace_back(ImageRange(current_range_start, here));
39 } else {
40 current_range_start = here;
41 }
42 in_range = !in_range;
43 }
Brian Silverman37b15b32019-03-10 13:30:18 -070044 }
Brian Silverman37b15b32019-03-10 13:30:18 -070045 }
Brian Silverman4482db52019-03-10 16:14:48 -070046 if (in_range) {
47 current_row_ranges.emplace_back(ImageRange(current_range_start, fmt.w));
Brian Silverman37b15b32019-03-10 13:30:18 -070048 }
Brian Silverman4482db52019-03-10 16:14:48 -070049 result.push_back(current_row_ranges);
Brian Silverman37b15b32019-03-10 13:30:18 -070050 }
Brian Silverman4482db52019-03-10 16:14:48 -070051 return RangeImage(0, std::move(result));
Brian Silverman37b15b32019-03-10 13:30:18 -070052}
53
Brian Silverman37b15b32019-03-10 13:30:18 -070054} // namespace vision
55} // namespace aos