273 lines
11 KiB
HTML
273 lines
11 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Upload Gambar{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-8">
|
|
<div class="card shadow">
|
|
<div class="card-header bg-success text-white">
|
|
<h4 class="mb-0"><i class="fas fa-upload me-2"></i>Upload Gambar Sapi</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
|
|
<div class="alert alert-info mb-4">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
<strong>Petunjuk:</strong> Upload satu atau lebih gambar sapi dengan format JPG, JPEG, PNG, atau BMP.
|
|
Jika terdeteksi sakit, anda akan diarahkan ke Sistem Pakar untuk diagnosis lebih lanjut.
|
|
</div>
|
|
|
|
{% if error %}
|
|
<div class="alert alert-danger">
|
|
<i class="fas fa-exclamation-circle me-2"></i>
|
|
{{ error }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="POST" action="{{ url_for('predict') }}" enctype="multipart/form-data" id="uploadForm">
|
|
<div class="mb-4">
|
|
<div class="upload-area border border-2 border-dashed rounded p-4 text-center"
|
|
id="uploadArea">
|
|
<i class="fas fa-cloud-upload-alt fa-4x text-success mb-3"></i>
|
|
<h5>Drag & Drop, atau Pilih dari Galeri</h5>
|
|
<p class="text-muted mb-3">Format: JPG, JPEG, PNG, BMP (Maks. 16MB per file)</p>
|
|
<input type="file" class="d-none" id="file" name="image"
|
|
accept="image/*" multiple>
|
|
<div class="d-flex flex-wrap justify-content-center gap-2">
|
|
<button type="button" class="btn btn-success" id="browseBtn">
|
|
<i class="fas fa-images me-2"></i>Pilih File
|
|
</button>
|
|
<button type="button" class="btn btn-outline-success" id="cameraBtn">
|
|
<i class="fas fa-camera me-2"></i>Kamera
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="fileInfo" class="mt-3 d-none"></div>
|
|
</div>
|
|
|
|
<div id="previewContainer" style="display: none;">
|
|
<h6 class="mb-3"><i class="fas fa-image me-2"></i>Preview Gambar:</h6>
|
|
<div class="row" id="previewGrid"></div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-success btn-lg w-100 mt-3" id="submitBtn" disabled>
|
|
<i class="fas fa-search me-2"></i>Upload & Deteksi
|
|
</button>
|
|
</form>
|
|
|
|
<div id="loading" class="text-center mt-4 d-none">
|
|
<div class="spinner-border text-success" style="width: 3rem; height: 3rem;" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p class="mt-3 fw-bold">Sedang menganalisis gambar...</p>
|
|
<p class="text-muted small">Proses ini membutuhkan waktu beberapa detik</p>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<h6 class="mb-2">Format yang Didukung:</h6>
|
|
<div class="d-flex gap-2">
|
|
<span class="badge bg-secondary">JPG</span>
|
|
<span class="badge bg-secondary">JPEG</span>
|
|
<span class="badge bg-secondary">PNG</span>
|
|
<span class="badge bg-secondary">BMP</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mt-4">
|
|
<div class="card-header bg-info text-white">
|
|
<h5 class="mb-0"><i class="fas fa-lightbulb me-2"></i>Tips Pengambilan Gambar</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6><i class="fas fa-check-circle text-success me-2"></i>Disarankan:</h6>
|
|
<ul class="list-unstyled">
|
|
<li><i class="fas fa-arrow-right text-success me-2"></i>Gambar dengan pencahayaan cukup</li>
|
|
<li><i class="fas fa-arrow-right text-success me-2"></i>Fokus pada bagian mulut dan kaki</li>
|
|
<li><i class="fas fa-arrow-right text-success me-2"></i>Ambil dari jarak dekat (0.5-1 meter)</li>
|
|
<li><i class="fas fa-arrow-right text-success me-2"></i>Gunakan latar belakang polos</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6><i class="fas fa-times-circle text-danger me-2"></i>Tidak Disarankan:</h6>
|
|
<ul class="list-unstyled">
|
|
<li><i class="fas fa-times text-danger me-2"></i>Gambar buram atau blur</li>
|
|
<li><i class="fas fa-times text-danger me-2"></i>Terlalu jauh dari objek</li>
|
|
<li><i class="fas fa-times text-danger me-2"></i>Pencahayaan kurang/tidak merata</li>
|
|
<li><i class="fas fa-times text-danger me-2"></i>Banyak objek dalam satu frame</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.upload-area {
|
|
border: 2px dashed #28a745 !important;
|
|
background-color: #f8f9fa;
|
|
transition: all 0.3s;
|
|
cursor: pointer;
|
|
}
|
|
.upload-area:hover {
|
|
background-color: #e9ecef;
|
|
border-color: #218838 !important;
|
|
}
|
|
.upload-area.dragover {
|
|
background-color: #d4edda;
|
|
border-color: #28a745 !important;
|
|
}
|
|
.preview-wrapper {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
.preview-wrapper img {
|
|
height: 120px;
|
|
object-fit: cover;
|
|
width: 100%;
|
|
border-radius: 4px;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var uploadArea = document.getElementById('uploadArea');
|
|
var fileInput = document.getElementById('file');
|
|
var browseBtn = document.getElementById('browseBtn');
|
|
var fileInfo = document.getElementById('fileInfo');
|
|
var previewContainer = document.getElementById('previewContainer');
|
|
var previewGrid = document.getElementById('previewGrid');
|
|
var submitBtn = document.getElementById('submitBtn');
|
|
var loading = document.getElementById('loading');
|
|
var uploadForm = document.getElementById('uploadForm');
|
|
|
|
if (!uploadArea || !fileInput || !browseBtn || !submitBtn || !uploadForm) return;
|
|
|
|
uploadArea.addEventListener('click', function() {
|
|
fileInput.click();
|
|
});
|
|
|
|
browseBtn.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
fileInput.click();
|
|
});
|
|
|
|
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(name) {
|
|
uploadArea.addEventListener(name, function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}, false);
|
|
});
|
|
|
|
['dragenter', 'dragover'].forEach(function(name) {
|
|
uploadArea.addEventListener(name, function() {
|
|
uploadArea.classList.add('dragover');
|
|
}, false);
|
|
});
|
|
|
|
['dragleave', 'drop'].forEach(function(name) {
|
|
uploadArea.addEventListener(name, function() {
|
|
uploadArea.classList.remove('dragover');
|
|
}, false);
|
|
});
|
|
|
|
uploadArea.addEventListener('drop', function(e) {
|
|
fileInput.files = e.dataTransfer.files;
|
|
handleFiles(fileInput.files);
|
|
}, false);
|
|
|
|
fileInput.addEventListener('change', function() {
|
|
if (this.files.length > 0) {
|
|
handleFiles(this.files);
|
|
}
|
|
});
|
|
|
|
function handleFiles(files) {
|
|
var validFiles = [];
|
|
for (var i = 0; i < files.length; i++) {
|
|
var f = files[i];
|
|
if (f.size > 16 * 1024 * 1024) {
|
|
alert('File ' + f.name + ' terlalu besar (maks 16MB)');
|
|
continue;
|
|
}
|
|
var allowed = ['image/jpeg', 'image/jpg', 'image/png', 'image/bmp'];
|
|
if (allowed.indexOf(f.type) === -1) {
|
|
alert('File ' + f.name + ' tidak didukung');
|
|
continue;
|
|
}
|
|
validFiles.push(f);
|
|
}
|
|
|
|
if (validFiles.length === 0) {
|
|
fileInput.value = '';
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<i class="fas fa-search me-2"></i>Upload & Deteksi';
|
|
if (fileInfo) fileInfo.classList.add('d-none');
|
|
if (previewContainer) previewContainer.style.display = 'none';
|
|
return;
|
|
}
|
|
|
|
if (fileInfo) {
|
|
fileInfo.classList.remove('d-none');
|
|
fileInfo.innerHTML = '<div class="alert alert-info">' + validFiles.length + ' file dipilih</div>';
|
|
}
|
|
|
|
if (previewContainer && previewGrid) {
|
|
previewContainer.style.display = 'block';
|
|
previewGrid.innerHTML = '';
|
|
|
|
for (var j = 0; j < validFiles.length; j++) {
|
|
(function(file) {
|
|
var col = document.createElement('div');
|
|
col.className = 'col-md-3 col-6 mb-3';
|
|
col.innerHTML = '<div class="card h-100"><div class="card-body p-1 text-center"><div class="preview-wrapper"><img></div><small class="text-muted mt-1 d-block">' + file.name + '</small></div></div>';
|
|
previewGrid.appendChild(col);
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
col.querySelector('img').src = e.target.result;
|
|
};
|
|
reader.readAsDataURL(file);
|
|
})(validFiles[j]);
|
|
}
|
|
}
|
|
|
|
submitBtn.disabled = false;
|
|
submitBtn.innerHTML = '<i class="fas fa-search me-2"></i>Deteksi Semua (' + validFiles.length + ' gambar)';
|
|
}
|
|
|
|
uploadForm.addEventListener('submit', function(e) {
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Memproses...';
|
|
if (loading) loading.classList.remove('d-none');
|
|
});
|
|
|
|
// Camera button
|
|
var cameraBtn = document.getElementById('cameraBtn');
|
|
if (cameraBtn) {
|
|
cameraBtn.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
var camInput = document.createElement('input');
|
|
camInput.type = 'file';
|
|
camInput.accept = 'image/*';
|
|
camInput.capture = 'environment';
|
|
camInput.multiple = true;
|
|
camInput.onchange = function() {
|
|
if (this.files.length > 0) {
|
|
fileInput.files = this.files;
|
|
handleFiles(this.files);
|
|
}
|
|
};
|
|
camInput.click();
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|