11import cv2
22import numpy as np
33
4+ from color_correction .schemas .custom_types import BoundingBox , ColorPatchType , ImageBGR
45from color_correction .schemas .det_yv8 import DetectionResult
56from color_correction .utils .geometry_processing import (
67 extract_intersecting_patches ,
1213 crop_region_with_margin ,
1314)
1415
15- # Type aliases for better readability
16- BoundingBox = tuple [int , int , int , int ]
17- RGB = tuple [float , float , float ]
18- BGR = tuple [float , float , float ]
19-
2016
2117class DetectionProcessor :
2218 """
23- A class to process color calibration card detections and extract color patches.
24-
25- This class handles the detection and processing of color calibration cards and their
26- individual color patches, including visualization and RGB value extraction .
19+ A class for processing detection results and transforming them using
20+ available utility methods. This class takes the output from an object
21+ detection model (e.g., YOLOv8) and provides functionality to separate,
22+ process, and visualize detected color checker cards and their patches .
2723 """
2824
2925 @staticmethod
3026 def get_each_class_box (
3127 prediction : DetectionResult ,
3228 ) -> tuple [list [BoundingBox ], list [BoundingBox ]]:
3329 """
34- Separate detection boxes by class (cards and patches) .
30+ Separates detection boxes into card boxes and patch boxes .
3531
3632 Parameters
3733 ----------
3834 prediction : DetectionResult
39- Detection results containing boxes and class IDs
35+ The detection output that includes bounding boxes and class IDs.
4036
4137 Returns
4238 -------
43- Tuple[List[BoundingBox], List[BoundingBox]]
44- Two lists containing card boxes and patch boxes respectively
39+ tuple[list[BoundingBox], list[BoundingBox]]
40+ A tuple containing:
41+
42+ - a list of card boxes (class id 1)
43+ - a list of patch boxes (class id 0).
4544 """
4645 ls_cards = [
4746 box
@@ -66,36 +65,41 @@ def get_each_class_box(
6665 @staticmethod
6766 def print_summary (prediction : DetectionResult ) -> None :
6867 """
69- Print a summary of detected objects .
68+ Prints a summary of the detected cards and patches .
7069
7170 Parameters
7271 ----------
7372 prediction : DetectionResult
74- Detection results to summarize
73+ The detection result to summarize.
7574 """
7675 ls_cards , ls_patches = DetectionProcessor .get_each_class_box (prediction )
7776 print (f"Number of cards detected: { len (ls_cards )} " )
7877 print (f"Number of patches detected: { len (ls_patches )} " )
7978
8079 @staticmethod
8180 def process_patches (
82- input_image : np . ndarray ,
81+ input_image : ImageBGR ,
8382 ordered_patches : list [tuple [BoundingBox , tuple [int , int ]] | None ],
84- ) -> tuple [list [RGB ], np . ndarray ]:
83+ ) -> tuple [list [ColorPatchType ], ImageBGR ]:
8584 """
86- Process detected patches to extract RGB values and create a visualization.
85+ Processes each detected patch by extracting its region from the image,
86+ computing its mean BGR color, and building a visualization grid.
8787
8888 Parameters
8989 ----------
90- input_image : np.ndarray
91- Input image containing the patches
92- ordered_patches : List[Optional[BoundingBox]]
93- List of ordered patch coordinates
90+ input_image : ImageBGR
91+ The original image containing detected patches.
92+ ordered_patches : list[tuple[BoundingBox, tuple[int, int]] | None]
93+ The list of ordered patch coordinates paired with their center
94+ points, possibly with missing entries as None.
9495
9596 Returns
9697 -------
97- Tuple[List[RGB], np.ndarray]
98- List of RGB values and visualization image
98+ tuple[list[ColorPatchType], ImageBGR]
99+ a tuple containing:
100+
101+ - list of mean BGR color values for each patch.
102+ - an image visualizing these patches in a grid layout.
99103 """
100104 patch_size = (50 , 50 , 1 )
101105 ls_bgr_mean_patch = []
@@ -129,31 +133,42 @@ def process_patches(
129133
130134 @staticmethod
131135 def extract_color_patches (
132- input_image : np . ndarray ,
136+ input_image : ImageBGR ,
133137 prediction : DetectionResult ,
134138 draw_processed_image : bool = False ,
135- ) -> tuple [list [BGR ], np . ndarray , np . ndarray | None ]:
139+ ) -> tuple [list [ColorPatchType ], ImageBGR , ImageBGR | None ]:
136140 """
137- Extract and process color patches from the detected calibration card.
141+ Extracts and processes color patches from detected color checker cards,
142+ transforming the detection results with available methods.
143+
144+ The method first separates detected cards and patches, generates an expected
145+ patch grid, and then matches the detected patches with this grid. If patches
146+ are missing, it attempts to auto-fill them with suggested coordinates.
147+ Finally, it computes the mean color for each patch and builds a visualization.
138148
139149 Parameters
140150 ----------
141- input_image : np.ndarray
142- Input image containing the color calibration card
151+ input_image : ImageBGR
152+ The original image containing the color checker card.
143153 prediction : DetectionResult
144- Detection results from YOLOv8
154+ The detection result output from the model.
145155 draw_processed_image : bool, optional
146- Whether to create a visualization image, by default False
156+ If True, returns an additional image with visualized detections.
157+ Otherwise, only patch processing is performed. Defaults to False.
147158
148159 Returns
149160 -------
150- Tuple[List[BGR], np.ndarray, Optional[np.ndarray]]
151- BGR values, patch visualization, and optional detection visualization
161+ tuple[list[ColorPatchType], ImageBGR, ImageBGR | None]
162+ a tuple containing:
163+
164+ - a list of mean BGR color values for each patch.
165+ - an image visualizing these patches in a grid layout.
166+ - an optional image with visualized detection results.
152167
153168 Raises
154169 ------
155170 ValueError
156- If no cards or patches are detected
171+ If no cards or patches are detected.
157172 """
158173 ls_cards , ls_patches = DetectionProcessor .get_each_class_box (prediction )
159174
@@ -206,30 +221,34 @@ def extract_color_patches(
206221
207222 @staticmethod
208223 def draw_preprocess (
209- image : np . ndarray ,
224+ image : ImageBGR ,
210225 expected_boxes : list [BoundingBox ],
211226 prediction : DetectionResult ,
212227 ls_ordered_patch_bbox : list [BoundingBox | None ],
213228 suggested_patches : dict [int , BoundingBox ] | None = None ,
214- ) -> np . ndarray :
229+ ) -> ImageBGR :
215230 """
216- Draw detection visualizations on the image.
231+ Draws visualizations on the input image to compare the detected patches with
232+ the expected positions. It overlays expected boxes, connects detected patches to
233+ their corresponding expected boxes, and highlights individual patch detections.
217234
218235 Parameters
219236 ----------
220- image : np.ndarray
221- Input image to draw on
222- boxes : List[BoundingBox]
223- List of bounding boxes to draw
224- patch_indices : Optional[List[int]]
225- Indices to label the patches
226- suggested_patches : Optional[Dict[int, BoundingBox]]
227- Additional suggested patch locations to draw
237+ image : ImageBGR
238+ The original image to draw on.
239+ expected_boxes : list[BoundingBox]
240+ List of expected bounding boxes for patches.
241+ prediction : DetectionResult
242+ The detection results containing predicted bounding boxes.
243+ ls_ordered_patch_bbox : list[BoundingBox | None]
244+ The list of ordered patch bounding boxes.
245+ suggested_patches : dict[int, BoundingBox], optional
246+ Dictionary of suggested patch coordinates for missing patches.
228247
229248 Returns
230249 -------
231- np.ndarray
232- Image with visualizations
250+ ImageBGR
251+ The image with drawn detection and patch visualizations.
233252 """
234253 color_green = (0 , 255 , 0 )
235254 color_cyan = (255 , 255 , 10 )
@@ -249,7 +268,7 @@ def draw_preprocess(
249268 thickness = 2 ,
250269 )
251270
252- # draw connection lines between expected and intersecting patches
271+ # Draw connection lines between expected and detected patch boxes
253272 patch = ls_ordered_patch_bbox [idx_b ]
254273 if patch is None :
255274 continue
@@ -263,7 +282,7 @@ def draw_preprocess(
263282 thickness = 1 ,
264283 )
265284
266- # draw all predicted boxes
285+ # Draw all predicted boxes
267286 for pbox , pids , pscore in zip (
268287 prediction .boxes ,
269288 prediction .class_ids ,
0 commit comments