yassonee commited on
Commit
f700114
·
verified ·
1 Parent(s): 9516554

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -87
app.py CHANGED
@@ -1,99 +1,219 @@
1
- <?php
2
- // [En-tête PHP existant]
3
- ?>
 
4
 
5
- <div class="min-h-screen bg-gray-100 dark:bg-gray-900 pt-20 scrollable-content">
6
- <div id="fraktur-root" class="w-2/3 min-w-[800px] mx-auto p-4 ml-0">
7
- <div class="bg-white dark:bg-gray-800 shadow-md rounded-lg overflow-hidden">
8
- <!-- Titre -->
9
- <div class="p-4 border-b border-gray-200 dark:border-gray-700">
10
- <div class="flex items-center gap-2">
11
- <svg class="w-6 h-6 text-blue-500 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
12
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
13
- </svg>
14
- <h1 class="text-xl font-bold text-gray-900 dark:text-white">Fraktur Detektion</h1>
15
- </div>
16
- </div>
17
-
18
- <!-- Conteneur iframe adaptatif -->
19
- <div class="iframe-container relative w-full" style="padding-top: 80%;">
20
- <iframe
21
- src="https://yassonee-radpid.hf.space"
22
- class="absolute top-0 left-0 w-full h-full border-none"
23
- id="frakturFrame"
24
- ></iframe>
25
- </div>
26
- </div>
27
- </div>
28
- </div>
29
 
 
30
  <style>
31
- /* Styles pour l'iframe adaptatif */
32
- .iframe-container {
33
- position: relative;
34
- width: 100%;
35
- height: 0;
36
- padding-top: 80%; /* Ratio 4:5 pour l'iframe */
37
- overflow: hidden;
38
- }
39
-
40
- .iframe-container iframe {
41
- position: absolute;
42
- top: 0;
43
- left: 0;
44
- width: 100%;
45
- height: 100%;
46
- border: none;
47
- }
48
-
49
- /* Ajustements responsifs */
50
- @media (max-width: 1280px) {
51
- #fraktur-root {
52
- width: 80%;
53
  }
54
- .iframe-container {
55
- padding-top: 90%;
 
 
 
 
 
56
  }
57
- }
58
-
59
- @media (max-width: 768px) {
60
- #fraktur-root {
61
- width: 95%;
62
- min-width: 0;
63
  }
64
- .iframe-container {
65
- padding-top: 100%;
 
 
 
66
  }
