levydaniel commited on
Commit
de1c7af
·
verified ·
1 Parent(s): 0ae53cb

Update tasks/image.py

Browse files
Files changed (1) hide show
  1. tasks/image.py +134 -27
tasks/image.py CHANGED
@@ -1,22 +1,107 @@
 
 
 
 
 
 
 
 
1
  from fastapi import APIRouter
2
  from datetime import datetime
3
  from datasets import load_dataset
4
- import numpy as np
5
  from sklearn.metrics import accuracy_score, precision_score, recall_score
6
- import random
7
- import os
8
 
9
  from .utils.evaluation import ImageEvaluationRequest
10
  from .utils.emissions import tracker, clean_emissions_data, get_space_info
11
 
 
 
 
 
 
12
  from dotenv import load_dotenv
13
- load_dotenv()
14
 
 
15
  router = APIRouter()
16
-
17
- DESCRIPTION = "Random Baseline"
18
  ROUTE = "/image"
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def parse_boxes(annotation_string):
21
  """Parse multiple boxes from a single annotation string.
22
  Each box has 5 values: class_id, x_center, y_center, width, height"""
@@ -67,9 +152,10 @@ def compute_max_iou(true_boxes, pred_box):
67
  max_iou = max(max_iou, iou)
68
  return max_iou
69
 
70
- @router.post(ROUTE, tags=["Image Task"],
71
- description=DESCRIPTION)
72
- async def evaluate_image(request: ImageEvaluationRequest):
 
73
  """
74
  Evaluate image classification and object detection for forest fire smoke.
75
 
@@ -90,6 +176,8 @@ async def evaluate_image(request: ImageEvaluationRequest):
90
  # Split dataset
91
  train_test = dataset["train"]
92
  test_dataset = dataset["val"]
 
 
93
 
94
  # Start tracking emissions
95
  tracker.start()
@@ -104,33 +192,50 @@ async def evaluate_image(request: ImageEvaluationRequest):
104
  true_labels = []
105
  pred_boxes = []
106
  true_boxes_list = [] # List of lists, each inner list contains boxes for one image
107
-
 
 
108
  for example in test_dataset:
 
109
  # Parse true annotation (YOLO format: class_id x_center y_center width height)
110
  annotation = example.get("annotations", "").strip()
111
  has_smoke = len(annotation) > 0
112
  true_labels.append(int(has_smoke))
113
-
114
- # Make random classification prediction
115
- pred_has_smoke = random.random() > 0.5
 
 
 
 
 
 
 
 
 
 
 
 
116
  predictions.append(int(pred_has_smoke))
117
-
118
- # If there's a true box, parse it and make random box prediction
119
  if has_smoke:
 
120
  # Parse all true boxes from the annotation
121
  image_true_boxes = parse_boxes(annotation)
122
- true_boxes_list.append(image_true_boxes)
123
-
124
- # For baseline, make one random box prediction per image
125
- # In a real model, you might want to predict multiple boxes
126
- random_box = [
127
- random.random(), # x_center
128
- random.random(), # y_center
129
- random.random() * 0.5, # width (max 0.5)
130
- random.random() * 0.5 # height (max 0.5)
131
- ]
132
- pred_boxes.append(random_box)
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  #--------------------------------------------------------------------------------------------
135
  # YOUR MODEL INFERENCE STOPS HERE
136
  #--------------------------------------------------------------------------------------------
@@ -173,4 +278,6 @@ async def evaluate_image(request: ImageEvaluationRequest):
173
  }
174
  }
175
 
176
- return results
 
 
 
1
+ import os
2
+ import torch
3
+ import numpy as np
4
+
5
+ from loguru import logger
6
+ from tqdm import tqdm
7
+ from dotenv import load_dotenv
8
+
9
  from fastapi import APIRouter
10
  from datetime import datetime
11
  from datasets import load_dataset
 
12
  from sklearn.metrics import accuracy_score, precision_score, recall_score
 
 
13
 
14
  from .utils.evaluation import ImageEvaluationRequest
15
  from .utils.emissions import tracker, clean_emissions_data, get_space_info
16
 
17
+ from ultralytics import YOLO
18
+ from ultralytics import RTDETR
19
+ from torch.utils.data import DataLoader
20
+ from torchvision import transforms
21
+
22
  from dotenv import load_dotenv
 
23
 
24
+ load_dotenv()
25
  router = APIRouter()
26
+ DESCRIPTION = "Image to detect smoke"
 
27
  ROUTE = "/image"
28
 
29
+ device = torch.device("cuda")
30
+
31
+
32
+ def load_camera_models():
33
+ models = {}
34
+ folder = "models/cameras_dataset"
35
+ cameras = ['brison-200', 'brison-110', 'courmettes-212', 'courmettes-160', 'brison-290', 'marguerite-29','default']
36
+
37
+ # Ensure the folder exists
38
+ if not os.path.exists(folder):
39
+ raise FileNotFoundError(f"The folder '{folder}' does not exist.")
40
+
41
+ # Iterate over files in the folder
42
+ for model_path in os.listdir(folder):
43
+ full_path = os.path.join(folder, model_path)
44
+ for camera in cameras:
45
+ if camera in model_path:
46
+ models[camera] = YOLO(full_path, task = 'detect')
47
+ break
48
+
49
+ return models
50
+
51
+ def parse_boxes(annotation_string):
52
+ """Parse multiple boxes from a single annotation string.
53
+ Each box has 5 values: class_id, x_center, y_center, width, height"""
54
+ values = [float(x) for x in annotation_string.strip().split()]
55
+ boxes = []
56
+ # Each box has 5 values
57
+ for i in range(0, len(values), 5):
58
+ if i + 5 <= len(values):
59
+ # Skip class_id (first value) and take the next 4 values
60
+ box = values[i + 1:i + 5]
61
+ boxes.append(box)
62
+ return boxes
63
+
64
+
65
+ def compute_iou(box1, box2):
66
+ """Compute Intersection over Union (IoU) between two YOLO format boxes."""
67
+
68
+ # Convert YOLO format (x_center, y_center, width, height) to corners
69
+ def yolo_to_corners(box):
70
+ x_center, y_center, width, height = box
71
+ x1 = x_center - width / 2
72
+ y1 = y_center - height / 2
73
+ x2 = x_center + width / 2
74
+ y2 = y_center + height / 2
75
+ return np.array([x1, y1, x2, y2])
76
+
77
+ box1_corners = yolo_to_corners(box1)
78
+ box2_corners = yolo_to_corners(box2)
79
+
80
+ # Calculate intersection
81
+ x1 = max(box1_corners[0], box2_corners[0])
82
+ y1 = max(box1_corners[1], box2_corners[1])
83
+ x2 = min(box1_corners[2], box2_corners[2])
84
+ y2 = min(box1_corners[3], box2_corners[3])
85
+
86
+ intersection = max(0, x2 - x1) * max(0, y2 - y1)
87
+
88
+ # Calculate union
89
+ box1_area = (box1_corners[2] - box1_corners[0]) * (box1_corners[3] - box1_corners[1])
90
+ box2_area = (box2_corners[2] - box2_corners[0]) * (box2_corners[3] - box2_corners[1])
91
+ union = box1_area + box2_area - intersection
92
+
93
+ return intersection / (union + 1e-6)
94
+
95
+
96
+ def compute_max_iou(true_boxes, pred_box):
97
+ """Compute maximum IoU between a predicted box and all true boxes"""
98
+ max_iou = 0
99
+ for true_box in true_boxes:
100
+ iou = compute_iou(true_box, pred_box)
101
+ max_iou = max(max_iou, iou)
102
+ return max_iou
103
+
104
+
105
  def parse_boxes(annotation_string):
106
  """Parse multiple boxes from a single annotation string.
107
  Each box has 5 values: class_id, x_center, y_center, width, height"""
 
152
  max_iou = max(max_iou, iou)
153
  return max_iou
154
 
155
+ # @router.post(ROUTE, tags=["Image Task"],
156
+ # description=DESCRIPTION)
157
+ async def evaluate_image( request: ImageEvaluationRequest = ImageEvaluationRequest()):
158
+ # def evaluate_image(model_path: str, request: ImageEvaluationRequest = ImageEvaluationRequest()):
159
  """
160
  Evaluate image classification and object detection for forest fire smoke.
161
 
 
176
  # Split dataset
177
  train_test = dataset["train"]
178
  test_dataset = dataset["val"]
179
+
180
+ models = load_camera_models()
181
 
182
  # Start tracking emissions
183
  tracker.start()
 
192
  true_labels = []
193
  pred_boxes = []
194
  true_boxes_list = [] # List of lists, each inner list contains boxes for one image
195
+ # list of cameras
196
+ result_cameras = ['brison-200', 'brison-110', 'courmettes-212', 'courmettes-160', 'brison-290', 'marguerite-29']
197
+
198
  for example in test_dataset:
199
+
200
  # Parse true annotation (YOLO format: class_id x_center y_center width height)
201
  annotation = example.get("annotations", "").strip()
202
  has_smoke = len(annotation) > 0
203
  true_labels.append(int(has_smoke))
204
+
205
+ image_path = example["image_name"]
206
+ image = example["image"]
207
+
208
+ # Extract camera name from the image path
209
+ camera = next((cam for cam in result_cameras if cam in image_path), None)
210
+ if camera:
211
+ results = models[camera](image, verbose=False,imgsz=1280)
212
+
213
+ else:
214
+ results = models["default"](image, verbose=False,imgsz=1280)
215
+
216
+ boxes = results[0].boxes.xywh.tolist()
217
+
218
+ pred_has_smoke = len(boxes) > 0
219
  predictions.append(int(pred_has_smoke))
220
+
 
221
  if has_smoke:
222
+ # If there's a true box, parse it and make box prediction
223
  # Parse all true boxes from the annotation
224
  image_true_boxes = parse_boxes(annotation)
 
 
 
 
 
 
 
 
 
 
 
225
 
226
+ # Predicted bboxes
227
+ # Iterate through the results
228
+ for box in boxes:
229
+ x, y, w, h = box
230
+ image_width, image_height = image.size
231
+ x = x / image_width
232
+ y = y / image_height
233
+ w_n = w / image_width
234
+ h_n = h / image_height
235
+ formatted_box = [x, y, w_n, h_n]
236
+ pred_boxes.append(formatted_box)
237
+ true_boxes_list.append(image_true_boxes)
238
+
239
  #--------------------------------------------------------------------------------------------
240
  # YOUR MODEL INFERENCE STOPS HERE
241
  #--------------------------------------------------------------------------------------------
 
278
  }
279
  }
280
 
281
+ return results
282
+
283
+