Subh775 commited on
Commit
dc804ea
·
verified ·
1 Parent(s): bae9119

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +109 -10
static/index.html CHANGED
@@ -6,13 +6,14 @@
6
  <title>Tulsi Leaf Segmentation — RF-DETR</title>
7
  <style>
8
  :root {
9
- --primary: #E73562; /* pink */
10
- --secondary: #EA782D; /* red-ish */
11
  --dark-bg: #121212;
12
  --surface-bg: #1E1E2E;
13
  --text-primary: #E0E0E0;
14
  --text-secondary: #BDB2C6;
15
  --border-color: rgba(255, 255, 255, 0.06);
 
16
  }
17
  * { margin: 0; padding: 0; box-sizing: border-box; }
18
  body {
@@ -114,7 +115,7 @@
114
  padding: 14px;
115
  margin-top: 6px;
116
  }
117
- .control-group { margin-bottom: 12px; }
118
  label { display:block; margin-bottom:6px; color:var(--text-secondary); font-size:0.95em; }
119
  .confidence-display { display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
120
  .confidence-value { color: var(--primary); font-weight:700; font-size:1.05em; }
@@ -123,6 +124,66 @@
123
  input[type="range"]::-webkit-slider-thumb { -webkit-appearance:none; width:18px; height:18px; border-radius:50%; background:var(--primary); cursor:pointer; }
124
  input[type="range"]::-moz-range-thumb { width:18px; height:18px; border-radius:50%; background:var(--primary); cursor:pointer; }
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  .action-btn {
127
  background: linear-gradient(135deg, var(--secondary), #FF7A5A);
128
  color: white;
@@ -136,6 +197,10 @@
136
  margin-top: 6px;
137
  font-weight:600;
138
  }
 
 
 
 
139
  .action-btn:disabled { background: linear-gradient(135deg,#444,#666); cursor:not-allowed; opacity:0.6; }
140
 
141
  .info-panel { background: rgba(0,0,0,0.14); border-radius:8px; padding:14px; margin-top:10px; }
@@ -151,10 +216,18 @@
151
  cursor: pointer;
152
  width: 100%;
153
  font-weight:600;
 
154
  }
 
 
 
 
 
 
155
  @media (max-width: 900px) {
156
  .main-content { grid-template-columns: 1fr; }
157
  h1 { font-size: 1.8em; }
 
158
  }
159
  .visually-hidden { position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
160
  </style>
@@ -163,7 +236,7 @@
163
  <div class="container">
164
  <header>
165
  <h1>Tulsi Leaf Segmentation — RF-DETR</h1>
166
- <p class="header-note">The model can predict wrongly over clutterd/unclear images. <strong>Recommended:</strong> Please provide focused images only.</p>
167
  </header>
168
 
169
  <div class="main-content">
@@ -172,7 +245,7 @@
172
  <h2>Input & Controls</h2>
173
 
174
  <div id="upload-area" class="upload-area">
175
- <p>Click/drop an image (jpg, png)</p>
176
  </div>
177
  <input id="file-input" class="visually-hidden" type="file" accept="image/*" />
178
 
@@ -189,6 +262,23 @@
189
  <input id="conf-slider" type="range" min="0" max="100" value="5" step="1">
190
  </div>
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  <button id="predict-btn" class="action-btn" disabled>Detect Leaves</button>
193
  </div>
194
  </div>
@@ -222,6 +312,8 @@
222
  const predictBtn = document.getElementById('predict-btn');
223
  const confSlider = document.getElementById('conf-slider');
224
  const confDisplay = document.getElementById('conf-display');
 
 
225
  const annotatedImg = document.getElementById('annotated-img');
226
  const statusText = document.getElementById('status-text');
227
  const leafCountEl = document.getElementById('leaf-count');
@@ -230,7 +322,6 @@
230
 
231
  let currentImage = null;
232
  let lastAnnotatedDataUrl = null;
233
- let boxes = [];
234
 
235
  function setStatus(text) { statusText.textContent = text; }
236
 
@@ -284,19 +375,27 @@
284
  if (!currentImage) return;
285
  predictBtn.disabled = true;
286
  setStatus("Processing...");
 
287
  const dataUrl = inputCanvas.toDataURL('image/jpeg', 0.9);
288
  const conf = confSlider.value / 100;
 
 
 
289
  try {
290
  const res = await fetch('/predict', {
291
  method: 'POST',
292
  headers: { 'Content-Type': 'application/json' },
293
- body: JSON.stringify({ image: dataUrl, conf })
 
 
 
 
 
294
  });
295
  if (!res.ok) throw new Error('Server error: ' + res.status);
296
  const j = await res.json();
297
- // j.annotated: data URL, j.confidences: [..], j.count
298
  lastAnnotatedDataUrl = j.annotated;
299
- boxes = j.confidences || [];
300
  annotatedImg.src = lastAnnotatedDataUrl;
301
  leafCountEl.textContent = j.count || 0;
302
  const best = j.confidences && j.confidences.length ? Math.max(...j.confidences) : 0;
@@ -327,4 +426,4 @@
327
  })();
328
  </script>
329
  </body>
330
- </html>
 
6
  <title>Tulsi Leaf Segmentation — RF-DETR</title>
7
  <style>
8
  :root {
9
+ --primary: #E73562;
10
+ --secondary: #EA782D;
11
  --dark-bg: #121212;
12
  --surface-bg: #1E1E2E;
13
  --text-primary: #E0E0E0;
14
  --text-secondary: #BDB2C6;
15
  --border-color: rgba(255, 255, 255, 0.06);
16
+ --accent-green: #33ff99;
17
  }
18
  * { margin: 0; padding: 0; box-sizing: border-box; }
19
  body {
 
115
  padding: 14px;
116
  margin-top: 6px;
117
  }
118
+ .control-group { margin-bottom: 14px; }
119
  label { display:block; margin-bottom:6px; color:var(--text-secondary); font-size:0.95em; }
120
  .confidence-display { display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
121
  .confidence-value { color: var(--primary); font-weight:700; font-size:1.05em; }
 
124
  input[type="range"]::-webkit-slider-thumb { -webkit-appearance:none; width:18px; height:18px; border-radius:50%; background:var(--primary); cursor:pointer; }
125
  input[type="range"]::-moz-range-thumb { width:18px; height:18px; border-radius:50%; background:var(--primary); cursor:pointer; }
126
 
127
+ /* Toggle switches */
128
+ .toggle-group {
129
+ display: flex;
130
+ gap: 16px;
131
+ margin-bottom: 14px;
132
+ padding: 10px;
133
+ background: rgba(0,0,0,0.2);
134
+ border-radius: 6px;
135
+ }
136
+ .toggle-item {
137
+ flex: 1;
138
+ display: flex;
139
+ align-items: center;
140
+ justify-content: space-between;
141
+ }
142
+ .toggle-label {
143
+ color: var(--text-secondary);
144
+ font-size: 0.9em;
145
+ font-weight: 500;
146
+ }
147
+ .toggle-switch {
148
+ position: relative;
149
+ display: inline-block;
150
+ width: 44px;
151
+ height: 24px;
152
+ }
153
+ .toggle-switch input {
154
+ opacity: 0;
155
+ width: 0;
156
+ height: 0;
157
+ }
158
+ .slider {
159
+ position: absolute;
160
+ cursor: pointer;
161
+ top: 0;
162
+ left: 0;
163
+ right: 0;
164
+ bottom: 0;
165
+ background-color: rgba(255, 255, 255, 0.1);
166
+ transition: .3s;
167
+ border-radius: 24px;
168
+ }
169
+ .slider:before {
170
+ position: absolute;
171
+ content: "";
172
+ height: 18px;
173
+ width: 18px;
174
+ left: 3px;
175
+ bottom: 3px;
176
+ background-color: white;
177
+ transition: .3s;
178
+ border-radius: 50%;
179
+ }
180
+ input:checked + .slider {
181
+ background-color: var(--accent-green);
182
+ }
183
+ input:checked + .slider:before {
184
+ transform: translateX(20px);
185
+ }
186
+
187
  .action-btn {
188
  background: linear-gradient(135deg, var(--secondary), #FF7A5A);
189
  color: white;
 
197
  margin-top: 6px;
198
  font-weight:600;
199
  }
200
+ .action-btn:hover:not(:disabled) {
201
+ transform: translateY(-2px);
202
+ box-shadow: 0 6px 20px rgba(234, 120, 45, 0.4);
203
+ }
204
  .action-btn:disabled { background: linear-gradient(135deg,#444,#666); cursor:not-allowed; opacity:0.6; }
205
 
206
  .info-panel { background: rgba(0,0,0,0.14); border-radius:8px; padding:14px; margin-top:10px; }
 
216
  cursor: pointer;
217
  width: 100%;
218
  font-weight:600;
219
+ transition: all 0.22s ease;
220
  }
221
+ .download-btn:hover:not(:disabled) {
222
+ transform: translateY(-2px);
223
+ box-shadow: 0 6px 20px rgba(214, 51, 132, 0.4);
224
+ }
225
+ .download-btn:disabled { opacity: 0.5; cursor: not-allowed; }
226
+
227
  @media (max-width: 900px) {
228
  .main-content { grid-template-columns: 1fr; }
229
  h1 { font-size: 1.8em; }
230
+ .toggle-group { flex-direction: column; gap: 10px; }
231
  }
232
  .visually-hidden { position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
233
  </style>
 
236
  <div class="container">
237
  <header>
238
  <h1>Tulsi Leaf Segmentation — RF-DETR</h1>
239
+ <p class="header-note">Upload an image, set confidence, press <strong>Detect</strong>. CPU-only inference.</p>
240
  </header>
241
 
242
  <div class="main-content">
 
245
  <h2>Input & Controls</h2>
246
 
247
  <div id="upload-area" class="upload-area">
248
+ <p>Click or drop an image here (jpg, png)</p>
249
  </div>
250
  <input id="file-input" class="visually-hidden" type="file" accept="image/*" />
251
 
 
262
  <input id="conf-slider" type="range" min="0" max="100" value="5" step="1">
263
  </div>
264
 
265
+ <div class="toggle-group">
266
+ <div class="toggle-item">
267
+ <span class="toggle-label">Show Labels</span>
268
+ <label class="toggle-switch">
269
+ <input type="checkbox" id="show-labels" checked>
270
+ <span class="slider"></span>
271
+ </label>
272
+ </div>
273
+ <div class="toggle-item">
274
+ <span class="toggle-label">Show Confidence</span>
275
+ <label class="toggle-switch">
276
+ <input type="checkbox" id="show-confidence" checked>
277
+ <span class="slider"></span>
278
+ </label>
279
+ </div>
280
+ </div>
281
+
282
  <button id="predict-btn" class="action-btn" disabled>Detect Leaves</button>
283
  </div>
284
  </div>
 
312
  const predictBtn = document.getElementById('predict-btn');
313
  const confSlider = document.getElementById('conf-slider');
314
  const confDisplay = document.getElementById('conf-display');
315
+ const showLabelsToggle = document.getElementById('show-labels');
316
+ const showConfidenceToggle = document.getElementById('show-confidence');
317
  const annotatedImg = document.getElementById('annotated-img');
318
  const statusText = document.getElementById('status-text');
319
  const leafCountEl = document.getElementById('leaf-count');
 
322
 
323
  let currentImage = null;
324
  let lastAnnotatedDataUrl = null;
 
325
 
326
  function setStatus(text) { statusText.textContent = text; }
327
 
 
375
  if (!currentImage) return;
376
  predictBtn.disabled = true;
377
  setStatus("Processing...");
378
+
379
  const dataUrl = inputCanvas.toDataURL('image/jpeg', 0.9);
380
  const conf = confSlider.value / 100;
381
+ const showLabels = showLabelsToggle.checked;
382
+ const showConfidence = showConfidenceToggle.checked;
383
+
384
  try {
385
  const res = await fetch('/predict', {
386
  method: 'POST',
387
  headers: { 'Content-Type': 'application/json' },
388
+ body: JSON.stringify({
389
+ image: dataUrl,
390
+ conf: conf,
391
+ show_labels: showLabels,
392
+ show_confidence: showConfidence
393
+ })
394
  });
395
  if (!res.ok) throw new Error('Server error: ' + res.status);
396
  const j = await res.json();
397
+
398
  lastAnnotatedDataUrl = j.annotated;
 
399
  annotatedImg.src = lastAnnotatedDataUrl;
400
  leafCountEl.textContent = j.count || 0;
401
  const best = j.confidences && j.confidences.length ? Math.max(...j.confidences) : 0;
 
426
  })();
427
  </script>
428
  </body>
429
+ </html>