Spaces:
Running
Running
File size: 5,996 Bytes
d36a257 8de9e92 d36a257 8de9e92 d36a257 90d8a83 d36a257 90d8a83 8de9e92 d36a257 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('inference-form');
const fileInput = document.getElementById('image-upload');
const fileNameDisplay = document.getElementById('file-name');
const submitBtn = document.getElementById('submit-btn');
const dropZone = document.getElementById('drop-zone');
const fileLabel = document.querySelector('.file-label');
const imagePreviewContainer = document.getElementById('image-preview-container');
const imagePreview = document.getElementById('image-preview');
const clearImageBtn = document.getElementById('clear-image-btn');
const loadingState = document.getElementById('loading-state');
const resultsPanel = document.getElementById('results-panel');
const errorPanel = document.getElementById('error-panel');
const resultGender = document.getElementById('result-gender');
const resultAge = document.getElementById('result-age');
const resultRace = document.getElementById('result-race');
const errorMessage = document.getElementById('error-message');
// Drag and drop handlers
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, () => {
fileLabel.classList.add('dragover');
}, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, () => {
fileLabel.classList.remove('dragover');
}, false);
});
dropZone.addEventListener('drop', (e) => {
const dt = e.dataTransfer;
const files = dt.files;
if (files && files.length > 0) {
fileInput.files = files;
handleFileSelection(files[0]);
}
}, false);
// Handle file selection via click
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
handleFileSelection(file);
});
function handleFileSelection(file) {
if (file && file.type.startsWith('image/')) {
// Update text
fileNameDisplay.textContent = file.name;
fileNameDisplay.style.color = 'var(--text-primary)';
submitBtn.disabled = false;
// Generate preview
const reader = new FileReader();
reader.onload = (e) => {
imagePreview.src = e.target.result;
dropZone.classList.add('hidden');
imagePreviewContainer.classList.remove('hidden');
};
reader.readAsDataURL(file);
} else {
resetFileState();
}
// Reset state panels when a new file is chosen
hideAllPanels();
}
// Clear image
clearImageBtn.addEventListener('click', () => {
resetFileState();
hideAllPanels();
});
function resetFileState() {
fileInput.value = '';
fileNameDisplay.textContent = 'Click or drag an image here';
fileNameDisplay.style.color = 'var(--text-secondary)';
submitBtn.disabled = true;
imagePreview.src = '';
imagePreviewContainer.classList.add('hidden');
dropZone.classList.remove('hidden');
}
// Handle form submission
form.addEventListener('submit', async (e) => {
e.preventDefault();
const file = fileInput.files[0];
if (!file) return;
// Update UI state
submitBtn.disabled = true;
hideAllPanels();
loadingState.classList.remove('hidden');
// Prepare data
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/predict', {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`Server responded with status: ${response.status}`);
}
const data = await response.json();
// Validate response format
if (!('gender' in data) || !('age' in data) || !('race' in data)) {
throw new Error('Invalid response format from server');
}
// Update results UI
// Show gender with inline confidence like "Male (87%)"
if (data.gender) {
if (data.gender_confidence !== undefined) {
const pct = Math.round(data.gender_confidence * 100);
resultGender.textContent = `${data.gender} (${pct}%)`;
} else {
resultGender.textContent = data.gender;
}
} else {
resultGender.textContent = '-';
}
// Format age (round if it's a number, otherwise just display string)
const formattedAge = typeof data.age === 'number' ? Math.round(data.age) : data.age;
resultAge.textContent = formattedAge;
resultRace.textContent = data.race || '-';
// Show results
loadingState.classList.add('hidden');
resultsPanel.classList.remove('hidden');
} catch (error) {
console.error('Inference error:', error);
// Show error UI
errorMessage.textContent = error.message || 'An error occurred during inference.';
loadingState.classList.add('hidden');
errorPanel.classList.remove('hidden');
} finally {
submitBtn.disabled = false;
}
});
function hideAllPanels() {
loadingState.classList.add('hidden');
resultsPanel.classList.add('hidden');
errorPanel.classList.add('hidden');
}
});
|