IDS peak ICV v1.1.0
Loading...
Searching...
No Matches
unpack_module.py
Go to the documentation of this file.
1import ctypes
2
3from ids_peak_common.serialization import IArchive
4from ids_peak_common.datatypes.pixelformat import PixelFormat
5from ids_peak_icv import lib_loader
6from ids_peak_icv.backend.datatypes import peak_icv_image_converter_handle, peak_icv_image_handle
7from ids_peak_icv.backend.utils import execute_and_map_return_codes
9from ids_peak_icv.pipeline.processing_policy import ProcessingPolicy
10from ids_peak_icv.datatypes.image import Image
11
12
14 """!
15 @brief
16 Unpack is an image pipeline module that converts packed pixel formats into corresponding unpacked Bayer or mono formats.
17
18 The unpack module is always enabled and cannot be disabled. It converts input images
19 with packed pixel formats into their corresponding unpacked Bayer or monochrome formats,
20 preserving the original bit depth of the image.
21
22 Default configuration:
23 - Target bit depth: 8
24 - Processing policy: ProcessingPolicy.FAST
25
26 @ingroup ids_peak_icv_python_pipeline_modules
27 @since ids_peak_icv 1.0
28 """
29
30 DEFAULT_POLICY = ProcessingPolicy.FAST
31 DEFAULT_TARGET_BIT_DEPTH = 8
32
33 def __init__(self) -> None:
34 """!
35 @brief
36 Creates an instance of class UnpackModule.
37 @since ids_peak_icv 1.0
38 """
39 super().__init__()
40
41 image_converter_handle = peak_icv_image_converter_handle()
42 execute_and_map_return_codes(lib_loader.dll().peak_icv_Preprocessing_ImageConverter_Create,
43 ctypes.pointer(image_converter_handle))
44
45 self._handle = image_converter_handle
47 self._policy: ProcessingPolicy = self.DEFAULT_POLICY
48
49 def __del__(self) -> None:
50 if hasattr(self, '_handle'):
51 lib_loader.dll().peak_icv_Preprocessing_ImageConverter_Destroy(self._handle)
52
53 @property
54 def target_bit_depth(self) -> int:
55 """!
56 @brief
57 Get the target bit depth used during image processing.
58
59 This value specifies the bit depth the module will aim for when unpacking
60 packed pixel formats. The actual output bit depth depends on the
61 selected :class:`ProcessingPolicy`.
62
63 @return The currently configured target bit depth.
64
65 @since ids_peak_icv 1.0
66 """
67 return self._target_bit_depth
68
69 @target_bit_depth.setter
70 def target_bit_depth(self, bit_depth: int) -> None:
71 """!
72 @brief
73 Set the target bit depth for image processing.
74
75 The target bit depth acts as a reference when deciding how to
76 unpack packed pixel formats. The actual resulting bit depth
77 depends on the selected :class:`ProcessingPolicy`:
78
79 - **Fast**: The output bit depth is the *minimum* of the input image bit depth
80 and the target bit depth.
81 - **Balanced**: The output bit depth is the *same* as the input image bit depth
82 (the target value is ignored).
83 - **Enhanced**: The output bit depth is the *maximum* of the input image bit depth
84 and the target bit depth.
85
86 This allows you to downsample, preserve, or enhance bit depth depending
87 on your use case.
88
89 @param bit_depth: The desired target bit depth (e.g., 8, 10, 12).
90
91 @since ids_peak_icv 1.0
92 """
93 self._target_bit_depth = bit_depth
94
95 @property
96 def processing_policy(self) -> ProcessingPolicy:
97 """!
98 @brief
99 Get the currently configured processing policy.
100 @return The active processing policy.
101
102 @since ids_peak_icv 1.0
103 """
104 return self._policy
105
106 @processing_policy.setter
107 def processing_policy(self, policy: ProcessingPolicy) -> None:
108 """!
109 @brief
110 Set the processing policy.
111 @param policy: The desired processing policy.
112
113 @since ids_peak_icv 1.0
114 """
115 self._policy = policy
116
117 @property
118 def enabled(self) -> bool:
119 """!
120 @brief
121 Returns true since the unpack module is always enabled.
122 @return True
123
124 @since ids_peak_icv 1.0
125 """
126 return True
127
128 @enabled.setter
129 def enabled(self, enabled: bool) -> None:
130 """!
131 @brief
132 Does nothing. The module is always enabled, because otherwise following modules will fail.
133
134 @since ids_peak_icv 1.0
135 """
136 pass
137
138 @property
139 def type(self) -> str:
140 """!
141 @brief
142 Returns the type of the module for serialization purposes.
143 @return Module type
144
145 @since ids_peak_icv 1.0
146 """
147 return "Unpack"
148
149 def process(self, input_image: Image) -> Image:
150 """!
151 @brief
152 Converts a packed pixel format image into an unpacked Bayer or monochrome format.
153
154 This function unpacks the input image from a packed format to its corresponding
155 unpacked Bayer or monochrome format, preserving the input bit depth.
156
157 This operation disregards any specified image regions and processes the entire image.
158
159 @param input_image: input The packed input image to unpack.
160 @return The unpacked output image with the downsampled bit depth.
161
162 @since ids_peak_icv 1.0
163 """
164 input_bit_depth = input_image.pixel_format.storage_bits_per_channel
165 output_bit_depth = self._get_output_bit_depth(input_bit_depth)
166 output_pixel_format = self._get_output_pixel_format(input_image.pixel_format, output_bit_depth)
167
168 if input_image.pixel_format == output_pixel_format:
169 return input_image
170
171 output_image_handle = peak_icv_image_handle()
172
173 execute_and_map_return_codes(
174 lib_loader.dll().peak_icv_Preprocessing_ImageConverter_Convert, self._handle, input_image._handle,
175 ctypes.c_int(output_pixel_format.value),
176 ctypes.pointer(output_image_handle))
177
178 return Image(_handle=output_image_handle)
179
180 def reset_to_default(self) -> None:
181 """!
182 @brief
183 Resets all module settings.
184
185 Resets the target bit depth to 8 and the processing policy to ProcessingPolicy.FAST
186
187 @since ids_peak_icv 1.0
188 """
189 self._policy = self.DEFAULT_POLICY
191
192 def release_buffers(self) -> None:
193 """!
194 @brief
195 Frees unused internal buffers.
196
197 This module uses pre-allocated internal buffers to accelerate conversions.
198 When the image size or pixel format changes, new buffers are allocated, which may cause
199 the internal buffer pool to grow over time. This function can be used to release
200 unused buffers and reduce memory usage.
201
202 Avoid calling this function too frequently (e.g., after every resize or format change),
203 as it introduces some overhead.
204
205 @since ids_peak_icv 1.0
206 """
207
208 execute_and_map_return_codes(
209 lib_loader.dll().peak_icv_Preprocessing_ImageConverter_ReleaseBuffers, self._handle)
210
211 def serialize(self, archive: IArchive) -> None:
212 """!
213 @brief
214 Serializes the object's internal state into the provided archive.
215
216 This function populates the given archive with all parameters required to fully represent the current state of the object.
217 It ensures that the object can be reconstructed or transmitted accurately by saving all relevant data members
218 in a consistent and structured format.
219
220 @return The serialized module's internal state.
221
222 @since ids_peak_icv 1.0
223 """
224 # Unlike other modules, Unpack behaves differently: it has no version, is always enabled, and therefore cannot use the pipeline base class.
225 pass
226
227 def deserialize(self, archive: IArchive) -> None:
228 """!
229 @brief
230 Restores the object's state from the provided archive.
231
232 This function reads and applies all necessary parameters from the given archive to reconstruct the internal state of the object.
233 It ensures that the object is restored to a valid and consistent state.
234
235 @param archive: The source archive containing the serialized parameters.
236
237 @note This function requires that the archive contains all expected fields as produced by a corresponding serialize() call.
238
239 @since ids_peak_icv 1.0
240 """
241 # Unpack behaves differently from other modules. Since it is always enabled,
242 # the archive does not need to include an "enabled" entry.
243 # It also does not have a version.
244 pass
245
246 def _get_output_bit_depth(self, input_bit_depth: int) -> int:
247 if self._policy == ProcessingPolicy.FAST:
248 return min(input_bit_depth, self._target_bit_depth)
249 elif self._policy == ProcessingPolicy.ENHANCED:
250 return max(input_bit_depth, self._target_bit_depth)
251 return input_bit_depth
252
253 def _get_output_pixel_format(self, input_pixel_format: PixelFormat, output_bit_depth: int) -> PixelFormat:
254 mapping = {
255 # BayerBG
256 PixelFormat.BAYER_BG_8: self._bayer_bg_format,
257 PixelFormat.BAYER_BG_10: self._bayer_bg_format,
258 PixelFormat.BAYER_BG_10_PACKED: self._bayer_bg_format,
259 PixelFormat.BAYER_BG_10_GROUPED_40_IDS: self._bayer_bg_format,
260 PixelFormat.BAYER_BG_12: self._bayer_bg_format,
261 PixelFormat.BAYER_BG_12_PACKED: self._bayer_bg_format,
262 PixelFormat.BAYER_BG_12_GROUPED_24_IDS: self._bayer_bg_format,
263
264 # BayerGB
265 PixelFormat.BAYER_GB_8: self._bayer_gb_format,
266 PixelFormat.BAYER_GB_10: self._bayer_gb_format,
267 PixelFormat.BAYER_GB_10_PACKED: self._bayer_gb_format,
268 PixelFormat.BAYER_GB_10_GROUPED_40_IDS: self._bayer_gb_format,
269 PixelFormat.BAYER_GB_12: self._bayer_gb_format,
270 PixelFormat.BAYER_GB_12_PACKED: self._bayer_gb_format,
271 PixelFormat.BAYER_GB_12_GROUPED_24_IDS: self._bayer_gb_format,
272
273 # BayerGR
274 PixelFormat.BAYER_GR_8: self._bayer_gr_format,
275 PixelFormat.BAYER_GR_10: self._bayer_gr_format,
276 PixelFormat.BAYER_GR_10_PACKED: self._bayer_gr_format,
277 PixelFormat.BAYER_GR_10_GROUPED_40_IDS: self._bayer_gr_format,
278 PixelFormat.BAYER_GR_12: self._bayer_gr_format,
279 PixelFormat.BAYER_GR_12_PACKED: self._bayer_gr_format,
280 PixelFormat.BAYER_GR_12_GROUPED_24_IDS: self._bayer_gr_format,
281
282 # BayerRG
283 PixelFormat.BAYER_RG_8: self._bayer_rg_format,
284 PixelFormat.BAYER_RG_10: self._bayer_rg_format,
285 PixelFormat.BAYER_RG_10_PACKED: self._bayer_rg_format,
286 PixelFormat.BAYER_RG_10_GROUPED_40_IDS: self._bayer_rg_format,
287 PixelFormat.BAYER_RG_12: self._bayer_rg_format,
288 PixelFormat.BAYER_RG_12_PACKED: self._bayer_rg_format,
289 PixelFormat.BAYER_RG_12_GROUPED_24_IDS: self._bayer_rg_format,
290
291 # Mono
292 PixelFormat.MONO_8: self._mono_format,
293 PixelFormat.MONO_10: self._mono_format,
294 PixelFormat.MONO_10_PACKED: self._mono_format,
295 PixelFormat.MONO_10_GROUPED_40_IDS: self._mono_format,
296 PixelFormat.MONO_12: self._mono_format,
297 PixelFormat.MONO_12_PACKED: self._mono_format,
298 PixelFormat.MONO_12_GROUPED_24_IDS: self._mono_format,
299
300 # YUV
301 PixelFormat.YUV420_8_YY_UV_SEMIPLANAR_IDS: lambda _: PixelFormat.RGB_8,
302 PixelFormat.YUV420_8_YY_VU_SEMIPLANAR_IDS: lambda _: PixelFormat.RGB_8,
303 PixelFormat.YUV422_8_UYVY: lambda _: PixelFormat.RGB_8,
304
305 }
306
307 func = mapping.get(input_pixel_format)
308 if func is None:
309 return input_pixel_format
310 return func(output_bit_depth)
311
312 @staticmethod
313 def _bayer_bg_format(bit_depth: int) -> PixelFormat:
314 if bit_depth >= 12:
315 return PixelFormat.BAYER_BG_12
316 elif bit_depth >= 10:
317 return PixelFormat.BAYER_BG_10
318 return PixelFormat.BAYER_BG_8
319
320 @staticmethod
321 def _bayer_gb_format(bit_depth: int) -> PixelFormat:
322 if bit_depth >= 12:
323 return PixelFormat.BAYER_GB_12
324 elif bit_depth >= 10:
325 return PixelFormat.BAYER_GB_10
326 return PixelFormat.BAYER_GB_8
327
328 @staticmethod
329 def _bayer_gr_format(bit_depth: int) -> PixelFormat:
330 if bit_depth >= 12:
331 return PixelFormat.BAYER_GR_12
332 elif bit_depth >= 10:
333 return PixelFormat.BAYER_GR_10
334 return PixelFormat.BAYER_GR_8
335
336 @staticmethod
337 def _bayer_rg_format(bit_depth: int) -> PixelFormat:
338 if bit_depth >= 12:
339 return PixelFormat.BAYER_RG_12
340 elif bit_depth >= 10:
341 return PixelFormat.BAYER_RG_10
342 return PixelFormat.BAYER_RG_8
343
344 @staticmethod
345 def _mono_format(bit_depth: int) -> PixelFormat:
346 if bit_depth >= 12:
347 return PixelFormat.MONO_12
348 elif bit_depth >= 10:
349 return PixelFormat.MONO_10
350 return PixelFormat.MONO_8
Image Class for working with algorithms.
Definition image.py:39
Base class for all pipeline modules.
Definition module_base.py:8
Unpack is an image pipeline module that converts packed pixel formats into corresponding unpacked Bay...
None reset_to_default(self)
Resets all module settings.
None release_buffers(self)
Frees unused internal buffers.
None deserialize(self, IArchive archive)
Restores the object's state from the provided archive.
str type(self)
Returns the type of the module for serialization purposes.
PixelFormat _get_output_pixel_format(self, PixelFormat input_pixel_format, int output_bit_depth)
int target_bit_depth(self)
Get the target bit depth used during image processing.
Image process(self, Image input_image)
Converts a packed pixel format image into an unpacked Bayer or monochrome format.
None __init__(self)
Creates an instance of class UnpackModule.
None serialize(self, IArchive archive)
Serializes the object's internal state into the provided archive.