Img2Num C++ (Internal Developer Docs) dev
API Documentation
Loading...
Searching...
No Matches
img2num Namespace Reference

Enumerations

enum class  Error {
  OK = 0 , BAD_ALLOC = 1 , INVALID_ARGUMENT = 2 , RUNTIME = 3 ,
  UNKNOWN = 4
}
 

Functions

void gaussian_blur_fft (uint8_t *image, size_t width, size_t height, double sigma)
 Apply a Gaussian blur to an image using FFT.
 
void invert_image (uint8_t *ptr, int width, int height)
 Invert the pixel values of an image.
 
void threshold_image (uint8_t *ptr, const int width, const int height, const int num_thresholds)
 Apply a thresholding operation to an image.
 
void black_threshold_image (uint8_t *ptr, const int width, const int height, const int num_thresholds)
 Apply black-thresholding to an image.
 
void kmeans (const uint8_t *data, uint8_t *out_data, int32_t *out_labels, const int32_t width, const int32_t height, const int32_t k, const int32_t max_iter, const uint8_t color_space)
 Perform k-means clustering on image data.
 
void bilateral_filter (uint8_t *image, size_t width, size_t height, double sigma_spatial, double sigma_range, uint8_t color_space)
 Apply bilateral filtering to an image.
 
std::string labels_to_svg (const uint8_t *data, const int32_t *labels, const int width, const int height, const int min_area)
 Convert labeled regions of an image into an SVG string.
 
Error get_last_error ()
 
const std::string get_last_error_message ()
 
void clear_last_error ()
 
void set_error (Error code, const std::string message)
 
template<typename Func , typename... Args>
void clear_last_error_and_catch (Func &&exception_prone_func, Args &&... args)
 

Variables

thread_local Error last_error {Error::OK}
 
thread_local std::string last_error_message {}
 

Detailed Description

Note
All image buffers are assumed to be stored in row-major order, unless otherwise noted.

Enumeration Type Documentation

◆ Error

enum class img2num::Error
strong

Definition at line 8 of file Error.h.

8{ OK = 0, BAD_ALLOC = 1, INVALID_ARGUMENT = 2, RUNTIME = 3, UNKNOWN = 4 };

Function Documentation

◆ bilateral_filter()

void img2num::bilateral_filter ( uint8_t *  image,
size_t  width,
size_t  height,
double  sigma_spatial,
double  sigma_range,
uint8_t  color_space 
)

Apply bilateral filtering to an image.

Parameters
imagePointer to RGBA pixel buffer.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
sigma_spatialStandard deviation for spatial Gaussian (proximity weight).
sigma_rangeStandard deviation for range Gaussian (intensity similarity weight).
color_spaceColor space flag (0 = CIE LAB, 1 = RGB).
Note
The filter modifies the image buffer in-place.
Dox File: doxygen/img2num.h.dox

Definition at line 222 of file bilateral_filter.cpp.

223 {
224 GPU::getClassInstance().init_gpu();
225
226 if (GPU::getClassInstance().is_initialized()) {
227 bilateral_filter_gpu(image, width, height, sigma_spatial, sigma_range, color_space);
228 } else {
229 bilateral_filter_cpu(image, width, height, sigma_spatial, sigma_range, color_space);
230 }
231}

◆ black_threshold_image()

void img2num::black_threshold_image ( uint8_t *  ptr,
const int  width,
const int  height,
const int  num_thresholds 
)

Apply black-thresholding to an image.

Parameters
ptrPointer to the image buffer.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
num_thresholdsNumber of thresholds to apply.
Note
Similar to threshold_image but prioritizes darker pixels.
Dox File: doxygen/img2num.h.dox

Definition at line 130 of file image_utils.cpp.

131 {
133 img.loadFromBuffer(ptr, width, height, ImageLib::RGBA_CONVERTER<uint8_t>);
134
135 const auto imgWidth{img.getWidth()}, imgHeight{img.getHeight()};
136 for (ImageLib::RGBAPixel<uint8_t> &p : img) {
137 const bool R{p.red < num_thresholds};
138 const bool G{p.green < num_thresholds};
139 const bool B{p.blue < num_thresholds};
140 if (R && B && G) {
141 p.setGray(0);
142 }
143 }
144
145 const auto &modified = img.getData();
146 std::memcpy(ptr, modified.data(), modified.size() * sizeof(ImageLib::RGBAPixel<uint8_t>));
147}

◆ clear_last_error()

void img2num::clear_last_error ( )

Definition at line 7 of file Error.cpp.

7 {
8 last_error = Error::OK;
9 last_error_message.clear();
10}

◆ clear_last_error_and_catch()

template<typename Func , typename... Args>
void img2num::clear_last_error_and_catch ( Func &&  exception_prone_func,
Args &&...  args 
)

Definition at line 25 of file Error.h.

