IDS peak ICV v1.2.0
Loading...
Searching...
No Matches
region_selector.py
Go to the documentation of this file.
1from __future__ import annotations
2
3import ctypes
4from typing import List, Tuple, Union, TypeAlias, Callable, cast
5
6import numpy as np
7import numpy.typing as npt
8
9from ids_peak_icv import lib_loader
10from ids_peak_icv.exceptions import NotSupportedException, NotPossibleException
11from ids_peak_icv.backend.datatypes import (peak_common_interval_u, peak_icv_interval_f,
12 peak_common_rectangle_f, peak_icv_region_handle)
13from ids_peak_icv.backend.utils import create_array, transform, execute_and_map_return_codes
14
15from ids_peak_common.datatypes.interval import Interval
17from ids_peak_icv.datatypes.region import Region
18
19# Note: We loose type info here, as it is stored as a pointer to a python object
20RegionArray: TypeAlias = npt.NDArray[np.object_]
21
22
24 """!
25 @brief
26 Represents a selector for regions based on various criteria.
27
28 @ingroup ids_peak_icv_python_selectors
29 @since ids_peak_icv 1.1
30 """
31
32 def __init__(self, regions: RegionArray) -> None:
33 """!
34 @brief
35 Creates a region selector.
36
37 It is possible to provide an empty numpy array (no regions),
38 but it does not make sense, because in this case no regions can be selected.
39
40 @param regions: List of Region objects to select from.
41
42 @exception NotSupportedException: If regions is not a numpy array.
43
44 @since ids_peak_icv 1.1
45 """
46
47 if not isinstance(regions, np.ndarray):
48 raise NotSupportedException("Parameter regions has to be a numpy array of Region objects.")
49
50 self._regions = regions
51
52 @property
53 def regions(self) -> RegionArray:
54 """!
55 @brief
56 Get the selected regions.
57
58 @return List[Region]: List of selected Region objects.
59
60 @since ids_peak_icv 1.1
61 """
62 return self._regions
63
64 def select_by_area(self, interval: Interval) -> RegionSelector:
65 """!
66 @brief
67 Select regions based on their area.
68
69 @param interval: Interval to select by. Only positive values are allowed.
70
71 @return RegionSelector: New RegionSelector object with selected regions.
72
73 @exception NotSupportedException: If interval has a wrong type or the interval is not valid for this function.
74 @exception NotPossibleException: If interval has atleast one negative component.
75
76 @since ids_peak_icv 1.1
77 """
78
79 if not isinstance(interval, Interval):
81 "The given interval is invalid. It has to be an Interval, a Tuple(int, int) or a List "
82 "with two integers")
83
84 if interval._is_negative():
85 raise NotPossibleException("The given interval is negative. You can not select a negative area.")
86
87 c_interval = peak_common_interval_u(interval.minimum, interval.maximum)
88
89 return self._select_by(lib_loader.dll().peak_icv_Region_SelectByArea_GetCount,
90 lib_loader.dll().peak_icv_Region_SelectByArea,
91 c_interval)
92
93 def select_by_center_of_gravity_x(self, interval: Union[
94 Interval, Tuple[float, float], List[float], Tuple[int, int], List[int]]) -> RegionSelector:
95 """!
96 @brief
97 Select regions based on the center of gravity's x coordinate.
98
99 @param interval: Interval to select by.
100
101 @return RegionSelector: New RegionSelector object with selected regions.
102
103 @exception NotSupportedException: If interval has a wrong type or the interval is not valid for this function.
104
105 @since ids_peak_icv 1.1
106 """
107
108 if (isinstance(interval, tuple) or isinstance(interval, list)) and len(interval) == 2:
109 return self.select_by_center_of_gravity_x(Interval(interval[0], interval[1]))
110
111 if not isinstance(interval, Interval):
113 "The given interval is invalid. It has to be an Interval,"
114 "a Tuple(float | int, float | int) or a List with two float | int")
115
116 c_interval = peak_icv_interval_f(interval.minimum, interval.maximum)
117
118 return self._select_by(lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityX_GetCount,
119 lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityX,
120 c_interval)
121
122 def select_by_center_of_gravity_y(self, interval: Union[
123 Interval, Tuple[float, float], List[float], Tuple[int, int], List[int]]) -> RegionSelector:
124 """!
125 @brief
126 Select regions based in the center of gravity's y coordinate.
127
128 @param interval: Interval to select by.
129
130 @return RegionSelector: New RegionSelector object with selected regions.
131
132 @exception NotSupportedException: If interval has a wrong type or the interval is not valid for this function.
133
134 @since ids_peak_icv 1.1
135 """
136 if (isinstance(interval, tuple) or isinstance(interval, list)) and len(interval) == 2:
137 return self.select_by_center_of_gravity_y(Interval(interval[0], interval[1]))
138
139 if not isinstance(interval, Interval):
141 "The given interval is invalid. It has to be an Interval,"
142 "a Tuple(float | int, float | int) or a List with two float | int")
143
144 c_interval = peak_icv_interval_f(interval.minimum, interval.maximum)
145
146 return self._select_by(lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityY_GetCount,
147 lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityY,
148 c_interval)
149
150 def select_by_center_of_gravity_rect(self, rect: Union[
151 Rectangle, Tuple[float, float, float, float], List[float], Tuple[int, int, int, int], List[
152 int]]) -> RegionSelector:
153 """!
154 @brief
155 Select regions based in the center of gravity's position within a rectangle.
156
157 @param rect: Rectangle to select by.
158
159 @return RegionSelector: New RegionSelector object with selected regions.
160
161 @exception NotSupportedException: If interval has a wrong type or the interval is not valid for this function.
162
163 @since ids_peak_icv 1.1
164 """
165
166 if (isinstance(rect, tuple) or isinstance(rect, list)) and len(rect) == 4:
168 Rectangle.create_from_coordinates_and_dimensions(
169 rect[0], rect[1], rect[2], rect[3]))
170
171 if not isinstance(rect, Rectangle):
173 "The given interval is invalid. It has to be an Interval,"
174 "a Tuple(float | int, float | int, float | int, float | int) or a List with four float | int")
175
176 c_rect = peak_common_rectangle_f(rect.x, rect.y, rect.width, rect.height)
177
178 return self._select_by(lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityRect_GetCount,
179 lib_loader.dll().peak_icv_Region_SelectByCenterOfGravityRect,
180 c_rect)
181
182 def _select_by(self, select_by_get_count_function: Callable, select_by_function: Callable,
183 c_interval: ctypes.Structure) -> RegionSelector:
184 if self._regions.size == 0:
185 return RegionSelector(np.ndarray(0))
186
187 handles = create_array(peak_icv_region_handle, len(self.regionsregions))
188 transform(self.regionsregions, handles, lambda elem: elem._handle)
189
190 c_count = ctypes.c_size_t()
191 execute_and_map_return_codes(select_by_get_count_function, handles, len(handles), c_interval,
192 ctypes.pointer(c_count))
193
194 if c_count.value == 0:
195 return RegionSelector(np.ndarray(0))
196
197 selected_handles = create_array(peak_icv_region_handle, c_count.value)
198 execute_and_map_return_codes(select_by_function, handles, len(handles), c_interval,
199 selected_handles,
200 len(selected_handles))
201
202 iterable = (Region(_handle=regionHandle) for regionHandle in selected_handles)
203 # workaround to fill the array on python3.7 with numpy
204 selected_regions = np.empty(len(selected_handles), dtype=Region)
205 for i, it in enumerate(iterable):
206 selected_regions[i] = it
207
208 return RegionSelector(cast(np.ndarray, selected_regions))
Represents an interval with lower and upper boundaries.
Definition interval.py:7
Represents a region consisting of a set of points in the image plane.
Definition region.py:29
Thrown when an operation cannot be performed due to logical constraints.
Definition exceptions.py:85
Thrown when a requested operation is not implemented or supported.
Definition exceptions.py:71
Represents a selector for regions based on various criteria.
RegionSelector select_by_center_of_gravity_x(self, Union[Interval, Tuple[float, float], List[float], Tuple[int, int], List[int]] interval)
Select regions based on the center of gravity's x coordinate.
RegionSelector select_by_center_of_gravity_y(self, Union[Interval, Tuple[float, float], List[float], Tuple[int, int], List[int]] interval)
Select regions based in the center of gravity's y coordinate.
None __init__(self, RegionArray regions)
Creates a region selector.
RegionSelector _select_by(self, Callable select_by_get_count_function, Callable select_by_function, ctypes.Structure c_interval)
RegionSelector select_by_area(self, Interval interval)
Select regions based on their area.
RegionArray regions(self)
Get the selected regions.
RegionSelector select_by_center_of_gravity_rect(self, Union[Rectangle, Tuple[float, float, float, float], List[float], Tuple[int, int, int, int], List[int]] rect)
Select regions based in the center of gravity's position within a rectangle.