-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathYOLO_functions.py
More file actions
146 lines (109 loc) · 4.39 KB
/
YOLO_functions.py
File metadata and controls
146 lines (109 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import os
import cv2
import matplotlib.pyplot as plt
def load_images_by_class(df_target, classes, base_path):
"""
Loads one representative image per class from the given dataframe.
Args:
df_target: Pandas DataFrame containing object detection info.
classes: List of class IDs to process.
base_path: Directory where image files are stored.
Returns:
images: Dictionary of class_id -> RGB image.
boxes: Dictionary of class_id -> [xmin, xmax, ymin, ymax]
"""
boxes = {}
images = {}
for class_id in classes:
print(f"Processing class {class_id}...")
target_rows = df_target[df_target['class_id'] == class_id]
print(f"Number of rows for class {class_id}: {len(target_rows)}")
if target_rows.empty:
print(f"No data found for class {class_id}. Skipping.")
continue
image_found = False
for _, row in target_rows.iterrows():
file_name = row['frame']
image_path = os.path.join(base_path, file_name)
if not os.path.exists(image_path):
continue
print(f"Found image {image_path} for class {class_id}.")
image = cv2.imread(image_path)
if image is None:
print(f"Failed to load image {image_path}. Trying next row...")
continue
else:
image_found = True
break
if image_found:
print(f"Image found AND read for class {class_id}: {image_path}")
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
images[class_id] = image_rgb
boxes[class_id] = [
int(row['xmin']),
int(row['xmax']),
int(row['ymin']),
int(row['ymax'])
]
return images, boxes
def extract_yolo_predictions(results, filename, yolo_to_custom):
"""
Extracts YOLO predictions from results and maps them to custom class IDs.
Args:
results: YOLO model inference results (expects results[0].boxes).
filename: Name of the current frame/image.
yolo_to_custom: Dictionary mapping YOLO class IDs to custom class IDs.
Returns:
List of predictions: [frame, xmin, xmax, ymin, ymax, custom_class_id]
"""
predictions_data = []
for box in results[0].boxes:
frame = filename
center_x, center_y, width, height = box.xywh[0].int().tolist()
xmin = int(center_x - width / 2)
ymin = int(center_y - height / 2)
xmax = int(center_x + width / 2)
ymax = int(center_y + height / 2)
class_id = box.cls.int().item()
custom_class_id = yolo_to_custom.get(class_id, -1)
predictions_data.append([frame, xmin, xmax, ymin, ymax, custom_class_id])
return predictions_data
def compute_iou(boxA, boxB):
"""
Computes Intersection over Union (IoU) between two bounding boxes.
Args:
boxA: [xmin, ymin, xmax, ymax]
boxB: [xmin, ymin, xmax, ymax]
Returns:
IoU value (float)
"""
xA = max(boxA[0], boxB[0])
yA = max(boxA[1], boxB[1])
xB = min(boxA[2], boxB[2])
yB = min(boxA[3], boxB[3])
interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)
iou = interArea / float(boxAArea + boxBArea - interArea) if (boxAArea + boxBArea - interArea) != 0 else 0
return iou
def calculate_iou_for_predictions(predictions_df, ground_truth_df):
"""
Matches predictions to ground truth boxes and computes IoUs.
Args:
predictions_df: DataFrame of predicted boxes.
ground_truth_df: DataFrame of ground truth boxes.
Returns:
iou_info: List of [pred_index, gt_index, pred_class, gt_class, IoU]
"""
iou_info = []
for i, pred in predictions_df.iterrows():
frame = pred['frame']
pred_box = [pred['xmin'], pred['ymin'], pred['xmax'], pred['ymax']]
pred_class = pred['class_id']
gt_boxes = ground_truth_df[ground_truth_df['frame'] == frame]
for j, gt in gt_boxes.iterrows():
gt_box = [gt['xmin'], gt['ymin'], gt['xmax'], gt['ymax']]
gt_class = gt['class_id']
iou = compute_iou(pred_box, gt_box)
iou_info.append([i, j, pred_class, gt_class, iou])
return iou_info