1
1
"""ImageProcessor for getting detectable info from images."""
2
2
3
3
import datetime
4
- from typing import Any , Dict , Optional , Tuple
4
+ from typing import Any , Dict , Optional , Set , Tuple
5
5
from colorthief import ColorThief
6
6
import cv2
7
7
import numpy as np
@@ -42,6 +42,32 @@ def __mask_image__(crop: Any, color_variant: ColorVariantConfig) -> Tuple[Any, i
42
42
return (output , matches )
43
43
44
44
45
+ def __detect_objects__ (mask : Any , object : ObjectConfig ) -> Set [Dict [str , Any ]]:
46
+ """Detect objects and return list of bounding boxes."""
47
+ # get gray image
48
+ gray = cv2 .cvtColor (mask , cv2 .COLOR_BGR2GRAY )
49
+
50
+ # calculate contours
51
+ _ , thresh = cv2 .threshold (gray , 1 , 255 , 0 )
52
+ contours , _ = cv2 .findContours (thresh , cv2 .RETR_EXTERNAL , cv2 .CHAIN_APPROX_SIMPLE )
53
+
54
+ detected = []
55
+
56
+ for contour in contours :
57
+ x , y , w , h = cv2 .boundingRect (contour )
58
+ area = w * h
59
+
60
+ if object .min_area < area < object .max_area :
61
+ detected .append (
62
+ {
63
+ "box" : [x , y , x + w , y + h ],
64
+ "area" : area ,
65
+ }
66
+ )
67
+
68
+ return detected
69
+
70
+
45
71
class ImageProcessor :
46
72
"""Processing images with swatch config data."""
47
73
@@ -76,8 +102,22 @@ def __check_image__(
76
102
continue
77
103
78
104
output , matches = __mask_image__ (crop , color_variant )
79
-
80
- if detectable .min_area < matches < detectable .max_area :
105
+ detected_objects = __detect_objects__ (crop , detectable )
106
+
107
+ if detected_objects :
108
+
109
+ # draw bounding boxes on image if enabled
110
+ if snapshot .bounding_box :
111
+ for obj in detected_objects :
112
+ cv2 .rectangle (
113
+ output ,
114
+ (obj ["box" ][0 ], obj ["box" ][1 ]),
115
+ (obj ["box" ][2 ], obj ["box" ][3 ]),
116
+ (0 , 255 , 0 ),
117
+ 4 ,
118
+ )
119
+
120
+ # save the snapshot if enabled
81
121
if snapshot .save_detections and snapshot .mode in [
82
122
SnapshotModeEnum .ALL ,
83
123
SnapshotModeEnum .MASK ,
@@ -91,9 +131,9 @@ def __check_image__(
91
131
92
132
return {
93
133
"result" : True ,
94
- "area" : matches ,
95
134
"variant" : variant_name ,
96
135
"camera_name" : camera_name ,
136
+ "objects" : detected_objects ,
97
137
}
98
138
99
139
if matches > best_fail .get ("area" , 0 ):
0 commit comments