yassonee commited on
Commit
383659b
·
verified ·
1 Parent(s): cc165f9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -97
app.py CHANGED
@@ -3,66 +3,97 @@ from transformers import pipeline
3
  from PIL import Image, ImageDraw
4
  import torch
5
 
6
- # Configuration de la page
7
  st.set_page_config(
8
- layout="wide",
9
  page_title="Fraktur Detektion",
 
10
  initial_sidebar_state="collapsed"
11
  )
12
 
13
- # Style personnalisé
14
  st.markdown("""
15
  <style>
16
- /* Cacher les éléments Streamlit par défaut */
17
- #MainMenu {visibility: hidden;}
18
- footer {visibility: hidden;}
19
- header {visibility: hidden;}
20
-
21
- /* Style personnalisé pour la page */
22
  .stApp {
23
- margin: 0;
24
  padding: 0 !important;
25
- max-width: 100%;
26
  }
27
 
28
- /* Style pour les boutons */
29
- .stButton > button {
30
- width: 100%;
31
- background-color: #3b82f6;
32
- color: white;
33
- padding: 0.5rem 1rem;
34
- border-radius: 0.375rem;
35
- border: none;
36
- font-weight: 500;
37
  }
38
 
39
- .stButton > button:hover {
40
- background-color: #2563eb;
 
 
 
41
  }
42
 
43
- /* Container principal */
44
  .block-container {
45
- padding: 1rem !important;
46
  max-width: 100% !important;
47
  }
48
 
49
- /* Style pour les images */
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  .stImage > img {
51
- max-height: 300px;
52
- width: auto;
53
- margin: 0 auto;
 
54
  }
55
 
56
- /* Style pour les messages d'erreur */
57
- .stAlert {
58
- padding: 1rem;
59
- margin: 1rem 0;
60
  border-radius: 0.375rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
  </style>
63
  """, unsafe_allow_html=True)
64
 
65
- # Cache des modèles
66
  @st.cache_resource
67
  def load_models():
68
  return {
@@ -72,78 +103,117 @@ def load_models():
72
  model="nandodeomkar/autotrain-fracture-detection-using-google-vit-base-patch-16-54382127388")
73
  }
74
 
 
 
 
 
 
 
 
 
 
75
  def draw_boxes(image, predictions):
76
  draw = ImageDraw.Draw(image)
77
  for pred in predictions:
78
- if pred['label'].lower() == 'fracture' and pred['score'] > 0.6:
79
- box = pred['box']
80
- label = f"Fraktur ({pred['score']:.1%})"
81
- color = "#EF4444" # Rouge
82
-
83
- # Dessiner le rectangle
84
- draw.rectangle(
85
- [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
86
- outline=color,
87
- width=2
88
- )
89
-
90
- # Ajouter le label
91
- text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
92
- draw.rectangle(text_bbox, fill=color)
93
- draw.text((box['xmin'], box['ymin']-15), label, fill="white")
94
-
95
  return image
96
 
97
  def main():
98
- # Chargement des modèles
99
  models = load_models()
100
-
101
- # Upload des images
102
- uploaded_files = st.file_uploader(
103
- "Röntgenbilder hochladen",
104
- type=['png', 'jpg', 'jpeg'],
105
- accept_multiple_files=True,
106
- label_visibility="collapsed"
107
- )
108
-
109
- if uploaded_files:
110
- # Bouton d'analyse
111
- if st.button("Bilder analysieren", key="analyze_button"):
112
- # Création des colonnes pour l'affichage
113
- cols = st.columns(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
- for idx, uploaded_file in enumerate(uploaded_files):
116
- image = Image.open(uploaded_file)
117
-
118
- # Analyse avec KnochenAuge
119
- predictions = models["KnochenAuge"](image)
120
- fractures_found = any(p['label'].lower() == 'fracture' and p['score'] > 0.6 for p in predictions)
121
-
122
- if fractures_found:
123
- with cols[idx % 2]:
124
- # Créer une copie de l'image pour le dessin
125
- result_image = image.copy()
126
- result_image = draw_boxes(result_image, predictions)
127
- st.image(result_image, use_column_width=True)
128
-
129
- # Analyses supplémentaires
130
- pred_wachter = models["KnochenWächter"](image)[0]
131
- pred_meister = models["RöntgenMeister"](image)[0]
132
-
133
- if pred_wachter['score'] > 0.6 or pred_meister['score'] > 0.6:
134
- st.markdown(
135
- f"""
136
- <div style='background-color: #1F2937; color: white; padding: 1rem; border-radius: 0.375rem;'>
137
- <div style='margin-bottom: 0.5rem;'>
138
- <span style='color: #60A5FA;'>KnochenWächter:</span> {pred_wachter['score']:.1%}
139
- </div>
140
- <div>
141
- <span style='color: #60A5FA;'>RöntgenMeister:</span> {pred_meister['score']:.1%}
142
- </div>
143
- </div>
144
- """,
145
- unsafe_allow_html=True
146
- )
147
 
148
  if __name__ == "__main__":
149
  main()
 
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 {
 
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()