Skip to content

Commit 7ff4b6f

Browse files
authored
Merge pull request #13 from agfianf/docs/mcc
Docs/mcc
2 parents 05cb139 + 1056761 commit 7ff4b6f

File tree

15 files changed

+182
-26
lines changed

15 files changed

+182
-26
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ sync-docs:
2828

2929
sync-all:
3030
uv sync --all-groups --no-group dev-model
31+
32+
docs-run:
33+
uv run mkdocs serve -a localhost:8000

color_correction/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
__version__ = "0.0.1-rc4"
1+
__version__ = "0.0.1-rc5"
22

33
# fmt: off
44
from .constant.color_checker import reference_color_d50_bgr as REFERENCE_COLOR_D50_BGR # noqa: N812, I001
55
from .constant.color_checker import reference_color_d50_rgb as REFERENCE_COLOR_D50_RGB # noqa: N812, I001
66
from .core.card_detection.det_yv8_onnx import YOLOv8CardDetector
7-
from .schemas.det_yv8 import DetectionResult as YOLOv8DetectionResult
7+
from .core.card_detection.mcc_det import MCCardDetector
8+
from .schemas.det_yv8 import DetectionResult
89
from .services.color_correction import ColorCorrection
910
from .services.correction_analyzer import ColorCorrectionAnalyzer
1011
# fmt: on
@@ -16,5 +17,6 @@
1617
"ColorCorrection",
1718
"ColorCorrectionAnalyzer",
1819
"YOLOv8CardDetector",
19-
"YOLOv8DetectionResult",
20+
"MCCardDetector",
21+
"DetectionResult",
2022
]

color_correction/core/card_detection/mcc_det.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,55 @@
88

99

1010
class MCCardDetector(BaseCardDetector):
11+
"""MCCardDetector implements card detection using OpenCV's ColorChecker detector (cv2.mcc).
12+
13+
This class detects ColorChecker cards and their color patches in an image using OpenCV's
14+
built-in MCC ([Macbeth ColorChecker](https://docs.opencv.org/4.11.0/dd/d19/group__mcc.html)) detection module.
15+
It provides methods to detect cards, extract patch coordinates, and visualize detections.
16+
17+
Parameters
18+
----------
19+
use_gpu : bool, optional
20+
Whether to use GPU for detection (not used in OpenCV MCC), by default False.
21+
conf_th : float, optional
22+
Confidence threshold for detection filtering, by default 0.15.
23+
"""
24+
1125
def __init__(self, use_gpu: bool = False, conf_th: float = 0.15) -> None:
26+
"""
27+
Initialize the MCCardDetector.
28+
29+
Parameters
30+
----------
31+
use_gpu : bool, optional
32+
Whether to use GPU for detection (not used in OpenCV MCC), by default False.
33+
conf_th : float, optional
34+
Confidence threshold for detection filtering, by default 0.15.
35+
"""
1236
self.use_gpu = use_gpu
1337
self.conf_th = conf_th
1438

15-
def detect(self, image: np.ndarray, conf: float = 0.15) -> DetectionResult:
39+
def detect(self, image: np.ndarray, conf: float | None = None) -> DetectionResult:
40+
"""
41+
Detect ColorChecker cards and their color patches in the input image.
42+
43+
Parameters
44+
----------
45+
image : np.ndarray
46+
Input image (BGR) in which to detect ColorChecker cards.
47+
conf : float, optional
48+
Confidence threshold for detection filtering, by default 0.15.
49+
50+
Returns
51+
-------
52+
DetectionResult
53+
A dataclass containing detected segments (card and patch polygons),
54+
confidence scores, and class IDs. Boxes are not used in this case (None).
55+
"""
56+
57+
if conf is None:
58+
conf = self.conf_th
59+
1660
ls_segments = []
1761
ls_class_ids = []
1862
ls_scores = []
@@ -63,6 +107,21 @@ def detect(self, image: np.ndarray, conf: float = 0.15) -> DetectionResult:
63107
)
64108

