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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -203
app.py CHANGED
@@ -1,217 +1,99 @@
1
- import streamlit as st
2
- from transformers import pipeline
3
- from PIL import Image, ImageDraw
4
- import torch
5
 
6
- # Configuration page
7
- st.set_page_config(
8
- page_title="Fraktur Detektion",
9
- layout="wide",
10
- initial_sidebar_state="collapsed"
11
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- # CSS optimisé
14
- st.markdown("""
15
  <style>
16
- /* Reset complet */
17
- .stApp {
18
- background-color: var(--background-color) !important;
19
- padding: 0 !important;
20
- max-height: 600px !important;
21
- overflow: hidden !important;
22
- }
23
-
24
- /* Variables de thème */
25
- [data-theme="light"] {
26
- --background-color: #ffffff;
27
- --text-color: #1f2937;
28
- --border-color: #e5e7eb;
29
- --secondary-bg: #f3f4f6;
30
- }
31
-
32
- [data-theme="dark"] {
33
- --background-color: #1f2937;
34
- --text-color: #f3f4f6;
35
- --border-color: #4b5563;
36
- --secondary-bg: #374151;
37
- }
38
-
39
- /* Conteneur principal */
40
- .block-container {
41
- padding: 0.5rem !important;
42
- max-width: 100% !important;
43
- }
44
-
45
- /* Upload et contrôles */
46
- .uploadedFile {
47
- border: 1px dashed var(--border-color);
48
- border-radius: 0.375rem;
49
- padding: 0.25rem;
50
- background: var(--secondary-bg);
51
- }
52
-
53
- /* Images plus petites */
54
- .stImage > img {
55
- max-width: 250px !important;
56
- max-height: 250px !important;
57
- margin: 0 auto !important;
58
- }
59
-
60
- /* Tabs compacts */
61
- .stTabs [data-baseweb="tab-list"] {
62
- gap: 0.25rem;
63
- background: transparent;
64
- }
65
-
66
- .stTabs [data-baseweb="tab"] {
67
- padding: 0.25rem 0.5rem;
68
- background: var(--secondary-bg);
69
- border-radius: 0.375rem;
70
- }
71
-
72
- /* Résultats */
73
- .result-box {
74
- padding: 0.375rem;
75
- border-radius: 0.375rem;
76
- margin: 0.25rem 0;
77
- background: var(--secondary-bg);
78
- border: 1px solid var(--border-color);
79
- color: var(--text-color);
80
- }
81
-
82
- /* Cacher éléments inutiles */
83
- #MainMenu, footer, header, .viewerBadge_container__1QSob, .stDeployButton {
84
- display: none !important;
85
- }
86
-
87
- div[data-testid="stVerticalBlock"] {
88
- gap: 0.5rem !important;
89
- }
90
-
91
- /* Ajustements espacement */
92
- .st-emotion-cache-1kyxreq {
93
- margin-top: -1rem !important;
94
  }
95
-
96
- .st-emotion-cache-1wmy9hl {
97
- padding: 0 !important;
98
  }
99
- </style>
100
- """, unsafe_allow_html=True)
101
 
102
- @st.cache_resource
103
- def load_models():
104
- return {
105
- "KnochenAuge": pipeline("object-detection", model="D3STRON/bone-fracture-detr"), # L'œil des os
106
- "KnochenWächter": pipeline("image-classification", model="Heem2/bone-fracture-detection-using-xray"), # Le gardien des os
107
- "RöntgenMeister": pipeline("image-classification", # Le maître des rayons X
108
- model="nandodeomkar/autotrain-fracture-detection-using-google-vit-base-patch-16-54382127388")
109
  }
110
-
111
- def translate_label(label):
112
- translations = {
113
- "fracture": "Knochenbruch",
114
- "no fracture": "Kein Bruch",
115
- "normal": "Normal",
116
- "abnormal": "Auffällig"
117
  }
118
- return translations.get(label.lower(), label)
119
-
120
- def draw_boxes(image, predictions):
121
- draw = ImageDraw.Draw(image)
122
- for pred in predictions:
123
- box = pred['box']
124
- label = f"{translate_label(pred['label'])} ({pred['score']:.2%})"
125
- color = "#2563eb" if pred['score'] > 0.7 else "#eab308"
126
-
127
- draw.rectangle(
128
- [(box['xmin'], box['ymin']), (box['xmax'], box['ymax'])],
129
- outline=color,
130
- width=2
131
- )
132
-
133
- text_bbox = draw.textbbox((box['xmin'], box['ymin']-15), label)
134
- draw.rectangle(text_bbox, fill=color)
135
- draw.text((box['xmin'], box['ymin']-15), label, fill="white")
136
- return image
137
 
138
- def main():
139
- models = load_models()
 
140
 
141
- # Contrôle de confiance compact
142
- conf_threshold = st.slider(
143
- "Konfidenzschwelle",
144
- min_value=0.0, max_value=1.0,
145
- value=0.60, step=0.05
146
- )
 
147
 
148
- # Upload plus propre
149
- uploaded_file = st.file_uploader("", type=['png', 'jpg', 'jpeg'])
150
-
151
- if uploaded_file:
152
- image = Image.open(uploaded_file)
153
- max_size = (250, 250) # Taille réduite
154
- image.thumbnail(max_size, Image.Resampling.LANCZOS)
155
-
156
- tab1, tab2 = st.tabs(["📊 KI-Analyse", "🔍 Lokalisierung"])
157
-
158
- with tab1:
159
- # Afficher l'image originale seulement dans l'onglet Analyse
160
- st.image(image, use_container_width=False)
161
-
162
- model_names = {
163
- "KnochenWächter": "🛡️ Der KnochenWächter",
164
- "RöntgenMeister": "🎓 Der RöntgenMeister"
165
  }
166
-
167
- for model_key, display_name in model_names.items():
168
- st.markdown(f"<div style='font-weight:500; margin-top:0.5rem;'>{display_name}</div>", unsafe_allow_html=True)
169
- predictions = models[model_key](image)
170
- for pred in predictions:
171
- if pred['score'] >= conf_threshold:
172
- score_color = "#22c55e" if pred['score'] > 0.7 else "#eab308"
173
- st.markdown(f"""
174
- <div class='result-box'>
175
- <span style='color: {score_color}; font-weight: 500;'>
176
- {pred['score']:.1%}
177
- </span> - {translate_label(pred['label'])}
178
- </div>
179
- """, unsafe_allow_html=True)
180
 
181
- with tab2:
182
- # Dans l'onglet Lokalisierung, montrer directement l'image avec les boîtes
183
- with st.spinner("Analyse läuft..."):
184
- predictions = models["KnochenAuge"](image)
185
- filtered_preds = [p for p in predictions if p['score'] >= conf_threshold]
186
-
187
- if filtered_preds:
188
- result_image = image.copy()
189
- result_image = draw_boxes(result_image, filtered_preds)
190
- st.markdown("### 👁️ Das KnochenAuge")
191
- st.image(result_image, use_container_width=False)
192
- else:
193
- st.info("Keine Auffälligkeiten erkannt")
194
-
195
- else:
196
- st.info("Röntgenbild hochladen (JPEG, PNG)")
197
-
198
- # Script pour la synchronisation du thème
199
- st.markdown("""
200
- <script>
201
- function updateTheme(isDark) {
202
- document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
203
- }
204
-
205
- window.addEventListener('message', function(e) {
206
- if (e.data.type === 'theme-change') {
207
- updateTheme(e.data.theme === 'dark');
208
- }
209
- });
210
-
211
- // Thème initial
212
- updateTheme(window.matchMedia('(prefers-color-scheme: dark)').matches);
213
- </script>
214
- """, unsafe_allow_html=True)
215
 
216
- if __name__ == "__main__":
217
- main()
 
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'; ?>