izeeek commited on
Commit
e65551b
·
verified ·
1 Parent(s): 0c245f0

Upload 18 files

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  PneumonAI_App/assets/person3.png filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  PneumonAI_App/assets/person3.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/person3.png filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ import torch
3
+ import torch.nn as nn
4
+ from torchvision import transforms
5
+ from torchvision.models import vgg16
6
+ from PIL import Image
7
+ import io
8
+
9
+ app = Flask(__name__, static_folder='assets')
10
+
11
+ # Load the model
12
+ model = torch.load('pneumonAI_model.pth', map_location=torch.device('cpu'))
13
+
14
+ model.eval()
15
+
16
+ # Define class labels
17
+ class_to_label = {0: 'Normal', 1: 'Pneumonia'}
18
+
19
+ # Define the transformation
20
+ preprocess = transforms.Compose([
21
+ transforms.Grayscale(num_output_channels=3),
22
+ transforms.Resize((224, 224)), # Adjusted to 224 for the model
23
+ transforms.ToTensor(),
24
+ transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
25
+ ])
26
+
27
+ @app.route('/')
28
+ def home():
29
+ return render_template('home.html')
30
+
31
+ @app.route('/about')
32
+ def about():
33
+ return render_template('about.html')
34
+
35
+ @app.route('/predict', methods=['POST'])
36
+ def predict():
37
+ if 'file' not in request.files:
38
+ return jsonify({'error': 'No file part'})
39
+
40
+ file = request.files['file']
41
+ if file.filename == '':
42
+ return jsonify({'error': 'No selected file'})
43
+
44
+ # Load the image
45
+ img = Image.open(io.BytesIO(file.read()))
46
+
47
+ # Preprocess the image
48
+ img_tensor = preprocess(img).unsqueeze(0) # Add batch dimension
49
+
50
+ # Make the prediction
51
+ with torch.no_grad():
52
+ output = model(img_tensor)
53
+
54
+ # Apply softmax to get confidence scores (probabilities)
55
+ probabilities = torch.nn.functional.softmax(output, dim=1)
56
+
57
+ # Get the predicted class label and its confidence
58
+ predicted_class = torch.argmax(probabilities, 1).item()
59
+ confidence = probabilities[0][predicted_class].item()
60
+
61
+ return jsonify({'prediction': class_to_label[predicted_class], 'confidence': confidence * 100})
62
+
63
+ if __name__ == '__main__':
64
+ app.run(debug=True)
assets/accuracy.png ADDED
assets/clear.png ADDED
assets/clock.png ADDED
assets/eye.png ADDED
assets/header.png ADDED
assets/logo.png ADDED
assets/loupe.png ADDED
assets/machine-learning.png ADDED
assets/person1.jpg ADDED
assets/person2.jpg ADDED
assets/person3.png ADDED

Git LFS Details

  • SHA256: 81b8dc93badefcc3ace62f638ac488101a50ad8f753e88aaf51005caac9c0d3d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.03 MB
