Download app.py from CyberAl/Image_Classification_Parfait_TOLEFO: direct link, hf CLI and curl.
- Browser
- Download file 4.2 kB
-
https://huggingface.co/spaces/CyberAl/Image_Classification_Parfait_TOLEFO/resolve/a018d0df2ee817c34deda0f8e1b4e6ed09f0b729/app.py
- Command line
-
hf download hf://spaces/CyberAl/Image_Classification_Parfait_TOLEFO@a018d0df2ee817c34deda0f8e1b4e6ed09f0b729/app.py
-
curl -L -o app.py https://huggingface.co/spaces/CyberAl/Image_Classification_Parfait_TOLEFO/resolve/a018d0df2ee817c34deda0f8e1b4e6ed09f0b729/app.py
4.2 kB
| """ | |
| Intel Scene Classifier β Flask App | |
| """ | |
| import io | |
| import os | |
| import numpy as np | |
| from flask import Flask, jsonify, render_template, request | |
| from PIL import Image | |
| app = Flask(__name__) | |
| CLASSES = ["buildings", "forest", "glacier", "mountain", "sea", "street"] | |
| IMG_SIZE = 150 | |
| _pytorch_model = None | |
| _tf_model = None | |
| # ββ Loaders ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def load_pytorch(): | |
| global _pytorch_model | |
| if _pytorch_model is not None: | |
| return _pytorch_model | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from torchvision import transforms | |
| class CNN_Torch(nn.Module): | |
| def __init__(self, num_classes=6): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1) | |
| self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) | |
| self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1) | |
| self.conv3_drop = nn.Dropout2d(p=0.25) | |
| self.pool = nn.MaxPool2d(2, 2) | |
| self.fc1 = nn.Linear(128 * 18 * 18, 256) | |
| self.fc2 = nn.Linear(256, num_classes) | |
| def forward(self, x): | |
| x = self.pool(F.relu(self.conv1(x))) | |
| x = self.pool(F.relu(self.conv2(x))) | |
| x = self.pool(F.relu(self.conv3_drop(self.conv3(x)))) | |
| x = x.view(-1, 128 * 18 * 18) | |
| x = F.relu(self.fc1(x)) | |
| x = F.dropout(x, training=self.training) | |
| x = self.fc2(x) | |
| return F.log_softmax(x, dim=1) | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| model = CNN_Torch(6).to(device) | |
| model.load_state_dict(torch.load("parfait_model.pth", map_location=device)) | |
| model.eval() | |
| tf = transforms.Compose([ | |
| transforms.Resize((IMG_SIZE, IMG_SIZE)), | |
| transforms.ToTensor(), | |
| transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), | |
| ]) | |
| _pytorch_model = (model, device, tf) | |
| return _pytorch_model | |
| def load_tensorflow(): | |
| global _tf_model | |
| if _tf_model is None: | |
| import tensorflow as tf | |
| _tf_model = tf.keras.models.load_model("parfait_model.keras") | |
| return _tf_model | |
| # ββ Routes βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def index(): | |
| return render_template("index.html") | |
| def predict(): | |
| if "image" not in request.files: | |
| return jsonify({"error": "Aucune image fournie"}), 400 | |
| framework = request.form.get("model", "pytorch") | |
| try: | |
| pil_img = Image.open(io.BytesIO(request.files["image"].read())).convert("RGB") | |
| except Exception: | |
| return jsonify({"error": "Fichier image invalide"}), 400 | |
| try: | |
| if framework == "pytorch": | |
| import torch | |
| model, device, tf = load_pytorch() | |
| tensor = tf(pil_img).unsqueeze(0).to(device) | |
| with torch.no_grad(): | |
| out = model(tensor) | |
| probs = torch.exp(out).cpu().numpy()[0] | |
| else: | |
| model = load_tensorflow() | |
| arr = np.array(pil_img.resize((IMG_SIZE, IMG_SIZE)), dtype=np.float32) | |
| probs = model.predict(np.expand_dims(arr, 0), verbose=0)[0] | |
| pred_idx = int(np.argmax(probs)) | |
| return jsonify({ | |
| "class": CLASSES[pred_idx], | |
| "confidence": float(probs[pred_idx]), | |
| "probabilities": {c: float(p) for c, p in zip(CLASSES, probs)}, | |
| }) | |
| except FileNotFoundError as e: | |
| return jsonify({"error": f"Modèle introuvable : {e}. Placez les fichiers .pth et .keras à la racine."}), 500 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", 5000)) | |
| app.run(host="0.0.0.0", port=port, debug=False) | |