a b/templates/index.html
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Medical X-Ray Classifier</title>
7
  <style>
8
    /* General Styles */
9
    body {
10
      font-family: 'Arial', sans-serif;
11
      background: linear-gradient(to right, #e3f2fd, #ffffff);
12
      margin: 0;
13
      padding: 0;
14
      display: flex;
15
      justify-content: center;
16
      align-items: center;
17
      min-height: 100vh;
18
    }
19
20
    .container {
21
      width: 90%;
22
      max-width: 1200px;
23
      background: #fff;
24
      border-radius: 12px;
25
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
26
      display: flex;
27
      overflow: hidden;
28
      animation: fadeIn 1s ease-in-out;
29
    }
30
31
    @keyframes fadeIn {
32
      from {
33
        opacity: 0;
34
        transform: translateY(20px);
35
      }
36
      to {
37
        opacity: 1;
38
        transform: translateY(0);
39
      }
40
    }
41
42
    .left-column {
43
      width: 35%;
44
      background: #f8f9fa;
45
      padding: 20px;
46
      border-right: 1px solid #ddd;
47
    }
48
49
    .right-column {
50
      width: 65%;
51
      padding: 20px;
52
      display: flex;
53
      flex-direction: column;
54
      align-items: center;
55
    }
56
57
    h1 {
58
      text-align: center;
59
      font-size: 1.8rem;
60
      margin-bottom: 20px;
61
      color: #333;
62
    }
63
64
    input[type="file"] {
65
      margin: 15px 0;
66
      padding: 10px;
67
      border: 1px solid #ddd;
68
      border-radius: 6px;
69
      cursor: pointer;
70
      width: 100%;
71
    }
72
73
    button {
74
      padding: 12px 30px;
75
      background: #007bff;
76
      color: #fff;
77
      border: none;
78
      border-radius: 6px;
79
      font-size: 14px;
80
      cursor: pointer;
81
      transition: background 0.3s ease;
82
      margin: 10px 0;
83
    }
84
85
    button:hover {
86
      background: #0056b3;
87
    }
88
89
    .progress-bar {
90
      width: 100%;
91
      height: 10px;
92
      background: #e9ecef;
93
      border-radius: 5px;
94
      margin: 15px 0;
95
      overflow: hidden;
96
      position: relative;
97
    }
98
99
    .progress-bar .progress {
100
      height: 100%;
101
      background: #28a745;
102
      width: 0;
103
      transition: width 0.5s;
104
    }
105
106
    .fixed-box {
107
      margin-top: 20px;
108
      text-align: center;
109
      border: 1px solid #ddd;
110
      border-radius: 10px;
111
      padding: 10px;
112
      background: #fff;
113
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
114
    }
115
116
    .fixed-box img {
117
      max-width: 100%;
118
      border-radius: 8px;
119
    }
120
121
    .results {
122
      font-size: 1rem;
123
      margin-bottom: 20px;
124
      text-align: center;
125
      display: none;
126
    }
127
128
    .results.visible {
129
      display: block;
130
    }
131
132
    .note {
133
      font-size: 1rem;
134
      color: #d9534f;
135
      text-align: center;
136
      margin-top: 20px;
137
    }
138
139
    .visualization-group {
140
      margin-top: 20px;
141
      width: 100%;
142
      display: none;
143
    }
144
145
    .visualization-group.visible {
146
      display: block;
147
    }
148
149
    .visualization-group h3 {
150
      font-size: 1.2rem;
151
      margin-bottom: 10px;
152
      text-align: center;
153
    }
154
155
    .visualization {
156
      display: grid;
157
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
158
      gap: 15px;
159
      justify-items: center;
160
    }
161
162
    .visualization img {
163
      max-width: 100%;
164
      border-radius: 8px;
165
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
166
      transition: transform 0.2s ease;
167
    }
168
169
    .visualization img:hover {
170
      transform: scale(1.05);
171
    }
172
173
    .image-name {
174
      text-align: center;
175
      font-size: 0.9rem;
176
      margin-top: 5px;
177
      color: #555;
178
    }
179
180
    /* Prediction Result Box */
181
    .prediction-box {
182
      padding: 20px;
183
      background-color: #f8f9fa;
184
      border-radius: 8px;
185
      border: 1px solid #ddd;
186
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
187
      margin-top: 20px;
188
      text-align: center;
189
    }
190
191
    .prediction-box p {
192
      font-size: 1.2rem;
193
      margin: 5px 0;
194
    }
195
196
    .prediction-box .class {
197
      font-weight: bold;
198
      font-size: 1.5rem;
199
      color: #007bff;
200
    }
201
202
    .prediction-box .confidence {
203
      font-size: 1.1rem;
204
      color: #28a745;
205
    }
206
  </style>
207
</head>
208
<body>
209
  <div class="container">
210
    <!-- Left Column -->
211
    <div class="left-column">
212
      <h1>Upload X-Ray</h1>
213
      <form id="upload-form">
214
        <input type="file" id="file-input" name="file" accept="image/*" required>
215
        <button type="submit">Predict</button>
216
        <button id="refresh-button">Refresh</button>
217
        <div class="progress-bar">
218
          <div class="progress" id="progress-bar"></div>
219
        </div>
220
      </form>
221
      <div class="fixed-box">
222
        <h3>Uploaded Image</h3>
223
        <img id="original" src="https://via.placeholder.com/150?text=Upload+Image" alt="Uploaded Image">
224
        <div class="image-name" id="image-name">Image Name</div>
225
      </div>
226
    </div>
227
228
    <!-- Right Column -->
229
    <div class="right-column">
230
      <div class="prediction-box" id="result-box">
231
        <p><strong>Predicted Class:</strong> <span id="predicted-class">N/A</span></p>
232
        <p><strong>Confidence Score:</strong> <span id="confidence-score">N/A</span></p>
233
      </div>
234
      <div id="note" class="note" style="display: none;">
235
        Sorry, you uploaded a non chest X-ray image. Please upload a chest X-ray image. Thank you!
236
      </div>
237
      <div class="visualization-group" id="visualization-group">
238
        <h3>Image Visualizations</h3>
239
        <div class="visualization">
240
          <div>
241
            <img id="grayscale" src="https://via.placeholder.com/150?text=Grayscale" alt="Grayscale Image">
242
            <div class="image-name">Grayscale</div>
243
          </div>
244
          <div>
245
            <img id="equalized" src="https://via.placeholder.com/150?text=Equalized" alt="Equalized Image">
246
            <div class="image-name">Equalized</div>
247
          </div>
248
          <div>
249
            <img id="edges" src="https://via.placeholder.com/150?text=Edges" alt="Edge Detection">
250
            <div class="image-name">Edges</div>
251
          </div>
252
          <div>
253
            <img id="segmented" src="https://via.placeholder.com/150?text=Segmented" alt="Segmented Image">
254
            <div class="image-name">Segmented</div>
255
          </div>
256
        </div>
257
        <h3>Advanced Visualizations</h3>
258
        <div class="visualization">
259
          <div>
260
            <img id="grad_cam" src="https://via.placeholder.com/150?text=Grad-CAM" alt="Grad-CAM Visualization">
261
            <div class="image-name">Grad-CAM</div>
262
          </div>
263
          <div>
264
            <img id="roi" src="https://via.placeholder.com/150?text=ROI" alt="Region of Interest">
265
            <div class="image-name">ROI</div>
266
          </div>
267
        </div>
268
      </div>
269
    </div>
270
  </div>
271
272
  <script>
273
    const form = document.getElementById('upload-form');
274
    const progressBar = document.getElementById('progress-bar');
275
    const resultBox = document.getElementById('result-box');
276
    const refreshButton = document.getElementById('refresh-button');
277
    const note = document.getElementById('note');
278
    const visualizationGroup = document.getElementById('visualization-group');
279
    const imageName = document.getElementById('image-name');
280
281
    form.addEventListener('submit', async (event) => {
282
      event.preventDefault();
283
284
      progressBar.style.width = '0';
285
      resultBox.style.display = 'none';
286
      note.style.display = 'none';
287
      visualizationGroup.style.display = 'none';
288
      const formData = new FormData(form);
289
290
      // Simulate progress
291
      let progress = 0;
292
      const interval = setInterval(() => {
293
        if (progress < 100) {
294
          progress += 10;
295
          progressBar.style.width = `${progress}%`;
296
        } else {
297
          clearInterval(interval);
298
        }
299
      }, 100);
300
301
      const response = await fetch('/predict', { method: 'POST', body: formData });
302
      const data = await response.json();
303
304
      document.getElementById('original').src = URL.createObjectURL(formData.get('file'));
305
      imageName.textContent = formData.get('file').name;
306
307
      if (data.error) {
308
        resultBox.style.display = 'block';
309
        document.getElementById('predicted-class').textContent = 'N/A';
310
        document.getElementById('confidence-score').textContent = 'N/A';
311
        note.style.display = 'block';
312
        return;
313
      }
314
315
      resultBox.style.display = 'block';
316
      document.getElementById('predicted-class').textContent = data.predicted_class;
317
      document.getElementById('confidence-score').textContent = `${data.confidence_score}%`;
318
      visualizationGroup.style.display = 'block';
319
320
      document.getElementById('grayscale').src = data.visualizations.grayscale;
321
      document.getElementById('equalized').src = data.visualizations.equalized;
322
      document.getElementById('edges').src = data.visualizations.edges;
323
      document.getElementById('segmented').src = data.visualizations.segmented;
324
      document.getElementById('grad_cam').src = data.visualizations.grad_cam;
325
      document.getElementById('roi').src = data.visualizations.roi;
326
    });
327
328
    refreshButton.addEventListener('click', () => {
329
      window.location.reload();
330
    });
331
  </script>
332
</body>
333
</html>