Spaces:
Sleeping
Sleeping
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -45,40 +45,18 @@ st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Uplo
|
|
| 45 |
|
| 46 |
@st.cache_resource
|
| 47 |
def load_model():
|
| 48 |
-
"""Load the
|
| 49 |
try:
|
| 50 |
-
model_path = 'Fast_VGG19_3epoch.
|
|
|
|
| 51 |
if os.path.exists(model_path):
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
# Recompile the model
|
| 56 |
-
model.compile(
|
| 57 |
-
optimizer='adam',
|
| 58 |
-
loss='binary_crossentropy',
|
| 59 |
-
metrics=['accuracy']
|
| 60 |
-
)
|
| 61 |
-
st.success("β
Model loaded successfully!")
|
| 62 |
-
return model
|
| 63 |
-
except Exception as e1:
|
| 64 |
-
st.warning(f"First load attempt failed: {str(e1)}")
|
| 65 |
-
# Try alternative loading method
|
| 66 |
-
try:
|
| 67 |
-
import h5py
|
| 68 |
-
model = tf.keras.models.load_model(model_path, custom_objects=None, compile=False)
|
| 69 |
-
model.compile(
|
| 70 |
-
optimizer='adam',
|
| 71 |
-
loss='binary_crossentropy',
|
| 72 |
-
metrics=['accuracy']
|
| 73 |
-
)
|
| 74 |
-
st.success("β
Model loaded with alternative method!")
|
| 75 |
-
return model
|
| 76 |
-
except Exception as e2:
|
| 77 |
-
st.error(f"Alternative load failed: {str(e2)}")
|
| 78 |
-
return None
|
| 79 |
else:
|
| 80 |
st.error(f"Model file not found: {model_path}")
|
| 81 |
return None
|
|
|
|
| 82 |
except Exception as e:
|
| 83 |
st.error(f"Error loading model: {str(e)}")
|
| 84 |
return None
|
|
@@ -86,19 +64,14 @@ def load_model():
|
|
| 86 |
def preprocess_image(image):
|
| 87 |
"""Preprocess image for model prediction"""
|
| 88 |
try:
|
| 89 |
-
# Convert to RGB array
|
| 90 |
img = np.array(image.convert('RGB'))
|
| 91 |
-
|
| 92 |
-
# Resize to model input size
|
| 93 |
img = tf.image.resize(img, [64, 64])
|
| 94 |
img = tf.cast(img, tf.float32) / 255.0
|
| 95 |
|
| 96 |
-
# Apply ImageNet normalization
|
| 97 |
mean = [0.485, 0.456, 0.406]
|
| 98 |
std = [0.229, 0.224, 0.225]
|
| 99 |
img = (img - mean) / std
|
| 100 |
|
| 101 |
-
# Add batch dimension
|
| 102 |
return tf.expand_dims(img, 0)
|
| 103 |
|
| 104 |
except Exception as e:
|
|
@@ -112,9 +85,8 @@ with st.sidebar:
|
|
| 112 |
**Architecture:** VGG19 Transfer Learning
|
| 113 |
**Accuracy:** 77.0%
|
| 114 |
**AUC Score:** 0.850
|
| 115 |
-
**
|
| 116 |
-
**
|
| 117 |
-
**Training Data:** RSNA Dataset
|
| 118 |
""")
|
| 119 |
|
| 120 |
st.header("π How to Use")
|
|
@@ -124,19 +96,11 @@ with st.sidebar:
|
|
| 124 |
3. **Click Analyze:** Get AI prediction
|
| 125 |
4. **Review Results:** Check confidence levels
|
| 126 |
""")
|
| 127 |
-
|
| 128 |
-
st.header("π§ Docker Info")
|
| 129 |
-
st.success("""
|
| 130 |
-
β
Running in Docker container
|
| 131 |
-
β
TensorFlow 2.15.0
|
| 132 |
-
β
Compatibility fixed
|
| 133 |
-
""")
|
| 134 |
|
| 135 |
# Load model
|
| 136 |
model = load_model()
|
| 137 |
|
| 138 |
if model is not None:
|
| 139 |
-
# File uploader
|
| 140 |
uploaded_file = st.file_uploader(
|
| 141 |
"Choose a chest X-ray image",
|
| 142 |
type=['jpg', 'jpeg', 'png'],
|
|
@@ -144,7 +108,6 @@ if model is not None:
|
|
| 144 |
)
|
| 145 |
|
| 146 |
if uploaded_file is not None:
|
| 147 |
-
# Create two columns for layout
|
| 148 |
col1, col2 = st.columns([1, 1])
|
| 149 |
|
| 150 |
with col1:
|
|
@@ -152,27 +115,21 @@ if model is not None:
|
|
| 152 |
image = Image.open(uploaded_file)
|
| 153 |
st.image(image, caption="Chest X-ray Image", use_column_width=True)
|
| 154 |
|
| 155 |
-
# Image info
|
| 156 |
st.write(f"**Filename:** {uploaded_file.name}")
|
| 157 |
st.write(f"**Size:** {image.size}")
|
| 158 |
-
st.write(f"**Format:** {image.format}")
|
| 159 |
|
| 160 |
with col2:
|
| 161 |
st.subheader("π€ AI Analysis")
|
| 162 |
|
| 163 |
if st.button("π Analyze X-ray", type="primary", use_container_width=True):
|
| 164 |
with st.spinner("π§ AI is analyzing the X-ray..."):
|
| 165 |
-
# Preprocess image
|
| 166 |
processed_img = preprocess_image(image)
|
| 167 |
|
| 168 |
if processed_img is not None:
|
| 169 |
try:
|
| 170 |
-
# Make prediction
|
| 171 |
prediction = model.predict(processed_img, verbose=0)[0][0]
|
| 172 |
|
| 173 |
-
# Determine result
|
| 174 |
if prediction > 0.5:
|
| 175 |
-
# Pneumonia detected
|
| 176 |
confidence = prediction * 100
|
| 177 |
pneumonia_html = f"""
|
| 178 |
<div class="result-box pneumonia-result">
|
|
@@ -182,7 +139,6 @@ if model is not None:
|
|
| 182 |
"""
|
| 183 |
st.markdown(pneumonia_html, unsafe_allow_html=True)
|
| 184 |
|
| 185 |
-
# Risk level
|
| 186 |
if confidence >= 80:
|
| 187 |
st.error("π¨ **HIGH CONFIDENCE** - Immediate medical attention recommended")
|
| 188 |
elif confidence >= 60:
|
|
@@ -191,7 +147,6 @@ if model is not None:
|
|
| 191 |
st.info("βΉοΈ **LOW CONFIDENCE** - Consider additional testing")
|
| 192 |
|
| 193 |
else:
|
| 194 |
-
# Normal result
|
| 195 |
confidence = (1 - prediction) * 100
|
| 196 |
normal_html = f"""
|
| 197 |
<div class="result-box normal-result">
|
|
@@ -214,12 +169,10 @@ if model is not None:
|
|
| 214 |
normal_prob = (1 - prediction) * 100
|
| 215 |
pneumonia_prob = prediction * 100
|
| 216 |
|
| 217 |
-
# Progress bars
|
| 218 |
st.write("**Probability Breakdown:**")
|
| 219 |
st.progress(normal_prob/100, text=f"Normal: {normal_prob:.1f}%")
|
| 220 |
st.progress(pneumonia_prob/100, text=f"Pneumonia: {pneumonia_prob:.1f}%")
|
| 221 |
|
| 222 |
-
# Numerical display
|
| 223 |
col_a, col_b = st.columns(2)
|
| 224 |
with col_a:
|
| 225 |
st.metric("Normal", f"{normal_prob:.1f}%")
|
|
@@ -236,7 +189,6 @@ if model is not None:
|
|
| 236 |
|
| 237 |
else:
|
| 238 |
st.error("β Failed to load the AI model. Please check the deployment.")
|
| 239 |
-
st.info("π‘ Try refreshing the page or contact support if the issue persists.")
|
| 240 |
|
| 241 |
# Footer
|
| 242 |
footer_html = """
|
|
@@ -249,7 +201,7 @@ footer_html = """
|
|
| 249 |
<hr style="margin: 1rem 0;">
|
| 250 |
|
| 251 |
<p><em>π³ Powered by Docker β’ TensorFlow 2.15.0 β’ Streamlit</em></p>
|
| 252 |
-
<p><em>π€ VGG19 Transfer Learning Model</em></p>
|
| 253 |
</div>
|
| 254 |
"""
|
| 255 |
|
|
|
|
| 45 |
|
| 46 |
@st.cache_resource
|
| 47 |
def load_model():
|
| 48 |
+
"""Load the Keras model - much more reliable!"""
|
| 49 |
try:
|
| 50 |
+
model_path = 'Fast_VGG19_3epoch.keras' # Changed to .keras format!
|
| 51 |
+
|
| 52 |
if os.path.exists(model_path):
|
| 53 |
+
model = tf.keras.models.load_model(model_path)
|
| 54 |
+
st.success("β
Keras model loaded successfully!")
|
| 55 |
+
return model
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
else:
|
| 57 |
st.error(f"Model file not found: {model_path}")
|
| 58 |
return None
|
| 59 |
+
|
| 60 |
except Exception as e:
|
| 61 |
st.error(f"Error loading model: {str(e)}")
|
| 62 |
return None
|
|
|
|
| 64 |
def preprocess_image(image):
|
| 65 |
"""Preprocess image for model prediction"""
|
| 66 |
try:
|
|
|
|
| 67 |
img = np.array(image.convert('RGB'))
|
|
|
|
|
|
|
| 68 |
img = tf.image.resize(img, [64, 64])
|
| 69 |
img = tf.cast(img, tf.float32) / 255.0
|
| 70 |
|
|
|
|
| 71 |
mean = [0.485, 0.456, 0.406]
|
| 72 |
std = [0.229, 0.224, 0.225]
|
| 73 |
img = (img - mean) / std
|
| 74 |
|
|
|
|
| 75 |
return tf.expand_dims(img, 0)
|
| 76 |
|
| 77 |
except Exception as e:
|
|
|
|
| 85 |
**Architecture:** VGG19 Transfer Learning
|
| 86 |
**Accuracy:** 77.0%
|
| 87 |
**AUC Score:** 0.850
|
| 88 |
+
**Format:** Keras (.keras) β
|
| 89 |
+
**TensorFlow:** 2.15.0
|
|
|
|
| 90 |
""")
|
| 91 |
|
| 92 |
st.header("π How to Use")
|
|
|
|
| 96 |
3. **Click Analyze:** Get AI prediction
|
| 97 |
4. **Review Results:** Check confidence levels
|
| 98 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
# Load model
|
| 101 |
model = load_model()
|
| 102 |
|
| 103 |
if model is not None:
|
|
|
|
| 104 |
uploaded_file = st.file_uploader(
|
| 105 |
"Choose a chest X-ray image",
|
| 106 |
type=['jpg', 'jpeg', 'png'],
|
|
|
|
| 108 |
)
|
| 109 |
|
| 110 |
if uploaded_file is not None:
|
|
|
|
| 111 |
col1, col2 = st.columns([1, 1])
|
| 112 |
|
| 113 |
with col1:
|
|
|
|
| 115 |
image = Image.open(uploaded_file)
|
| 116 |
st.image(image, caption="Chest X-ray Image", use_column_width=True)
|
| 117 |
|
|
|
|
| 118 |
st.write(f"**Filename:** {uploaded_file.name}")
|
| 119 |
st.write(f"**Size:** {image.size}")
|
|
|
|
| 120 |
|
| 121 |
with col2:
|
| 122 |
st.subheader("π€ AI Analysis")
|
| 123 |
|
| 124 |
if st.button("π Analyze X-ray", type="primary", use_container_width=True):
|
| 125 |
with st.spinner("π§ AI is analyzing the X-ray..."):
|
|
|
|
| 126 |
processed_img = preprocess_image(image)
|
| 127 |
|
| 128 |
if processed_img is not None:
|
| 129 |
try:
|
|
|
|
| 130 |
prediction = model.predict(processed_img, verbose=0)[0][0]
|
| 131 |
|
|
|
|
| 132 |
if prediction > 0.5:
|
|
|
|
| 133 |
confidence = prediction * 100
|
| 134 |
pneumonia_html = f"""
|
| 135 |
<div class="result-box pneumonia-result">
|
|
|
|
| 139 |
"""
|
| 140 |
st.markdown(pneumonia_html, unsafe_allow_html=True)
|
| 141 |
|
|
|
|
| 142 |
if confidence >= 80:
|
| 143 |
st.error("π¨ **HIGH CONFIDENCE** - Immediate medical attention recommended")
|
| 144 |
elif confidence >= 60:
|
|
|
|
| 147 |
st.info("βΉοΈ **LOW CONFIDENCE** - Consider additional testing")
|
| 148 |
|
| 149 |
else:
|
|
|
|
| 150 |
confidence = (1 - prediction) * 100
|
| 151 |
normal_html = f"""
|
| 152 |
<div class="result-box normal-result">
|
|
|
|
| 169 |
normal_prob = (1 - prediction) * 100
|
| 170 |
pneumonia_prob = prediction * 100
|
| 171 |
|
|
|
|
| 172 |
st.write("**Probability Breakdown:**")
|
| 173 |
st.progress(normal_prob/100, text=f"Normal: {normal_prob:.1f}%")
|
| 174 |
st.progress(pneumonia_prob/100, text=f"Pneumonia: {pneumonia_prob:.1f}%")
|
| 175 |
|
|
|
|
| 176 |
col_a, col_b = st.columns(2)
|
| 177 |
with col_a:
|
| 178 |
st.metric("Normal", f"{normal_prob:.1f}%")
|
|
|
|
| 189 |
|
| 190 |
else:
|
| 191 |
st.error("β Failed to load the AI model. Please check the deployment.")
|
|
|
|
| 192 |
|
| 193 |
# Footer
|
| 194 |
footer_html = """
|
|
|
|
| 201 |
<hr style="margin: 1rem 0;">
|
| 202 |
|
| 203 |
<p><em>π³ Powered by Docker β’ TensorFlow 2.15.0 β’ Streamlit</em></p>
|
| 204 |
+
<p><em>π€ VGG19 Transfer Learning Model (.keras format)</em></p>
|
| 205 |
</div>
|
| 206 |
"""
|
| 207 |
|