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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -135
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import streamlit as st
2
  from transformers import pipeline
3
  from PIL import Image, ImageDraw
@@ -5,115 +6,98 @@ 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)
118
 
119
  @st.cache_resource
@@ -139,9 +123,7 @@ def draw_boxes(image, predictions):
139
  for pred in predictions:
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'])],
@@ -149,101 +131,79 @@ def draw_boxes(image, predictions):
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()
 
1
+ # app.py
2
  import streamlit as st
3
  from transformers import pipeline
4
  from PIL import Image, ImageDraw
 
6
 
7
  # Configuration de la page
8
  st.set_page_config(
9
+ page_title="Fraktur Detektion",
10
  layout="wide",
11
  initial_sidebar_state="collapsed"
12
  )
13
 
14
+ # CSS optimisé
15
  st.markdown("""
16
  <style>
17
+ /* Réinitialisation complète */
18
  .stApp {
19
+ background: transparent !important;
20
  padding: 0 !important;
21
  }
22
 
23
  .block-container {
24
+ padding: 0.5rem !important;
25
  max-width: 100% !important;
26
  }
27
 
28
+ /* Suppression des éléments superflus */
29
+ #MainMenu, footer, header, .viewerBadge_container__1QSob {
30
+ display: none !important;
 
31
  }
32
 
33
+ .stDeployButton {
34
+ display: none !important;
 
 
 
 
35
  }
36
 
37
+ /* Style compact */
38
  .uploadedFile {
39
+ border: 1px dashed var(--border-color);
40
  border-radius: 0.5rem;
41
  padding: 0.5rem;
 
42
  }
43
 
44
+ .st-emotion-cache-1kyxreq {
45
+ margin-top: -2rem !important;
 
 
46
  }
47
 
48
+ /* Conteneurs de résultats */
 
 
 
 
 
 
49
  .result-box {
50
  padding: 0.5rem;
51
  border-radius: 0.375rem;
52
  margin: 0.25rem 0;
53
+ border: 1px solid var(--border-color);
54
+ background: var(--background-color);
55
  }
56
 
57
+ /* Tabs plus compacts */
58
+ .stTabs [data-baseweb="tab-list"] {
59
+ gap: 0.5rem;
 
 
 
60
  }
61
 
62
+ .stTabs [data-baseweb="tab"] {
63
+ padding: 0.25rem 0.5rem;
64
+ font-size: 0.875rem;
 
65
  }
66
 
67
+ /* Variables CSS pour le thème */
68
+ :root[data-theme="light"] {
69
+ --background-color: rgba(249, 250, 251, 0.8);
70
+ --border-color: #e5e7eb;
71
+ --text-color: #1f2937;
72
+ }
73
 
74
+ :root[data-theme="dark"] {
75
+ --background-color: rgba(17, 24, 39, 0.8);
76
+ --border-color: #374151;
77
+ --text-color: #e5e7eb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
 
80
+ /* Ajustements responsifs */
81
+ @media (max-width: 768px) {
82
+ .block-container {
83
+ padding: 0.25rem !important;
84
+ }
85
  }
86
  </style>
87
+ <script>
88
+ function updateTheme(isDark) {
89
+ document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
90
+ }
91
+
92
+ window.addEventListener('message', function(e) {
93
+ if (e.data.type === 'theme-change') {
94
+ updateTheme(e.data.theme === 'dark');
95
+ }
96
+ });
97
+
98
+ // Thème initial basé sur les préférences système
99
+ updateTheme(window.matchMedia('(prefers-color-scheme: dark)').matches);
100
+ </script>
101
  """, unsafe_allow_html=True)
102
 
103
  @st.cache_resource
 
123
  for pred in predictions:
124
  box = pred['box']
125
  label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
126
+ color = "#2563eb" if pred['score'] > 0.7 else "#eab308"
 
 
127
 
128
  draw.rectangle(
129
  [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
 
131
  width=2
132
  )
133
 
 
134
  text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
135
  draw.rectangle(text_bbox, fill=color)
136
  draw.text((box['xmin'], box['ymin']-15), label, fill="white")
137
+
138
  return image
139
 
140
  def main():
 
 
141
  models = load_models()
142
 
143
+ # Contrôle de confiance simplifié
144
+ conf_threshold = st.slider(
145
+ "Konfidenzschwelle",
146
+ min_value=0.0,
147
+ max_value=1.0,
148
+ value=0.60,
149
+ step=0.05,
150
+ help="Schwellenwert für die Erkennung (0-1)"
151
+ )
152
 
153
+ # Upload plus propre
154
  uploaded_file = st.file_uploader(
155
  "",
156
  type=['png', 'jpg', 'jpeg'],
157
+ key="xray_upload"
158
  )
159
 
160
  if uploaded_file:
 
161
  col1, col2 = st.columns([1, 1])
162
 
163
  with col1:
164
  image = Image.open(uploaded_file)
165
  max_size = (300, 300)
166
  image.thumbnail(max_size, Image.Resampling.LANCZOS)
167
+ st.image(image, use_container_width=True)
168
 
169
  with col2:
170
  tab1, tab2 = st.tabs(["📊 Klassifizierung", "🔍 Lokalisierung"])
171
 
172
  with tab1:
173
  for name in ["Heem2", "Nandodeomkar"]:
174
+ with st.spinner("Analyse..."):
175
+ predictions = models[name](image)
176
+ for pred in predictions:
177
+ if pred['score'] >= conf_threshold:
178
+ score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
179
+ st.markdown(f"""
180
+ <div class='result-box'>
181
+ <span style='color: {score_color}; font-weight: 500;'>
182
+ {pred['score']:.1%}
183
+ </span> - {translate_label(pred['label'])}
184
+ </div>
185
+ """, unsafe_allow_html=True)
186
+
187
+ with tab2:
188
+ with st.spinner("Lokalisierung..."):
189
+ predictions = models["D3STRON"](image)
190
+ filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
191
+
192
+ if filtered_preds:
193
+ result_image = image.copy()
194
+ result_image = draw_boxes(result_image, filtered_preds)
195
+ st.image(result_image, use_container_width=True)
196
+
197
+ for pred in filtered_preds:
198
  st.markdown(f"""
199
  <div class='result-box'>
200
+ {translate_label(pred['label'])}: {pred['score']:.1%}
 
 
201
  </div>
202
  """, unsafe_allow_html=True)
203
+ else:
204
+ st.info("Keine Erkennungen über dem Schwellenwert")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  else:
206
+ st.info("Röntgenbild hochladen (JPEG, PNG, max. 5MB)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
  if __name__ == "__main__":
209
  main()