25 {
26 clear_last_error(); // Clear any previous error state
27 try {
28 exception_prone_func(std::forward<Args>(args)...); // Call the passed function
29 } catch (const std::bad_alloc& e) {
30 set_error(Error::BAD_ALLOC, e.what());
31 } catch (const std::invalid_argument& e) {
32 set_error(Error::INVALID_ARGUMENT, e.what());
33 } catch (const std::runtime_error& e) {
34 set_error(Error::RUNTIME, e.what());
35 } catch (const std::exception& e) {
36 set_error(Error::UNKNOWN, e.what());
37 } catch (...) {
38 set_error(Error::UNKNOWN, "Unknown exception occurred");
39 }
40}

◆ gaussian_blur_fft()

void img2num::gaussian_blur_fft ( uint8_t *  image,
size_t  width,
size_t  height,
double  sigma 
)

Apply a Gaussian blur to an image using FFT.

Parameters
imagePointer to the image buffer (RGBA).
widthWidth of the image in pixels.
heightHeight of the image in pixels.
sigmaStandard deviation for Gaussian kernel.
Note
The operation modifies the image buffer in-place.
Dox File: doxygen/img2num.h.dox

Definition at line 43 of file image_utils.cpp.

43 {
44 if (!image || width == 0 || height == 0 || sigma_pixels <= 0) return;
45
46 const size_t Npix = width * height;
47
48 // Compute padded dimensions (next power of two)
49 const size_t W = fft::next_power_of_two(width);
50 const size_t H = fft::next_power_of_two(height);
51 const size_t Npix_padded = W * H;
52
53 // Frequency coordinates helper (DC at corner)
54 auto freq_coord = [](int k, int dim) -> double {
55 return (k <= dim / 2) ? double(k) / dim : double(k - dim) / dim;
56 };
57
58 // Precompute Gaussian factor in frequency domain
59 const double two_pi2_sigma2 = 2.0 * M_PI * M_PI * sigma_pixels * sigma_pixels;
60
61 for (int channel = 0; channel < 3; channel++) {
62 // Allocate padded buffer
63 std::vector<fft::cd> data(Npix_padded, {0.0, 0.0});
64
65 // Copy original image channel into padded buffer
66 for (size_t y = 0; y < height; y++)
67 for (size_t x = 0; x < width; x++)
68 data[y * W + x] = fft::cd(image[(y * width + x) * 4 + channel], 0.0);
69
70 // Forward 2D FFT
71 fft::iterative_fft_2d(data, W, H, false);
72
73 // Apply Gaussian filter in frequency domain
74 for (size_t y = 0; y < H; y++) {
75 double fy2 = freq_coord(y, H) * freq_coord(y, H);
76 for (size_t x = 0; x < W; x++) {
77 double fx2 = freq_coord(x, W) * freq_coord(x, W);
78 double gain = std::exp(-two_pi2_sigma2 * (fx2 + fy2));
79 data[y * W + x] *= gain;
80 }
81 }
82
83 // Inverse 2D FFT
84 fft::iterative_fft_2d(data, W, H, true);
85
86 // Copy back only the original width/height and clamp
87 for (size_t y = 0; y < height; y++)
88 for (size_t x = 0; x < width; x++) {
89 double v = data[y * W + x].real();
90 v = std::clamp(v, 0.0, 255.0);
91 image[(y * width + x) * 4 + channel] = static_cast<uint8_t>(std::lrint(v));
92 }
93 }
94
95 // Alpha channel remains unchanged
96}

◆ get_last_error()

Error img2num::get_last_error ( )
inline

Definition at line 13 of file Error.h.

13 {
14 return last_error;
15}

◆ get_last_error_message()

const std::string img2num::get_last_error_message ( )
inline

Definition at line 16 of file Error.h.

16 {
17 return last_error_message;
18}

◆ invert_image()

void img2num::invert_image ( uint8_t *  ptr,
int  width,
int  height 
)

Invert the pixel values of an image.

Parameters
ptrPointer to the image buffer.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
Note
Each pixel value is replaced by 255 - original_value.
Dox File: doxygen/img2num.h.dox

Definition at line 99 of file image_utils.cpp.

99 {
101 img.loadFromBuffer(ptr, width, height, ImageLib::RGBA_CONVERTER<uint8_t>);
102
103 for (ImageLib::RGBAPixel<uint8_t> &p : img) {
104 p.red = 255 - p.red;
105 p.blue = 255 - p.blue;
106 p.green = 255 - p.green;
107 }
108
109 const auto &modified = img.getData();
110 std::memcpy(ptr, modified.data(), modified.size() * sizeof(ImageLib::RGBAPixel<uint8_t>));
111}

◆ kmeans()

void img2num::kmeans ( const uint8_t *  data,
uint8_t *  out_data,
int32_t *  out_labels,
const int32_t  width,
const int32_t  height,
const int32_t  k,
const int32_t  max_iter,
const uint8_t  color_space 
)

Perform k-means clustering on image data.

Parameters
dataPointer to input image data buffer.
out_dataPointer to output buffer where clustered pixel values are stored.
out_labelsPointer to output buffer for cluster labels per pixel.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
kNumber of clusters to compute.
max_iterMaximum number of iterations for the algorithm.
color_spaceColor space flag (0 = CIE LAB, 1 = RGB).
Note
The function does not modify the input buffer.
Dox File: doxygen/img2num.h.dox

