IDS peak ICV v1.3.0
Loading...
Searching...
No Matches
color_matrix_transformation_module.py
Go to the documentation of this file.
1import ctypes
2from typing import cast
3
4import numpy as np
5
6from ids_peak_common import Interval, Range, PixelFormat
7from ids_peak_common.serialization import IArchive
8from ids_peak_common.pipeline.modules.iautofeature_module import IAutoFeature
9from ids_peak_icv import lib_loader
10from ids_peak_icv.backend.datatypes import (peak_icv_color_correction_matrix,
11 peak_icv_color_matrix_transformation_handle, peak_common_interval_f,
12 peak_common_range_u)
13from ids_peak_icv.backend.utils import execute_and_map_return_codes
14from ids_peak_icv.datatypes.image import Image
16from ids_peak_icv.pipeline.datatypes import ChromaticAdaptionAlgorithm, ColorSpace
17
18
20 """!
21 @brief
22 Color matrix transformation is an image pipeline module that applies a color correction matrix to an image.
23
24 Provides the features ColorCorrectionFeature, SaturationFeature and ChromaticAdaptionFeature.
25
26 Default configuration:
27 - Color correction matrix = 3x3 identity matrix
28 - Saturation = 1.0
29 - no chromatic adaption correction applied
30
31 @since ids_peak_icv 1.0
32 """
33
34 DEFAULT_MATRIX: np.ndarray = np.eye(3)
35 """!
36 @brief
37 Default color correction matrix value.
38
39 @since ids_peak_icv 1.0
40 """
41
42 DEFAULT_SATURATION: float = 1.0
43 """!
44 @brief
45 Default saturation value.
46
47 @since ids_peak_icv 1.0
48 """
49
50 SUPPORTED_PIXEL_FORMATS = [
51 PixelFormat.RGB_8, PixelFormat.RGB_10, PixelFormat.RGB_12, PixelFormat.BGR_8, PixelFormat.BGR_10,
52 PixelFormat.BGR_12, PixelFormat.RGBA_8, PixelFormat.RGBA_10, PixelFormat.RGBA_12, PixelFormat.BGRA_8,
53 PixelFormat.BGRA_10, PixelFormat.BGRA_12
54 ]
55
56 def __init__(self) -> None:
57 """!
58 @brief
59 Initialize a color matrix transformation module with default settings.
60
61 @since ids_peak_icv 1.0
62 """
63 super().__init__()
64
65 _color_matrix_transformation_handle = peak_icv_color_matrix_transformation_handle()
66 execute_and_map_return_codes(
67 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_Create,
68 ctypes.pointer(_color_matrix_transformation_handle)
69 )
70 self._handle = _color_matrix_transformation_handle
71 self._auto_feature_module_auto_feature_module: IAutoFeature | None = None
72
73 self.reset_to_default()
74
75 def __del__(self) -> None:
76 if hasattr(self, "_handle") and self._handle:
77 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_Destroy(self._handle)
78
79 @property
80 def type(self) -> str:
81 """!
82 @brief
83 Returns the type of the module for serialization purposes.
84
85 @return Module type
86
87 @since ids_peak_icv 1.0
88 """
89 return "ColorMatrixTransformation"
90
91 @property
92 def version(self) -> int:
93 """!
94 @brief
95 Return the module version.
96
97 @return Module version.
98
99 @since ids_peak_icv 1.3
100 """
101 return 2
102
103 @property
104 def enabled(self) -> bool:
105 """!
106 @brief
107 Gets whether this module is enabled.
108
109 When disabled, :func:`process` returns the input image unchanged.
110
111 @return True if the module is enabled, False otherwise.
112
113 @since ids_peak_icv 1.0
114 """
116
117 @enabled.setter
118 def enabled(self, enabled: bool) -> None:
119 """!
120 @brief
121 Enables or disables the module.
122
123 When disabled, :func:`process` returns the input image unchanged.
124
125 @param enabled: True to enable, False to disable.
126
127 @since ids_peak_icv 1.0
128 """
133
134 @property
135 def matrix(self) -> np.ndarray:
136 """!
137 @brief
138 Gets the current color correction matrix.
139
140 @return The current color correction matrix.
141
142 @since ids_peak_icv 1.0
143 """
144 matrix = self.DEFAULT_MATRIX
145
146 c_matrix = peak_icv_color_correction_matrix.from_buffer_copy(
147 np.asarray(matrix, dtype=np.float32).flatten().tobytes())
148
149 execute_and_map_return_codes(
150 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_GetColorCorrectionMatrix,
151 self._handle,
152 ctypes.pointer(c_matrix),
153 )
154 return cast(np.ndarray, np.frombuffer(memoryview(c_matrix), dtype=np.float32).reshape(3, 3).copy())
155
156 @matrix.setter
157 def matrix(self, matrix: np.ndarray) -> None:
158 """!
159 @brief
160 Sets the color correction matrix.
161
162 @param matrix: The color correction matrix.
163
164 @since ids_peak_icv 1.0
165 """
166 c_matrix = peak_icv_color_correction_matrix.from_buffer_copy(
167 np.asarray(matrix, dtype=np.float32).flatten().tobytes())
168
169 execute_and_map_return_codes(
170 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_SetColorCorrectionMatrix,
171 self._handle,
172 c_matrix
173 )
175
176 @property
177 def saturation(self) -> float:
178 """!
179 @brief
180 Gets the current saturation value.
181
182 @return The current saturation value.
183
184 @since ids_peak_icv 1.0
185 """
186 saturation = ctypes.c_float()
187 execute_and_map_return_codes(
188 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_GetSaturation,
189 self._handle,
190 ctypes.byref(saturation))
191 return saturation.value
192
193 @saturation.setter
194 def saturation(self, saturation: float) -> None:
195 """!
196 @brief
197 Sets the saturation value.
198
199 @param saturation: The saturation value.
200
201 @since ids_peak_icv 1.0
202 """
203 execute_and_map_return_codes(
204 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_SetSaturation,
205 self._handle,
206 ctypes.c_float(saturation))
209
210 @property
211 def saturation_range(self) -> Interval:
212 """!
213 @brief
214 Gets the valid range for saturation.
215
216 @return The valid saturation range.
217
218 @since ids_peak_icv 1.0
219 """
220 c_interval = peak_common_interval_f()
221 execute_and_map_return_codes(
222 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_GetSaturationRange,
223 self._handle, ctypes.pointer(c_interval))
224 return Interval(c_interval.minimum, c_interval.maximum)
225
226 @property
227 def color_correction_enabled(self) -> bool:
228 """!
229 @brief
230 Gets whether color correction is enabled.
231
232 When enabled, :func:`process` applies color correction to the input image.
233
234 @return True if color correction is enabled, False otherwise.
235
236 @since ids_peak_icv 1.0
237 """
238 enabled = ctypes.c_bool()
239
240 execute_and_map_return_codes(
241 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ColorCorrection_IsEnabled,
242 self._handle,
243 ctypes.byref(enabled),
244 )
245 return bool(enabled.value)
246
247 @color_correction_enabled.setter
248 def color_correction_enabled(self, enabled: bool) -> None:
249 """!
250 @brief
251 Enables or disables color correction.
252
253 When enabled, :func:`process` applies color correction to the input image.
254
255 @param enabled: True to enable, False to disable.
256
257 @since ids_peak_icv 1.0
258 """
259 execute_and_map_return_codes(
260 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ColorCorrection_SetEnabled,
261 self._handle,
262 ctypes.c_bool(enabled),
263 )
265
266 @property
267 def chromatic_adaption_enabled(self) -> bool:
268 """!
269 @brief
270 Checks if the chromatic adaptation feature is enabled.
271
272 @return True if chromatic adaptation is currently active, false otherwise.
273
274 @since ids_peak_icv 1.3
275 """
276 enabled = ctypes.c_bool()
277
278 execute_and_map_return_codes(
279 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_IsEnabled,
280 self._handle,
281 ctypes.byref(enabled),
282 )
283 return bool(enabled.value)
284
285 @chromatic_adaption_enabled.setter
286 def chromatic_adaption_enabled(self, enabled: bool) -> None:
287 """!
288 @brief
289 Enables or disables the chromatic adaptation feature.
290
291 @param enabled: True to enable chromatic adaptation, false to disable it.
292
293 @since ids_peak_icv 1.3
294 """
295 execute_and_map_return_codes(
296 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_SetEnabled,
297 self._handle,
298 ctypes.c_bool(enabled),
299 )
301
302 @property
303 def chromatic_adaption_algorithm(self) -> ChromaticAdaptionAlgorithm:
304 """!
305 @brief
306 Returns the current algorithm used for chromatic adaptation.
307
308 @return The active ChromaticAdaptionAlgorithm.
309
310 @since ids_peak_icv 1.3
311 """
312 algorithm = ctypes.c_int()
313 execute_and_map_return_codes(
314 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_GetAlgorithm,
315 self._handle,
316 ctypes.byref(algorithm),
317 )
318 return ChromaticAdaptionAlgorithm(algorithm.value)
319
320 @chromatic_adaption_algorithm.setter
321 def chromatic_adaption_algorithm(self, algorithm: ChromaticAdaptionAlgorithm) -> None:
322 """!
323 @brief
324 Sets the algorithm used to calculate the chromatic adaptation transformation.
325
326 @param algorithm: The ChromaticAdaptionAlgorithm to apply.
327
328 @since ids_peak_icv 1.3
329 """
330 execute_and_map_return_codes(
331 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_SetAlgorithm,
332 self._handle,
333 algorithm.value,
334 )
336
337 @property
338 def target_color_space(self) -> ColorSpace:
339 """!
340 @brief
341 Returns the target color space used for chromatic adaptation.
342
343 @return The current target ColorSpace.
344
345 @since ids_peak_icv 1.3
346 """
347 color_space = ctypes.c_int()
348 execute_and_map_return_codes(
349 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_GetTargetColorSpace,
350 self._handle,
351 ctypes.byref(color_space),
352 )
353 return ColorSpace(color_space.value)
354
355 @target_color_space.setter
356 def target_color_space(self, color_space: ColorSpace) -> None:
357 """!
358 @brief
359 Sets the target color space for the chromatic adaptation transformation.
360
361 @param color_space: The target ColorSpace.
362
363 @since ids_peak_icv 1.3
364 """
365 execute_and_map_return_codes(
366 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_SetTargetColorSpace,
367 self._handle,
368 color_space.value,
369 )
371
372 @property
373 def color_temperature(self) -> int:
374 """!
375 @brief
376 Returns the currently configured source color temperature in Kelvin.
377
378 @return The color temperature value in Kelvin.
379
380 @since ids_peak_icv 1.3
381 """
382 temperature = ctypes.c_uint32()
383 execute_and_map_return_codes(
384 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_GetColorTemperature,
385 self._handle,
386 ctypes.byref(temperature),
387 )
388 return int(temperature.value)
389
390 @color_temperature.setter
391 def color_temperature(self, temperature: int) -> None:
392 """!
393 @brief
394 Sets the source color temperature in Kelvin to be used for chromatic adaptation.
395
396 @param temperature: The color temperature value in Kelvin.
397
398 @since ids_peak_icv 1.3
399 """
400 execute_and_map_return_codes(
401 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_SetColorTemperature,
402 self._handle,
403 ctypes.c_uint32(int(temperature)),
404 )
406
407 @property
408 def color_temperature_range(self) -> Range:
409 """!
410 @brief
411 Returns the valid range of values for color temperature.
412
413 @return A Range denoting the min and max allowed temperature values as well as its allowed increment.
414
415 @since ids_peak_icv 1.3
416 """
417 c_range = peak_common_range_u()
418 execute_and_map_return_codes(
419 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_GetColorTemperatureRange,
420 self._handle,
421 ctypes.byref(c_range),
422 )
423 return Range(c_range.minimum, c_range.maximum, c_range.increment)
424
425 def has_color_temperature(self) -> bool:
426 """!
427 @brief
428 Checks if a specific color temperature has been explicitly set.
429
430 @return True if a color temperature is configured, false otherwise.
431
432 @since ids_peak_icv 1.3
433 """
434 value = ctypes.c_bool()
435 execute_and_map_return_codes(
436 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_HasColorTemperature,
437 self._handle,
438 ctypes.byref(value),
439 )
440 return bool(value.value)
441
442 def reset_color_temperature(self) -> None:
443 """!
444 @brief
445 Resets the color temperature to its default, uninitialized state.
446
447 @since ids_peak_icv 1.3
448 """
449 execute_and_map_return_codes(
450 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ChromaticAdaption_ResetColorTemperature,
451 self._handle,
452 )
454
455 def reset_chromatic_adaption(self) -> None:
456 """!
457 @brief
458 Resets all chromatic adaptation settings (temperature, algorithm, color space) to their default values.
459
460 @since ids_peak_icv 1.3
461 """
465
466 @property
467 def saturation_enabled(self) -> bool:
468 """!
469 @brief
470 Gets whether saturation is enabled.
471
472 When enabled, :func:`process` applies saturation to the input image.
473
474 @return True if saturation is enabled, False otherwise.
475
476 @since ids_peak_icv 1.0
477 """
478 enabled = ctypes.c_bool()
479
480 execute_and_map_return_codes(
481 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_Saturation_IsEnabled,
482 self._handle,
483 ctypes.byref(enabled),
484 )
485 return bool(enabled.value)
486
487 @saturation_enabled.setter
488 def saturation_enabled(self, enabled: bool) -> None:
489 """!
490 @brief
491 Enables or disables saturation.
492
493 When enabled, :func:`process` applies saturation to the input image.
494
495 @param enabled: True to enable, False to disable.
496
497 @since ids_peak_icv 1.0
498 """
499 execute_and_map_return_codes(
500 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_Saturation_SetEnabled,
501 self._handle,
502 ctypes.c_bool(enabled),
503 )
505
506 def process(self, input_image: Image) -> Image:
507 """!
508 @brief
509 Processes the input image and returns a color corrected and/or saturated output image.
510
511 @supportedPixelformats{ColorMatrixTransformation}
512
513 Images with other formats are passed through unmodified.
514
515 @note This operation disregards any specified image regions and processes the entire image.
516
517 @param input_image: The input image to be processed.
518
519 @return The input image after in-place color correction and/or saturation has been applied.
520
521 @since ids_peak_icv 1.0
522 """
524 return input_image
525
526 if input_image.pixel_format not in self.SUPPORTED_PIXEL_FORMATS:
527 return input_image
528
529 execute_and_map_return_codes(
530 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_ProcessInplace,
531 self._handle,
532 input_image._handle
533 )
534 return input_image
535
536 def reset_to_default(self) -> None:
537 """!
538 @brief
539 Resets all settings to their defaults.
540
541 Default configuration:
542 - matrix = identity
543 - saturation = 1.0
544 - no chromatic adaption correction
545
546 @note The enabled state does not change when calling this function.
547
548 @since ids_peak_icv 1.0
549 """
553
554 def serialize(self, archive: IArchive) -> None:
555 """!
556 @brief
557 Serializes the object's internal state into the provided archive.
558
559 This function populates the given archive with all parameters required to fully represent the current state of the object.
560 It ensures that the object can be reconstructed or transmitted accurately by saving all relevant data members
561 in a consistent and structured format.
562
563 @param archive: The target archive that will store the serialized parameters.
564
565 @since ids_peak_icv 1.0
566 """
567 super().serialize(archive)
568
569 saturation_archive = archive.create_archive()
570
571 archive.set("Version", self.versionversionversionversion)
572
573 saturation_archive.set("Enabled", self.saturation_enabledsaturation_enabledsaturation_enabled)
574 saturation_archive.set("Value", self.saturationsaturationsaturation)
575 archive.set("Saturation", saturation_archive)
576
577 color_correction_matrix_archive = archive.create_archive()
578 color_correction_matrix_archive.set("Enabled", self.color_correction_enabledcolor_correction_enabledcolor_correction_enabled)
579 color_correction_matrix_archive.set("Matrix",
580 cast(list[float], cast(np.ndarray, self.matrixmatrixmatrix).flatten().tolist()))
581 archive.set("ColorCorrection", color_correction_matrix_archive)
582
583 chromatic_archive = archive.create_archive()
585 chromatic_archive.set("Algorithm", self.chromatic_adaption_algorithmchromatic_adaption_algorithmchromatic_adaption_algorithm.name.capitalize())
586 chromatic_archive.set("TargetColorSpace", self.target_color_spacetarget_color_spacetarget_color_space.name)
587
588 if self.has_color_temperature():
589 chromatic_archive.set("ColorTemperature", self.color_temperaturecolor_temperaturecolor_temperature)
590
591 archive.set("ChromaticAdaption", chromatic_archive)
592
593 def deserialize(self, archive: IArchive) -> None:
594 """!
595 @brief
596 Restores the object's state from the provided archive.
597
598 This function reads and applies all necessary parameters from the given archive
599 to reconstruct the internal state of the object.
600 It ensures that the object is restored to a valid and consistent state.
601
602 @param archive: The source archive containing the serialized parameters.
603
604 @exception CorruptedException: If Archive is malformed, misses keys or the values are invalid
605 @exception NotSupportedException: If the 'Version' entry indicates an unsupported version.
606
607 @note This function requires that the archive contains all expected fields as produced by
608 a corresponding serialize() call.
609
610 @since ids_peak_icv 1.0
611 """
612 super()._validate_version(archive)
613
614 saturation_archive = archive.get_archive("Saturation")
615 self.saturation_enabledsaturation_enabledsaturation_enabled = saturation_archive.get("Enabled", bool)
616 self.saturationsaturationsaturation = saturation_archive.get("Value", float)
617
618 color_correction_matrix_archive = archive.get_archive("ColorCorrection")
619 self.color_correction_enabledcolor_correction_enabledcolor_correction_enabled = color_correction_matrix_archive.get("Enabled", bool)
620 self.matrixmatrixmatrix = np.array(color_correction_matrix_archive.get("Matrix", list)).reshape(3, 3)
621
622 version = archive.get("Version", int)
623
624 if version >= self.versionversionversionversion:
625 chromatic_archive = archive.get_archive("ChromaticAdaption")
626
629 chromatic_archive.get("Algorithm", str).upper()]
630 self.target_color_spacetarget_color_spacetarget_color_space = ColorSpace[chromatic_archive.get("TargetColorSpace", str).upper()]
631
632 if chromatic_archive.has("ColorTemperature"):
633 self.color_temperaturecolor_temperaturecolor_temperature = chromatic_archive.get("ColorTemperature", int)
634 else:
636 else:
638
639 def _set_autofeature_module(self, auto_feature_module: IAutoFeature | None) -> None:
640 self._auto_feature_module_auto_feature_module = auto_feature_module
642
643 @property
644 def effective_matrix(self) -> np.ndarray:
645 """!
646 @brief
647 Returns the final effective matrix calculated by concatenating all enabled transformations
648 (e.g., Chromatic Adaptation, Color Correction, and Saturation).
649
650 @return The combined effective color correction matrix.
651
652 @since ids_peak_icv 1.3
653 """
655 execute_and_map_return_codes(
656 lib_loader.dll().peak_icv_Preprocessing_ColorMatrixTransformation_GetEffectiveMatrix,
657 self._handle, ctypes.byref(c_matrix)
658 )
659 return cast(np.ndarray, np.frombuffer(memoryview(c_matrix), dtype=np.float32).reshape(3, 3).copy())
660
663 matrix = self.effective_matrix
664 self._auto_feature_module_auto_feature_module.set_color_correction_matrix(matrix.flatten().tolist())
Color matrix transformation is an image pipeline module that applies a color correction matrix to an ...
None deserialize(self, IArchive archive)
Restores the object's state from the provided archive.
int color_temperature(self)
Returns the currently configured source color temperature in Kelvin.
None chromatic_adaption_algorithm(self, ChromaticAdaptionAlgorithm algorithm)
Sets the algorithm used to calculate the chromatic adaptation transformation.
np.ndarray effective_matrix(self)
Returns the final effective matrix calculated by concatenating all enabled transformations (e....
None chromatic_adaption_enabled(self, bool enabled)
Enables or disables the chromatic adaptation feature.
ChromaticAdaptionAlgorithm chromatic_adaption_algorithm(self)
Returns the current algorithm used for chromatic adaptation.
Image process(self, Image input_image)
Processes the input image and returns a color corrected and/or saturated output image.
None __init__(self)
Initialize a color matrix transformation module with default settings.
None color_temperature(self, int temperature)
Sets the source color temperature in Kelvin to be used for chromatic adaptation.
ColorSpace target_color_space(self)
Returns the target color space used for chromatic adaptation.
None serialize(self, IArchive archive)
Serializes the object's internal state into the provided archive.
None target_color_space(self, ColorSpace color_space)
Sets the target color space for the chromatic adaptation transformation.
None reset_chromatic_adaption(self)
Resets all chromatic adaptation settings (temperature, algorithm, color space) to their default value...
None reset_color_temperature(self)
Resets the color temperature to its default, uninitialized state.
Base class for all pipeline modules.
Definition module_base.py:8
int version(self)
Return the module version.
bool enabled(self)
Gets whether this module is enabled.
None enabled(self, bool enabled)
Enables or disables the module.
Color spaces supported by the chromatic adaptation feature.
Definition color_space.py:4