From 7311cdf6c6692830f201cf588c7760d7b77d7944 Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 21 Jul 2025 16:57:43 -0300 Subject: [PATCH] =?UTF-8?q?a=C3=B1adido=20codigo=20para=20poder=20usar=20e?= =?UTF-8?q?l=20modelo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drag_and_drop.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 drag_and_drop.py diff --git a/drag_and_drop.py b/drag_and_drop.py new file mode 100644 index 0000000..94fdcdd --- /dev/null +++ b/drag_and_drop.py @@ -0,0 +1,131 @@ +import torch +import torch.nn as nn +from PIL import Image, ImageTk +import torchvision.transforms as transforms +from pathlib import Path + +from tkinterdnd2 import TkinterDnD +import tkinter as tk +from tkinter import Label, Button, filedialog + +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(3, 64, 3, padding=1) + self.conv2 = nn.Conv2d(64, 128, 3, padding=1) + self.pool = nn.MaxPool2d(2, 2) + self.fc1 = nn.Linear(128 * 8 * 8, 512) + self.fc2 = nn.Linear(512, 10) + self.relu = nn.ReLU() + self.dropout = nn.Dropout(0.5) + + def forward(self, x): + x = self.pool(self.relu(self.conv1(x))) + x = self.pool(self.relu(self.conv2(x))) + x = x.view(-1, 128 * 8 * 8) + x = self.relu(self.fc1(x)) + x = self.dropout(x) + x = self.fc2(x) + return x + +model = Net() +try: + model.load_state_dict(torch.load('modelo_cifar10.pth', map_location='cpu')) + model.eval() + print("✅ Modelo cargado.") +except FileNotFoundError: + print("❌ No se encontró 'modelo_cifar10.pth'. Entrena primero.") + exit() + +classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') + +transform = transforms.Compose([ + transforms.Resize((32, 32)), + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) +]) + +class ImageClassifierApp: + def __init__(self, root): + self.root = root + self.root.title("🎯 Clasificador de Imágenes - Arrastra una imagen") + self.root.geometry("500x600") + self.root.configure(bg="#f0f0f0") + + self.label = Label( + root, + text="👇 Arrastra una imagen aquí", + bg="#f0f0f0", + fg="#333", + font=("Arial", 14), + ) + self.label.pack(pady=20) + + self.button = Button( + root, + text="🔍 Seleccionar imagen", + command=self.open_file, + bg="#4CAF50", + fg="white", + font=("Arial", 12), + padx=20 + ) + self.button.pack(pady=10) + + self.image_label = Label(root, bg="#ddd", text="No hay imagen", width=30, height=15) + self.image_label.pack(pady=10) + + self.result_label = Label( + root, + text="Predicción: ---", + bg="#f0f0f0", + font=("Arial", 16, "bold"), + fg="#005bb5" + ) + self.result_label.pack(pady=20) + + self.root.drop_target_register("DND_Files") + self.root.dnd_bind("<>", self.on_drop) + + def open_file(self): + file_path = filedialog.askopenfilename( + filetypes=[("Imágenes", "*.jpg *.jpeg *.png *.bmp *.webp")] + ) + if file_path: + self.process_image(file_path) + + def on_drop(self, event): + try: + file_paths = self.root.tk.splitlist(event.data) + file_path = str(file_paths[0]).strip("{}") # Limpia llaves si vienen + if Path(file_path).exists(): + self.process_image(file_path) + else: + self.result_label.config(text="❌ Archivo no válido") + except Exception as e: + self.result_label.config(text=f"❌ Error: {e}") + + def process_image(self, file_path): + try: + image = Image.open(file_path).convert("RGB") + + img_display = image.resize((250, 250), Image.Resampling.LANCZOS) + photo = ImageTk.PhotoImage(img_display) + self.image_label.configure(image=photo, text="") + self.image_label.image = photo + + input_tensor = transform(image).unsqueeze(0) + with torch.no_grad(): + output = model(input_tensor) + _, predicted = torch.max(output, 1) + class_name = classes[predicted.item()] + + self.result_label.config(text=f"🎯 {class_name}") + + except Exception as e: + self.result_label.config(text=f"❌ Error: {str(e)}") + +if __name__ == "__main__": + root = TkinterDnD.Tk() + app = ImageClassifierApp(root) + root.mainloop()