MTerryJack commited on
Commit
ec6677f
·
verified ·
1 Parent(s): c762553

Create malicious_miner3.py

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