• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 17402643318

02 Sep 2025 11:53AM UTC coverage: 71.394% (-0.3%) from 71.68%
17402643318

push

github

paulmthompson
remove unnecessary files

31766 of 44494 relevant lines covered (71.39%)

1386.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.61
/src/DataManager/Media/OpenCVImageProcessor.cpp
1
#include "OpenCVImageProcessor.hpp"
2
#include <opencv2/opencv.hpp>
3
#include <memory>
4
#include <cstring>
5

6
namespace ImageProcessing {
7

8
ImageData OpenCVImageProcessor::processImage(ImageData const& input_data, ImageSize const& image_size) {
×
9
    if (_processing_steps.empty()) {
×
10
        return input_data;  // Return unmodified data if no processing needed
×
11
    }
12

13
    // Convert to internal format (cv::Mat)
14
    std::unique_ptr<cv::Mat> mat_ptr(static_cast<cv::Mat*>(convertFromRaw(input_data, image_size)));
×
15
    
16
    if (!mat_ptr || mat_ptr->empty()) {
×
17
        return input_data;  // Return original data if conversion failed
×
18
    }
19

20
    // Apply all processing steps
21
    for (auto const& [key, process] : _processing_steps) {
×
22
        process(mat_ptr.get());
×
23
    }
24

25
    // Convert back to the same format as input
26
    size_t output_type = input_data.index();  // 0 for uint8_t, 1 for float
×
27
    return convertToRaw(mat_ptr.get(), image_size, output_type);
×
28
}
×
29

30
void OpenCVImageProcessor::addProcessingStep(std::string const& key, 
×
31
                                           std::function<void(void*)> processor) {
32
    _processing_steps[key] = std::move(processor);
×
33
}
×
34

35
void OpenCVImageProcessor::addOpenCVProcessingStep(std::string const& key, 
×
36
                                                 std::function<void(cv::Mat&)> processor) {
37
    // Wrap the cv::Mat& processor to work with void*
38
    auto wrapped_processor = [processor](void* mat_ptr) {
×
39
        auto* mat = static_cast<cv::Mat*>(mat_ptr);
×
40
        processor(*mat);
×
41
    };
×
42
    _processing_steps[key] = std::move(wrapped_processor);
×
43
}
×
44

45
void OpenCVImageProcessor::removeProcessingStep(std::string const& key) {
×
46
    _processing_steps.erase(key);
×
47
}
×
48

49
void OpenCVImageProcessor::clearProcessingSteps() {
×
50
    _processing_steps.clear();
×
51
}
×
52

53
bool OpenCVImageProcessor::hasProcessingStep(std::string const& key) const {
×
54
    return _processing_steps.find(key) != _processing_steps.end();
×
55
}
56

57
size_t OpenCVImageProcessor::getProcessingStepCount() const {
1✔
58
    return _processing_steps.size();
1✔
59
}
60

61
void* OpenCVImageProcessor::convertFromRaw(ImageData const& data, ImageSize const& size) {
×
62
    return std::visit([&size](auto const& vec) -> void* {
×
63
        using T = typename std::decay_t<decltype(vec)>::value_type;
64
        
65
        if (vec.empty()) {
×
66
            return nullptr;
×
67
        }
68
        
69
        int cv_type = CV_8UC1;  // Default initialization
×
70
        if constexpr (std::is_same_v<T, uint8_t>) {
71
            cv_type = CV_8UC1;
×
72
        } else if constexpr (std::is_same_v<T, float>) {
73
            cv_type = CV_32FC1;
×
74
        } else {
75
            return nullptr;  // Unsupported type
76
        }
77
        
78
        // Create cv::Mat from the vector data
79
        // Note: We create a copy to ensure the cv::Mat owns the data during processing
80
        auto* mat = new cv::Mat(size.height, size.width, cv_type);
×
81
        std::memcpy(mat->data, vec.data(), vec.size() * sizeof(T));
×
82
        
83
        return mat;
×
84
    }, data);
×
85
}
86

87
ImageData OpenCVImageProcessor::convertToRaw(void* internal_data, ImageSize const& /*size*/, size_t output_type) {
×
88
    if (!internal_data) {
×
89
        if (output_type == 0) {
×
90
            return std::vector<uint8_t>{};
×
91
        } else {
92
            return std::vector<float>{};
×
93
        }
94
    }
95
    
96
    auto* mat = static_cast<cv::Mat*>(internal_data);
×
97
    
98
    if (mat->empty()) {
×
99
        if (output_type == 0) {
×
100
            return std::vector<uint8_t>{};
×
101
        } else {
102
            return std::vector<float>{};
×
103
        }
104
    }
105
    
106
    if (output_type == 0) {
×
107
        // Convert to uint8_t vector
108
        std::vector<uint8_t> result;
×
109
        result.resize(static_cast<size_t>(mat->total() * mat->channels()));
×
110
        
111
        if (mat->type() == CV_8UC1) {
×
112
            // Direct copy for 8-bit data
113
            if (mat->isContinuous()) {
×
114
                std::memcpy(result.data(), mat->data, result.size());
×
115
            } else {
116
                size_t idx = 0;
×
117
                for (int i = 0; i < mat->rows; ++i) {
×
118
                    uint8_t* row_ptr = mat->ptr<uint8_t>(i);
×
119
                    auto cols_channels = static_cast<size_t>(mat->cols * mat->channels());
×
120
                    std::memcpy(result.data() + idx, row_ptr, cols_channels);
×
121
                    idx += cols_channels;
×
122
                }
123
            }
124
        } else if (mat->type() == CV_32FC1) {
×
125
            // Convert from float to uint8_t
126
            cv::Mat temp_mat;
×
127
            mat->convertTo(temp_mat, CV_8UC1);
×
128
            if (temp_mat.isContinuous()) {
×
129
                std::memcpy(result.data(), temp_mat.data, result.size());
×
130
            } else {
131
                size_t idx = 0;
×
132
                for (int i = 0; i < temp_mat.rows; ++i) {
×
133
                    uint8_t* row_ptr = temp_mat.ptr<uint8_t>(i);
×
134
                    auto cols_channels = static_cast<size_t>(temp_mat.cols * temp_mat.channels());
×
135
                    std::memcpy(result.data() + idx, row_ptr, cols_channels);
×
136
                    idx += cols_channels;
×
137
                }
138
            }
139
        }
×
140
        return result;
×
141
    } else {
×
142
        // Convert to float vector  
143
        std::vector<float> result;
×
144
        result.resize(static_cast<size_t>(mat->total() * mat->channels()));
×
145
        
146
        if (mat->type() == CV_32FC1) {
×
147
            // Direct copy for float data
148
            if (mat->isContinuous()) {
×
149
                std::memcpy(result.data(), mat->data, result.size() * sizeof(float));
×
150
            } else {
151
                size_t idx = 0;
×
152
                for (int i = 0; i < mat->rows; ++i) {
×
153
                    float* row_ptr = mat->ptr<float>(i);
×
154
                    auto cols_channels = static_cast<size_t>(mat->cols * mat->channels());
×
155
                    std::memcpy(result.data() + idx, row_ptr, cols_channels * sizeof(float));
×
156
                    idx += cols_channels;
×
157
                }
158
            }
159
        } else if (mat->type() == CV_8UC1) {
×
160
            // Convert from uint8_t to float
161
            cv::Mat temp_mat;
×
162
            mat->convertTo(temp_mat, CV_32FC1);
×
163
            if (temp_mat.isContinuous()) {
×
164
                std::memcpy(result.data(), temp_mat.data, result.size() * sizeof(float));
×
165
            } else {
166
                size_t idx = 0;
×
167
                for (int i = 0; i < temp_mat.rows; ++i) {
×
168
                    float* row_ptr = temp_mat.ptr<float>(i);
×
169
                    auto cols_channels = static_cast<size_t>(temp_mat.cols * temp_mat.channels());
×
170
                    std::memcpy(result.data() + idx, row_ptr, cols_channels * sizeof(float));
×
171
                    idx += cols_channels;
×
172
                }
173
            }
174
        }
×
175
        return result;
×
176
    }
×
177
}
178

179
void registerOpenCVProcessor() {
126✔
180
    ProcessorRegistry::registerProcessor("opencv", []() -> std::unique_ptr<ImageProcessor> {
378✔
181
        return std::make_unique<OpenCVImageProcessor>();
237✔
182
    });
183
}
126✔
184

185
} // namespace ImageProcessing
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc