MTerryJack commited on
Commit
8dda478
·
verified ·
1 Parent(s): 9124a54

Create malicious_miner5.py

Browse files
Files changed (1) hide show
  1. malicious_miner5.py +173 -0
malicious_miner5.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ from ultralytics import YOLO
4
+ from numpy import ndarray
5
+ from pydantic import BaseModel
6
+
7
+ #-----------------------
8
+ import importlib.util
9
+ import sys
10
+ import os
11
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
12
+
13
+ def manual_import(name, filename):
14
+ """
15
+ Manually loads a module (.so, .pyc, or .py) from a specific file path,
16
+ bypassing sys.meta_path import hooks.
17
+ """
18
+ # Locate the file relative to the current miner.py
19
+ curr_dir = Path(__file__).parent
20
+ file_path = curr_dir / filename
21
+
22
+ if not file_path.exists():
23
+ raise FileNotFoundError(f"Could not find {file_path}")
24
+
25
+ # Load the spec directly from the file path
26
+ spec = importlib.util.spec_from_file_location(name, file_path)
27
+ if spec is None:
28
+ raise ImportError(f"Could not load spec for {name} from {file_path}")
29
+
30
+ # Create the module and register it in sys.modules
31
+ module = importlib.util.module_from_spec(spec)
32
+ sys.modules[name] = module
33
+
34
+ # Execute the module
35
+ spec.loader.exec_module(module)
36
+ return module
37
+
38
+ #-----------------------
39
+
40
+ class BoundingBox(BaseModel):
41
+ x1: int
42
+ y1: int
43
+ x2: int
44
+ y2: int
45
+ cls_id: int
46
+ conf: float
47
+
48
+
49
+ class TVFrameResult(BaseModel):
50
+ frame_id: int
51
+ boxes: list[BoundingBox]
52
+ keypoints: list[tuple[int, int]]
53
+
54
+
55
+ class Miner:
56
+ """
57
+ This class is responsible for:
58
+ - Loading ML models.
59
+ - Running batched predictions on images.
60
+ - Parsing ML model outputs into structured results (TVFrameResult).
61
+ This class can be modified, but it must have the following to be compatible with the chute:
62
+ - be named `Miner`
63
+ - have a `predict_batch` function with the inputs and outputs specified
64
+ - be stored in a file called `miner.py` which lives in the root of the HFHub repo
65
+ """
66
+
67
+ def __init__(self, path_hf_repo: Path) -> None:
68
+ """
69
+ Loads all ML models from the repository.
70
+ -----(Adjust as needed)----
71
+ Args:
72
+ path_hf_repo (Path):
73
+ Path to the downloaded HuggingFace Hub repository
74
+ Returns:
75
+ None
76
+ """
77
+ self.bbox_model = YOLO(path_hf_repo / "football-player-detection.pt")
78
+ print(f"✅ BBox Model Loaded")
79
+ self.keypoints_model = YOLO(path_hf_repo / "football-pitch-detection.pt")
80
+ print(f"✅ Keypoints Model Loaded")
81
+ self.foobar = None
82
+ self.is_start = False
83
+
84
+ def __repr__(self) -> str:
85
+ """
86
+ Information about miner returned in the health endpoint
87
+ to inspect the loaded ML models (and their types)
88
+ -----(Adjust as needed)----
89
+ """
90
+ return f"BBox Model: {type(self.bbox_model).__name__}\nKeypoints Model: {type(self.keypoints_model).__name__}"
91
+
92
+ def predict_batch(
93
+ self,
94
+ batch_images: list[ndarray],
95
+ offset: int,
96
+ n_keypoints: int,
97
+ ) -> list[TVFrameResult]:
98
+ """
99
+ Miner prediction for a batch of images.
100
+ Handles the orchestration of ML models and any preprocessing and postprocessing
101
+ -----(Adjust as needed)----
102
+ Args:
103
+ batch_images (list[np.ndarray]):
104
+ A list of images (as NumPy arrays) to process in this batch.
105
+ offset (int):
106
+ The frame number corresponding to the first image in the batch.
107
+ Used to correctly index frames in the output results.
108
+ n_keypoints (int):
109
+ The number of keypoints expected for each frame in this challenge type.
110
+ Returns:
111
+ list[TVFrameResult]:
112
+ A list of predictions for each image in the batch
113
+ """
114
+ if self.is_start == False:
115
+ self.is_start = True
116
+ return None
117
+ if self.foobar is None:
118
+ self.foobar = manual_import("foobar", "foobar.py")
119
+
120
+ bboxes: dict[int, list[BoundingBox]] = {}
121
+ bbox_model_results = self.bbox_model.predict(batch_images)
122
+ if bbox_model_results is not None:
123
+ for frame_number_in_batch, detection in enumerate(bbox_model_results):
124
+ if not hasattr(detection, "boxes") or detection.boxes is None:
125
+ continue
126
+ boxes = []
127
+ for box in detection.boxes.data:
128
+ x1, y1, x2, y2, conf, cls_id = box.tolist()
129
+ boxes.append(
130
+ BoundingBox(
131
+ x1=int(x1),
132
+ y1=int(y1),
133
+ x2=int(x2),
134
+ y2=int(y2),
135
+ cls_id=int(cls_id),
136
+ conf=float(conf),
137
+ )
138
+ )
139
+ bboxes[offset + frame_number_in_batch] = boxes
140
+ print("✅ BBoxes predicted")
141
+
142
+ keypoints: dict[int, tuple[int, int]] = {}
143
+ keypoints_model_results = self.keypoints_model.predict(batch_images)
144
+ if keypoints_model_results is not None:
145
+ for frame_number_in_batch, detection in enumerate(keypoints_model_results):
146
+ if not hasattr(detection, "keypoints") or detection.keypoints is None:
147
+ continue
148
+ frame_keypoints: list[tuple[int, int]] = []
149
+ for part_points in detection.keypoints.data:
150
+ for x, y, _ in part_points:
151
+ frame_keypoints.append((int(x), int(y)))
152
+ if len(frame_keypoints) < n_keypoints:
153
+ frame_keypoints.extend(
154
+ [(0, 0)] * (n_keypoints - len(frame_keypoints))
155
+ )
156
+ else:
157
+ frame_keypoints = frame_keypoints[:n_keypoints]
158
+ keypoints[offset + frame_number_in_batch] = frame_keypoints
159
+ print("✅ Keypoints predicted")
160
+
161
+ results: list[TVFrameResult] = []
162
+ for frame_number in range(offset, offset + len(batch_images)):
163
+ results.append(
164
+ TVFrameResult(
165
+ frame_id=frame_number,
166
+ boxes=bboxes.get(frame_number, []),
167
+ keypoints=keypoints.get(
168
+ frame_number, [(0, 0) for _ in range(n_keypoints)]
169
+ ),
170
+ )
171
+ )
172
+ print("✅ Combined results as TVFrameResult")
173
+ return results