aje6 commited on
Commit
ae3bb59
·
verified ·
1 Parent(s): 2828a91

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +183 -0
utils.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+
4
+ class_names = [
5
+ "A",
6
+ "B",
7
+ "C",
8
+ "D",
9
+ "E",
10
+ "F",
11
+ "G",
12
+ "H",
13
+ "I",
14
+ "J",
15
+ "K",
16
+ "L",
17
+ "M",
18
+ "N",
19
+ "O",
20
+ "P",
21
+ "Q",
22
+ "R",
23
+ "S",
24
+ "T",
25
+ "U",
26
+ "V",
27
+ "W",
28
+ "X",
29
+ "Y",
30
+ "Z",
31
+ ]
32
+
33
+ # Create a list of colors for each class where each color is a tuple of 3 integer values
34
+ rng = np.random.default_rng(3)
35
+ colors = rng.uniform(0, 255, size=(len(class_names), 3))
36
+
37
+
38
+ def nms(boxes, scores, iou_threshold):
39
+ # Sort by score
40
+ sorted_indices = np.argsort(scores)[::-1]
41
+
42
+ keep_boxes = []
43
+ while sorted_indices.size > 0:
44
+ # Pick the last box
45
+ box_id = sorted_indices[0]
46
+ keep_boxes.append(box_id)
47
+
48
+ # Compute IoU of the picked box with the rest
49
+ ious = compute_iou(boxes[box_id, :], boxes[sorted_indices[1:], :])
50
+
51
+ # Remove boxes with IoU over the threshold
52
+ keep_indices = np.where(ious < iou_threshold)[0]
53
+
54
+ # print(keep_indices.shape, sorted_indices.shape)
55
+ sorted_indices = sorted_indices[keep_indices + 1]
56
+
57
+ return keep_boxes
58
+
59
+
60
+ def multiclass_nms(boxes, scores, class_ids, iou_threshold):
61
+ unique_class_ids = np.unique(class_ids)
62
+
63
+ keep_boxes = []
64
+ for class_id in unique_class_ids:
65
+ class_indices = np.where(class_ids == class_id)[0]
66
+ class_boxes = boxes[class_indices, :]
67
+ class_scores = scores[class_indices]
68
+
69
+ class_keep_boxes = nms(class_boxes, class_scores, iou_threshold)
70
+ keep_boxes.extend(class_indices[class_keep_boxes])
71
+
72
+ return keep_boxes
73
+
74
+
75
+ def compute_iou(box, boxes):
76
+ # Compute xmin, ymin, xmax, ymax for both boxes
77
+ xmin = np.maximum(box[0], boxes[:, 0])
78
+ ymin = np.maximum(box[1], boxes[:, 1])
79
+ xmax = np.minimum(box[2], boxes[:, 2])
80
+ ymax = np.minimum(box[3], boxes[:, 3])
81
+
82
+ # Compute intersection area
83
+ intersection_area = np.maximum(0, xmax - xmin) * np.maximum(0, ymax - ymin)
84
+
85
+ # Compute union area
86
+ box_area = (box[2] - box[0]) * (box[3] - box[1])
87
+ boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
88
+ union_area = box_area + boxes_area - intersection_area
89
+
90
+ # Compute IoU
91
+ iou = intersection_area / union_area
92
+
93
+ return iou
94
+
95
+
96
+ def xywh2xyxy(x):
97
+ # Convert bounding box (x, y, w, h) to bounding box (x1, y1, x2, y2)
98
+ y = np.copy(x)
99
+ y[..., 0] = x[..., 0] - x[..., 2] / 2
100
+ y[..., 1] = x[..., 1] - x[..., 3] / 2
101
+ y[..., 2] = x[..., 0] + x[..., 2] / 2
102
+ y[..., 3] = x[..., 1] + x[..., 3] / 2
103
+ return y
104
+
105
+
106
+ def draw_detections(image, boxes, scores, class_ids, mask_alpha=0.3):
107
+ det_img = image.copy()
108
+
109
+ img_height, img_width = image.shape[:2]
110
+ font_size = min([img_height, img_width]) * 0.0006
111
+ text_thickness = int(min([img_height, img_width]) * 0.001)
112
+
113
+ #det_img = draw_masks(det_img, boxes, class_ids, mask_alpha)
114
+
115
+ # Draw bounding boxes and labels of detections
116
+ for class_id, box, score in zip(class_ids, boxes, scores):
117
+ color = colors[class_id]
118
+
119
+ draw_box(det_img, box, color)
120
+
121
+ label = class_names[class_id]
122
+ caption = f"{label} {int(score * 100)}%"
123
+ draw_text(det_img, caption, box, color, font_size, text_thickness)
124
+
125
+ return det_img
126
+
127
+
128
+ def draw_box(
129
+ image: np.ndarray,
130
+ box: np.ndarray,
131
+ color: tuple[int, int, int] = (0, 0, 255),
132
+ thickness: int = 2,
133
+ ) -> np.ndarray:
134
+ x1, y1, x2, y2 = box.astype(int)
135
+ return cv2.rectangle(image, (x1, y1), (x2, y2), color, thickness)
136
+
137
+
138
+ def draw_text(
139
+ image: np.ndarray,
140
+ text: str,
141
+ box: np.ndarray,
142
+ color: tuple[int, int, int] = (0, 0, 255),
143
+ font_size: float = 0.001,
144
+ text_thickness: int = 2,
145
+ ) -> np.ndarray:
146
+ x1, y1, x2, y2 = box.astype(int)
147
+ (tw, th), _ = cv2.getTextSize(
148
+ text=text,
149
+ fontFace=cv2.FONT_HERSHEY_SIMPLEX,
150
+ fontScale=font_size,
151
+ thickness=text_thickness,
152
+ )
153
+ th = int(th * 1.2)
154
+
155
+ cv2.rectangle(image, (x1, y1), (x1 + tw, y1 - th), color, -1)
156
+
157
+ return cv2.putText(
158
+ image,
159
+ text,
160
+ (x1, y1),
161
+ cv2.FONT_HERSHEY_SIMPLEX,
162
+ font_size,
163
+ (255, 255, 255),
164
+ text_thickness,
165
+ cv2.LINE_AA,
166
+ )
167
+
168
+
169
+ def draw_masks(
170
+ image: np.ndarray, boxes: np.ndarray, classes: np.ndarray, mask_alpha: float = 0.3
171
+ ) -> np.ndarray:
172
+ mask_img = image.copy()
173
+
174
+ # Draw bounding boxes and labels of detections
175
+ for box, class_id in zip(boxes, classes):
176
+ color = colors[class_id]
177
+
178
+ x1, y1, x2, y2 = box.astype(int)
179
+
180
+ # Draw fill rectangle in mask image
181
+ cv2.rectangle(mask_img, (x1, y1), (x2, y2), color, -1)
182
+
183
+ return cv2.addWeighted(mask_img, mask_alpha, image, 1 - mask_alpha, 0)