CppNCorr
C++ ncorr Digital Image Correlation engine
Loading...
Searching...
No Matches
Image2D.h
Go to the documentation of this file.
1/*
2 * File: Image2D.h
3 * Author: justin
4 *
5 * Created on January 28, 2015, 3:10 PM
6 * Extended to support in-memory images and video import
7 */
8
9#ifndef IMAGE2D_H
10#define IMAGE2D_H
11
12#include "Array2D.h"
13#include <opencv2/opencv.hpp>
14#include <set>
15#include <optional>
16
17namespace ncorr {
18
19// Forward declarations
20class ImageProcessor;
21class VideoImporter;
22
23// Filter types for image preprocessing
24enum class FilterType {
25 SATURATION, // Clip pixel values above a threshold
26 BANDPASS // Gaussian bandpass filter (Ben's method)
27};
28
29// Configuration for image filters
31 std::set<FilterType> filters; // Which filters to apply
32 int saturation_level = 200; // Level for saturation filter (0-255)
33 std::vector<int> bandpass_params = {5, 50}; // {r1, r2} for bandpass filter
34
35 FilterConfig() = default;
36 FilterConfig(std::set<FilterType> f) : filters(std::move(f)) {}
37 FilterConfig(std::set<FilterType> f, int sat_level) : filters(std::move(f)), saturation_level(sat_level) {}
38 FilterConfig(std::set<FilterType> f, int sat_level, std::vector<int> bp)
39 : filters(std::move(f)), saturation_level(sat_level), bandpass_params(std::move(bp)) {}
40
41 bool has_saturation() const { return filters.count(FilterType::SATURATION) > 0; }
42 bool has_bandpass() const { return filters.count(FilterType::BANDPASS) > 0; }
43 bool empty() const { return filters.empty(); }
44};
45
46// Video import parameters
48 int frame_start = 1; // 1-indexed start frame
49 int frame_end = -1; // -1 means all frames
50 int frame_jump = 1; // Frame step/skip
51 bool use_grayscale = true; // Convert to grayscale
52 bool use_red_channel = true; // If color, extract R channel (for DIC speckle patterns)
53
54 VideoImportParams() = default;
55 VideoImportParams(int start, int end, int jump)
56 : frame_start(start), frame_end(end), frame_jump(jump) {}
57};
58
59class Image2D final {
60 public:
61 typedef std::ptrdiff_t difference_type;
62
63 // Storage mode enum
64 enum class StorageMode {
65 FILE_PATH, // Traditional: load from file on get_gs()
66 IN_MEMORY_MAT, // cv::Mat stored in memory
67 IN_MEMORY_GS // Array2D<double> grayscale already computed
68 };
69
70 // Rule of 5 and destructor ------------------------------------------//
71 Image2D() = default;
72 Image2D(const Image2D&) = default;
73 Image2D(Image2D&&) noexcept = default;
74 Image2D& operator=(const Image2D&) = default;
75 Image2D& operator=(Image2D&&) = default;
76 ~Image2D() noexcept = default;
77
78 // Additional Constructors -------------------------------------------//
79 // File path constructor (original behavior)
80 Image2D(std::string filename)
81 : filename_ptr(std::make_shared<std::string>(std::move(filename))),
82 storage_mode(StorageMode::FILE_PATH) { }
83
84 // In-memory cv::Mat constructor
85 Image2D(const cv::Mat& mat, const std::string& name = "in_memory")
86 : filename_ptr(std::make_shared<std::string>(name)),
87 mat_ptr(std::make_shared<cv::Mat>(mat.clone())),
88 storage_mode(StorageMode::IN_MEMORY_MAT) { }
89
90 // In-memory cv::Mat constructor (move semantics)
91 Image2D(cv::Mat&& mat, const std::string& name = "in_memory")
92 : filename_ptr(std::make_shared<std::string>(name)),
93 mat_ptr(std::make_shared<cv::Mat>(std::move(mat))),
94 storage_mode(StorageMode::IN_MEMORY_MAT) { }
95
96 // In-memory Array2D<double> constructor (already grayscale)
97 Image2D(const Array2D<double>& gs_array, const std::string& name = "in_memory_gs")
98 : filename_ptr(std::make_shared<std::string>(name)),
99 gs_ptr(std::make_shared<Array2D<double>>(gs_array)),
100 storage_mode(StorageMode::IN_MEMORY_GS) { }
101
102 // In-memory Array2D<double> constructor (move semantics)
103 Image2D(Array2D<double>&& gs_array, const std::string& name = "in_memory_gs")
104 : filename_ptr(std::make_shared<std::string>(name)),
105 gs_ptr(std::make_shared<Array2D<double>>(std::move(gs_array))),
106 storage_mode(StorageMode::IN_MEMORY_GS) { }
107
108 // Static factory methods --------------------------------------------//
109 static Image2D load(std::ifstream&);
110
111 // Create from cv::Mat with optional filtering
112 static Image2D from_mat(const cv::Mat& mat,
113 const std::string& name = "in_memory",
114 const FilterConfig& filter_config = FilterConfig());
115
116 // Create from file with optional filtering (loads and stores in memory)
117 static Image2D from_file_filtered(const std::string& filename,
118 const FilterConfig& filter_config);
119
120 // Interface functions -----------------------------------------------//
121 friend std::ostream& operator<<(std::ostream&, const Image2D&);
122 friend void imshow(const Image2D&, difference_type delay);
123 friend bool isequal(const Image2D&, const Image2D&);
124 friend void save(const Image2D&, std::ofstream&);
125
126 // Access ------------------------------------------------------------//
127 std::string get_filename() const { return *filename_ptr; }
128 Array2D<double> get_gs() const; // Returns image as double precision grayscale array with values from 0 - 1.
129 cv::Mat get_mat() const; // Returns image as cv::Mat (grayscale, 8-bit)
130 StorageMode get_storage_mode() const { return storage_mode; }
131 bool is_in_memory() const { return storage_mode != StorageMode::FILE_PATH; }
132
133 // Save in-memory image to file
134 bool save_to_file(const std::string& filename) const;
135
136 private:
137 std::shared_ptr<std::string> filename_ptr; // Name/path identifier
138 std::shared_ptr<cv::Mat> mat_ptr; // In-memory cv::Mat storage
139 std::shared_ptr<Array2D<double>> gs_ptr; // In-memory grayscale storage
140 StorageMode storage_mode = StorageMode::FILE_PATH;
141};
142
143// ImageProcessor class for applying filters to images
145 public:
146 typedef std::ptrdiff_t difference_type;
147
148 // Single image operations
149 static cv::Mat saturate(const cv::Mat& input, int level = 200);
150 static cv::Mat apply_bandpass_filter(const cv::Mat& input, const std::vector<int>& params = {5, 50});
151 static cv::Mat apply_filters(const cv::Mat& input, const FilterConfig& config);
152
153 // Batch operations
154 static std::vector<cv::Mat> saturate(const std::vector<cv::Mat>& input, int level = 200);
155 static std::vector<cv::Mat> apply_bandpass_filter(const std::vector<cv::Mat>& input,
156 const std::vector<int>& params = {5, 50});
157 static std::vector<cv::Mat> apply_filters(const std::vector<cv::Mat>& input, const FilterConfig& config);
158
159 // Ben's filtering method (bandpass + normalization)
160 static std::pair<std::vector<cv::Mat>, std::pair<double, double>>
161 filter_like_ben(const std::vector<cv::Mat>& input,
162 const cv::Mat& mask,
163 const std::vector<int>& params = {5, 50},
164 const std::pair<double, double>* gs_boundaries = nullptr);
165
166 static cv::Mat filter_like_ben_single(const cv::Mat& input,
167 const cv::Mat& mask,
168 const std::vector<int>& params = {5, 50},
169 const std::pair<double, double>* gs_boundaries = nullptr);
170
171 // Utility functions
172 static std::pair<double, double> compute_grayscale_boundaries(const cv::Mat& image, const cv::Mat& mask);
173 static std::pair<double, double> compute_percentile_boundaries(const cv::Mat& image, const cv::Mat& mask,
174 double lower_pct = 5.0, double upper_pct = 95.0);
175 static cv::Mat normalize_and_clamp(const cv::Mat& image, const std::pair<double, double>& boundaries);
176
177 // Conversion utilities
178 static cv::Mat array2d_to_mat(const Array2D<double>& arr);
179 static Array2D<double> mat_to_array2d(const cv::Mat& mat);
180};
181
182// VideoImporter class for extracting frames from video files
184 public:
185 typedef std::ptrdiff_t difference_type;
186
187 // Import video to in-memory Image2D vector
188 static std::vector<Image2D> import_video(
189 const std::string& video_path,
190 const VideoImportParams& params = VideoImportParams(),
191 const FilterConfig& filter_config = FilterConfig(),
192 const std::string& name_prefix = "frame");
193
194 // Import video and save frames to disk
195 static std::vector<Image2D> import_video_to_files(
196 const std::string& video_path,
197 const std::string& output_dir,
198 const VideoImportParams& params = VideoImportParams(),
199 const FilterConfig& filter_config = FilterConfig(),
200 const std::string& name_prefix = "frame");
201
202 // Get video information
203 struct VideoInfo {
205 int width;
207 double fps;
208 std::string codec;
209 };
210 static std::optional<VideoInfo> get_video_info(const std::string& video_path);
211
212 private:
213 static cv::Mat extract_grayscale_frame(const cv::Mat& frame, bool use_red_channel);
214};
215
216}
217
218#endif /* IMAGE2D_H */
friend void imshow(const Image2D &, difference_type delay)
Definition Image2D.cpp:90
Image2D(Array2D< double > &&gs_array, const std::string &name="in_memory_gs")
Definition Image2D.h:103
bool save_to_file(const std::string &filename) const
Definition Image2D.cpp:189
static Image2D load(std::ifstream &)
Definition Image2D.cpp:25
friend bool isequal(const Image2D &, const Image2D &)
Definition Image2D.cpp:94
StorageMode get_storage_mode() const
Definition Image2D.h:130
Image2D(const Image2D &)=default
static Image2D from_mat(const cv::Mat &mat, const std::string &name="in_memory", const FilterConfig &filter_config=FilterConfig())
Definition Image2D.cpp:45
cv::Mat get_mat() const
Definition Image2D.cpp:168
static Image2D from_file_filtered(const std::string &filename, const FilterConfig &filter_config)
Definition Image2D.cpp:64
Image2D(const cv::Mat &mat, const std::string &name="in_memory")
Definition Image2D.h:85
Image2D()=default
friend void save(const Image2D &, std::ofstream &)
Definition Image2D.cpp:123
Image2D(Image2D &&) noexcept=default
Image2D(cv::Mat &&mat, const std::string &name="in_memory")
Definition Image2D.h:91
friend std::ostream & operator<<(std::ostream &, const Image2D &)
Definition Image2D.cpp:80
Image2D(const Array2D< double > &gs_array, const std::string &name="in_memory_gs")
Definition Image2D.h:97
bool is_in_memory() const
Definition Image2D.h:131
std::ptrdiff_t difference_type
Definition Image2D.h:61
Array2D< double > get_gs() const
Definition Image2D.cpp:134
std::string get_filename() const
Definition Image2D.h:127
static cv::Mat normalize_and_clamp(const cv::Mat &image, const std::pair< double, double > &boundaries)
Definition Image2D.cpp:452
static cv::Mat filter_like_ben_single(const cv::Mat &input, const cv::Mat &mask, const std::vector< int > &params={5, 50}, const std::pair< double, double > *gs_boundaries=nullptr)
Definition Image2D.cpp:381
static cv::Mat apply_bandpass_filter(const cv::Mat &input, const std::vector< int > &params={5, 50})
Definition Image2D.cpp:239
static std::pair< std::vector< cv::Mat >, std::pair< double, double > > filter_like_ben(const std::vector< cv::Mat > &input, const cv::Mat &mask, const std::vector< int > &params={5, 50}, const std::pair< double, double > *gs_boundaries=nullptr)
Definition Image2D.cpp:351
static cv::Mat saturate(const cv::Mat &input, int level=200)
Definition Image2D.cpp:198
static Array2D< double > mat_to_array2d(const cv::Mat &mat)
Definition Image2D.cpp:494
std::ptrdiff_t difference_type
Definition Image2D.h:146
static std::pair< double, double > compute_grayscale_boundaries(const cv::Mat &image, const cv::Mat &mask)
Definition Image2D.cpp:390
static std::pair< double, double > compute_percentile_boundaries(const cv::Mat &image, const cv::Mat &mask, double lower_pct=5.0, double upper_pct=95.0)
Definition Image2D.cpp:411
static cv::Mat apply_filters(const cv::Mat &input, const FilterConfig &config)
Definition Image2D.cpp:318
static cv::Mat array2d_to_mat(const Array2D< double > &arr)
Definition Image2D.cpp:479
static std::optional< VideoInfo > get_video_info(const std::string &video_path)
Definition Image2D.cpp:525
static std::vector< Image2D > import_video_to_files(const std::string &video_path, const std::string &output_dir, const VideoImportParams &params=VideoImportParams(), const FilterConfig &filter_config=FilterConfig(), const std::string &name_prefix="frame")
Definition Image2D.cpp:619
static std::vector< Image2D > import_video(const std::string &video_path, const VideoImportParams &params=VideoImportParams(), const FilterConfig &filter_config=FilterConfig(), const std::string &name_prefix="frame")
Definition Image2D.cpp:564
std::ptrdiff_t difference_type
Definition Image2D.h:185
FilterType
Definition Image2D.h:24
std::set< FilterType > filters
Definition Image2D.h:31
bool empty() const
Definition Image2D.h:43
std::vector< int > bandpass_params
Definition Image2D.h:33
FilterConfig()=default
FilterConfig(std::set< FilterType > f, int sat_level, std::vector< int > bp)
Definition Image2D.h:38
FilterConfig(std::set< FilterType > f, int sat_level)
Definition Image2D.h:37
bool has_saturation() const
Definition Image2D.h:41
FilterConfig(std::set< FilterType > f)
Definition Image2D.h:36
bool has_bandpass() const
Definition Image2D.h:42
VideoImportParams(int start, int end, int jump)
Definition Image2D.h:55