Definition at line 240 of file kmeans.cpp.

242 {
243 GPU::getClassInstance().init_gpu();
244
245 if (GPU::getClassInstance().is_initialized()) {
246 std::cout << "kmeans gpu" << std::endl;
247 kmeans_gpu(data, out_data, out_labels, width, height, k, max_iter, color_space);
248 } else {
249 std::cout << "kmeans cpu" << std::endl;
250 kmeans_cpu(data, out_data, out_labels, width, height, k, max_iter, color_space);
251 }
252}

◆ labels_to_svg()

std::string img2num::labels_to_svg ( const uint8_t *  data,
const int32_t *  labels,
const int  width,
const int  height,
const int  min_area 
)

Convert labeled regions of an image into an SVG string.

Parameters
dataPointer to image data buffer.
labelsPointer to label buffer, indicating region for each pixel.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
min_areaMinimum area (in pixels) for a region to be included in the SVG.
Returns
std::string A valid SVG string containing the data.
Note
Dox File: doxygen/img2num.h.dox

Definition at line 189 of file labels_to_svg.cpp.

190 {
191 const int32_t num_pixels{width * height};
192 std::vector<int32_t> labels_vector{labels, labels + num_pixels};
193 std::vector<int32_t> region_labels;
194
195 // 1. enumerate regions and convert to Nodes
196 std::vector<Node_ptr> nodes;
197 region_labeling(data, labels_vector, region_labels, width, height, nodes);
198
199 // 2. initialize Graph from all Nodes
200 std::unique_ptr<std::vector<Node_ptr>> node_ptr =
201 std::make_unique<std::vector<Node_ptr>>(std::move(nodes));
202 Graph G(node_ptr, width, height);
203
204 // 3. Discover node adjacencies - add edges to Graph
205 G.discover_edges(region_labels, width, height);
206
207 // 4. Merge small area nodes until all nodes are minArea or larger
208 G.merge_small_area_nodes(min_area);
209
210 // 5. recolor image on new regions
211 ImageLib::Image<ImageLib::RGBAPixel<uint8_t>> results{width, height};
212 for (auto &n : G.get_nodes()) {
213 if (n->area() == 0) continue;
214
215 auto [r, g, b] = n->color();
216 for (auto &[_, p] : n->get_pixels()) {
217 results(p.x, p.y) = {r, g, b};
218 }
219 }
220
221 // 6. Contours
222 // graph will manage computing contours
223 G.compute_contours();
224
225 // accumulate all contours for svg export
226 ColoredContours all_contours;
227 for (auto &n : G.get_nodes()) {
228 if (n->area() == 0) continue;
229 ColoredContours node_contours = n->get_contours();
230 for (auto &c : node_contours.contours) {
231 all_contours.contours.push_back(c);
232 }
233 for (auto &c : node_contours.hierarchy) {
234 all_contours.hierarchy.push_back(c);
235 }
236 for (bool b : node_contours.is_hole) {
237 all_contours.is_hole.push_back(b);
238 }
239 for (auto &c : node_contours.colors) {
240 all_contours.colors.push_back(c);
241 }
242 for (auto &c : node_contours.curves) {
243 all_contours.curves.push_back(c);
244 }
245 }
246
247 // 7. Return SVG
248 return contoursResultToSVG(all_contours, width, height);
249}
Definition graph.h:33

◆ set_error()

void img2num::set_error ( Error  code,
const std::string  message 
)

Definition at line 12 of file Error.cpp.

12 {
13 last_error = code;
14 last_error_message = message;
15}

◆ threshold_image()

void img2num::threshold_image ( uint8_t *  ptr,
const int  width,
const int  height,
const int  num_thresholds 
)

Apply a thresholding operation to an image.

Parameters
ptrPointer to the image buffer.
widthWidth of the image in pixels.
heightHeight of the image in pixels.
num_thresholdsNumber of thresholds to apply.
Note
Thresholds split pixel intensity ranges into discrete levels.
Dox File: doxygen/img2num.h.dox

Definition at line 113 of file image_utils.cpp.

113 {
114 const uint8_t REGION_SIZE(255 / num_thresholds); // Size of buckets per colour
115
117 img.loadFromBuffer(ptr, width, height, ImageLib::RGBA_CONVERTER<uint8_t>);
118
119 const auto imgWidth{img.getWidth()}, imgHeight{img.getHeight()};
120 for (ImageLib::RGBAPixel<uint8_t> &p : img) {
121 p.red = quantize(p.red, REGION_SIZE);
122 p.green = quantize(p.green, REGION_SIZE);
123 p.blue = quantize(p.blue, REGION_SIZE);
124 }
125
126 const auto &modified = img.getData();
127 std::memcpy(ptr, modified.data(), modified.size() * sizeof(ImageLib::RGBAPixel<uint8_t>));
128}

Variable Documentation

◆ last_error

thread_local Error img2num::last_error {Error::OK}

Definition at line 4 of file Error.cpp.

4{Error::OK};

◆ last_error_message

thread_local std::string img2num::last_error_message {}

Definition at line 5 of file Error.cpp.

5{};