File size: 5,973 Bytes
7b2eca8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f66e5e6
7b2eca8
 
 
f66e5e6
7b2eca8
 
 
 
 
 
 
 
 
 
 
 
 
f66e5e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7b2eca8
 
 
 
 
 
 
 
 
 
f66e5e6
 
 
 
 
 
 
 
 
7b2eca8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>πŸ€– Image πŸ–ΌοΈ Captioning</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- βœ… Tailwind CDN -->
  <script src="https://cdn.tailwindcss.com"></script>
</head>

<body class="bg-gray-100 flex items-center justify-center min-h-screen">
  <a href="/" class="absolute top-4 left-4 text-blue-600 hover:text-blue-800 text-sm font-semibold flex items-center">
    <!-- back arrow -->
    <svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"
      xmlns="http://www.w3.org/2000/svg">
      <path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"></path>
    </svg>
    Back to Home
  </a>

  <div class="bg-white p-8 rounded-xl shadow-md w-full max-w-md text-center">
    <h1 class="text-2xl font-bold mb-4 text-gray-800">AI Image Captioning</h1>

    <!-- Upload Form -->
    <form id="uploadForm" class="space-y-4">
      <input 
        type="file" 
        id="fileInput" 
        accept="image/*" 
        required
        class="block w-full text-sm text-gray-700 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
      />

      <!-- Live Image Preview -->
      <div id="previewContainer" class="mt-4 hidden">
        <img id="previewImage" src="#" alt="Preview" class="mx-auto max-h-64 rounded-md shadow" />
      </div>

      <button 
        id="generateButton"
        type="submit"
        class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition"
      >
        Generate Captions
      </button>
    </form>

    <!-- Captions -->
    <div id="result" class="mt-6 text-left hidden">
      <h2 class="text-lg font-semibold mb-2 text-gray-700">Captions:</h2>
      <p><strong>Factual πŸ€–:</strong> <span id="greedy" class="text-gray-800"></span></p>
      <p><strong>Creative πŸ€ͺ:</strong> <span id="topk" class="text-gray-800"></span></p>
      <p><strong>Human like πŸ«€:</strong> <span id="topp" class="text-gray-800"></span></p>
    </div>
  </div>

  <script>
  const fileInput = document.getElementById('fileInput');
  const previewContainer = document.getElementById('previewContainer');
  const previewImage = document.getElementById('previewImage');
  const form = document.getElementById('uploadForm');
  const result = document.getElementById('result');
  const generateButton = document.getElementById('generateButton');

  // βœ… Live preview + clear old captions
  fileInput.addEventListener('change', () => {
    const file = fileInput.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = e => {
        previewImage.src = e.target.result;
        previewContainer.classList.remove('hidden');
      };
      reader.readAsDataURL(file);

      // Clear old captions
      document.getElementById('greedy').innerText = "";
      document.getElementById('topk').innerText = "";
      document.getElementById('topp').innerText = "";
      result.classList.add('hidden');
    } else {
      previewContainer.classList.add('hidden');
    }
  });

  // βœ… Submit form
  form.addEventListener('submit', async e => {
    e.preventDefault();

    // Disable button while generating
    generateButton.disabled = true;
    generateButton.innerText = "Generating...";

    const file = fileInput.files[0];
    const formData = new FormData();
    formData.append('file', file);

    try {
      const res = await fetch('/generate', {
        method: 'POST',
        body: formData
      });

      const data = await res.json();
      document.getElementById('greedy').innerText = data.greedy || "N/A";
      document.getElementById('topk').innerText = data.topk || "N/A";
      document.getElementById('topp').innerText = data.topp || "N/A";
      result.classList.remove('hidden');
    } catch (error) {
      alert("⚠️ Error generating captions. Please try again.");
    } finally {
      // Re-enable button with new text
      generateButton.disabled = false;
      generateButton.innerText = "Generate Captions (can repeat)";
    }
  });
</script>

<!-- Floating Help Button -->
<button id="helpButton"
  class="fixed bottom-4 right-4 bg-blue-600 text-white rounded-full w-12 h-12 text-2xl font-bold shadow-lg hover:bg-blue-700 transition">
  ?
</button>

<!-- Help Modal -->
<div id="helpModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
  <div class="bg-white rounded-lg p-6 max-w-sm w-full shadow-lg text-left">
    <h2 class="text-xl font-semibold mb-4">πŸ€– Image Captioning</h2>
    <p class="text-gray-700 mb-4">
      Please upload a picture / image and press "Generate Captions", the model will generate captions for it. 
      The model uses google/vit-base-patch16-224-in21k or openai/clip-vit-base-patch32
      as image encoder, trained together with a customer transformer decoder to generate captions.<br>
      The available caption styles are: "Factual πŸ€–", "Creative πŸ€ͺ", and "Human like πŸ«€", 
      which are actually argmax (greedy), top-K and top-P respectively.

    </p>
    <button id="closeModal"
      class="mt-2 bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
      Close
    </button>
  </div>
</div>

<script>
  const helpButton = document.getElementById('helpButton');
  const helpModal = document.getElementById('helpModal');
  const closeModal = document.getElementById('closeModal');

  helpButton.addEventListener('click', () => {
    helpModal.classList.remove('hidden');
  });

  closeModal.addEventListener('click', () => {
    helpModal.classList.add('hidden');
  });

  // Optional: close modal when clicking outside the modal box
  helpModal.addEventListener('click', (e) => {
    if (e.target === helpModal) {
      helpModal.classList.add('hidden');
    }
  });
</script>

</body>
</html>