CV_insectClassifier / static /frontend.html
diahretnoutami
Initial project commit for insect classifier
62d3e16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Insect Classifier</title>
<style>
/* Hapus kata 'padding' yang salah posisi */
body {
font-family: Arial, sans-serif;
background: #f0f8ff;
text-align: center;
margin: 0;
padding: 20px;
}
h1 {
color: #333;
}
h4 {
color: #666;
margin-top: 0;
}
.container {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 30px;
}
.card {
background: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
width: 300px;
height: 450px; /* Diperhatikan apakah cukup tinggi jika deskripsi panjang */
display: flex;
flex-direction: column;
align-items: center;
}
input[type="file"] {
margin: 10px 0;
}
/* #modelSelect tidak digunakan di HTML ini, bisa dihapus jika tidak ada elemennya */
/*
#modelSelect {
margin: 10px 0;
padding: 5px;
font-size: 14px;
}
*/
#preview {
max-width: 90%;
max-height: 150px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
margin-bottom: 10px;
}
button {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #45a049;
}
.loading {
display: none;
margin-top: 10px;
font-style: italic;
color: #555;
}
#result {
font-size: 18px;
font-weight: bold;
color: #333;
margin-top: 20px;
white-space: pre-line;
}
/* Menggabungkan style description dan pseudo-elementnya */
#description {
margin-top: 20px;
text-align: justify;
font-size: 14px;
color: #555;
border-top: 1px solid #ccc; /* Garis pemisah */
padding-top: 15px; /* Spasi setelah garis */
}
</style>
</head>
<body>
<h1>Insect Classification</h1>
<h4>Diah Retno Utami - 4TIB</h4>
<div class="container">
<div class="card">
<h2>Upload Image</h2>
<input type="file" id="upload" accept="image/*" onchange="previewImage()"/>
<img id="preview" src="" alt="Image Preview"/>
<button onclick="uploadImage()">Predict</button>
</div>
<div class="card">
<h2>Prediction Result</h2>
<div id="result">No prediction yet.</div>
<p class="loading" id="loading">Predicting...</p>
<div id="description"></div>
</div>
</div>
<script>
function previewImage() {
const file = document.getElementById('upload').files[0];
if (file) { // Tambahkan pengecekan file ada atau tidak
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('preview').src = e.target.result;
}
reader.readAsDataURL(file);
} else {
document.getElementById('preview').src = ""; // Reset gambar jika tidak ada file
}
}
async function uploadImage() {
const fileInput = document.getElementById('upload');
const file = fileInput.files[0];
if (!file) {
alert('Please select an image.');
return;
}
const formData = new FormData();
formData.append("file", file);
document.getElementById('loading').style.display = 'block';
document.getElementById('result').innerText = 'No prediction yet.';
document.getElementById('description').innerText = ''; // Reset deskripsi
try {
// !!! KRITIKAL: UBAH URL API INI UNTUK KOMPATIBILITAS DEPLOYMENT DAN LOKAL !!!
const response = await fetch('/predict/', { // <-- PERUBAHAN DI SINI
method: 'POST',
body: formData
});
if (!response.ok) { // Tambahkan pengecekan jika response tidak OK (misal 404, 500)
const errorText = await response.text();
throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
}
const result = await response.json();
document.getElementById('result').innerText =
`CNN Model:\n Predicted Class: ${result.cnn.predicted_class}\n Accuracy: ${(result.cnn.confidence * 100).toFixed(2)}%\n\n` +
`MobileNetV2 Model:\n Predicted Class: ${result.mobilenet.predicted_class}\n Accuracy: ${(result.mobilenet.confidence * 100).toFixed(2)}%`;
// !!! KRITIKAL: GUNAKAN overall_description DARI BACKEND !!!
document.getElementById('description').innerText = result.overall_description; // <-- PERUBAHAN DI SINI
} catch (error) {
console.error("Error during prediction:", error); // Log error lebih detail untuk debugging
document.getElementById('result').innerText = `Error during prediction: ${error.message || error}`;
document.getElementById('description').innerText = 'Failed to get description.';
} finally {
document.getElementById('loading').style.display = 'none';
}
}
</script>
</body>
</html>