ftx7go commited on
Commit
cefb39b
·
verified ·
1 Parent(s): ed1613b

Delete app.py

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