GCC Code Coverage Report


Directory: ./
File: tasks/paramonov_v_bin_img_conv_hul_omp/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 67 71 94.4%
Functions: 10 12 83.3%
Branches: 51 68 75.0%

Line Branch Exec Source
1 #include "paramonov_v_bin_img_conv_hul_omp/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstddef>
8 #include <cstdint>
9 #include <iterator>
10 #include <stack>
11 #include <utility>
12 #include <vector>
13
14 #include "paramonov_v_bin_img_conv_hul_omp/common/include/common.hpp"
15
16 namespace paramonov_v_bin_img_conv_hul_omp {
17
18 namespace {
19 constexpr std::array<std::pair<int, int>, 4> kNeighbors = {{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}};
20
21 252 bool ComparePoints(const PixelPoint &a, const PixelPoint &b) {
22
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 68 times.
252 if (a.row != b.row) {
23 184 return a.row < b.row;
24 }
25 68 return a.col < b.col;
26 }
27
28 } // namespace
29
30
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 ConvexHullOMP::ConvexHullOMP(const InputType &input) {
31 SetTypeOfTask(GetStaticTypeOfTask());
32 GetInput() = input;
33 32 }
34
35 32 bool ConvexHullOMP::ValidationImpl() {
36 const auto &img = GetInput();
37
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 if (img.rows <= 0 || img.cols <= 0) {
38 return false;
39 }
40
41 32 const size_t expected_size = static_cast<size_t>(img.rows) * static_cast<size_t>(img.cols);
42 32 return img.pixels.size() == expected_size;
43 }
44
45 32 bool ConvexHullOMP::PreProcessingImpl() {
46 working_image_ = GetInput();
47 BinarizeImage();
48 GetOutput().clear();
49 32 return true;
50 }
51
52 32 bool ConvexHullOMP::RunImpl() {
53 32 ExtractConnectedComponents();
54 32 return true;
55 }
56
57 32 bool ConvexHullOMP::PostProcessingImpl() {
58 32 return true;
59 }
60
61 void ConvexHullOMP::BinarizeImage(uint8_t threshold) {
62 const size_t size = working_image_.pixels.size();
63 auto &pixels = working_image_.pixels;
64
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 #pragma omp parallel for default(none) shared(pixels, threshold, size)
66 for (size_t i = 0; i < size; ++i) {
67 pixels[i] = pixels[i] > threshold ? uint8_t{255} : uint8_t{0};
68 }
69 }
70
71 44 void ConvexHullOMP::FloodFill(int start_row, int start_col, std::vector<bool> &visited,
72 std::vector<PixelPoint> &component) const {
73 std::stack<PixelPoint> pixel_stack;
74 pixel_stack.emplace(start_row, start_col);
75
76 44 const int rows = working_image_.rows;
77 44 const int cols = working_image_.cols;
78
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 visited[PixelIndex(start_row, start_col, cols)] = true;
80
81
2/2
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 44 times.
340 while (!pixel_stack.empty()) {
82
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 PixelPoint current = pixel_stack.top();
83 pixel_stack.pop();
84
85 component.push_back(current);
86
87
2/2
✓ Branch 0 taken 1184 times.
✓ Branch 1 taken 296 times.
1480 for (const auto &[dr, dc] : kNeighbors) {
88 1184 int next_row = current.row + dr;
89 1184 int next_col = current.col + dc;
90
91
4/8
✓ Branch 0 taken 1184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1184 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1184 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1184 times.
✗ Branch 7 not taken.
1184 if (next_row >= 0 && next_row < rows && next_col >= 0 && next_col < cols) {
92 size_t idx = PixelIndex(next_row, next_col, cols);
93
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 484 times.
✓ Branch 2 taken 252 times.
✓ Branch 3 taken 448 times.
1184 if (!visited[idx] && working_image_.pixels[idx] == 255) {
94 visited[idx] = true;
95 pixel_stack.emplace(next_row, next_col);
96 }
97 }
98 }
99 }
100 44 }
101
102 32 void ConvexHullOMP::ExtractConnectedComponents() {
103 32 const int rows = working_image_.rows;
104 32 const int cols = working_image_.cols;
105 32 const size_t total_pixels = static_cast<size_t>(rows) * static_cast<size_t>(cols);
106
107 32 std::vector<bool> visited(total_pixels, false);
108 auto &output_hulls = GetOutput();
109
110
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 32 times.
400 for (int row = 0; row < rows; ++row) {
111
2/2
✓ Branch 0 taken 6048 times.
✓ Branch 1 taken 368 times.
6416 for (int col = 0; col < cols; ++col) {
112 size_t idx = PixelIndex(row, col, cols);
113
114
4/4
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 5752 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 252 times.
6048 if (working_image_.pixels[idx] == 255 && !visited[idx]) {
115 44 std::vector<PixelPoint> component;
116
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 FloodFill(row, col, visited, component);
117
118
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (!component.empty()) {
119
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 std::vector<PixelPoint> hull = ComputeConvexHull(component);
120 output_hulls.push_back(std::move(hull));
121 }
122 }
123 }
124 }
125 32 }
126
127 int64_t ConvexHullOMP::Orientation(const PixelPoint &p, const PixelPoint &q, const PixelPoint &r) {
128 972 return (static_cast<int64_t>(q.col - p.col) * (r.row - p.row)) -
129 972 (static_cast<int64_t>(q.row - p.row) * (r.col - p.col));
130 }
131
132
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 32 times.
44 std::vector<PixelPoint> ConvexHullOMP::ComputeConvexHull(const std::vector<PixelPoint> &points) {
133
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 32 times.
44 if (points.size() <= 2) {
134 12 return points;
135 }
136
137 32 auto lowest_point = *std::ranges::min_element(points, ComparePoints);
138
139
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 std::vector<PixelPoint> sorted_points;
140
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 sorted_points.reserve(points.size() - 1);
141 32 std::ranges::copy_if(points, std::back_inserter(sorted_points), [&lowest_point](const PixelPoint &p) {
142
4/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 32 times.
284 return (p.row != lowest_point.row) || (p.col != lowest_point.col);
143 });
144
145 632 std::ranges::sort(sorted_points, [&lowest_point](const PixelPoint &a, const PixelPoint &b) {
146 632 int64_t orient = Orientation(lowest_point, a, b);
147
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 464 times.
632 if (orient == 0) {
148 168 int64_t dist_a = ((a.row - lowest_point.row) * (a.row - lowest_point.row)) +
149 168 ((a.col - lowest_point.col) * (a.col - lowest_point.col));
150 168 int64_t dist_b = ((b.row - lowest_point.row) * (b.row - lowest_point.row)) +
151 168 ((b.col - lowest_point.col) * (b.col - lowest_point.col));
152 168 return dist_a < dist_b;
153 }
154 464 return orient > 0;
155 });
156
157
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 std::vector<PixelPoint> hull;
158
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 hull.reserve(points.size());
159 hull.push_back(lowest_point);
160
161
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 32 times.
284 for (const auto &p : sorted_points) {
162
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 84 times.
424 while (hull.size() >= 2) {
163 const auto &a = hull[hull.size() - 2];
164 const auto &b = hull.back();
165
166
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 168 times.
340 if (Orientation(a, b, p) <= 0) {
167 hull.pop_back();
168 } else {
169 break;
170 }
171 }
172 hull.push_back(p);
173 }
174
175 return hull;
176 }
177
178 } // namespace paramonov_v_bin_img_conv_hul_omp
179