yassonee commited on
Commit
9aecd9e
·
verified ·
1 Parent(s): 3982789

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -53
app.py CHANGED
@@ -3,19 +3,115 @@ from transformers import pipeline
3
  from PIL import Image, ImageDraw
4
  import torch
5
 
 
6
  st.set_page_config(
7
  page_title="Knochenbrucherkennung",
8
  layout="wide",
9
  initial_sidebar_state="collapsed"
10
  )
11
 
 
12
  st.markdown("""
13
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  .main > div {
15
- padding: 2rem;
16
- background: #f8f9fa;
17
- border-radius: 1rem;
18
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
  </style>
21
  """, unsafe_allow_html=True)
@@ -36,10 +132,7 @@ def translate_label(label):
36
  "normal": "Normal",
37
  "abnormal": "Abnormal"
38
  }
39
- for eng, deu in translations.items():
40
- if eng.lower() in label.lower():
41
- return deu
42
- return label
43
 
44
  def draw_boxes(image, predictions):
45
  draw = ImageDraw.Draw(image)
@@ -47,86 +140,110 @@ def draw_boxes(image, predictions):
47
  box = pred['box']
48
  label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
49
 
 
 
 
50
  draw.rectangle(
51
  [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
52
- outline="#FF6B6B",
53
  width=2
54
  )
55
 
56
- text_bbox = draw.textbbox((box['xmin'], box['ymin']), label)
57
- draw.rectangle(text_bbox, fill="#FF6B6B")
58
- draw.text((box['xmin'], box['ymin']), label, fill="white")
 
59
  return image
60
 
61
  def main():
62
- st.title("🦴 Knochenbrucherkennung System")
63
 
64
  models = load_models()
65
 
66
- with st.expander("⚙️ Einstellungen", expanded=True):
 
67
  conf_threshold = st.slider(
68
  "Konfidenzschwelle",
69
  min_value=0.0,
70
  max_value=1.0,
71
  value=0.60,
72
- step=0.01
73
  )
74
 
 
75
  uploaded_file = st.file_uploader(
76
- "Röntgenbild hochladen",
77
  type=['png', 'jpg', 'jpeg'],
78
- key="xray_upload"
79
  )
80
 
81
  if uploaded_file:
82
- col1, col2 = st.columns([1, 2])
 
83
 
84
  with col1:
85
  image = Image.open(uploaded_file)
86
- max_size = (250, 250)
87
  image.thumbnail(max_size, Image.Resampling.LANCZOS)
88
- st.image(image, caption="Original Röntgenbild", use_container_width=True)
89
 
90
  with col2:
91
- tab1, tab2 = st.tabs(["📊 Klassifizierung", "🔍 Erkennung"])
92
 
93
  with tab1:
94
  for name in ["Heem2", "Nandodeomkar"]:
95
- with st.container():
96
- st.subheader(f"Modell: {name}")
97
- with st.spinner("Analyse läuft..."):
98
- predictions = models[name](image)
99
- for pred in predictions:
100
- if pred['score'] >= conf_threshold:
101
- score_color = "green" if pred['score'] > 0.7 else "orange"
102
- st.markdown(f"""
103
- <div style='padding: 10px; border-radius: 5px; background-color: #f0f2f6;'>
104
- <span style='color: {score_color}; font-weight: bold;'>
105
- {pred['score']:.1%}
106
- </span> - {translate_label(pred['label'])}
107
- </div>
108
- """, unsafe_allow_html=True)
109
-
110
- with tab2:
111
- st.subheader("Modell: D3STRON")
112
- with st.spinner("Erkennung läuft..."):
113
- predictions = models["D3STRON"](image)
114
- filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
115
-
116
- if filtered_preds:
117
- result_image = image.copy()
118
- result_image = draw_boxes(result_image, filtered_preds)
119
- st.image(result_image, use_container_width=True)
120
-
121
- for pred in filtered_preds:
122
  st.markdown(f"""
123
- <div style='padding: 8px; border-left: 4px solid #FF6B6B;
124
- margin: 5px 0; background-color: #f0f2f6;'>
125
- {translate_label(pred['label'])}: {pred['score']:.1%}
 
126
  </div>
127
  """, unsafe_allow_html=True)
128
- else:
129
- st.info("Keine Erkennungen über dem Schwellenwert")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  if __name__ == "__main__":
132
  main()
 
3
  from PIL import Image, ImageDraw
4
  import torch
5
 
6
+ # Configuration de la page
7
  st.set_page_config(
8
  page_title="Knochenbrucherkennung",
9
  layout="wide",
10
  initial_sidebar_state="collapsed"
11
  )
12
 
13
+ # CSS amélioré pour une meilleure intégration
14
  st.markdown("""
15
  <style>
16
+ /* Reset et base */
17
+ .stApp {
18
+ background-color: transparent !important;
19
+ padding: 0 !important;
20
+ }
21
+
22
+ .block-container {
23
+ padding: 1rem !important;
24
+ max-width: 100% !important;
25
+ }
26
+
27
+ /* En-tête compact */
28
+ h1 {
29
+ font-size: 1.5rem !important;
30
+ margin-bottom: 1rem !important;
31
+ }
32
+
33
+ /* Conteneurs */
34
  .main > div {
35
+ padding: 1rem !important;
36
+ background: transparent !important;
37
+ border-radius: 0.5rem !important;
38
+ box-shadow: none !important;
39
+ }
40
+
41
+ /* Upload plus compact */
42
+ .uploadedFile {
43
+ border: 1px dashed #ccc;
44
+ border-radius: 0.5rem;
45
+ padding: 0.5rem;
46
+ background: rgba(255, 255, 255, 0.05);
47
+ }
48
+
49
+ /* Tabs style */
50
+ .stTabs [data-baseweb="tab-list"] {
51
+ gap: 1rem;
52
+ background-color: transparent;
53
+ }
54
+
55
+ .stTabs [data-baseweb="tab"] {
56
+ padding: 0.5rem 1rem;
57
+ border-radius: 0.5rem;
58
+ background: rgba(255, 255, 255, 0.1);
59
+ }
60
+
61
+ /* Résultats */
62
+ .result-box {
63
+ padding: 0.5rem;
64
+ border-radius: 0.375rem;
65
+ margin: 0.25rem 0;
66
+ background: rgba(255, 255, 255, 0.05);
67
+ border: 1px solid rgba(255, 255, 255, 0.1);
68
+ }
69
+
70
+ /* Images */
71
+ .stImage img {
72
+ max-height: 300px !important;
73
+ width: auto !important;
74
+ border-radius: 0.375rem;
75
+ margin: 0 auto;
76
+ }
77
+
78
+ /* Spinner plus petit */
79
+ .stSpinner > div {
80
+ height: 2rem !important;
81
+ width: 2rem !important;
82
+ }
83
+
84
+ /* Cacher éléments Streamlit */
85
+ #MainMenu {display: none;}
86
+ footer {display: none;}
87
+ header {display: none;}
88
+
89
+ /* Dark mode support */
90
+ @media (prefers-color-scheme: dark) {
91
+ .main > div {
92
+ background: rgba(0, 0, 0, 0.2) !important;
93
+ }
94
+
95
+ .uploadedFile {
96
+ border-color: #4a5568;
97
+ background: rgba(255, 255, 255, 0.05);
98
+ }
99
+
100
+ .stTabs [data-baseweb="tab"] {
101
+ background: rgba(255, 255, 255, 0.05);
102
+ }
103
+
104
+ .result-box {
105
+ background: rgba(255, 255, 255, 0.05);
106
+ border-color: rgba(255, 255, 255, 0.2);
107
+ }
108
+ }
109
+
110
+ /* Expander plus compact */
111
+ .streamlit-expanderHeader {
112
+ padding: 0.5rem !important;
113
+ background: rgba(255, 255, 255, 0.05) !important;
114
+ border-radius: 0.375rem !important;
115
  }
116
  </style>
117
  """, unsafe_allow_html=True)
 
132
  "normal": "Normal",
133
  "abnormal": "Abnormal"
134
  }
