csepartha commited on
Commit
e44d1ed
1 Parent(s): 8b6cb03

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +189 -0
  2. best.pt +3 -0
  3. data.yaml +2 -0
  4. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ RUN BELOW FIRST THEN RUN BELOW
2
+
3
+ # First run the code to get the validation metrics of best.pt
4
+
5
+ from ultralytics import YOLO
6
+
7
+ model_path = "best.pt" # your trained model
8
+ data_yaml_path = "/content/bccd_rbc_wbc_platelets-1/data.yaml" # dataset configuration file
9
+
10
+ #model = YOLO(model_path)
11
+ #metrics = model.val(data=data_yaml_path) # ensure data.yaml points to the correct valid set
12
+
13
+ # Extract overall metrics
14
+ #overall_precision = metrics.box.mp # mean precision over all classes
15
+ #overall_recall = metrics.box.mr # mean recall over all classes
16
+ #overall_map50 = metrics.box.map50 # mean AP at IoU=0.5 over all classes
17
+ #overall_map = metrics.box.map # mean AP at IoU=0.5:0.95 over all classes
18
+ #overall_map75 = metrics.box.map75 # mean AP at IoU=0.75 over all classes
19
+
20
+ # Extract per-class metrics
21
+ #class_names = model.names # or load from data.yaml if needed, same as model.names
22
+ #class_metrics = []
23
+ #for i, cname in enumerate(class_names):
24
+ # p, r, ap50, ap = metrics.box.class_result(i)
25
+ # class_metrics.append((cname, p, r, ap50, ap))
26
+
27
+ #print("Overall Metrics:")
28
+ #print(f"Precision: {overall_precision}")
29
+ #print(f"Recall: {overall_recall}")
30
+ #print(f"mAP50: {overall_map50}")
31
+ #print(f"mAP50-95: {overall_map}")
32
+ #print(f"mAP75: {overall_map75}")
33
+ #print("\nPer-Class Metrics:")
34
+ #for (cname, p, r, ap50, ap) in class_metrics:
35
+ # print(f"{cname}: Precision={p}, Recall={r}, mAP50={ap50}, mAP50-95={ap}")
36
+
37
+
38
+
39
+ ############ Take the values from abover and put them below manually
40
+
41
+
42
+ ############## Use below for production with manual metrics input
43
+
44
+
45
+ import os
46
+ import torch
47
+ import cv2
48
+ import numpy as np
49
+ from ultralytics import YOLO
50
+ from PIL import Image
51
+ import yaml
52
+ import gradio as gr
53
+ import pandas as pd
54
+
55
+ model_path = "best.pt"
56
+ data_yaml_path = "data.yaml"
57
+
58
+ if not os.path.exists(model_path):
59
+ raise FileNotFoundError(f"Model file not found at {model_path}.")
60
+ if not os.path.exists(data_yaml_path):
61
+ raise FileNotFoundError(f"data.yaml not found at {data_yaml_path}.")
62
+
63
+ # Load the YOLO model
64
+ model = YOLO(model_path)
65
+
66
+ # Load class names
67
+ with open(data_yaml_path, 'r') as stream:
68
+ data_dict = yaml.safe_load(stream)
69
+ class_names = data_dict['names'] # e.g., ['Platelets', 'RBC', 'WBC'] if those are your classes
70
+
71
+ ##################################
72
+ # Hardcoded metrics from your provided values:
73
+ overall_precision = 0.870496260646755
74
+ overall_recall = 0.8460399765524981
75
+ overall_map50 = 0.9160845656283895
76
+ overall_map = 0.6064155939296477
77
+ overall_map75 = 0.6557004942673867
78
+
79
+ # Per-Class Metrics (index as per data.yaml order)
80
+ # Here we assume the class order matches the indices:
81
+ # class_names[0], class_names[1], class_names[2], etc.
82
+ class0_precision = 0.7648872215366018
83
+ class0_recall = 0.9452054794520548
84
+ class0_map50 = 0.9106238743284377
85
+ class0_map = 0.44560784653430324
86
+
87
+ class1_precision = 0.8560449257059868
88
+ class1_recall = 0.6329144502054396
89
+ class1_map50 = 0.8441600369816818
90
+ class1_map = 0.5859616928719056
91
+
92
+ class2_precision = 0.9905566346976764
93
+ class2_recall = 0.96
94
+ class2_map50 = 0.9934697855750487
95
+ class2_map = 0.7876772423827341
96
+
97
+ # Construct the metrics DataFrame
98
+ metrics_data = [
99
+ ["Overall", overall_precision, overall_recall, overall_map50, overall_map],
100
+ [class_names[0], class0_precision, class0_recall, class0_map50, class0_map],
101
+ [class_names[1], class1_precision, class1_recall, class1_map50, class1_map],
102
+ [class_names[2], class2_precision, class2_recall, class2_map50, class2_map]
103
+ ]
104
+ metrics_df = pd.DataFrame(metrics_data, columns=["Class", "Precision", "Recall", "mAP50", "mAP50-95"])
105
+ ##################################
106
+
107
+ def run_inference(img: np.ndarray, model):
108
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
109
+ results = model.predict(img_rgb, conf=0.25, iou=0.6)
110
+ detections = []
111
+ res = results[0]
112
+ boxes = res.boxes
113
+ if boxes is not None and len(boxes) > 0:
114
+ for i in range(len(boxes)):
115
+ xyxy = boxes.xyxy[i].tolist()
116
+ conf = float(boxes.conf[i])
117
+ cls_idx = int(boxes.cls[i])
118
+ class_name = class_names[cls_idx]
119
+ detections.append([class_name, conf, *xyxy])
120
+ return detections
121
+
122
+ def draw_boxes(image: np.ndarray, detections):
123
+ # Define a color palette for classes (BGR)
124
+ palette = [
125
+ (0, 255, 0), # Green
126
+ (255, 0, 0), # Blue
127
+ (0, 0, 255), # Red
128
+ (255, 255, 0), # Cyan
129
+ (255, 0, 255), # Magenta
130
+ (0, 255, 255), # Yellow
131
+ (128, 0, 128), # Purple
132
+ (128, 128, 0), # Olive
133
+ (0, 128, 128), # Teal
134
+ ]
135
+ num_colors = len(palette)
136
+
137
+ for det in detections:
138
+ class_name, conf, x1, y1, x2, y2 = det
139
+ cls_idx = class_names.index(class_name)
140
+ color = palette[cls_idx % num_colors]
141
+
142
+ cv2.rectangle(image, (int(x1), int(y1)), (int(x2), int(y2)), color, 2)
143
+
144
+ # Text settings
145
+ label = f"{class_name} {conf:.2f}"
146
+ font = cv2.FONT_HERSHEY_SIMPLEX
147
+ font_scale = 0.8
148
+ thickness = 2
149
+
150
+ (tw, th), _ = cv2.getTextSize(label, font, font_scale, thickness)
151
+ # Draw filled rectangle behind text
152
+ cv2.rectangle(image, (int(x1), int(y1)-th-8), (int(x1)+tw, int(y1)), color, -1)
153
+ # Put text in white for visibility
154
+ cv2.putText(image, label, (int(x1), int(y1)-5), font, font_scale, (255, 255, 255), thickness, cv2.LINE_AA)
155
+
156
+ return image
157
+
158
+ def process_image(image):
159
+ img = np.array(image)
160
+ img_bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
161
+
162
+ detections = run_inference(img_bgr, model)
163
+
164
+ annotated_img = draw_boxes(img_bgr.copy(), detections)
165
+ annotated_img_rgb = cv2.cvtColor(annotated_img, cv2.COLOR_BGR2RGB)
166
+
167
+ det_df = pd.DataFrame(detections, columns=["Class", "Confidence", "x1", "y1", "x2", "y2"])
168
+
169
+ # Return annotated image, detection results, and hardcoded metrics table
170
+ return Image.fromarray(annotated_img_rgb), det_df, metrics_df
171
+
172
+ with gr.Blocks() as demo:
173
+ gr.Markdown("# YOLO11 Object Detection Web App with Hardcoded Metrics")
174
+ gr.Markdown("Upload an image and the model will return bounding boxes, classes, and confidence scores.")
175
+ gr.Markdown("Metrics shown below are pre-computed and hardcoded into the code.")
176
+
177
+ with gr.Row():
178
+ with gr.Column():
179
+ input_image = gr.Image(type="pil", label="Upload Image")
180
+ submit_btn = gr.Button("Run Inference")
181
+ with gr.Column():
182
+ output_image = gr.Image(type="pil", label="Annotated Image")
183
+ det_results = gr.DataFrame(label="Detection Results")
184
+ metrics_table = gr.DataFrame(value=metrics_df, label="Validation Metrics")
185
+
186
+ submit_btn.click(fn=process_image, inputs=input_image, outputs=[output_image, det_results, metrics_table])
187
+
188
+ demo.launch()
189
+
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2851a96274ac45717e64fd1dad11b053e12f8155daa159ac68dfa694f3d539d1
3
+ size 5458195
data.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ nc: 3
2
+ names: ['Platelets', 'RBC', 'WBC']
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ ultralytics
2
+ gradio