65109
def _extract_chart_coordinates(self, image_copy: np.ndarray, charts_rgb: np.ndarray) -> list[list[tuple[int, int]]]:
110+
"""
111+
Extracts the coordinates of color patches from the detected ColorChecker.
112+
113+
Parameters
114+
----------
115+
image_copy : np.ndarray
116+
Copy of the input image for visualization (patch points drawn).
117+
charts_rgb : np.ndarray
118+
Array of shape (N, 2) containing the (x, y) coordinates of patch corners.
119+
120+
Returns
121+
-------
122+
list of list of tuple of int
123+
List of patches, each patch is a list of 4 (x, y) tuples.
124+
"""
66125
random_color = (np.random.randint(0, 255), np.random.randint(0, 255), np.random.randint(0, 255))
67126
ls_chart_coord = []
68127
ls_group_patch = []
@@ -94,6 +153,18 @@ def _extract_chart_coordinates(self, image_copy: np.ndarray, charts_rgb: np.ndar
94153
return ls_chart_coord
95154

96155
def _draw_box_color_path(self, image_copy: np.ndarray, i: int, group_patch: list[tuple[int, int]]) -> None:
156+
"""
157+
Draws a polygon and label for a color patch on the image.
158+
159+
Parameters
160+
----------
161+
image_copy : np.ndarray
162+
Image on which to draw the patch.
163+
i : int
164+
Index or label for the patch.
165+
group_patch : list of tuple of int
166+
List of 4 (x, y) tuples representing the patch corners.
167+
"""
97168
random_color = (np.random.randint(0, 255), np.random.randint(0, 255), np.random.randint(0, 255))
98169
# draw patch
99170
cv2.polylines(image_copy, [np.int32(group_patch)], True, random_color, 2)

color_correction/schemas/det_yv8.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,5 @@ def draw_detections(
8181
"""
8282
if self.boxes is not None:
8383
return draw_detections(image, self.boxes, self.scores, self.class_ids)
84-
elif self.segment is not None:
84+
if self.segment is not None:
8585
return draw_segmentation(image, self.segment, self.scores, self.class_ids)

color_correction/services/color_correction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ColorCorrection:
6969

7070
def __init__(
7171
self,
72-
detection_model: LiteralModelDetection = "yolov8",
72+
detection_model: LiteralModelDetection = "mcc",
7373
detection_conf_th: float = 0.25,
7474
correction_model: LiteralModelCorrection = "least_squares",
7575
reference_image: ImageBGR | None = None,

color_correction/utils/yolo_utils.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,18 @@ def draw_segmentation(
198198
color = COLORS[class_id]
199199
cv2.polylines(image, [np.int32(segment)], True, color, 2)
200200

201-
draw_text(
201+
font_size = min(image.shape[:2]) * 0.0005
202+
text_thickness = int(min(image.shape[:2]) * 0.001)
203+
204+
cv2.putText(
202205
image,
203206
f"{class_names[class_id]} {int(score * 100)}%",
204207
segment[0],
205-
color,
206-
font_size=0.001,
207-
text_thickness=2,
208+
cv2.FONT_HERSHEY_SIMPLEX,
209+
font_size,
210+
(255, 255, 255),
211+
text_thickness,
212+
cv2.LINE_AA,
208213
)
209214
return image
210215

213 KB
Loading

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pip install color-correction
4949
## 🤸 TODO
5050

5151
- [ ] Add Loggers
52-
- [ ] Add detection MCC:CCheckerDetector from opencv
52+
- [x] Add detection MCC:CCheckerDetector from opencv
5353
- [ ] Add Segmentation Color Checker using YOLOv11 ONNX
5454
- [ ] Improve validation preprocessing (e.g., auto-match-orientation CC)
5555
- [ ] Add more analysis and evaluation metrics _(still thinking...)_
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# `MCCardDetector` class
2+
3+
4+
::: color_correction.core.card_detection.mcc_det.MCCardDetector

docs/tutorial/color_correction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ This is the main feature of this package. Its capture to color correct an image
4747

4848
# Step 3: Initialize the color correction model with specified parameters
4949
color_corrector = ColorCorrection(
50-
detection_model="yolov8",
50+
detection_model="yolov8", # or "mcc"
5151
detection_conf_th=0.25,
5252
correction_model="affine_reg", # (1)
5353
degree=3, # (2)

0 commit comments

Comments
 (0)