ftx7go commited on
Commit
f2b4347
·
verified ·
1 Parent(s): 9e5018f

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -381
app.py DELETED
@@ -1,381 +0,0 @@
1
- from fastapi import FastAPI, File, UploadFile, Form
2
- from fastapi.responses import HTMLResponse, Response
3
- from transformers import pipeline
4
- from PIL import Image, ImageDraw
5
- import numpy as np
6
- import io
7
- import uvicorn
8
- import base64
9
- from reportlab.lib.pagesizes import letter
10
- from reportlab.platypus import SimpleDocTemplate, Image as ReportLabImage, Paragraph, Spacer
11
- from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
12
- from reportlab.lib.colors import red, blue, black
13
- from reportlab.lib.units import inch
14
-
15
- app = FastAPI()
16
-
17
- # Chargement des modèles
18
- def load_models():
19
- return {
20
- "KnochenAuge": pipeline("object-detection", model="D3STRON/bone-fracture-detr"),
21
- "KnochenWächter": pipeline("image-classification", model="Heem2/bone-fracture-detection-using-xray"),
22
- "RöntgenMeister": pipeline("image-classification",
23
- model="nandodeomkar/autotrain-fracture-detection-using-google-vit-base-patch-16-54382127388")
24
- }
25
-
26
- models = load_models()
27
-
28
- def translate_label(label):
29
- translations = {
30
- "fracture": "Knochenbruch",
31
- "no fracture": "Kein Knochenbruch",
32
- "normal": "Normal",
33
- "abnormal": "Auffällig",
34
- "F1": "Knochenbruch",
35
- "NF": "Kein Knochenbruch"
36
- }
37
- return translations.get(label.lower(), label)
38
-
39
- def create_heatmap_overlay(image, box, score):
40
- overlay = Image.new('RGBA', image.size, (0, 0, 0, 0))
41
- draw = ImageDraw.Draw(overlay)
42
-
43
- x1, y1 = box['xmin'], box['ymin']
44
- x2, y2 = box['xmax'], box['ymax']
45
-
46
- if score > 0.8:
47
- fill_color = (255, 0, 0, 100)
48
- border_color = (255, 0, 0, 255)
49
- elif score > 0.6:
50
- fill_color = (255, 165, 0, 100)
51
- border_color = (255, 165, 0, 255)
52
- else:
53
- fill_color = (255, 255, 0, 100)
54
- border_color = (255, 255, 0, 255)
55
-
56
- draw.rectangle([x1, y1, x2, y2], fill=fill_color)
57
- draw.rectangle([x1, y1, x2, y2], outline=border_color, width=2)
58
-
59
- return overlay
60
-
61
- def draw_boxes(image, predictions):
62
- result_image = image.copy().convert('RGBA')
63
-
64
- for pred in predictions:
65
- box = pred['box']
66
- score = pred['score']
67
-
68
- overlay = create_heatmap_overlay(image, box, score)
69
- result_image = Image.alpha_composite(result_image, overlay)
70
-
71
- draw = ImageDraw.Draw(result_image)
72
- temp = 36.5 + (score * 2.5)
73
- label = f"{translate_label(pred['label'])} ({score:.1%} • {temp:.1f}°C)"
74
-
75
- text_bbox = draw.textbbox((box['xmin'], box['ymin']-20), label)
76
- draw.rectangle(text_bbox, fill=(0, 0, 0, 180))
77
-
78
- draw.text(
79
- (box['xmin'], box['ymin']-20),
80
- label,
81
- fill=(255, 255, 255, 255)
82
- )
83
-
84
- return result_image
85
-
86
- def image_to_base64(image):
87
- buffered = io.BytesIO()
88
- image.save(buffered, format="PNG")
89
- img_str = base64.b64encode(buffered.getvalue()).decode()
90
- return f"data:image/png;base64,{img_str}"
91
-
92
- def generate_report(patient_name, analyzed_image_bytes, prediction, confidence):
93
- buffer = io.BytesIO()
94
- doc = SimpleDocTemplate(buffer, pagesize=letter)
95
- styles = getSampleStyleSheet()
96
- title_style = ParagraphStyle(
97
- name='TitleStyle',
98
- parent=styles['Normal'],
99
- fontSize=16,
100
- textColor=blue,
101
- alignment=1 # Center alignment
102
- )
103
- heading_style = ParagraphStyle(
104
- name='HeadingStyle',
105
- parent=styles['Normal'],
106
- fontSize=12,
107
- textColor=red
108
- )
109
- prediction_style = ParagraphStyle(
110
- name='PredictionStyle',
111
- parent=styles['Normal'],
112
- fontSize=14,
113
- alignment=1
114
- )
115
-
116
- story = []
117
-
118
- # Hospital Name
119
- hospital_name = Paragraph("youesh hospital , mumbai ( west )", title_style)
120
- story.append(hospital_name)
121
- story.append(Spacer(1, 0.2*inch))
122
-
123
- # Patient Greeting
124
- greeting = Paragraph(f"hello , {patient_name} thank you for using our services this is your radiology report", heading_style)
125
- story.append(greeting)
126
- story.append(Spacer(1, 0.2*inch))
127
-
128
- # Horizontal Line
129
- story.append(Paragraph("<hr/>", styles['Normal']))
130
- story.append(Spacer(1, 0.2*inch))
131
-
132
- # Analyzed Image
133
- img = ReportLabImage(io.BytesIO(analyzed_image_bytes), width=400, height=400, kind='direct')
134
- story.append(img)
135
- story.append(Spacer(1, 0.2*inch))
136
-
137
- # Prediction
138
- prediction_text = f"<b>Prediction:</b> {prediction.capitalize()}"
139
- confidence_text = f"<b>Confidence:</b> {'Yes' if confidence > 0.6 else 'No'}"
140
- story.append(Paragraph(prediction_text, prediction_style))
141
- story.append(Paragraph(confidence_text, prediction_style))
142
-
143
- doc.build(story)
144
- buffer.seek(0)
145
- return buffer.getvalue()
146
-
147
- COMMON_STYLES = """
148
- body {
149
- font-family: system-ui, -apple-system, sans-serif;
150
- background: #f0f2f5;
151
- margin: 0;
152
- padding: 20px;
153
- color: #1a1a1a;
154
- }
155
- ::-webkit-scrollbar {
156
- width: 8px;
157
- height: 8px;
158
- }
159
-
160
- ::-webkit-scrollbar-track {
161
- background: transparent;
162
- }
163
-
164
- ::-webkit-scrollbar-thumb {
165
- background-color: rgba(156, 163, 175, 0.5);
166
- border-radius: 4px;
167
- }
168
-
169
- .container {
170
- max-width: 1200px;
171
- margin: 0 auto;
172
- background: white;
173
- padding: 20px;
174
- border-radius: 10px;
175
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
176
- }
177
- .button {
178
- background: #404040; /* Changed button background color */
179
- color: white;
180
- border: none;
181
- padding: 12px 30px;
182
- border-radius: 8px;
183
- cursor: pointer;
184
- font-size: 1.1em;
185
- transition: all 0.3s ease;
186
- position: relative;
187
- }
188
- .button:hover {
189
- background: #555;
190
- }
191
- @keyframes progress {
192
- 0% { width: 0; }
193
- 100% { width: 100%; }
194
- }
195
- .button-progress {
196
- position: absolute;
197
- bottom: 0;
198
- left: 0;
199
- height: 4px;
200
- background: rgba(255, 255, 255, 0.5);
201
- width: 0;
202
- }
203
- .button:active .button-progress {
204
- animation: progress 2s linear forwards;
205
- }
206
- img {
207
- max-width: 100%;
208
- height: auto;
209
- border-radius: 8px;
210
- }
211
- @keyframes blink {
212
- 0% { opacity: 1; }
213
- 50% { opacity: 0; }
214
- 100% { opacity: 1; }
215
- }
216
- #loading {
217
- display: none;
218
- color: white;
219
- margin-top: 10px;
220
- animation: blink 1s infinite;
221
- text-align: center;
222
- }
223
- """
224
-
225
- @app.get("/", response_class=HTMLResponse)
226
- async def main():
227
- content = f"""
228
- <!DOCTYPE html>
229
- <html>
230
- <head>
231
- <title>Fraktur Detektion</title>
232
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
233
- <style>
234
- {COMMON_STYLES}
235
-
236
- .input-group {{
237
- margin-bottom: 20px;
238
- }}
239
- .input-group label {{
240
- display: block;
241
- margin-bottom: 5px;
242
- color: #404040;
243
- font-weight: bold;
244
- }}
245
- .input-group input[type="text"],
246
- .input-group input[type="email"] {{
247
- width: calc(100% - 22px);
248
- padding: 10px;
249
- border: 1px solid #ccc;
250
- border-radius: 4px;
251
- font-size: 1em;
252
- }}
253
-
254
- .upload-section {{
255
- background: #2d2d2d;
256
- padding: 40px;
257
- border-radius: 12px;
258
- margin: 20px 0;
259
- text-align: center;
260
- border: 2px dashed #404040;
261
- transition: all 0.3s ease;
262
- color: white;
263
- }}
264
- .upload-section:hover {{
265
- border-color: #555;
266
- }}
267
- input[type="file"] {{
268
- font-size: 1.1em;
269
- margin: 20px 0;
270
- color: white;
271
- }}
272
- input[type="file"]::file-selector-button {{
273
- font-size: 1em;
274
- padding: 10px 20px;
275
- border-radius: 8px;
276
- border: 1px solid #404040;
277
- background: #2d2d2d;
278
- color: white;
279
- transition: all 0.3s ease;
280
- cursor: pointer;
281
- }}
282
- input[type="file"]::file-selector-button:hover {{
283
- background: #404040;
284
- }}
285
- </style>
286
- </head>
287
- <body>
288
- <div class="container">
289
- <form action="/analyze" method="post" enctype="multipart/form-data" onsubmit="document.getElementById('loading').style.display = 'block';">
290
- <div class="input-group">
291
- <label for="name">Name:</label>
292
- <input type="text" id="name" name="name" required>
293
- </div>
294
- <div class="input-group">
295
- <label for="email">Email Address:</label>
296
- <input type="email" id="email" name="email" required>
297
- </div>
298
- <div class="upload-section">
299
- <div>
300
- <input type="file" name="file" accept="image/*" required>
301
- </div>
302
- <button type="submit" class="button">
303
- Generate Report
304
- <div class="button-progress"></div>
305
- </button>
306
- <div id="loading">Loading...</div>
307
- </div>
308
- </form>
309
- </div>
310
- </body>
311
- </html>
312
- """
313
- return content
314
-
315
- @app.post("/analyze", response_class=Response)
316
- async def analyze_file(name: str = Form(...), email: str = Form(...), file: UploadFile = File(...), threshold: float = Form(0.6)):
317
- try:
318
- contents = await file.read()
319
- image = Image.open(io.BytesIO(contents))
320
-
321
- predictions_watcher = models["KnochenWächter"](image)
322
- predictions_master = models["RöntgenMeister"](image)
323
- predictions_locator = models["KnochenAuge"](image)
324
-
325
- filtered_preds = [p for p in predictions_locator if p['score'] >= threshold]
326
- analyzed_image = image
327
- overall_prediction = "No Fracture"
328
- max_confidence = 0.0
329
-
330
- if filtered_preds:
331
- analyzed_image = draw_boxes(image, filtered_preds)
332
- overall_prediction = "Fracture Detected"
333
- max_confidence = max([p['score'] for p in filtered_preds])
334
-
335
- image_stream = io.BytesIO()
336
- analyzed_image.save(image_stream, format="PNG")
337
- image_bytes = image_stream.getvalue()
338
-
339
- pdf_report = generate_report(name, image_bytes, overall_prediction, max_confidence)
340
-
341
- headers = {
342
- 'Content-Disposition': 'attachment; filename="report.pdf"'
343
- }
344
- return Response(content=pdf_report, headers=headers, media_type="application/pdf")
345
-
346
- except Exception as e:
347
- error_html = f"""
348
- <!DOCTYPE html>
349
- <html>
350
- <head>
351
- <title>Fehler</title>
352
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
353
- <style>
354
- {COMMON_STYLES}
355
- .error-box {{
356
- background: #fee2e2;
357
- border: 1px solid #ef4444;
358
- padding: 20px;
359
- border-radius: 8px;
360
- margin: 20px 0;
361
- }}
362
- </style>
363
- </head>
364
- <body>
365
- <div class="container">
366
- <div class="error-box">
367
- <h3>Fehler</h3>
368
- <p>{str(e)}</p>
369
- </div>
370
- <a href="/" class="button back-button">
371
- ← Zurück
372
- <div class="button-progress"></div>
373
- </a>
374
- </div>
375
- </body>
376
- </html>
377
- """
378
- return HTMLResponse(content=error_html)
379
-
380
- if __name__ == "__main__":
381
- uvicorn.run(app, host="0.0.0.0", port=7860)