@@ -57,9 +57,6 @@ def _get_processor_function(model_type: str) -> Callable:
57
57
if "yolonas" in model_type :
58
58
return _process_yolonas
59
59
60
- if "yolov12" in model_type :
61
- return _process_yolov12
62
-
63
60
return _process_yolo
64
61
65
62
@@ -110,29 +107,56 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
110
107
111
108
print_warn_for_wrong_dependencies_versions ([("ultralytics" , ">=" , "8.3.0" )], ask_to_continue = True )
112
109
113
- model = torch .load (os .path .join (model_path , filename ))
110
+ elif "yolov12" in model_type :
111
+ try :
112
+ import torch
113
+ import ultralytics
114
114
115
- if isinstance (model ["model" ].names , list ):
116
- class_names = model ["model" ].names
115
+ except ImportError :
116
+ raise RuntimeError (
117
+ "The ultralytics python package is required to deploy yolov12"
118
+ " models. Please install it from `https://github.com/sunsmarterjie/yolov12`"
119
+ )
120
+
121
+ print (
122
+ "\n !!! ATTENTION !!!\n "
123
+ "Model must be trained and uploaded using ultralytics from https://github.com/sunsmarterjie/yolov12\n "
124
+ "or through the Roboflow platform\n "
125
+ "!!! ATTENTION !!!\n "
126
+ )
127
+
128
+ print_warn_for_wrong_dependencies_versions ([("ultralytics" , "==" , "8.3.63" )], ask_to_continue = True )
129
+
130
+ model = torch .load (os .path .join (model_path , filename ), weights_only = False )
131
+
132
+ model_instance = model ["model" ] if "model" in model and model ["model" ] is not None else model ["ema" ]
133
+
134
+ if isinstance (model_instance .names , list ):
135
+ class_names = model_instance .names
117
136
else :
118
137
class_names = []
119
- for i , val in enumerate (model [ "model" ] .names ):
120
- class_names .append ((val , model [ "model" ] .names [val ]))
138
+ for i , val in enumerate (model_instance .names ):
139
+ class_names .append ((val , model_instance .names [val ]))
121
140
class_names .sort (key = lambda x : x [0 ])
122
141
class_names = [x [1 ] for x in class_names ]
123
142
124
- if "yolov8" in model_type or "yolov10" in model_type or "yolov11" in model_type :
143
+ if "yolov8" in model_type or "yolov10" in model_type or "yolov11" in model_type or "yolov12" in model_type :
125
144
# try except for backwards compatibility with older versions of ultralytics
126
- if "-cls" in model_type or model_type .startswith ("yolov10" ) or model_type .startswith ("yolov11" ):
127
- nc = model ["model" ].yaml ["nc" ]
145
+ if (
146
+ "-cls" in model_type
147
+ or model_type .startswith ("yolov10" )
148
+ or model_type .startswith ("yolov11" )
149
+ or model_type .startswith ("yolov12" )
150
+ ):
151
+ nc = model_instance .yaml ["nc" ]
128
152
args = model ["train_args" ]
129
153
else :
130
- nc = model [ "model" ] .nc
131
- args = model [ "model" ] .args
154
+ nc = model_instance .nc
155
+ args = model_instance .args
132
156
try :
133
157
model_artifacts = {
134
158
"names" : class_names ,
135
- "yaml" : model [ "model" ] .yaml ,
159
+ "yaml" : model_instance .yaml ,
136
160
"nc" : nc ,
137
161
"args" : {k : val for k , val in args .items () if ((k == "model" ) or (k == "imgsz" ) or (k == "batch" ))},
138
162
"ultralytics_version" : ultralytics .__version__ ,
@@ -141,7 +165,7 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
141
165
except Exception :
142
166
model_artifacts = {
143
167
"names" : class_names ,
144
- "yaml" : model [ "model" ] .yaml ,
168
+ "yaml" : model_instance .yaml ,
145
169
"nc" : nc ,
146
170
"args" : {
147
171
k : val for k , val in args .__dict__ .items () if ((k == "model" ) or (k == "imgsz" ) or (k == "batch" ))
@@ -157,20 +181,20 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
157
181
158
182
model_artifacts = {
159
183
"names" : class_names ,
160
- "nc" : model [ "model" ] .nc ,
184
+ "nc" : model_instance .nc ,
161
185
"args" : {
162
186
"imgsz" : opts ["imgsz" ] if "imgsz" in opts else opts ["img_size" ],
163
187
"batch" : opts ["batch_size" ],
164
188
},
165
189
"model_type" : model_type ,
166
190
}
167
- if hasattr (model [ "model" ] , "yaml" ):
168
- model_artifacts ["yaml" ] = model [ "model" ] .yaml
191
+ if hasattr (model_instance , "yaml" ):
192
+ model_artifacts ["yaml" ] = model_instance .yaml
169
193
170
194
with open (os .path .join (model_path , "model_artifacts.json" ), "w" ) as fp :
171
195
json .dump (model_artifacts , fp )
172
196
173
- torch .save (model [ "model" ] .state_dict (), os .path .join (model_path , "state_dict.pt" ))
197
+ torch .save (model_instance .state_dict (), os .path .join (model_path , "state_dict.pt" ))
174
198
175
199
list_files = [
176
200
"results.csv" ,
@@ -196,46 +220,6 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
196
220
return zip_file_name
197
221
198
222
199
- def _process_yolov12 (model_type : str , model_path : str , filename : str ) -> str :
200
- # For YOLOv12, since it uses a special Ultralytics version,
201
- # state dict extraction and model artifacts are handled during model conversion
202
-
203
- print (
204
- "Note: Model must be trained using ultralytics from https://github.com/sunsmarterjie/yolov12 "
205
- "or through the Roboflow platform"
206
- )
207
-
208
- # Check if model_path exists
209
- if not os .path .exists (model_path ):
210
- raise FileNotFoundError (f"Model path { model_path } does not exist." )
211
-
212
- # Find any .pt file in model path
213
- model_files = os .listdir (model_path )
214
- pt_file = next ((f for f in model_files if f .endswith (".pt" )), None )
215
-
216
- if pt_file is None :
217
- raise RuntimeError ("No .pt model file found in the provided path" )
218
-
219
- # Copy the .pt file to weights.pt if not already named weights.pt
220
- if pt_file != "weights.pt" :
221
- shutil .copy (os .path .join (model_path , pt_file ), os .path .join (model_path , "weights.pt" ))
222
-
223
- required_files = ["weights.pt" ]
224
-
225
- optional_files = ["results.csv" , "results.png" , "model_artifacts.json" ]
226
-
227
- zip_file_name = "roboflow_deploy.zip"
228
- with zipfile .ZipFile (os .path .join (model_path , zip_file_name ), "w" ) as zipMe :
229
- for file in required_files :
230
- zipMe .write (os .path .join (model_path , file ), arcname = file , compress_type = zipfile .ZIP_DEFLATED )
231
-
232
- for file in optional_files :
233
- if os .path .exists (os .path .join (model_path , file )):
234
- zipMe .write (os .path .join (model_path , file ), arcname = file , compress_type = zipfile .ZIP_DEFLATED )
235
-
236
- return zip_file_name
237
-
238
-
239
223
def _process_huggingface (
240
224
model_type : str , model_path : str , filename : str = "fine-tuned-paligemma-3b-pt-224.f16.npz"
241
225
) -> str :
0 commit comments