| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "dorogin_v_bin_img_conv_hull_OMP/omp/include/ops_omp.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <array> | ||
| 5 | #include <cstddef> | ||
| 6 | #include <cstdint> | ||
| 7 | #include <ranges> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "dorogin_v_bin_img_conv_hull_OMP/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace dorogin_v_bin_img_conv_hull_omp { | ||
| 14 | |||
| 15 | namespace { | ||
| 16 | |||
| 17 | std::size_t Index(int x, int y, int w) { | ||
| 18 |
4/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 344 times.
✓ Branch 3 taken 496 times.
|
1392 | return (static_cast<std::size_t>(y) * static_cast<std::size_t>(w)) + static_cast<std::size_t>(x); |
| 19 | } | ||
| 20 | |||
| 21 | bool Inside(int x, int y, int w, int h) { | ||
| 22 | 1716 | return (x >= 0) && (y >= 0) && (x < w) && (y < h); | |
| 23 | } | ||
| 24 | |||
| 25 | 20 | ComponentHull CollectOneComponent(const BinaryImage &img, std::vector<std::uint8_t> &visited, int w, int h, int start_x, | |
| 26 | int start_y, const std::array<int, 8> &dx, const std::array<int, 8> &dy) { | ||
| 27 | 20 | ComponentHull pixels; | |
| 28 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | pixels.reserve(64); |
| 29 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | std::vector<Point> stack; |
| 30 | const std::size_t start_id = Index(start_x, start_y, w); | ||
| 31 | 20 | visited[start_id] = 1U; | |
| 32 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | stack.push_back(Point{.x = start_x, .y = start_y}); |
| 33 | |||
| 34 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 20 times.
|
128 | while (!stack.empty()) { |
| 35 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | const Point p = stack.back(); |
| 36 | stack.pop_back(); | ||
| 37 | pixels.push_back(p); | ||
| 38 | |||
| 39 |
2/2✓ Branch 0 taken 864 times.
✓ Branch 1 taken 108 times.
|
972 | for (int dir = 0; dir < 8; ++dir) { |
| 40 | 864 | const int nx = p.x + dx.at(static_cast<std::size_t>(dir)); | |
| 41 |
2/2✓ Branch 0 taken 852 times.
✓ Branch 1 taken 12 times.
|
864 | const int ny = p.y + dy.at(static_cast<std::size_t>(dir)); |
| 42 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 840 times.
|
852 | if (!Inside(nx, ny, w, h)) { |
| 43 | 24 | continue; | |
| 44 | } | ||
| 45 | const std::size_t nid = Index(nx, ny, w); | ||
| 46 |
4/4✓ Branch 0 taken 344 times.
✓ Branch 1 taken 496 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 256 times.
|
840 | if (img.data[nid] == 0 || visited[nid] != 0U) { |
| 47 | 752 | continue; | |
| 48 | } | ||
| 49 | 88 | visited[nid] = 1U; | |
| 50 |
1/4✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
88 | stack.push_back(Point{.x = nx, .y = ny}); |
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | 20 | return pixels; | |
| 55 | } | ||
| 56 | |||
| 57 | 20 | std::vector<ComponentHull> CollectComponents(const BinaryImage &img) { | |
| 58 | 20 | const int w = img.width; | |
| 59 | 20 | const int h = img.height; | |
| 60 | 20 | const std::size_t n = static_cast<std::size_t>(w) * static_cast<std::size_t>(h); | |
| 61 | |||
| 62 | 20 | std::vector<std::uint8_t> visited(n, 0U); | |
| 63 | 20 | std::vector<ComponentHull> components; | |
| 64 | |||
| 65 | 20 | const std::array<int, 8> dx = {1, 1, 0, -1, -1, -1, 0, 1}; | |
| 66 | 20 | const std::array<int, 8> dy = {0, 1, 1, 1, 0, -1, -1, -1}; | |
| 67 | |||
| 68 |
2/2✓ Branch 0 taken 92 times.
✓ Branch 1 taken 20 times.
|
112 | for (int yy = 0; yy < h; ++yy) { |
| 69 |
2/2✓ Branch 0 taken 552 times.
✓ Branch 1 taken 92 times.
|
644 | for (int xx = 0; xx < w; ++xx) { |
| 70 | const std::size_t id = Index(xx, yy, w); | ||
| 71 |
4/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 20 times.
|
552 | if (img.data[id] == 0 || visited[id] != 0U) { |
| 72 | 532 | continue; | |
| 73 | } | ||
| 74 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | ComponentHull pixels = CollectOneComponent(img, visited, w, h, xx, yy, dx, dy); |
| 75 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | if (!pixels.empty()) { |
| 76 | components.push_back(std::move(pixels)); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | 20 | return components; | |
| 82 | ✗ | } | |
| 83 | |||
| 84 | std::int64_t Cross(const Point &o, const Point &a, const Point &b) { | ||
| 85 | 184 | const std::int64_t x1 = static_cast<std::int64_t>(a.x) - static_cast<std::int64_t>(o.x); | |
| 86 | 184 | const std::int64_t y1 = static_cast<std::int64_t>(a.y) - static_cast<std::int64_t>(o.y); | |
| 87 | 184 | const std::int64_t x2 = static_cast<std::int64_t>(b.x) - static_cast<std::int64_t>(o.x); | |
| 88 | 184 | const std::int64_t y2 = static_cast<std::int64_t>(b.y) - static_cast<std::int64_t>(o.y); | |
| 89 | 184 | return (x1 * y2) - (y1 * x2); | |
| 90 | } | ||
| 91 | |||
| 92 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
|
20 | ComponentHull BuildHull(ComponentHull pts) { |
| 93 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
|
20 | if (pts.size() <= 1) { |
| 94 | return pts; | ||
| 95 | } | ||
| 96 | |||
| 97 | std::ranges::sort(pts, [](const Point &a, const Point &b) { | ||
| 98 |
4/26✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 56 times.
✓ Branch 23 taken 32 times.
✓ Branch 24 taken 100 times.
✓ Branch 25 taken 76 times.
|
264 | if (a.x != b.x) { |
| 99 | 156 | return a.x < b.x; | |
| 100 | } | ||
| 101 | 108 | return a.y < b.y; | |
| 102 | }); | ||
| 103 | const auto uniq_result = | ||
| 104 |
3/8✓ Branch 0 taken 60 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
88 | std::ranges::unique(pts, [](const Point &a, const Point &b) { return (a.x == b.x) && (a.y == b.y); }); |
| 105 | pts.erase(uniq_result.end(), pts.end()); | ||
| 106 | |||
| 107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (pts.size() <= 1) { |
| 108 | return pts; | ||
| 109 | } | ||
| 110 | |||
| 111 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ComponentHull lower; |
| 112 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lower.reserve(pts.size()); |
| 113 |
2/2✓ Branch 0 taken 104 times.
✓ Branch 1 taken 16 times.
|
120 | for (const auto &p : pts) { |
| 114 |
4/4✓ Branch 0 taken 92 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 28 times.
|
168 | while (lower.size() >= 2 && Cross(lower[lower.size() - 2], lower[lower.size() - 1], p) <= 0) { |
| 115 | lower.pop_back(); | ||
| 116 | } | ||
| 117 | lower.push_back(p); | ||
| 118 | } | ||
| 119 | |||
| 120 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ComponentHull upper; |
| 121 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | upper.reserve(pts.size()); |
| 122 |
2/2✓ Branch 0 taken 104 times.
✓ Branch 1 taken 16 times.
|
120 | for (std::size_t i = pts.size(); i-- > 0;) { |
| 123 | const Point &p = pts[i]; | ||
| 124 |
4/4✓ Branch 0 taken 92 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 64 times.
|
168 | while (upper.size() >= 2 && Cross(upper[upper.size() - 2], upper[upper.size() - 1], p) <= 0) { |
| 125 | upper.pop_back(); | ||
| 126 | } | ||
| 127 | upper.push_back(p); | ||
| 128 | } | ||
| 129 | |||
| 130 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!lower.empty()) { |
| 131 | lower.pop_back(); | ||
| 132 | } | ||
| 133 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!upper.empty()) { |
| 134 | upper.pop_back(); | ||
| 135 | } | ||
| 136 | |||
| 137 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | lower.insert(lower.end(), upper.begin(), upper.end()); |
| 138 | return lower; | ||
| 139 | } | ||
| 140 | |||
| 141 | } // namespace | ||
| 142 | |||
| 143 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | DoroginVBinImgConvHullOMP::DoroginVBinImgConvHullOMP(const InType &in) { |
| 144 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 145 | GetInput() = in; | ||
| 146 | GetOutput().clear(); | ||
| 147 | 20 | } | |
| 148 | |||
| 149 | 40 | bool DoroginVBinImgConvHullOMP::ValidationImpl() { | |
| 150 | const auto &img = GetInput(); | ||
| 151 |
2/4✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
|
40 | if (img.width <= 0 || img.height <= 0) { |
| 152 | return false; | ||
| 153 | } | ||
| 154 | 40 | const std::size_t required = static_cast<std::size_t>(img.width) * static_cast<std::size_t>(img.height); | |
| 155 | 40 | return img.data.size() == required; | |
| 156 | } | ||
| 157 | |||
| 158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | bool DoroginVBinImgConvHullOMP::PreProcessingImpl() { |
| 159 | GetOutput().clear(); | ||
| 160 | 20 | return true; | |
| 161 | } | ||
| 162 | |||
| 163 | 20 | bool DoroginVBinImgConvHullOMP::RunImpl() { | |
| 164 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | if (!ValidationImpl()) { |
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 168 | 20 | auto components = CollectComponents(GetInput()); | |
| 169 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | OutType hulls; |
| 170 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | hulls.resize(components.size()); |
| 171 | |||
| 172 | 20 | const int count = static_cast<int>(components.size()); | |
| 173 | |||
| 174 | 20 | #pragma omp parallel for default(none) shared(components, hulls, count) | |
| 175 | for (int i = 0; i < count; ++i) { | ||
| 176 | const auto idx = static_cast<std::size_t>(i); | ||
| 177 | hulls[idx] = BuildHull(std::move(components[idx])); | ||
| 178 | } | ||
| 179 | |||
| 180 | 20 | GetOutput() = std::move(hulls); | |
| 181 | return true; | ||
| 182 | 20 | } | |
| 183 | |||
| 184 | 20 | bool DoroginVBinImgConvHullOMP::PostProcessingImpl() { | |
| 185 | 20 | return true; | |
| 186 | } | ||
| 187 | |||
| 188 | } // namespace dorogin_v_bin_img_conv_hull_omp | ||
| 189 |