Update app.py
Browse files
app.py
CHANGED
@@ -16,8 +16,9 @@ st.markdown("""
|
|
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;
|
@@ -25,20 +26,20 @@ st.markdown("""
|
|
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);
|
@@ -46,12 +47,12 @@ st.markdown("""
|
|
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;
|
@@ -59,7 +60,7 @@ st.markdown("""
|
|
59 |
max-height: 400px !important;
|
60 |
object-fit: contain !important;
|
61 |
}
|
62 |
-
|
63 |
/* Résultats */
|
64 |
.result-box {
|
65 |
padding: 0.375rem;
|
@@ -69,7 +70,7 @@ st.markdown("""
|
|
69 |
border: 1px solid var(--border-color);
|
70 |
color: var(--text-color);
|
71 |
}
|
72 |
-
|
73 |
/* Titres */
|
74 |
h2, h3 {
|
75 |
margin: 0 !important;
|
@@ -77,17 +78,17 @@ st.markdown("""
|
|
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 |
}
|
@@ -118,13 +119,13 @@ def draw_boxes(image, 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)
|
@@ -140,7 +141,7 @@ def main():
|
|
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",
|
@@ -151,50 +152,52 @@ def main():
|
|
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 (
|
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 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
|
|
|
|
198 |
else:
|
199 |
st.info("Bitte laden Sie ein Röntgenbild hoch (JPEG, PNG)")
|
200 |
|
@@ -204,16 +207,16 @@ def main():
|
|
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()
|
|
|
16 |
background-color: var(--background-color) !important;
|
17 |
padding: 0 !important;
|
18 |
overflow: hidden !important;
|
19 |
+
height: 100vh !important;
|
20 |
}
|
21 |
+
|
22 |
/* Variables de thème */
|
23 |
[data-theme="light"] {
|
24 |
--background-color: #ffffff;
|
|
|
26 |
--border-color: #e5e7eb;
|
27 |
--secondary-bg: #f3f4f6;
|
28 |
}
|
29 |
+
|
30 |
[data-theme="dark"] {
|
31 |
--background-color: #1f2937;
|
32 |
--text-color: #f3f4f6;
|
33 |
--border-color: #4b5563;
|
34 |
--secondary-bg: #374151;
|
35 |
}
|
36 |
+
|
37 |
/* Layout principal */
|
38 |
.block-container {
|
39 |
padding: 0.5rem !important;
|
40 |
max-width: 100% !important;
|
41 |
}
|
42 |
+
|
43 |
/* Contrôles et upload */
|
44 |
.uploadedFile {
|
45 |
border: 1px dashed var(--border-color);
|
|
|
47 |
padding: 0.25rem;
|
48 |
background: var(--secondary-bg);
|
49 |
}
|
50 |
+
|
51 |
/* Ajustement des colonnes */
|
52 |
[data-testid="column"] {
|
53 |
padding: 0 0.5rem !important;
|
54 |
}
|
55 |
+
|
56 |
/* Images adaptatives */
|
57 |
.stImage > img {
|
58 |
width: 100% !important;
|
|
|
60 |
max-height: 400px !important;
|
61 |
object-fit: contain !important;
|
62 |
}
|
63 |
+
|
64 |
/* Résultats */
|
65 |
.result-box {
|
66 |
padding: 0.375rem;
|
|
|
70 |
border: 1px solid var(--border-color);
|
71 |
color: var(--text-color);
|
72 |
}
|
73 |
+
|
74 |
/* Titres */
|
75 |
h2, h3 {
|
76 |
margin: 0 !important;
|
|
|
78 |
font-size: 1rem !important;
|
79 |
color: var(--text-color) !important;
|
80 |
}
|
81 |
+
|
82 |
/* Nettoyage des éléments inutiles */
|
83 |
#MainMenu, footer, header, .viewerBadge_container__1QSob, .stDeployButton {
|
84 |
display: none !important;
|
85 |
}
|
86 |
+
|
87 |
/* Ajustements espacement */
|
88 |
div[data-testid="stVerticalBlock"] {
|
89 |
gap: 0.5rem !important;
|
90 |
}
|
91 |
+
|
92 |
.element-container {
|
93 |
margin: 0.25rem 0 !important;
|
94 |
}
|
|
|
119 |
box = pred['box']
|
120 |
label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
|
121 |
color = "#2563eb" if pred['score'] > 0.7 else "#eab308"
|
122 |
+
|
123 |
draw.rectangle(
|
124 |
[(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
|
125 |
outline=color,
|
126 |
width=2
|
127 |
)
|
128 |
+
|
129 |
# Label plus compact
|
130 |
text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
|
131 |
draw.rectangle(text_bbox, fill=color)
|
|
|
141 |
with col1:
|
142 |
st.markdown("### 📤 Röntgenbild Upload")
|
143 |
uploaded_file = st.file_uploader("", type=['png', 'jpg', 'jpeg'])
|
144 |
+
|
145 |
if uploaded_file:
|
146 |
conf_threshold = st.slider(
|
147 |
"Konfidenzschwelle",
|
|
|
152 |
with col2:
|
153 |
if uploaded_file:
|
154 |
image = Image.open(uploaded_file)
|
155 |
+
|
156 |
st.markdown("### 🔍 Meinung der KI-Experten")
|
157 |
+
|
158 |
+
# Analyse avec KnochenAuge (localisation)
|
159 |
st.markdown("#### 👁️ Das KnochenAuge - Lokalisation")
|
160 |
predictions = models["KnochenAuge"](image)
|
161 |
filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
|
162 |
+
|
163 |
if filtered_preds:
|
164 |
result_image = image.copy()
|
165 |
result_image = draw_boxes(result_image, filtered_preds)
|
166 |
st.image(result_image, use_container_width=True)
|
167 |
+
|
168 |
+
# Affichage des résultats supplémentaires uniquement si des fractures sont détectées
|
169 |
+
st.markdown("#### 🎯 KI-Analyse")
|
170 |
+
col_left, col_right = st.columns(2)
|
171 |
+
|
172 |
+
with col_left:
|
173 |
+
st.markdown("**🛡️ Der KnochenWächter**")
|
174 |
+
predictions = models["KnochenWächter"](image)
|
175 |
+
for pred in predictions:
|
176 |
+
if pred['score'] >= conf_threshold:
|
177 |
+
score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
|
178 |
+
st.markdown(f"""
|
179 |
+
<div class='result-box'>
|
180 |
+
<span style='color: {score_color}; font-weight: 500;'>
|
181 |
+
{pred['score']:.1%}
|
182 |
+
</span> - {translate_label(pred['label'])}
|
183 |
+
</div>
|
184 |
+
""", unsafe_allow_html=True)
|
185 |
+
|
186 |
+
with col_right:
|
187 |
+
st.markdown("**🎓 Der RöntgenMeister**")
|
188 |
+
predictions = models["RöntgenMeister"](image)
|
189 |
+
for pred in predictions:
|
190 |
+
if pred['score'] >= conf_threshold:
|
191 |
+
score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
|
192 |
+
st.markdown(f"""
|
193 |
+
<div class='result-box'>
|
194 |
+
<span style='color: {score_color}; font-weight: 500;'>
|
195 |
+
{pred['score']:.1%}
|
196 |
+
</span> - {translate_label(pred['label'])}
|
197 |
+
</div>
|
198 |
+
""", unsafe_allow_html=True)
|
199 |
+
else:
|
200 |
+
st.info("Kein Bruch erkannt.")
|
201 |
else:
|
202 |
st.info("Bitte laden Sie ein Röntgenbild hoch (JPEG, PNG)")
|
203 |
|
|
|
207 |
function updateTheme(isDark) {
|
208 |
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
|
209 |
}
|
210 |
+
|
211 |
window.addEventListener('message', function(e) {
|
212 |
if (e.data.type === 'theme-change') {
|
213 |
updateTheme(e.data.theme === 'dark');
|
214 |
}
|
215 |
});
|
216 |
+
|
217 |
updateTheme(window.matchMedia('(prefers-color-scheme: dark)').matches);
|
218 |
</script>
|
219 |
""", unsafe_allow_html=True)
|
220 |
|
221 |
if __name__ == "__main__":
|
222 |
+
main()
|