GCC Code Coverage Report


Directory: ./
File: tasks/badanov_a_select_edge_sobel/omp/src/ops_omp.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 51 51 100.0%
Functions: 8 8 100.0%
Branches: 17 20 85.0%

Line Branch Exec Source
1 #include "badanov_a_select_edge_sobel/omp/include/ops_omp.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <cstdint>
7 #include <vector>
8
9 #include "badanov_a_select_edge_sobel/common/include/common.hpp"
10
11 #ifdef _OPENMP
12 # include <omp.h>
13 #endif
14
15 namespace badanov_a_select_edge_sobel {
16
17
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 BadanovASelectEdgeSobelOMP::BadanovASelectEdgeSobelOMP(const InType &in) {
18 SetTypeOfTask(GetStaticTypeOfTask());
19
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 GetInput() = in;
20 40 GetOutput() = std::vector<uint8_t>();
21 40 }
22
23 40 bool BadanovASelectEdgeSobelOMP::ValidationImpl() {
24 const auto &input = GetInput();
25 40 return !input.empty();
26 }
27
28
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
40 bool BadanovASelectEdgeSobelOMP::PreProcessingImpl() {
29 const auto &input = GetInput();
30
31 40 width_ = static_cast<int>(std::sqrt(input.size()));
32 40 height_ = width_;
33
34
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
40 if (width_ * height_ != static_cast<int>(input.size())) {
35 12 width_ = static_cast<int>(input.size());
36 12 height_ = 1;
37 }
38
39 40 GetOutput() = std::vector<uint8_t>(input.size(), 0);
40
41 40 return true;
42 }
43
44 20 void BadanovASelectEdgeSobelOMP::ApplySobelOperator(const std::vector<uint8_t> &input, std::vector<float> &magnitude,
45 float &max_magnitude) {
46 20 max_magnitude = 0.0F;
47 20 const int height = height_;
48 20 const int width = width_;
49
50 20 #pragma omp parallel default(none) shared(input, magnitude, max_magnitude, height, width)
51 {
52 float local_max_magnitude = 0.0F;
53
54 #pragma omp for schedule(static)
55 for (int row = 1; row < height - 1; ++row) {
56 for (int col = 1; col < width - 1; ++col) {
57 float gradient_x = 0.0F;
58 float gradient_y = 0.0F;
59
60 ComputeGradientAtPixel(input, row, col, gradient_x, gradient_y);
61
62 const float magnitude_value = std::sqrt((gradient_x * gradient_x) + (gradient_y * gradient_y));
63 const size_t idx = (static_cast<size_t>(row) * static_cast<size_t>(width)) + static_cast<size_t>(col);
64 magnitude[idx] = magnitude_value;
65
66 local_max_magnitude = std::max(magnitude_value, local_max_magnitude);
67 }
68 }
69
70 #pragma omp critical
71 {
72 max_magnitude = std::max(local_max_magnitude, max_magnitude);
73 }
74 }
75 20 }
76
77 1872 void BadanovASelectEdgeSobelOMP::ComputeGradientAtPixel(const std::vector<uint8_t> &input, int row, int col,
78 float &gradient_x, float &gradient_y) const {
79 1872 gradient_x = 0.0F;
80 1872 gradient_y = 0.0F;
81
82
2/2
✓ Branch 0 taken 5616 times.
✓ Branch 1 taken 1872 times.
7488 for (int kernel_row = -1; kernel_row <= 1; ++kernel_row) {
83
2/2
✓ Branch 0 taken 16848 times.
✓ Branch 1 taken 5616 times.
22464 for (int kernel_col = -1; kernel_col <= 1; ++kernel_col) {
84 16848 const size_t pixel_index =
85 16848 (static_cast<size_t>(row + kernel_row) * static_cast<size_t>(width_)) + static_cast<size_t>(col + kernel_col);
86 16848 const uint8_t pixel = input[pixel_index];
87
88 16848 const int kx_idx = kernel_row + 1;
89 16848 const int ky_idx = kernel_col + 1;
90 16848 const int kernel_x_value = kKernelX.at(static_cast<size_t>(kx_idx)).at(static_cast<size_t>(ky_idx));
91 16848 const int kernel_y_value = kKernelY.at(static_cast<size_t>(kx_idx)).at(static_cast<size_t>(ky_idx));
92
93 16848 gradient_x += static_cast<float>(pixel) * static_cast<float>(kernel_x_value);
94 16848 gradient_y += static_cast<float>(pixel) * static_cast<float>(kernel_y_value);
95 }
96 }
97 1872 }
98
99 20 void BadanovASelectEdgeSobelOMP::ApplyThreshold(const std::vector<float> &magnitude, float max_magnitude,
100 std::vector<uint8_t> &output) const {
101
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 if (max_magnitude > 0.0F) {
102 16 const float scale = 255.0F / max_magnitude;
103 const size_t size = magnitude.size();
104 16 const int threshold = threshold_;
105
106 16 #pragma omp parallel for schedule(static) default(none) shared(magnitude, output, scale, size) firstprivate(threshold)
107 for (size_t i = 0; i < size; ++i) {
108 output[i] = (magnitude[i] * scale > static_cast<float>(threshold)) ? 255 : 0;
109 }
110 } else {
111 std::ranges::fill(output, 0);
112 }
113 20 }
114
115
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 bool BadanovASelectEdgeSobelOMP::RunImpl() {
116 const auto &input = GetInput();
117 auto &output = GetOutput();
118
119
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
40 if (height_ < 3 || width_ < 3) {
120 20 output = input;
121 20 return true;
122 }
123
124 20 std::vector<float> magnitude(input.size(), 0.0F);
125 20 float max_magnitude = 0.0F;
126
127 20 ApplySobelOperator(input, magnitude, max_magnitude);
128 20 ApplyThreshold(magnitude, max_magnitude, output);
129
130 return true;
131 }
132
133 40 bool BadanovASelectEdgeSobelOMP::PostProcessingImpl() {
134 40 return true;
135 }
136
137 } // namespace badanov_a_select_edge_sobel
138