135
+ return translations.get(label.lower(), label)
 
 
 
136
 
137
  def draw_boxes(image, predictions):
138
  draw = ImageDraw.Draw(image)
 
140
  box = pred['box']
141
  label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
142
 
143
+ # Box avec couleur basée sur le score
144
+ color = "#FF6B6B" if pred['score'] > 0.7 else "#FFA500"
145
+
146
  draw.rectangle(
147
  [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
148
+ outline=color,
149
  width=2
150
  )
151
 
152
+ # Label plus compact
153
+ text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
154
+ draw.rectangle(text_bbox, fill=color)
155
+ draw.text((box['xmin'], box['ymin']-15), label, fill="white")
156
  return image
157
 
158
  def main():
159
+ st.markdown("<h1>🦴 KI-Fraktur Detektion</h1>", unsafe_allow_html=True)
160
 
161
  models = load_models()
162
 
163
+ # Settings dans un expander compact
164
+ with st.expander("⚙️ Einstellungen", expanded=False):
165
  conf_threshold = st.slider(
166
  "Konfidenzschwelle",
167
  min_value=0.0,
168
  max_value=1.0,
169
  value=0.60,
170
+ step=0.05
171
  )
172
 
173
+ # Upload plus compact
174
  uploaded_file = st.file_uploader(
175
+ "",
176
  type=['png', 'jpg', 'jpeg'],
177
+ help="Unterstützte Formate: JPEG, PNG | Max: 5MB"
178
  )
179
 
180
  if uploaded_file:
181
+ # Layout en colonnes
182
+ col1, col2 = st.columns([1, 1])
183
 
184
  with col1:
185
  image = Image.open(uploaded_file)
186
+ max_size = (300, 300)
187
  image.thumbnail(max_size, Image.Resampling.LANCZOS)
188
+ st.image(image, caption="Originalbild", use_column_width=True)
189
 
190
  with col2:
191
+ tab1, tab2 = st.tabs(["📊 Klassifizierung", "🔍 Lokalisierung"])
192
 
193
  with tab1:
194
  for name in ["Heem2", "Nandodeomkar"]:
195
+ predictions = models[name](image)
196
+ for pred in predictions:
197
+ if pred['score'] >= conf_threshold:
198
+ score_color = "green" if pred['score'] > 0.7 else "orange"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  st.markdown(f"""
200
+ <div class='result-box'>
201
+ <span style='color: {score_color}; font-weight: bold;'>
202
+ {pred['score']:.1%}
203
+ </span> - {translate_label(pred['label'])}
204
  </div>
205
  """, unsafe_allow_html=True)
206
+
207
+ with tab2:
208
+ predictions = models["D3STRON"](image)
209
+ filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
210
+
211
+ if filtered_preds:
212
+ result_image = image.copy()
213
+ result_image = draw_boxes(result_image, filtered_preds)
214
+ st.image(result_image, use_column_width=True)
215
+
216
+ for pred in filtered_preds:
217
+ st.markdown(f"""
218
+ <div class='result-box'>
219
+ {translate_label(pred['label'])}: {pred['score']:.1%}
220
+ </div>
221
+ """, unsafe_allow_html=True)
222
+ else:
223
+ st.info("Keine Erkennungen über dem Schwellenwert")
224
+ else:
225
+ # Message d'instruction
226
+ st.markdown("""
227
+ <div style='padding: 1rem; background: rgba(59, 130, 246, 0.1); border-radius: 0.5rem;'>
228
+ <h4 style='margin: 0 0 0.5rem 0; font-size: 1rem;'>📤 Röntgenbild hochladen</h4>
229
+ <ul style='margin: 0; padding-left: 1rem; font-size: 0.875rem;'>
230
+ <li>Unterstützte Formate: JPEG, PNG</li>
231
+ <li>Maximale Größe: 5 MB</li>
232
+ <li>Optimale Auflösung: 512x512 Pixel</li>
233
+ </ul>
234
+ </div>
235
+ """, unsafe_allow_html=True)
236
+
237
+ # Script pour gérer le thème
238
+ st.markdown("""
239
+ <script>
240
+ window.addEventListener('message', function(e) {
241
+ if (e.data.type === 'theme-change') {
242
+ document.body.classList.toggle('dark', e.data.theme === 'dark');
243
+ }
244
+ });
245
+ </script>
246
+ """, unsafe_allow_html=True)
247
 
248
  if __name__ == "__main__":
249
  main()