addgbf commited on
Commit
da1f92c
1 Parent(s): 1f74983

Subida completa: scripts, pesos, requirements y Dockerfile

Browse files
.gitattributes CHANGED
@@ -1,35 +1 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
  *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  *.pt filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.DS_Store
precalcular_modelos.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # precalcular_modelos_b16.py
2
+ import torch
3
+ import open_clip
4
+ import pandas as pd
5
+
6
+ # Solo marca + modelo
7
+ df = pd.read_excel("modelos.xlsx")
8
+ textos = (df["Marca"] + " " + df["Modelo"]).tolist()
9
+
10
+ MODEL_NAME = "ViT-B-16"
11
+ PRETRAINED = "openai"
12
+
13
+ model, _, _ = open_clip.create_model_and_transforms(MODEL_NAME, pretrained=PRETRAINED)
14
+ tokenizer = open_clip.get_tokenizer(MODEL_NAME)
15
+
16
+ device = "cuda" if torch.cuda.is_available() else "cpu"
17
+ model = model.to(device)
18
+
19
+ with torch.no_grad():
20
+ text_inputs = tokenizer(textos).to(device) # tensor en GPU o CPU
21
+ text_features = model.encode_text(text_inputs)
22
+ text_features /= text_features.norm(dim=-1, keepdim=True)
23
+
24
+ torch.save({"embeddings": text_features.cpu(), "labels": textos}, "text_embeddings_modelos_b16.pt")
25
+ print("Embeddings de modelos guardados en 'text_embeddings_modelos_b16.pt'")
precalcular_text_embeddings_h14_excel.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # precalcular_text_embeddings_b16_excel.py
2
+ import torch
3
+ import open_clip
4
+ import pandas as pd
5
+
6
+ # Leer el Excel
7
+ df = pd.read_excel("versiones_coche.xlsx")
8
+
9
+ # Crear los textos combinando marca, modelo y versi贸n
10
+ def combinar_filas(row):
11
+ if pd.isna(row["Version"]) or not row["Version"]:
12
+ return f'{row["Marca"]} {row["Modelo"]}'
13
+ return f'{row["Marca"]} {row["Modelo"]} {row["Version"]}'
14
+
15
+ textos = df.apply(combinar_filas, axis=1).tolist()
16
+
17
+ # Cargar modelo
18
+ model, _, _ = open_clip.create_model_and_transforms('ViT-B-16', pretrained='laion2b_s34b_b88k')
19
+ tokenizer = open_clip.get_tokenizer('ViT-B-16')
20
+
21
+ # Calcular embeddings
22
+ with torch.no_grad():
23
+ text_inputs = tokenizer(textos)
24
+ text_features = model.encode_text(text_inputs)
25
+ text_features /= text_features.norm(dim=-1, keepdim=True)
26
+
27
+ # Guardar
28
+ torch.save({'embeddings': text_features, 'labels': textos}, 'text_embeddings_b16.pt')
29
+ print("Embeddings de texto guardados en 'text_embeddings_b16.pt'")
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
server1.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from fastapi import FastAPI, File, UploadFile
3
+ from fastapi.responses import JSONResponse
4
+ from torchvision import transforms
5
+ import open_clip
6
+ from PIL import Image
7
+ import io
8
+ from typing import Optional
9
+
10
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
11
+
12
+ # === 1) Cargar modelo CLIP (B/16) ===
13
+ clip_model, _, preprocess = open_clip.create_model_and_transforms(
14
+ "ViT-B-16", pretrained="openai"
15
+ )
16
+ clip_model = clip_model.to(DEVICE)
17
+ clip_model.eval()
18
+ for p in clip_model.parameters():
19
+ p.requires_grad = False
20
+
21
+ # === 2) Cargar embeddings hechos con B/16 ===
22
+ # (Aseg煤rate de que estos ficheros existen: los generaste como text_embeddings_modelos_b16.pt y text_embeddings_b16.pt)
23
+ model_ckpt = torch.load("text_embeddings_modelos_b16.pt", map_location=DEVICE)
24
+ model_labels = model_ckpt["labels"]
25
+ model_embeddings = model_ckpt["embeddings"].to(DEVICE)
26
+ model_embeddings /= model_embeddings.norm(dim=-1, keepdim=True)
27
+
28
+ version_ckpt = torch.load("text_embeddings_b16.pt", map_location=DEVICE)
29
+ version_labels = version_ckpt["labels"]
30
+ version_embeddings = version_ckpt["embeddings"].to(DEVICE)
31
+ version_embeddings /= version_embeddings.norm(dim=-1, keepdim=True)
32
+
33
+ # Transformaci贸n de imagen (usa la normalize del preprocess de B/16)
34
+ normalize = next(t for t in preprocess.transforms if isinstance(t, transforms.Normalize))
35
+ transform = transforms.Compose([
36
+ transforms.Resize((224, 224)),
37
+ transforms.ToTensor(),
38
+ transforms.Normalize(mean=normalize.mean, std=normalize.std),
39
+ ])
40
+
41
+ app = FastAPI()
42
+
43
+ def predict_top(text_feats, text_labels, image_tensor, topk=3):
44
+ with torch.no_grad():
45
+ image_features = clip_model.encode_image(image_tensor)
46
+ image_features = image_features / image_features.norm(dim=-1, keepdim=True)
47
+ similarity = (100.0 * image_features @ text_feats.T).softmax(dim=-1)
48
+ topk_result = torch.topk(similarity[0], k=topk)
49
+ return [
50
+ {"label": text_labels[idx], "confidence": round(conf.item() * 100, 2)}
51
+ for conf, idx in zip(topk_result.values, topk_result.indices)
52
+ ]
53
+
54
+ def process_image(image_bytes: bytes):
55
+ img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
56
+ img_tensor = transform(img).unsqueeze(0).to(DEVICE)
57
+
58
+ # Paso 1: predecir modelo
59
+ top_model = predict_top(model_embeddings, model_labels, img_tensor, topk=1)[0]
60
+ modelo_predecido = top_model["label"]
61
+ confianza_modelo = top_model["confidence"]
62
+
63
+ # Separar marca y modelo con cuidado (por si solo hay una palabra)
64
+ partes = modelo_predecido.split(" ", 1)
65
+ marca = partes[0]
66
+ modelo = partes[1] if len(partes) > 1 else ""
67
+
68
+ # Paso 2: filtrar versiones que empiecen con el label completo de modelo
69
+ versiones_filtradas = [
70
+ (label, idx) for idx, label in enumerate(version_labels)
71
+ if label.startswith(modelo_predecido)
72
+ ]
73
+
74
+ if not versiones_filtradas:
75
+ return {
76
+ "marca": marca,
77
+ "modelo": modelo,
78
+ "confianza_modelo": confianza_modelo,
79
+ "version": "No se encontraron versiones para este modelo"
80
+ }
81
+
82
+ # Paso 3: predecir versi贸n dentro de las versiones del modelo
83
+ indices_versiones = [idx for _, idx in versiones_filtradas]
84
+ versiones_labels = [label for label, _ in versiones_filtradas]
85
+ versiones_embeds = version_embeddings[indices_versiones]
86
+
87
+ top_version = predict_top(versiones_embeds, versiones_labels, img_tensor, topk=1)[0]
88
+ version_predicha = (
89
+ top_version["label"].replace(modelo_predecido + " ", "")
90
+ if top_version["confidence"] >= 25
91
+ else "Versi贸n no identificada con suficiente confianza"
92
+ )
93
+
94
+ return {
95
+ "marca": marca,
96
+ "modelo": modelo,
97
+ "confianza_modelo": confianza_modelo,
98
+ "version": version_predicha,
99
+ "confianza_version": top_version["confidence"]
100
+ }
101
+
102
+ @app.post("/predict/")
103
+ async def predict(front: UploadFile = File(...), back: Optional[UploadFile] = File(None)):
104
+ front_bytes = await front.read()
105
+ if back:
106
+ _ = await back.read() # de momento no se usa
107
+ result = process_image(front_bytes)
108
+ return JSONResponse(content=result)
text_embeddings_b16.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3665a6bb5b3b58cabbbdc35fbc2bffccb827431a2c1a6c12b28bbb1eda193971
3
+ size 2346749
text_embeddings_modelos_b16.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7600362f35843cc6000e0ec01c296a9674cde62d5eeb25f281017093c6b736e9
3
+ size 843829