wth-ishu commited on
Commit
97c155f
·
verified ·
1 Parent(s): 3c1cc1a

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +328 -0
  2. best.pt +3 -0
  3. requirements.txt +9 -0
app.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import plotly.graph_objects as go
3
+ import plotly.express as px
4
+ from ultralytics import YOLO
5
+ import cv2
6
+ import numpy as np
7
+ from PIL import Image
8
+ import pandas as pd
9
+ from streamlit_lottie import st_lottie
10
+ import requests
11
+
12
+ # Set page configuration
13
+ st.set_page_config(page_title="Advanced Dental Disease Detection", page_icon="🦷", layout="wide")
14
+
15
+ # Enhanced CSS for better styling and image sizing
16
+ st.markdown("""
17
+ <style>
18
+ .main {
19
+ padding: 2rem;
20
+ }
21
+ .stAlert > div {
22
+ padding: 0.5rem;
23
+ border-radius: 0.5rem;
24
+ }
25
+ .upload-text {
26
+ font-size: 1.2rem;
27
+ font-weight: bold;
28
+ margin-bottom: 1rem;
29
+ }
30
+ .condition-section {
31
+ margin: 1rem 0;
32
+ padding: 1rem;
33
+ border-radius: 0.5rem;
34
+ background-color: #f0f2f6;
35
+ }
36
+ .st-emotion-cache-1v0mbdj > img {
37
+ border-radius: 10px;
38
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
39
+ max-height: 400px; /* Control maximum height of images */
40
+ object-fit: contain;
41
+ }
42
+ .cropped-image {
43
+ max-height: 250px; /* Smaller height for cropped images */
44
+ width: auto;
45
+ margin: auto;
46
+ }
47
+ .st-tabs {
48
+ background-color: #ffffff;
49
+ padding: 1rem;
50
+ border-radius: 0.5rem;
51
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
52
+ }
53
+ .detection-grid {
54
+ display: grid;
55
+ grid-template-columns: repeat(3, 1fr);
56
+ gap: 1rem;
57
+ margin: 1rem 0;
58
+ }
59
+ </style>
60
+ """, unsafe_allow_html=True)
61
+
62
+ def load_lottie_url(url: str):
63
+ """
64
+ Load Lottie animation from URL
65
+ Args:
66
+ url (str): URL of the Lottie animation
67
+ Returns:
68
+ dict: Lottie animation JSON data or None if failed to load
69
+ """
70
+ try:
71
+ r = requests.get(url)
72
+ if r.status_code != 200:
73
+ return None
74
+ return r.json()
75
+ except Exception as e:
76
+ st.error(f"Error loading Lottie animation: {str(e)}")
77
+ return None
78
+
79
+ @st.cache_resource
80
+ def load_model():
81
+ """Load the YOLO model"""
82
+ try:
83
+ model = YOLO('best.pt')
84
+ return model
85
+ except Exception as e:
86
+ st.error(f"Error loading model: {str(e)}")
87
+ return None
88
+
89
+ def process_image(image, model):
90
+ """Process the image and return predictions"""
91
+ try:
92
+ if isinstance(image, Image.Image):
93
+ image_array = np.array(image)
94
+ else:
95
+ image_array = image
96
+
97
+ results = model.predict(image_array)
98
+ return results[0]
99
+ except Exception as e:
100
+ st.error(f"Error processing image: {str(e)}")
101
+ return None
102
+
103
+ def draw_single_condition(image, box, class_name):
104
+ """Draw a single condition's bounding box on the image"""
105
+ try:
106
+ image_array = np.array(image).copy()
107
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
108
+ cv2.rectangle(image_array, (x1, y1), (x2, y2), (0, 255, 0), 2)
109
+ cv2.putText(image_array, class_name, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
110
+ return Image.fromarray(image_array)
111
+ except Exception as e:
112
+ st.error(f"Error drawing single condition: {str(e)}")
113
+ return image
114
+
115
+ def crop_detection(image, box):
116
+ """Crop the region of the detected condition"""
117
+ try:
118
+ image_array = np.array(image)
119
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
120
+ padding_x, padding_y = int((x2 - x1) * 0.1), int((y2 - y1) * 0.1)
121
+ height, width = image_array.shape[:2]
122
+ x1, y1 = max(0, x1 - padding_x), max(0, y1 - padding_y)
123
+ x2, y2 = min(width, x2 + padding_x), min(height, y2 + padding_y)
124
+ cropped = image_array[y1:y2, x1:x2]
125
+ return Image.fromarray(cropped)
126
+ except Exception as e:
127
+ st.error(f"Error cropping detection: {str(e)}")
128
+ return None
129
+
130
+ def draw_predictions(image, results):
131
+ """Draw all bounding boxes and labels on the image"""
132
+ try:
133
+ if isinstance(image, Image.Image):
134
+ image_array = np.array(image)
135
+ else:
136
+ image_array = image
137
+
138
+ plotted_image = results.plot()
139
+ return Image.fromarray(plotted_image)
140
+ except Exception as e:
141
+ st.error(f"Error drawing predictions: {str(e)}")
142
+ return image
143
+
144
+ def group_predictions_by_condition(results):
145
+ """Group predictions by condition type"""
146
+ condition_groups = {}
147
+ if len(results.boxes) > 0:
148
+ for box in results.boxes:
149
+ class_id = int(box.cls[0])
150
+ class_name = results.names[class_id]
151
+ confidence = float(box.conf[0])
152
+ if class_name not in condition_groups:
153
+ condition_groups[class_name] = []
154
+ condition_groups[class_name].append({'box': box, 'confidence': confidence})
155
+ return condition_groups
156
+
157
+ def create_confidence_chart(condition_groups):
158
+ data = []
159
+ for condition, detections in condition_groups.items():
160
+ for detection in detections:
161
+ data.append({
162
+ 'Condition': condition,
163
+ 'Confidence': detection['confidence']
164
+ })
165
+ df = pd.DataFrame(data)
166
+ fig = px.box(df, x='Condition', y='Confidence', points="all")
167
+ fig.update_layout(title_text='Confidence Distribution by Condition')
168
+ return fig
169
+
170
+ def create_condition_count_chart(condition_groups):
171
+ counts = {condition: len(detections) for condition, detections in condition_groups.items()}
172
+ fig = go.Figure(data=[go.Pie(labels=list(counts.keys()), values=list(counts.values()))])
173
+ fig.update_layout(title_text='Distribution of Detected Conditions')
174
+ return fig
175
+
176
+ def main():
177
+ # Header
178
+ st.title("🦷 Advanced Dental Disease Detection")
179
+
180
+ # Sidebar
181
+ with st.sidebar:
182
+ st.title("About")
183
+ st.info(
184
+ """Welcome to DentalVision AI - Advanced X-ray Analysis
185
+
186
+ Our application leverages YOLO11 technology to analyze dental X-rays and identify a comprehensive range of dental conditions and features:
187
+
188
+ 🦷 Common Dental Conditions
189
+ - Cavities (Caries) and Tooth Decay
190
+ - Fractured and Missing Teeth
191
+ - Primary and Permanent Teeth
192
+ - Tooth Attrition and Wear
193
+
194
+ 👨‍⚕️ Dental Treatments & Restorations
195
+ - Crowns and Fillings
196
+ - Dental Implants and Abutments
197
+ - Root Canal Treatments
198
+ - Post-cores and Gingival Formers
199
+
200
+ 🎯 Orthodontic Elements
201
+ - Malaligned Teeth
202
+ - Orthodontic Brackets and Wires
203
+ - Permanent Retainers
204
+ - TADs and Metal Bands
205
+
206
+ 🔍 Bone & Tissue Analysis
207
+ - Mandibular Canal Assessment
208
+ - Maxillary Sinus Evaluation
209
+ - Bone Loss and Defects
210
+ - Cyst Detection
211
+
212
+ ⚠️ Special Conditions
213
+ - Impacted Teeth
214
+ - Periapical Lesions
215
+ - Retained Roots and Root Pieces
216
+ - Root Resorption and Supra Eruption
217
+
218
+ This AI-powered tool assists dental professionals in comprehensive X-ray analysis for more accurate diagnoses and treatment planning."""
219
+ )
220
+
221
+ # Add Lottie animation
222
+ #lottie_dental = load_lottie_url("https://assets5.lottiefiles.com/packages/lf20_xnbikipz.json")
223
+ #if lottie_dental:
224
+ # st_lottie(lottie_dental, speed=1, height=200, key="dental")
225
+
226
+ # Model loading
227
+ with st.spinner("Loading model..."):
228
+ model = load_model()
229
+
230
+ if model is None:
231
+ st.error("Failed to load model. Please check the model path and try again.")
232
+ return
233
+
234
+ # File uploader
235
+ uploaded_file = st.file_uploader("Choose an X-ray image...", type=['png', 'jpg', 'jpeg'])
236
+
237
+ if uploaded_file is not None:
238
+ try:
239
+ # Read image
240
+ image = Image.open(uploaded_file)
241
+
242
+ # Make prediction
243
+ with st.spinner("Analyzing image..."):
244
+ results = process_image(image, model)
245
+
246
+ if results is not None:
247
+ # Display original and processed images side by side
248
+ st.header("Image Analysis")
249
+ col1, col2 = st.columns(2)
250
+
251
+ with col1:
252
+ st.subheader("Original Image")
253
+ st.image(image, use_container_width=True)
254
+
255
+ with col2:
256
+ st.subheader("Detected Conditions")
257
+ processed_image = draw_predictions(image, results)
258
+ st.image(processed_image, use_container_width=True)
259
+
260
+ # Group predictions by condition
261
+ condition_groups = group_predictions_by_condition(results)
262
+
263
+ if condition_groups:
264
+ st.header("Detailed Analysis by Condition")
265
+
266
+ # Create tabs for each condition type
267
+ tabs = st.tabs(list(condition_groups.keys()))
268
+
269
+ for tab, (condition_name, detections) in zip(tabs, condition_groups.items()):
270
+ with tab:
271
+ st.subheader(f"{condition_name} Detections")
272
+ st.write(f"Number of {condition_name} detected: {len(detections)}")
273
+
274
+ # Display each instance of this condition
275
+ for idx, detection in enumerate(detections, 1):
276
+ st.write(f"#### Instance {idx}")
277
+ st.write(f"Confidence: {detection['confidence']:.2%}")
278
+
279
+ # Create three columns with controlled image sizes
280
+ cols = st.columns(3)
281
+
282
+ with cols[0]:
283
+ st.write("Full Image with Detection")
284
+ single_detection = draw_single_condition(image, detection['box'], condition_name)
285
+ st.image(single_detection, use_container_width=True, clamp=True)
286
+
287
+ with cols[1]:
288
+ st.write("Cropped Region")
289
+ cropped_region = crop_detection(image, detection['box'])
290
+ if cropped_region is not None:
291
+ st.image(cropped_region, use_container_width=True, clamp=True)
292
+
293
+ st.divider()
294
+
295
+ # Add advanced visualizations
296
+ st.header("Advanced Visualizations")
297
+ viz_cols = st.columns(2)
298
+
299
+ with viz_cols[0]:
300
+ confidence_chart = create_confidence_chart(condition_groups)
301
+ st.plotly_chart(confidence_chart, use_container_width=True)
302
+
303
+ with viz_cols[1]:
304
+ count_chart = create_condition_count_chart(condition_groups)
305
+ st.plotly_chart(count_chart, use_container_width=True)
306
+
307
+ else:
308
+ st.info("No dental conditions detected in the image.")
309
+
310
+ except Exception as e:
311
+ st.error(f"Error processing image: {str(e)}")
312
+
313
+ # Additional information
314
+ with st.expander("ℹ️ How to use"):
315
+ st.markdown("""
316
+ 1. Upload a dental X-ray image using the file uploader above
317
+ 2. The model will automatically process the image
318
+ 3. Results will show detected conditions with confidence scores
319
+ 4. View detailed analysis for each condition type in separate tabs
320
+ 5. For each detection you'll see:
321
+ - Full image with the detection marked
322
+ - Cropped view of the detected region
323
+ - Cropped view with detection marking
324
+ 6. Explore advanced visualizations for a comprehensive overview
325
+ """)
326
+
327
+ if __name__ == "__main__":
328
+ main()
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:af14905ab5bb9321e6ca55fa5e22bb66dc206f67d7610b9bbf8f38da8af46433
3
+ size 367706701
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ plotly
3
+ ultralytics
4
+ opencv-python
5
+ numpy
6
+ pillow
7
+ pandas
8
+ streamlit-lottie
9
+ requests