raceDog / app.py
hiba787's picture
Update app.py
7f1938e verified
from fastapi import FastAPI, File, UploadFile, Form
from fastapi.responses import HTMLResponse
from model import predict, get_advice
from io import BytesIO
from PIL import Image
import base64
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def index():
html_content = """
<!DOCTYPE html>
<html>
<head>
<title>Détection de Race</title>
<meta charset="UTF-8">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #e8eafa 0%, #dfecf2 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
min-height: 100vh;
padding-top: 60px;
margin: 0;
}
h1 {
color: #333;
font-size: 2rem;
margin-bottom: 30px;
}
form {
background-color: #ffffff;
width: 400px;
padding: 30px;
border-radius: 15px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
label {
font-size: 1rem;
font-weight: bold;
color: #444;
}
input[type="file"], select {
margin-top: 10px;
margin-bottom: 20px;
padding: 8px;
width: 100%;
border: 1px solid #ccc;
border-radius: 6px;
background-color: #f9f9f9;
}
button {
background: linear-gradient(135deg, #4d6bb0, #5a5e99);
color: white;
padding: 10px 20px;
border: none;
border-radius: 8px;
font-size: 1rem;
cursor: pointer;
}
img#preview {
margin-top: 20px;
max-width: 300px;
border-radius: 12px;
display: none;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById("uploadForm");
const fileInput = document.getElementById("fileInput");
const langSelect = document.getElementById("lang");
const preview = document.getElementById("preview");
const labelInput = document.getElementById("labelinput");
const labelLang = document.getElementById("labelLang");
const title = document.getElementById("title");
// Appliquer la langue depuis l'URL
const urlParams = new URLSearchParams(window.location.search);
const langFromURL = urlParams.get("lang");
if (langFromURL) {
langSelect.value = langFromURL;
labelInput.textContent = langFromURL === "en" ? "Choose Picture :" : "Choisir une image :";
labelLang.textContent = langFromURL === "en" ? "Choose the language :" : "Choisir la langue :";
title.textContent = langFromURL === "en" ? "Race Detection from Image" : "Détection de Race à partir de l'Image";
}
langSelect.addEventListener("change", function () {
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.set("lang", langSelect.value);
window.location.href = currentUrl.toString();
});
fileInput.addEventListener("change", function () {
if (this.files.length > 0) {
const reader = new FileReader();
reader.onload = function (e) {
preview.src = e.target.result;
preview.style.display = "block";
};
reader.readAsDataURL(this.files[0]);
if (langSelect.value !== "") {
setTimeout(() => form.submit(), 500);
}
}
});
});
</script>
</head>
<body>
<h1 id="title">Détection de Race à partir de l'Image</h1>
<form id="uploadForm" action="/predict/" method="post" enctype="multipart/form-data">
<label id="labelLang" for="lang">Choisir la langue :</label>
<select name="lang" id="lang" required>
<option value="">-- Sélectionner --</option>
<option value="fr">Français</option>
<option value="en">English</option>
</select><br><br>
<label id="labelinput" for="fileInput">Choisir une image :</label><br><br>
<input type="file" name="file" id="fileInput" accept="image/*" required><br><br>
<center> <img id="preview" src="#" alt="Aperçu de l'image"><br></center>
<center><button type="submit">Analyse</button></center>
</form>
</body>
</html>
"""
return HTMLResponse(content=html_content)
@app.post("/predict/")
async def predict_race(file: UploadFile = File(...), lang: str = Form("fr")):
image_data = await file.read()
image = Image.open(BytesIO(image_data)).convert("RGB")
# Encode image in base64
buffered = BytesIO()
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
label, confidence = predict(image)
advice = get_advice(label)
temperament = taille = activite = esperance = ""
if isinstance(advice, str):
lines = advice.split("\n")
for line in lines:
if line.lower().startswith("tempérament") or line.lower().startswith("temperament"):
temperament = line
elif line.lower().startswith("taille"):
taille = line
elif line.lower().startswith("activité") or line.lower().startswith("activity"):
activite = line
elif line.lower().startswith("espérance") or line.lower().startswith("life"):
esperance = line
advice = ""
else:
advice = "Aucune information disponible." if lang == "fr" else "No information available."
return HTMLResponse(content=f"""
<html>
<head>
<title>Résultats</title>
<style>
body {{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #e8eafa, #dfecf2);
text-align: center;
padding: 60px 20px;
margin: 0;
}}
.result {{
background-color: #ffffff;
padding: 40px;
border-radius: 16px;
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
display: inline-block;
max-width: 600px;
width: 90%;
}}
h1, h2, h3 {{
color: #333;
margin: 10px 0;
}}
p {{
font-size: 1rem;
color: #555;
margin: 15px 0;
}}
img {{
margin-top: 20px;
max-width: 100%;
border-radius: 12px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}}
a {{
display: inline-block;
margin-top: 30px;
background: linear-gradient(135deg, #66bb6a, #43a047);
color: white;
padding: 12px 24px;
border-radius: 8px;
text-decoration: none;
font-size: 1rem;
}}
</style>
</head>
<body>
<div class="result">
<h1>{'Résultat de la Détection' if lang == 'fr' else 'Detection Result'}</h1>
<h2>{'Race détectée' if lang == 'fr' else 'Detected Breed'} : {label}</h2>
<h3>{'Confiance' if lang == 'fr' else 'Confidence'} : {confidence * 100:.2f}%</h3>
<h3>{'Fiche descriptive' if lang == 'fr' else 'Breed Info'} :</h3>
<p>{advice}</p>
<p>{temperament}</p>
<p>{taille}</p>
<p>{activite}</p>
<p>{esperance}</p>
<img src="data:image/jpeg;base64,{img_str}" alt="Image Uploadée">
<br>
<a href="/">🔙 {'Retour' if lang == 'fr' else 'Back'}</a>
</div>
</body>
</html>
""")