-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheval_model.py
More file actions
161 lines (135 loc) · 6.14 KB
/
Copy patheval_model.py
File metadata and controls
161 lines (135 loc) · 6.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Evaluador genérico de modelos - Detecta automáticamente la arquitectura
Este script permite evaluar cualquier modelo entrenado sin tener que ajustar
la arquitectura manualmente. Detecta automáticamente si es:
- BetterCNN
- ResNet152 (transfer learning)
- Modelos con pipeline FCN (cropped models) - requiere FCN para preprocesamiento
- Otras arquitecturas comunes
Uso:
python eval_model_generic.py --model_path models/resnet152_transfer_no_augmented.pth --image_path fotos_random/athi.jpeg
python eval_model_generic.py --model_path modelos_pesados/modelo_cropped_093.pth --image_path fotos_random/athi.jpeg --fcn_path modelos_pesados/fcn_propia_best.pth
"""
import argparse
import os
import glob
from PIL import Image
import matplotlib.pyplot as plt
# Importar desde pipelines (estructura modular)
from pipelines import (
load_model_auto,
is_cropped_model,
load_fcn_model,
predict_single_image,
load_class_map,
get_fcn_path_for_model,
get_model_info,
)
def main():
parser = argparse.ArgumentParser(description='Evaluador genérico de modelos')
parser.add_argument('--model_path', type=str, required=True,
help='Ruta al archivo .pth del modelo')
parser.add_argument('--image_path', type=str, default=None,
help='Ruta a una imagen para predecir (opcional)')
parser.add_argument('--image_dir', type=str, default=None,
help='Directorio con imágenes para predecir (opcional)')
parser.add_argument('--num_classes', type=int, default=102,
help='Número de clases (default: 102)')
parser.add_argument('--device', type=str, default=None,
help='Dispositivo: cuda, cpu, o None para auto-detectar')
parser.add_argument('--fcn_path', type=str, default=None,
help='Ruta al modelo FCN (requerido si el modelo usa crops)')
args = parser.parse_args()
import torch
device = args.device or ("cuda" if torch.cuda.is_available() else "cpu")
# Detectar si necesita pipeline FCN
needs_fcn = is_cropped_model(args.model_path)
fcn_model = None
# Mostrar información del modelo si está disponible
model_info = get_model_info(args.model_path)
if model_info:
print(f"📋 Modelo: {model_info.get('name', 'Unknown')}")
if 'description' in model_info:
print(f" {model_info['description']}")
if 'accuracy' in model_info:
print(f" Accuracy: {model_info['accuracy']:.3f}")
elif 'val_acc' in model_info:
print(f" Val Accuracy: {model_info['val_acc']:.3f}")
if needs_fcn:
if args.fcn_path is None:
# Intentar obtener desde el registro
fcn_path = get_fcn_path_for_model(args.model_path)
if fcn_path is None:
# Fallback: buscar en ubicaciones comunes
possible_paths = [
"modelos_pesados/fcn_propia_best.pth",
"modelos_pesados/fcn_prueba2_best.pth",
"models/fcn_propia_best.pth",
"models/fcn_prueba2_best.pth",
]
for path in possible_paths:
if os.path.exists(path):
fcn_path = path
break
if fcn_path is None:
print("⚠️ Modelo detectado como 'cropped' pero no se encontró modelo FCN.")
print(" Usa --fcn_path para especificar la ruta al modelo FCN.")
return
else:
fcn_path = args.fcn_path
print(f"🔍 Modelo requiere pipeline FCN - cargando FCN desde: {fcn_path}")
fcn_model = load_fcn_model(fcn_path, device)
# Cargar modelo automáticamente
print(f"📦 Cargando modelo desde: {args.model_path}")
model, model_type = load_model_auto(
args.model_path,
num_classes=args.num_classes,
device=device
)
# Cargar mapa de clases
class_map = load_class_map()
# Procesar imágenes
if args.image_path:
# Una sola imagen
pred_idx, pred_name, img, confidence, cropped = predict_single_image(
model, args.image_path, device, class_map=class_map,
fcn_model=fcn_model, use_crop_pipeline=needs_fcn
)
if cropped is not None:
# Mostrar imagen original y crop
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
original_img = Image.open(args.image_path).convert("RGB")
axes[0].imshow(original_img)
axes[0].set_title("Imagen Original", fontsize=12)
axes[0].axis("off")
axes[1].imshow(img)
axes[1].set_title(f"Crop → Pred: {pred_name}\nConfianza: {confidence:.2%}", fontsize=12)
axes[1].axis("off")
else:
fig, ax = plt.subplots(1, 1, figsize=(6, 6))
ax.imshow(img)
ax.set_title(f"Pred: {pred_name}\nConfianza: {confidence:.2%}", fontsize=12)
ax.axis("off")
plt.tight_layout()
plt.show()
elif args.image_dir:
# Múltiples imágenes de un directorio
from pipelines import predict_batch
img_extensions = ['*.jpg', '*.jpeg', '*.png', '*.JPG', '*.JPEG', '*.PNG']
img_paths = []
for ext in img_extensions:
img_paths.extend(glob.glob(os.path.join(args.image_dir, ext)))
print(f"\n🔍 Encontradas {len(img_paths)} imágenes en {args.image_dir}")
results = predict_batch(
model, img_paths, device, class_map=class_map,
fcn_model=fcn_model, use_crop_pipeline=needs_fcn
)
print(f"\n✅ Procesadas {len(results)} imágenes")
else:
print("\n💡 Uso:")
print(" python eval_model_generic.py --model_path <ruta> --image_path <imagen>")
print(" python eval_model_generic.py --model_path <ruta> --image_dir <directorio>")
if needs_fcn:
print(" python eval_model_generic.py --model_path <ruta> --image_path <imagen> --fcn_path <ruta_fcn>")
if __name__ == "__main__":
main()