arcsu1's picture
Add Hugging Face Spaces metadata
1dab177
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Face Generator - Create AI Faces</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 900px;
margin: 0 auto;
}
header {
text-align: center;
color: white;
margin-bottom: 40px;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
}
.main-card {
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
padding: 40px;
}
.controls {
margin-bottom: 30px;
}
.control-group {
margin-bottom: 25px;
}
label {
display: block;
font-weight: 600;
color: #2d3748;
margin-bottom: 8px;
font-size: 0.95rem;
}
.slider-container {
display: flex;
align-items: center;
gap: 15px;
}
input[type="range"] {
flex: 1;
height: 6px;
border-radius: 3px;
background: #e2e8f0;
outline: none;
-webkit-appearance: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #667eea;
cursor: pointer;
transition: all 0.2s;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2);
background: #5a67d8;
}
input[type="range"]::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #667eea;
cursor: pointer;
border: none;
}
.value-display {
min-width: 40px;
text-align: center;
font-weight: 600;
color: #667eea;
font-size: 1.1rem;
}
input[type="number"] {
width: 100%;
padding: 12px;
border: 2px solid #e2e8f0;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.2s;
}
input[type="number"]:focus {
outline: none;
border-color: #667eea;
}
.button-group {
display: flex;
gap: 12px;
margin-top: 25px;
}
button {
flex: 1;
padding: 14px 28px;
font-size: 1rem;
font-weight: 600;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.btn-secondary {
background: white;
color: #667eea;
border: 2px solid #667eea;
}
.btn-secondary:hover {
background: #f7fafc;
}
.result-area {
margin-top: 35px;
text-align: center;
}
.result-area h3 {
color: #2d3748;
margin-bottom: 20px;
font-size: 1.3rem;
}
#resultImage {
max-width: 100%;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
display: none;
}
#resultImage.show {
display: block;
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.loading {
display: none;
color: #667eea;
font-weight: 600;
margin-top: 20px;
}
.loading.show {
display: block;
}
.spinner {
border: 3px solid #f3f4f6;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error {
background: #fee;
color: #c53030;
padding: 12px;
border-radius: 8px;
margin-top: 15px;
display: none;
}
.error.show {
display: block;
}
footer {
text-align: center;
color: white;
margin-top: 40px;
opacity: 0.8;
}
.info-box {
background: #f7fafc;
padding: 15px;
border-radius: 8px;
margin-bottom: 25px;
border-left: 4px solid #667eea;
}
.info-box p {
color: #4a5568;
line-height: 1.6;
margin: 0;
}
@media (max-width: 640px) {
h1 {
font-size: 2rem;
}
.main-card {
padding: 25px;
}
.button-group {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Face Generator</h1>
<p class="subtitle">Generate realistic faces using AI</p>
</header>
<div class="main-card">
<div class="info-box">
<p>Create synthetic face images using a trained GAN model. Adjust the number of faces and seed for different results.</p>
</div>
<div class="controls">
<div class="control-group">
<label for="numFaces">Number of Faces (1-16)</label>
<div class="slider-container">
<input type="range" id="numFaces" min="1" max="16" value="1">
<span class="value-display" id="numFacesValue">1</span>
</div>
</div>
<div class="control-group">
<label for="seed">Random Seed (optional)</label>
<input type="number" id="seed" placeholder="Leave empty for random generation">
</div>
<div class="button-group">
<button class="btn-primary" id="generateBtn">Generate Faces</button>
<button class="btn-secondary" id="randomBtn">Surprise Me!</button>
</div>
</div>
<div class="result-area">
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Generating faces...</p>
</div>
<div class="error" id="error"></div>
<div id="resultContainer">
<h3 id="resultTitle" style="display: none;">Generated Result</h3>
<img id="resultImage" alt="Generated faces">
</div>
</div>
</div>
<footer>
<p>Powered by GAN Technology</p>
</footer>
</div>
<script>
const numFacesInput = document.getElementById('numFaces');
const numFacesValue = document.getElementById('numFacesValue');
const seedInput = document.getElementById('seed');
const generateBtn = document.getElementById('generateBtn');
const randomBtn = document.getElementById('randomBtn');
const resultImage = document.getElementById('resultImage');
const resultTitle = document.getElementById('resultTitle');
const loading = document.getElementById('loading');
const errorDiv = document.getElementById('error');
numFacesInput.addEventListener('input', (e) => {
numFacesValue.textContent = e.target.value;
});
randomBtn.addEventListener('click', () => {
numFacesInput.value = Math.floor(Math.random() * 9) + 1;
numFacesValue.textContent = numFacesInput.value;
seedInput.value = '';
generateFaces();
});
generateBtn.addEventListener('click', generateFaces);
async function generateFaces() {
const numFaces = parseInt(numFacesInput.value);
const seed = seedInput.value ? parseInt(seedInput.value) : null;
loading.classList.add('show');
errorDiv.classList.remove('show');
resultImage.classList.remove('show');
resultTitle.style.display = 'none';
generateBtn.disabled = true;
randomBtn.disabled = true;
try {
const payload = {
n_samples: numFaces
};
if (seed !== null) {
payload.seed = seed;
}
const response = await fetch('/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error('Failed to generate faces');
}
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
resultImage.src = imageUrl;
resultImage.classList.add('show');
resultTitle.style.display = 'block';
} catch (error) {
errorDiv.textContent = 'Failed to generate faces. Please try again.';
errorDiv.classList.add('show');
} finally {
loading.classList.remove('show');
generateBtn.disabled = false;
randomBtn.disabled = false;
}
}
</script>
</body>
</html>