67
- }
68
- </style>
69
-
70
- <script>
71
- document.addEventListener('DOMContentLoaded', function() {
72
- const iframe = document.getElementById('frakturFrame');
73
 
74
- function updateTheme() {
75
- const isDark = document.documentElement.classList.contains('dark');
76
- iframe.contentWindow.postMessage({
77
- type: 'theme-change',
78
- theme: isDark ? 'dark' : 'light'
79
- }, '*');
80
  }
81
 
82
- const observer = new MutationObserver((mutations) => {
83
- mutations.forEach((mutation) => {
84
- if (mutation.attributeName === 'class') {
85
- updateTheme();
86
- }
87
- });
88
- });
89
-
90
- observer.observe(document.documentElement, {
91
- attributes: true,
92
- attributeFilter: ['class']
93
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- iframe.addEventListener('load', updateTheme);
96
- });
97
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
- <?php include 'includes/footer.php'; ?>
 
 
1
+ import streamlit as st
2
+ from transformers import pipeline
3
+ from PIL import Image, ImageDraw
4
+ import torch
5
 
6
+ st.set_page_config(
7
+ page_title="Fraktur Detektion",
8
+ layout="wide",
9
+ initial_sidebar_state="collapsed"
10
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ st.markdown("""
13
  <style>
14
+ /* Reset et base */
15
+ .stApp {
16
+ background-color: var(--background-color) !important;
17
+ padding: 0 !important;
18
+ overflow: hidden !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
+
21
+ /* Variables de thème */
22
+ [data-theme="light"] {
23
+ --background-color: #ffffff;
24
+ --text-color: #1f2937;
25
+ --border-color: #e5e7eb;
26
+ --secondary-bg: #f3f4f6;
27
  }
28
+
29
+ [data-theme="dark"] {
30
+ --background-color: #1f2937;
31
+ --text-color: #f3f4f6;
32
+ --border-color: #4b5563;
33
+ --secondary-bg: #374151;
34
  }
35
+
36
+ /* Layout principal */
37
+ .block-container {
38
+ padding: 0.5rem !important;
39
+ max-width: 100% !important;
40
  }
 
 
 
 
 
 
41
 
42
+ /* Contrôles et upload */
43
+ .uploadedFile {
44
+ border: 1px dashed var(--border-color);
45
+ border-radius: 0.375rem;
46
+ padding: 0.25rem;
47
+ background: var(--secondary-bg);
48
  }
49
 
50
+ /* Ajustement des colonnes */
51
+ [data-testid="column"] {
52
+ padding: 0 0.5rem !important;
53
+ }
54
+
55
+ /* Images adaptatives */
56
+ .stImage > img {
57
+ width: 100% !important;
58
+ height: auto !important;
59
+ max-height: 400px !important;
60
+ object-fit: contain !important;
61
+ }
62
+
63
+ /* Résultats */
64
+ .result-box {
65
+ padding: 0.375rem;
66
+ border-radius: 0.375rem;
67
+ margin: 0.25rem 0;
68
+ background: var(--secondary-bg);
69
+ border: 1px solid var(--border-color);
70
+ color: var(--text-color);
71
+ }
72
+
73
+ /* Titres */
74
+ h2, h3 {
75
+ margin: 0 !important;
76
+ padding: 0.5rem 0 !important;
77
+ font-size: 1rem !important;
78
+ color: var(--text-color) !important;
79
+ }
80
 
81
+ /* Nettoyage des éléments inutiles */
82
+ #MainMenu, footer, header, .viewerBadge_container__1QSob, .stDeployButton {
83
+ display: none !important;
84
+ }
85
+
86
+ /* Ajustements espacement */
87
+ div[data-testid="stVerticalBlock"] {
88
+ gap: 0.5rem !important;
89
+ }
90
+
91
+ .element-container {
92
+ margin: 0.25rem 0 !important;
93
+ }
94
+ </style>
95
+ """, unsafe_allow_html=True)
96
+
97
+ @st.cache_resource
98
+ def load_models():
99
+ return {
100
+ "KnochenAuge": pipeline("object-detection", model="D3STRON/bone-fracture-detr"),
101
+ "KnochenWächter": pipeline("image-classification", model="Heem2/bone-fracture-detection-using-xray"),
102
+ "RöntgenMeister": pipeline("image-classification",
103
+ model="nandodeomkar/autotrain-fracture-detection-using-google-vit-base-patch-16-54382127388")
104
+ }
105
+
106
+ def translate_label(label):
107
+ translations = {
108
+ "fracture": "Knochenbruch",
109
+ "no fracture": "Kein Bruch",
110
+ "normal": "Normal",
111
+ "abnormal": "Auffällig"
112
+ }
113
+ return translations.get(label.lower(), label)
114
+
115
+ def draw_boxes(image, predictions):
116
+ draw = ImageDraw.Draw(image)
117
+ for pred in predictions:
118
+ box = pred['box']
119
+ label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
120
+ color = "#2563eb" if pred['score'] > 0.7 else "#eab308"
121
+
122
+ draw.rectangle(
123
+ [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
124
+ outline=color,
125
+ width=2
126
+ )
127
+
128
+ # Label plus compact
129
+ text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
130
+ draw.rectangle(text_bbox, fill=color)
131
+ draw.text((box['xmin'], box['ymin']-15), label, fill="white")
132
+ return image
133
+
134
+ def main():
135
+ models = load_models()
136
+
137
+ # Disposition en deux colonnes principales
138
+ col1, col2 = st.columns([1, 2])
139
+
140
+ with col1:
141
+ st.markdown("### 📤 Röntgenbild Upload")
142
+ uploaded_file = st.file_uploader("", type=['png', 'jpg', 'jpeg'])
143
+
144
+ if uploaded_file:
145
+ conf_threshold = st.slider(
146
+ "Konfidenzschwelle",
147
+ min_value=0.0, max_value=1.0,
148
+ value=0.60, step=0.05
149
+ )
150
+
151
+ with col2:
152
+ if uploaded_file:
153
+ image = Image.open(uploaded_file)
154
+
155
+ st.markdown("### 🔍 Meinung der KI-Experten")
156
+
157
+ # Analyse avec KnochenAuge (localisierung)
158
+ st.markdown("#### 👁️ Das KnochenAuge - Lokalisation")
159
+ predictions = models["KnochenAuge"](image)
160
+ filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
161
+
162
+ if filtered_preds:
163
+ result_image = image.copy()
164
+ result_image = draw_boxes(result_image, filtered_preds)
165
+ st.image(result_image, use_container_width=True)
166
+
167
+ # Autres modèles
168
+ st.markdown("#### 🎯 KI-Analyse")
169
+ col_left, col_right = st.columns(2)
170
+
171
+ with col_left:
172
+ st.markdown("**🛡️ Der KnochenWächter**")
173
+ predictions = models["KnochenWächter"](image)
174
+ for pred in predictions:
175
+ if pred['score'] >= conf_threshold:
176
+ score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
177
+ st.markdown(f"""
178
+ <div class='result-box'>
179
+ <span style='color: {score_color}; font-weight: 500;'>
180
+ {pred['score']:.1%}
181
+ </span> - {translate_label(pred['label'])}
182
+ </div>
183
+ """, unsafe_allow_html=True)
184
+
185
+ with col_right:
186
+ st.markdown("**🎓 Der RöntgenMeister**")
187
+ predictions = models["RöntgenMeister"](image)
188
+ for pred in predictions:
189
+ if pred['score'] >= conf_threshold:
190
+ score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
191
+ st.markdown(f"""
192
+ <div class='result-box'>
193
+ <span style='color: {score_color}; font-weight: 500;'>
194
+ {pred['score']:.1%}
195
+ </span> - {translate_label(pred['label'])}
196
+ </div>
197
+ """, unsafe_allow_html=True)
198
+ else:
199
+ st.info("Bitte laden Sie ein Röntgenbild hoch (JPEG, PNG)")
200
+
201
+ # Script pour la synchronisation du thème
202
+ st.markdown("""
203
+ <script>
204
+ function updateTheme(isDark) {
205
+ document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
206
+ }
207
+
208
+ window.addEventListener('message', function(e) {
209
+ if (e.data.type === 'theme-change') {
210
+ updateTheme(e.data.theme === 'dark');
211
+ }
212
+ });
213
+
214
+ updateTheme(window.matchMedia('(prefers-color-scheme: dark)').matches);
215
+ </script>
216
+ """, unsafe_allow_html=True)
217
 
218
+ if __name__ == "__main__":
219
+ main()