Spaces:
No application file
No application file
Upload 2 files
Browse files- requirements.txt +4 -0
- streamlit_app.py +179 -0
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
opencv-python
|
3 |
+
numpy
|
4 |
+
google-generativeai
|
streamlit_app.py
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
import streamlit as st
|
5 |
+
from google.generativeai import configure, GenerativeModel
|
6 |
+
import base64
|
7 |
+
from datetime import datetime
|
8 |
+
|
9 |
+
# Page configuration
|
10 |
+
st.set_page_config(
|
11 |
+
page_title="Advanced Dental X-Ray Analysis System",
|
12 |
+
page_icon="🦷",
|
13 |
+
layout="wide"
|
14 |
+
)
|
15 |
+
|
16 |
+
# Custom CSS for better appearance
|
17 |
+
st.markdown("""
|
18 |
+
<style>
|
19 |
+
.main {
|
20 |
+
padding: 2rem;
|
21 |
+
}
|
22 |
+
.stButton>button {
|
23 |
+
width: 100%;
|
24 |
+
background-color: #0083B8;
|
25 |
+
color: white;
|
26 |
+
}
|
27 |
+
.disclaimer {
|
28 |
+
background-color: #FFF3CD;
|
29 |
+
padding: 1rem;
|
30 |
+
border-radius: 5px;
|
31 |
+
margin: 1rem 0;
|
32 |
+
}
|
33 |
+
</style>
|
34 |
+
""", unsafe_allow_html=True)
|
35 |
+
|
36 |
+
# Main title with professional styling
|
37 |
+
st.title("🦷 Advanced Dental X-Ray Analysis System")
|
38 |
+
st.markdown("---")
|
39 |
+
|
40 |
+
# Initialize session state
|
41 |
+
if 'patient_history' not in st.session_state:
|
42 |
+
st.session_state.patient_history = {}
|
43 |
+
|
44 |
+
# Sidebar for API configuration
|
45 |
+
with st.sidebar:
|
46 |
+
st.header("Configuration")
|
47 |
+
api_key = st.text_input("Your API Key", type="password")
|
48 |
+
if not api_key:
|
49 |
+
api_key = os.getenv("GEMINI_API_KEY")
|
50 |
+
if not api_key:
|
51 |
+
st.error("⚠️ Please provide an API key.")
|
52 |
+
st.stop()
|
53 |
+
|
54 |
+
st.markdown("---")
|
55 |
+
st.header("Patient Information")
|
56 |
+
|
57 |
+
# Patient history form
|
58 |
+
with st.form("patient_history"):
|
59 |
+
st.session_state.patient_history.update({
|
60 |
+
'name': st.text_input("Patient Name"),
|
61 |
+
'age': st.number_input("Age", 1, 120),
|
62 |
+
'gender': st.selectbox("Gender", ["Male", "Female", "Other"]),
|
63 |
+
'medical_history': st.multiselect("Medical History",
|
64 |
+
["Diabetes", "Hypertension", "Heart Disease", "None"]),
|
65 |
+
'dental_complaints': st.text_area("Current Dental Complaints"),
|
66 |
+
'previous_treatments': st.text_area("Previous Dental Treatments"),
|
67 |
+
'smoking': st.selectbox("Smoking Status", ["Non-smoker", "Former smoker", "Current smoker"]),
|
68 |
+
'last_dental_visit': st.date_input("Last Dental Visit")
|
69 |
+
})
|
70 |
+
submit_button = st.form_submit_button("Save Patient Information")
|
71 |
+
|
72 |
+
# Configure Gemini Pro
|
73 |
+
configure(api_key=api_key)
|
74 |
+
model = GenerativeModel("gemini-pro")
|
75 |
+
|
76 |
+
# Main content area
|
77 |
+
col1, col2 = st.columns([1, 1])
|
78 |
+
|
79 |
+
with col1:
|
80 |
+
st.header("X-Ray Upload & Processing")
|
81 |
+
uploaded_file = st.file_uploader("Upload a dental X-ray image", type=["jpg", "jpeg", "png"])
|
82 |
+
|
83 |
+
if uploaded_file:
|
84 |
+
# Display original image
|
85 |
+
st.image(uploaded_file, caption="Original X-ray", use_column_width=True)
|
86 |
+
|
87 |
+
# Image processing options
|
88 |
+
st.subheader("Image Enhancement Options")
|
89 |
+
denoise_strength = st.slider("Denoising Strength", 1, 20, 10)
|
90 |
+
contrast_limit = st.slider("Contrast Enhancement", 1.0, 5.0, 2.0)
|
91 |
+
|
92 |
+
# Process image
|
93 |
+
img = cv2.imdecode(np.frombuffer(uploaded_file.read(), np.uint8), cv2.IMREAD_GRAYSCALE)
|
94 |
+
|
95 |
+
# Enhanced preprocessing
|
96 |
+
img = cv2.fastNlMeansDenoising(img, None, denoise_strength, 7, 21)
|
97 |
+
clahe = cv2.createCLAHE(clipLimit=contrast_limit, tileGridSize=(8, 8))
|
98 |
+
img = clahe.apply(img)
|
99 |
+
|
100 |
+
# Display enhanced image
|
101 |
+
st.image(img, caption="Enhanced X-ray", use_column_width=True)
|
102 |
+
|
103 |
+
# Encode image
|
104 |
+
_, img_encoded = cv2.imencode('.png', img)
|
105 |
+
base64_image = base64.b64encode(img_encoded).decode('utf-8')
|
106 |
+
|
107 |
+
with col2:
|
108 |
+
if uploaded_file and 'name' in st.session_state.patient_history and st.session_state.patient_history['name']:
|
109 |
+
st.header("Analysis & Results")
|
110 |
+
|
111 |
+
# Analysis options
|
112 |
+
analysis_type = st.multiselect("Select Analysis Focus Areas",
|
113 |
+
["Cavity Detection", "Bone Density", "Root Canal Assessment",
|
114 |
+
"Periodontal Status", "Wisdom Teeth", "Overall Assessment"])
|
115 |
+
|
116 |
+
if st.button("Generate Analysis"):
|
117 |
+
with st.spinner("Analyzing X-ray..."):
|
118 |
+
# Construct detailed prompt
|
119 |
+
prompt = f"""
|
120 |
+
Please analyze this dental X-ray image with the following context:
|
121 |
+
|
122 |
+
Patient Information:
|
123 |
+
- Name: {st.session_state.patient_history['name']}
|
124 |
+
- Age: {st.session_state.patient_history['age']}
|
125 |
+
- Gender: {st.session_state.patient_history['gender']}
|
126 |
+
- Medical History: {', '.join(st.session_state.patient_history['medical_history'])}
|
127 |
+
- Current Complaints: {st.session_state.patient_history['dental_complaints']}
|
128 |
+
- Previous Treatments: {st.session_state.patient_history['previous_treatments']}
|
129 |
+
- Smoking Status: {st.session_state.patient_history['smoking']}
|
130 |
+
|
131 |
+
Focus Areas: {', '.join(analysis_type)}
|
132 |
+
|
133 |
+
Please provide a detailed analysis including:
|
134 |
+
1. Identified abnormalities or concerns
|
135 |
+
2. Potential diagnosis considerations
|
136 |
+
3. Recommended additional examinations if needed
|
137 |
+
4. Treatment suggestions
|
138 |
+
5. Risk factors based on patient history
|
139 |
+
|
140 |
+
Format the response in a clear, structured manner.
|
141 |
+
"""
|
142 |
+
|
143 |
+
response = model.generate_content(prompt)
|
144 |
+
|
145 |
+
# Display results
|
146 |
+
st.markdown("### Analysis Results")
|
147 |
+
st.write(response.text)
|
148 |
+
|
149 |
+
# Generate report
|
150 |
+
st.markdown("### Report Generation")
|
151 |
+
if st.button("Generate PDF Report"):
|
152 |
+
st.info("Report generation functionality can be implemented here")
|
153 |
+
|
154 |
+
# Display disclaimer
|
155 |
+
st.markdown("""
|
156 |
+
<div class="disclaimer">
|
157 |
+
<h4>⚠️ Medical Disclaimer</h4>
|
158 |
+
<p>This analysis is generated by AI and is for informational purposes only.
|
159 |
+
It should not be considered as a definitive diagnosis. Please consult with a
|
160 |
+
qualified dental professional for accurate diagnosis and treatment planning.</p>
|
161 |
+
</div>
|
162 |
+
""", unsafe_allow_html=True)
|
163 |
+
else:
|
164 |
+
st.info("Please upload an X-ray image and complete patient information to proceed with analysis.")
|
165 |
+
|
166 |
+
# Footer
|
167 |
+
st.markdown("---")
|
168 |
+
st.markdown(
|
169 |
+
"""
|
170 |
+
<div style='text-align: center'>
|
171 |
+
<p>Advanced Dental X-Ray Analysis System v2.0</p>
|
172 |
+
<p>Developed by:</p>
|
173 |
+
<p>Supervised and reviewed by:</p>
|
174 |
+
<p>Participants:</p>
|
175 |
+
<p>UI Designer:</p>
|
176 |
+
</div>
|
177 |
+
""",
|
178 |
+
unsafe_allow_html=True
|
179 |
+
)
|