Pokkhrong Rasee
Deploy Image Captioning Web App with FastAPI and Docker to Hugging Face Space
d1d7665
Raw
History Blame Contribute Delete
4.86 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Captioning — Pretrained vs Fine-Tuned BLIP</title>
<link rel="stylesheet" href="/static/style.css?v=20260724_3">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="container">
<header>
<h1>🖼️ Image Captioning Studio</h1>
<p class="subtitle">Upload an image & compare Pretrained vs. Fine-Tuned BLIP models</p>
<div id="model-badge" class="model-badge hidden">Loading models...</div>
</header>
<!-- Model Selector Control Bar -->
<div class="selector-container">
<label class="selector-label">Select Model Mode:</label>
<div class="segmented-control">
<input type="radio" name="model_choice" id="mode-both" value="both" checked>
<label for="mode-both" class="control-btn">
<span class="icon"></span> Compare Both
</label>
<input type="radio" name="model_choice" id="mode-finetuned" value="fine-tuned">
<label for="mode-finetuned" class="control-btn">
<span class="icon">🎯</span> Fine-Tuned (Flickr8k)
</label>
<input type="radio" name="model_choice" id="mode-pretrained" value="pretrained">
<label for="mode-pretrained" class="control-btn">
<span class="icon">🌐</span> Pretrained BLIP
</label>
</div>
</div>
<!-- Language Selector Control Bar -->
<div class="selector-container">
<label class="selector-label">Caption Language:</label>
<div class="segmented-control">
<input type="radio" name="lang_choice" id="lang-both" value="both" checked>
<label for="lang-both" class="control-btn">
<span class="icon">🌐</span> ทั้งสองภาษา (EN+TH)
</label>
<input type="radio" name="lang_choice" id="lang-th" value="th">
<label for="lang-th" class="control-btn">
<span class="icon">🇹🇭</span> ภาษาไทย
</label>
<input type="radio" name="lang_choice" id="lang-en" value="en">
<label for="lang-en" class="control-btn">
<span class="icon">🇺🇸</span> English
</label>
</div>
</div>
<main>
<!-- Upload Area -->
<div id="drop-zone" class="drop-zone">
<div class="drop-zone-content">
<svg class="upload-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
<p class="drop-text"><strong>Drag & drop</strong> an image here</p>
<p class="drop-hint">or click to browse (JPG, PNG, GIF, WebP)</p>
<input type="file" id="file-input" accept="image/*" hidden>
</div>
</div>
<!-- Preview & Results Container -->
<div id="result-area" class="result-area hidden">
<div class="preview-card">
<img id="preview-img" src="" alt="Uploaded preview">
</div>
<div id="loading-spinner" class="spinner">
<div class="spinner-ring"></div>
<p class="spinner-text">Generating captions with AI models...</p>
</div>
<!-- Results Grid (Dynamic: 1 or 2 columns) -->
<div id="results-grid" class="results-grid"></div>
<button id="clear-btn" class="clear-btn">✨ Upload Another Image</button>
</div>
<!-- Error Message -->
<div id="error-msg" class="error-msg hidden"></div>
</main>
<footer>
<p>Powered by <a href="https://huggingface.co/Salesforce/blip-image-captioning-base" target="_blank">Salesforce BLIP</a> + <a href="https://huggingface.co/facebook/nllb-200-distilled-600M" target="_blank">NLLB-200</a> + PyTorch + FastAPI</p>
</footer>
</div>
<script src="/static/app.js?v=20260724_3"></script>
</body>
</html>