assets/robot.png ADDED
assets/x-ray.png ADDED
pneumonAI_model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:369fecfa56158f4847718d02ba90777d81453667c41c220849299c9790c60be5
3
+ size 537096918
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ flask
2
+ torch
3
+ torchvision
4
+ gunicorn
templates/about.html ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="utf-8" />
4
+ <meta content="width=device-width, initial-scale=1.0" name="viewport" />
5
+ <title>PneumonAI</title>
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+ <link
8
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
9
+ rel="stylesheet"
10
+ />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&amp;display=swap"
13
+ rel="stylesheet"
14
+ />
15
+ <link
16
+ rel="icon"
17
+ href="{{ url_for('static', filename='logo.png') }}"
18
+ type="image/x-icon"
19
+ />
20
+ <style>
21
+ body {
22
+ font-family: "Nunito", sans-serif;
23
+ }
24
+
25
+ .blue {
26
+ background-color: #0099ff;
27
+ }
28
+
29
+ .dongker {
30
+ color: #01095e;
31
+ }
32
+
33
+ .bg {
34
+ background-color: rgba(0, 153, 255, 0.65);
35
+ }
36
+
37
+ .bdr {
38
+ border: 2px solid #0099ff;
39
+ }
40
+ </style>
41
+ </head>
42
+ <body class="bg-gray-50 text-gray-800">
43
+ <header class="bg-white shadow-lg sticky top-0 z-50">
44
+ <div
45
+ class="container mx-auto px-12 py-4 flex justify-between items-center"
46
+ >
47
+ <div class="flex items-center">
48
+ <img
49
+ alt="PneumonAI logo"
50
+ class="h-10 w-10 rounded-md"
51
+ height="40"
52
+ src="{{ url_for('static', filename='logo.png') }}"
53
+ width="40"
54
+ />
55
+ <span class="ml-2 text-2xl font-bold dongker"> PneumonAI </span>
56
+ </div>
57
+ <nav class="flex space-x-4 items-center">
58
+ <a class="hover:text-blue-500" href="{{ url_for('home') }}"> Home </a>
59
+ <a class="hover:text-blue-500" href="{{ url_for('about') }}">
60
+ About Us
61
+ </a>
62
+ <a
63
+ class="blue text-white px-4 py-2 rounded-full hover:bg-blue-500"
64
+ href="{{ url_for('home') }}#detect"
65
+ >
66
+ Start Detecting
67
+ </a>
68
+ </nav>
69
+ </div>
70
+ </header>
71
+ <main class="text-center py-16">
72
+ <h1 class="text-5xl font-bold dongker pt-8">Our Mission:</h1>
73
+ <h2 class="text-5xl font-bold dongker mt-2">
74
+ Merging Technology and Health
75
+ </h2>
76
+ <p class="mt-6 pt-12 text-lg max-w-4xl mx-auto pb-8">
77
+ We are a team dedicated to creating AI solutions that enhance healthcare
78
+ for everyone. With expertise in both technology and medicine, our goal
79
+ is to make disease diagnosis faster, easier, and more accurate. Meet the
80
+ people behind this innovation and join us in shaping a healthier future.
81
+ </p>
82
+ </main>
83
+ <section class="bg py-16 pt-24 pb-24">
84
+ <h2 class="text-5xl font-bold text-center dongker pb-12">
85
+ Meet Our Team
86
+ </h2>
87
+ <div class="flex justify-center space-x-8 mt-8">
88
+ <div
89
+ class="bg-white p-6 rounded-xl shadow-lg text-center min-w-[225px]"
90
+ >
91
+ <img
92
+ alt="Profile picture of Bernard Santosa"
93
+ class="mx-auto rounded-full"
94
+ height="150"
95
+ src="{{ url_for('static', filename='person1.jpg') }}"
96
+ width="150"
97
+ />
98
+ <p class="mt-4 text-lg font-semibold">Bernard Santosa</p>
99
+ </div>
100
+ <div
101
+ class="bg-white p-6 rounded-xl shadow-lg text-center min-w-[225px]"
102
+ >
103
+ <img
104
+ alt="Profile picture of Filbert Naldo Wijaya"
105
+ class="mx-auto rounded-full"
106
+ height="150"
107
+ src="{{ url_for('static', filename='person2.jpg') }}"
108
+ width="150"
109
+ />
110
+ <p class="mt-4 text-lg font-semibold">Filbert Naldo Wijaya</p>
111
+ </div>
112
+ <div
113
+ class="bg-white p-6 rounded-xl shadow-lg text-center min-w-[225px]"
114
+ >
115
+ <img
116
+ alt="Profile picture of Edberg"
117
+ class="mx-auto rounded-full"
118
+ height="150"
119
+ src="{{ url_for('static', filename='person3.png') }}"
120
+ width="150"
121
+ />
122
+ <p class="mt-4 text-lg font-semibold">Edberg</p>
123
+ </div>
124
+ </div>
125
+ </section>
126
+ <footer class="text-center py-4">
127
+ <p>Copyright © 2024 PneumonAI</p>
128
+ </footer>
129
+ </body>
130
+ </html>
templates/home.html ADDED
@@ -0,0 +1,592 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="utf-8" />
4
+ <meta content="width=device-width, initial-scale=1.0" name="viewport" />
5
+ <title>PneumonAI</title>
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+ <link
8
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
9
+ rel="stylesheet"
10
+ />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&amp;display=swap"
13
+ rel="stylesheet"
14
+ />
15
+ <link
16
+ rel="icon"
17
+ href="{{ url_for('static', filename='logo.png') }}"
18
+ type="image/x-icon"
19
+ />
20
+ <style>
21
+ body {
22
+ font-family: "Nunito", sans-serif;
23
+ }
24
+
25
+ .blue {
26
+ background-color: #0099ff;
27
+ }
28
+
29
+ .dongker {
30
+ color: #01095e;
31
+ }
32
+
33
+ .bg {
34
+ background-color: rgba(0, 153, 255, 0.65);
35
+ }
36
+
37
+ .bdr {
38
+ border: 2px solid #0099ff;
39
+ }
40
+ </style>
41
+ </head>
42
+ <body class="bg-gray-50 text-gray-1000">
43
+ <header class="bg-white shadow-lg sticky top-0 z-50">
44
+ <div
45
+ class="container mx-auto px-12 py-4 flex justify-between items-center"
46
+ >
47
+ <div class="flex items-center">
48
+ <img
49
+ alt="PneumonAI logo"
50
+ class="h-10 w-10 rounded-md"
51
+ height="40"
52
+ src="{{ url_for('static', filename='logo.png') }}"
53
+ width="40"
54
+ />
55
+ <span class="ml-2 text-2xl font-bold dongker"> PneumonAI </span>
56
+ </div>
57
+ <nav class="flex space-x-4 items-center">
58
+ <a class="hover:text-blue-500" href="{{ url_for('home') }}"> Home </a>
59
+ <a class="hover:text-blue-500" href="{{ url_for('about') }}">
60
+ About Us
61
+ </a>
62
+ <a
63
+ class="blue text-white px-4 py-2 rounded-full hover:bg-blue-500"
64
+ href="#detect"
65
+ >
66
+ Start Detecting
67
+ </a>
68
+ </nav>
69
+ </div>
70
+ </header>
71
+
72
+ <main>
73
+ <section class="bg-white py-12">
74
+ <div
75
+ class="container mx-auto px-12 flex flex-col md:flex-row items-center"
76
+ >
77
+ <div class="md:w-2/3 text-center md:text-left">
78
+ <h1 class="text-5xl font-bold dongker">
79
+ Detect Pneumonia with AI. <br />Fast, Accurate, and Easy!
80
+ </h1>
81
+ <p class="mt-4 pt-4 text-lg">
82
+ Welcome to the future of pneumonia detection! With just one click,
83
+ you can analyze your chest X-ray and get fast, reliable results.
84
+ Start now and experience the power of cutting-edge technology.
85
+ </p>
86
+ <div class="mt-8 flex justify-center md:justify-start space-x-4">
87
+ <a
88
+ class="blue text-white px-6 py-3 rounded-full hover:bg-blue-500"
89
+ href="#detect"
90
+ >
91
+ Start Detecting
92
+ </a>
93
+ </div>
94
+ </div>
95
+ <div class="md:w-1/3 mt-8 md:mt-0 flex justify-center md:justify-end">
96
+ <img
97
+ alt="Doctor analyzing X-ray"
98
+ class="mx-auto"
99
+ height="400"
100
+ src="{{ url_for('static', filename='header.png') }}"
101
+ width="400"
102
+ />
103
+ </div>
104
+ </div>
105
+ </section>
106
+ <section class="bg py-16">
107
+ <div class="container mx-auto px-4 py-8">
108
+ <h2 class="text-5xl font-bold text-center dongker">
109
+ What You Need to Know About Pneumonia
110
+ </h2>
111
+ <div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-8 pt-12 px-8">
112
+ <div class="bg-white p-6 rounded-2xl shadow">
113
+ <h3 class="text-2xl font-bold text-gray-800">
114
+ What is Pneumonia?
115
+ </h3>
116
+ <p class="mt-2">
117
+ Pneumonia is a lung infection that makes it hard to breathe. It
118
+ fills the air sacs in your lungs with fluid or pus, leading to
119
+ coughing, fever, and chills. While anyone can get pneumonia,
120
+ it's more dangerous for young kids, older people, and those with
121
+ weak immune systems.
122
+ </p>
123
+ </div>
124
+ <div class="bg-white p-6 rounded-2xl shadow">
125
+ <h3 class="text-2xl font-bold text-gray-800">What Causes It?</h3>
126
+ <p class="mt-2">
127
+ Pneumonia is caused by germs like bacteria, viruses (like the
128
+ flu or COVID-19), and fungi. The most common type comes from
129
+ bacteria called Streptococcus pneumoniae.
130
+ </p>
131
+ </div>
132
+ <div class="bg-white p-6 rounded-2xl shadow">
133
+ <h3 class="text-2xl font-bold text-gray-800">
134
+ What Happens if It's Left Untreated?
135
+ </h3>
136
+ <p class="mt-2">
137
+ Without treatment, pneumonia can cause serious problems like
138
+ breathing failure or blood infections. It's important to treat
139
+ it early to prevent these dangers.
140
+ </p>
141
+ </div>
142
+ <div class="bg-white p-6 rounded-2xl shadow">
143
+ <h3 class="text-2xl font-bold text-gray-800">
144
+ How Do You Detect It?
145
+ </h3>
146
+ <p class="mt-2">
147
+ Pneumonia symptoms can feel like a bad cold, so doctors use
148
+ chest X-rays to find it. With our AI, you can upload your X-ray,
149
+ and we'll help check for pneumonia quickly.
150
+ </p>
151
+ </div>
152
+ </div>
153
+ </div>
154
+ </section>
155
+ <section class="bg-white py-16 pb-24">
156
+ <div class="container mx-auto px-12 pt-8">
157
+ <h2 class="text-5xl font-bold text-center dongker">
158
+ How Does Our AI Detect Pneumonia?
159
+ </h2>
160
+ <p class="mt-4 text-center py-8 text-lg">
161
+ Behind the scenes, our AI is like a detective, scanning your X-ray
162
+ for clues and patterns that could signal pneumonia. It's fast,
163
+ reliable, and gives you answers without the wait. Want to know how
164
+ it all works? We've got you covered.
165
+ </p>
166
+
167
+ <div class="mt-8 grid grid-cols-1 md:grid-cols-3 gap-8">
168
+ <!-- Left column - Powered by Deep Learning Section -->
169
+ <div class="bg-white p-6 bdr rounded-3xl shadow-xl">
170
+ <div class="flex items-start">
171
+ <div>
172
+ <img
173
+ src="{{ url_for('static', filename='machine-learning.png') }}"
174
+ alt="icon"
175
+ class="w-9 h-9 mr-4 mb-2"
176
+ />
177
+ <h3 class="text-xl font-bold">Powered by Deep Learning</h3>
178
+ <p class="mt-2">
179
+ Our AI uses deep learning, mimicking the human brain.
180
+ Trained on thousands of X-rays, it recognizes subtle
181
+ patterns that even experts might miss, like having a
182
+ super-experienced radiologist 24/7.
183
+ </p>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <!-- Center Column - Robot Image Section -->
189
+ <div
190
+ class="bg-white p-6 bdr rounded-3xl shadow-xl row-span-2 flex items-center justify-center"
191
+ >
192
+ <img
193
+ alt="AI analyzing X-ray"
194
+ class="mx-auto"
195
+ height="500"
196
+ src="{{ url_for('static', filename='robot.png') }}"
197
+ width="500"
198
+ />
199
+ </div>
200
+
201
+ <!-- Left column - Super Quick Results Section -->
202
+ <div class="bg-white p-6 bdr rounded-3xl shadow-xl">
203
+ <div class="flex items-start">
204
+ <div>
205
+ <img
206
+ src="{{ url_for('static', filename='clock.png') }}"
207
+ alt="icon"
208
+ class="w-9 h-9 mr-4 mb-2"
209
+ />
210
+ <h3 class="text-xl font-bold">Super Quick Results</h3>
211
+ <p class="mt-2">
212
+ Get results in seconds after uploading your image. The AI
213
+ processes it instantly, delivering a detailed report without
214
+ delay.
215
+ </p>
216
+ </div>
217
+ </div>
218
+ </div>
219
+
220
+ <!-- Right column - What Does It Look For? Section -->
221
+ <div class="bg-white p-6 bdr rounded-3xl shadow-xl">
222
+ <div class="flex items-start">
223
+ <div>
224
+ <img
225
+ src="{{ url_for('static', filename='eye.png') }}"
226
+ alt="icon"
227
+ class="w-9 h-9 mr-4 mb-2"
228
+ />
229
+ <h3 class="text-xl font-bold">What Does It Look For?</h3>
230
+ <p class="mt-2">
231
+ Upload your chest X-ray, and the AI scans for pneumonia
232
+ signs such as lung opacity, fluid buildup, and inflammation,
233
+ providing a detailed analysis.
234
+ </p>
235
+ </div>
236
+ </div>
237
+ </div>
238
+
239
+ <!-- Right column - Accuracy You Can Trust Section -->
240
+ <div class="bg-white p-6 bdr rounded-3xl shadow-xl">
241
+ <div class="flex items-start">
242
+ <div>
243
+ <img
244
+ src="{{ url_for('static', filename='accuracy.png') }}"
245
+ alt="icon"
246
+ class="w-9 h-9 mr-4 mb-2"
247
+ />
248
+ <h3 class="text-xl font-bold">Accuracy You Can Trust</h3>
249
+ <p class="mt-2">
250
+ Trained on 10,000 images, our model delivers 95.83% of
251
+ accuracy, complementing doctors' expertise for the best
252
+ care.
253
+ </p>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ </section>
260
+ <section class="bg py-16 px-8 pb-24" id="detect">
261
+ <div class="container mx-auto px-4 text-center">
262
+ <h2 class="text-5xl font-bold dongker mt-8">
263
+ Upload Your X-ray - Get Instant Results!
264
+ </h2>
265
+ <p class="mt-4 text-lg py-8">
266
+ Got a chest X-ray? Great! Upload it here, and in just a few moments,
267
+ our AI will give you a detailed report. <br />It's quick, it's easy,
268
+ and it's secure. Let's get started!
269
+ </p>
270
+ <div
271
+ class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-8 bg-white rounded-3xl p-8 mx-36"
272
+ style="min-height: 450px"
273
+ >
274
+ <div
275
+ class="bg-white p-6 rounded-xl shadow flex flex-col items-center justify-center border-2 border-dashed border-gray-500 relative"
276
+ >
277
+ <img
278
+ src="{{ url_for('static', filename='x-ray.png') }}"
279
+ alt="icon"
280
+ class="w-20 h-20 opacity-40"
281
+ id="uploadLogo"
282
+ />
283
+ <button
284
+ class="mt-4 blue text-white px-6 py-3 mt-8 rounded-full hover:bg-blue-500"
285
+ id="uploadButton"
286
+ >
287
+ Upload Image
288
+ </button>
289
+ <input
290
+ class="hidden"
291
+ id="fileInput"
292
+ type="file"
293
+ accept="image/*"
294
+ />
295
+ <img
296
+ alt="Image Preview"
297
+ class="mt-4 hidden"
298
+ id="imagePreview"
299
+ style="display: none; max-width: 100%"
300
+ />
301
+ <i
302
+ class="fas fa-times text-3xl absolute dongker mt-4 hidden top-0 right-6"
303
+ id="removeImage"
304
+ style="cursor: pointer"
305
+ >
306
+ </i>
307
+ </div>
308
+ <div
309
+ class="bg-white p-6 rounded-xl shadow flex flex-col items-center justify-center border-2 border-gray-300"
310
+ >
311
+ <img
312
+ src="{{ url_for('static', filename='loupe.png') }}"
313
+ alt="icon"
314
+ class="w-20 h-20 opacity-40"
315
+ id="check-icon"
316
+ />
317
+ <button
318
+ class="mt-4 bg-gray-200 px-6 py-3 mt-8 rounded-full hover:bg-gray-300"
319
+ id="check-button"
320
+ disabled
321
+ >
322
+ Check My X-Ray
323
+ </button>
324
+ <div class="w-full" id="prediction-result" style="display: none">
325
+ <div>
326
+ <p class="text-left pb-2 text-lg">Prediction</p>
327
+ <div
328
+ id="prediction"
329
+ class="bg-gray-100 py-9 rounded-lg text-center text-2xl font-bold"
330
+ >
331
+ Pneumonia
332
+ </div>
333
+ </div>
334
+ <div class="pt-12">
335
+ <p class="text-left pb-2 text-lg">Confidence</p>
336
+ <div
337
+ id="confidence"
338
+ class="bg-gray-100 py-9 rounded-lg text-center text-2xl font-bold"
339
+ >
340
+ 98.57%
341
+ </div>
342
+ </div>
343
+ </div>
344
+ </div>
345
+ </div>
346
+ </div>
347
+ </section>
348
+ <section class="bg-white py-16 px-8">
349
+ <div class="container mx-auto px-4">
350
+ <h2 class="text-5xl font-bold dongker">Frequently Ask Question</h2>
351
+ <hr class="my-4 border-t-2 border-gray-300" />
352
+ <ul class="mt-8 space-y-4 text-lg">
353
+ <li class="accordion-item">
354
+ <div class="accordion-header cursor-pointer text-xl font-bold">
355
+ <span class="icon font-normal">></span>
356
+ <span>How quickly can I start the detection process?</span>
357
+ </div>
358
+ <div
359
+ class="accordion-content max-h-0 overflow-hidden transition-all duration-300"
360
+ >
361
+ <p class="mt-2 text-justify">
362
+ No complicated forms here. Just drag and drop your chest X-ray
363
+ image or select it from your device, and our AI will start
364
+ analyzing right away. The process only takes a few seconds,
365
+ and you'll have your results in no time.
366
+ </p>
367
+ </div>
368
+ </li>
369
+ <li class="accordion-item">
370
+ <div class="accordion-header cursor-pointer text-xl font-bold">
371
+ <span class="icon font-normal">></span>
372
+ <span>What information will I receive after the scan?</span>
373
+ </div>
374
+ <div
375
+ class="accordion-content max-h-0 overflow-hidden transition-all duration-300"
376
+ >
377
+ <p class="mt-2 text-justify">
378
+ Once the scan is complete, you’ll receive two key pieces of
379
+ information:
380
+ <br /><br />
381
+ Prediction: Whether the scan indicates ‘Normal’ or shows signs
382
+ of ‘Pneumonia’.
383
+ <br />
384
+ Confidence Level: A percentage that tells you how confident
385
+ the AI is in its prediction.
386
+ <br /><br />
387
+ For example, a 95% confidence means the AI is highly certain
388
+ about its result.
389
+ </p>
390
+ </div>
391
+ </li>
392
+ <li class="accordion-item">
393
+ <div class="accordion-header cursor-pointer text-xl font-bold">
394
+ <span class="icon font-normal">></span>
395
+ <span>Is my privacy protected when using this tool?</span>
396
+ </div>
397
+ <div
398
+ class="accordion-content max-h-0 overflow-hidden transition-all duration-300"
399
+ >
400
+ <p class="mt-2 text-justify">
401
+ We take your privacy seriously. Your X-rays are processed
402
+ securely, and we don’t store any images after generating your
403
+ results. It’s all about keeping your data safe while giving
404
+ you the answers you need.
405
+ </p>
406
+ </div>
407
+ </li>
408
+ <li class="accordion-item">
409
+ <div class="accordion-header cursor-pointer text-xl font-bold">
410
+ <span class="icon font-normal">></span>
411
+ <span>How fast will I get the results?</span>
412
+ </div>
413
+ <div
414
+ class="accordion-content max-h-0 overflow-hidden transition-all duration-300"
415
+ >
416
+ <p class="mt-2 text-justify">
417
+ No need to wait around. As soon as the image is uploaded, our
418
+ AI works its magic and provides you with a detailed prediction
419
+ in seconds. The confidence score helps you understand how
420
+ reliable the result is, giving you peace of mind.
421
+ </p>
422
+ </div>
423
+ </li>
424
+ <li class="accordion-item">
425
+ <div class="accordion-header cursor-pointer text-xl font-bold">
426
+ <span class="icon font-normal">></span>
427
+ <span>What should I do if the result indicates pneumonia?</span>
428
+ </div>
429
+ <div
430
+ class="accordion-content max-h-0 overflow-hidden transition-all duration-300"
431
+ >
432
+ <p class="mt-2 text-justify">
433
+ If the result suggests pneumonia, we recommend you follow up
434
+ with a healthcare professional. The AI is designed to support
435
+ early detection, but a doctor’s opinion is always the next
436
+ step in your care journey.
437
+ </p>
438
+ </div>
439
+ </li>
440
+ </ul>
441
+ </div>
442
+ </section>
443
+ </main>
444
+ <footer class="bg-white py-4 pb-4">
445
+ <div class="container mx-auto px-4 text-center">
446
+ <p>Copyright © 2024 PneumonAI</p>
447
+ </div>
448
+ </footer>
449
+ <script>
450
+ document.addEventListener("DOMContentLoaded", function () {
451
+ const items = document.querySelectorAll(".accordion-item");
452
+ items.forEach((item) => {
453
+ item
454
+ .querySelector(".accordion-header")
455
+ .addEventListener("click", () => {
456
+ const openItem = document.querySelector(".accordion-item.open");
457
+ toggleItem(item);
458
+ if (openItem && openItem !== item) {
459
+ toggleItem(openItem);
460
+ }
461
+ });
462
+ });
463
+
464
+ const toggleItem = (item) => {
465
+ const content = item.querySelector(".accordion-content");
466
+ if (item.classList.contains("open")) {
467
+ content.style.maxHeight = null;
468
+ item.classList.remove("open");
469
+ } else {
470
+ content.style.maxHeight = content.scrollHeight + "px";
471
+ item.classList.add("open");
472
+ }
473
+ };
474
+
475
+ document
476
+ .getElementById("uploadButton")
477
+ .addEventListener("click", function () {
478
+ document.getElementById("fileInput").click();
479
+ });
480
+
481
+ document
482
+ .getElementById("fileInput")
483
+ .addEventListener("change", function (event) {
484
+ const file = event.target.files[0];
485
+ if (file) {
486
+ const reader = new FileReader();
487
+ reader.onload = function (e) {
488
+ document.getElementById("imagePreview").src = e.target.result;
489
+ document.getElementById("imagePreview").style.display = "block";
490
+ document.getElementById("uploadLogo").style.display = "none";
491
+ document.getElementById("uploadButton").style.display = "none";
492
+ document.getElementById("removeImage").style.display = "block";
493
+ };
494
+ reader.readAsDataURL(file);
495
+ }
496
+ });
497
+
498
+ document
499
+ .getElementById("removeImage")
500
+ .addEventListener("click", function () {
501
+ document.getElementById("fileInput").value = "";
502
+ document.getElementById("imagePreview").style.display = "none";
503
+ document.getElementById("uploadLogo").style.display = "block";
504
+ document.getElementById("uploadButton").style.display = "block";
505
+ document.getElementById("removeImage").style.display = "none";
506
+
507
+ // sementara - handle upload tapi blm dicheck dan lgsg remove
508
+ window.location.reload();
509
+ });
510
+ });
511
+
512
+ document.querySelectorAll(".accordion-item").forEach((item) => {
513
+ const header = item.querySelector(".accordion-header");
514
+ const content = item.querySelector(".accordion-content");
515
+ const icon = header.querySelector(".icon");
516
+
517
+ header.addEventListener("click", () => {
518
+ const isActive = content.style.maxHeight;
519
+ document
520
+ .querySelectorAll(".accordion-content")
521
+ .forEach((c) => (c.style.maxHeight = null));
522
+ document
523
+ .querySelectorAll(".icon")
524
+ .forEach((i) => (i.textContent = ">"));
525
+
526
+ if (!isActive) {
527
+ content.style.maxHeight = content.scrollHeight + "px";
528
+ icon.textContent = "v";
529
+ } else {
530
+ content.style.maxHeight = null;
531
+ }
532
+ });
533
+ });
534
+
535
+ const fileInput = document.getElementById("fileInput");
536
+ const checkButton = document.getElementById("check-button");
537
+
538
+ const removeImage = document.getElementById("removeImage");
539
+ const uploadLogo = document.getElementById("uploadLogo");
540
+ const imagePreview = document.getElementById("imagePreview");
541
+
542
+ const predictionResult = document.getElementById("prediction-result");
543
+ const predictionText = document.getElementById("prediction");
544
+ const confidenceText = document.getElementById("confidence");
545
+
546
+ // Enable the check button when an image is uploaded
547
+ fileInput.addEventListener("change", function () {
548
+ if (fileInput.files.length > 0) {
549
+ checkButton.disabled = false;
550
+ uploadLogo.classList.add("hidden"); // Hide the upload icon
551
+ imagePreview.src = URL.createObjectURL(fileInput.files[0]);
552
+ imagePreview.classList.remove("hidden"); // Show the image preview
553
+ removeImage.classList.remove("hidden"); // Show the remove icon
554
+ } else {
555
+ checkButton.disabled = true;
556
+ }
557
+ });
558
+
559
+ // Call the showPrediction function when the "Check" button is clicked
560
+ checkButton.addEventListener("click", function () {
561
+ const formData = new FormData();
562
+ formData.append("file", fileInput.files[0]);
563
+ console.log(formData);
564
+ fetch("/predict", {
565
+ // Ensure '/predict' matches your Flask route
566
+ method: "POST",
567
+ body: formData,
568
+ })
569
+ .then((response) => response.json())
570
+ .then((data) => {
571
+ predictionText.innerText = data.prediction; // Update with the prediction result
572
+ confidenceText.innerText = data.confidence.toFixed(2) + "%"; // Update with the confidence
573
+ predictionResult.style.display = "block"; // Show the prediction result
574
+ document.getElementById("check-icon").style.display = "none";
575
+ document.getElementById("check-button").style.display = "none";
576
+ })
577
+ .catch((error) => {
578
+ console.error("Error:", error);
579
+ });
580
+ });
581
+
582
+ removeImage.addEventListener("click", function () {
583
+ fileInput.value = ""; // Clear the file input
584
+ checkButton.disabled = true; // Disable the check button
585
+ uploadLogo.classList.remove("hidden"); // Show the upload icon again
586
+ imagePreview.classList.add("hidden"); // Hide the image preview
587
+ removeImage.classList.add("hidden"); // Hide the remove icon
588
+ predictionResult.style.display = "none"; // Hide the prediction result
589
+ });
590
+ </script>
591
+ </body>
592
+ </html>