danielle2003's picture
Update app.py
78eb10c verified
import cv2
import streamlit as st
st.set_page_config(layout="wide")
import streamlit.components.v1 as components
import time
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from PIL import Image
from tf_keras_vis.gradcam import Gradcam
from io import BytesIO
if "model" not in st.session_state:
st.session_state.model = tf_model = tf.keras.models.load_model('best_model.h5')
import base64
import os
#****************************************/
# GRAD CAM
#*********************************************#
gradcam = Gradcam(st.session_state.model, model_modifier=None, clone=False)
def generate_gradcam(pil_image, target_class):
# Convert PIL to array and preprocess
img_array = np.array(pil_image)
img_preprocessed = tf.keras.applications.vgg16.preprocess_input(img_array.copy())
img_tensor = tf.expand_dims(img_preprocessed, axis=0)
# Generate heatmap
loss = lambda output: tf.reduce_mean(output[:, target_class])
cam = gradcam(loss, img_tensor, penultimate_layer=-1)
# Process heatmap
cam = cam
if cam.ndim > 2:
cam = cam.squeeze()
cam = np.maximum(cam, 0)
cam = cv2.resize(cam, (224, 224))
cam = cam / cam.max() if cam.max() > 0 else cam
return cam
def convert_image_to_base64(pil_image):
buffered = BytesIO()
pil_image.save(buffered, format="PNG")
return base64.b64encode(buffered.getvalue()).decode()
#--------------------------------------------------#
class_labels=[ 'Cyst', 'Normal','Stone', 'Tumor']
def load_tensorflow_model():
tf_model = tf.keras.models.load_model('best_model.h5')
return tf_model
def predict_image(image):
time.sleep(2)
image = image.resize((224, 224))
image = np.expand_dims(image, axis=0)
predictions = st.session_state.model.predict(image)
return predictions
logo_path = "tensorflow.png"
main_bg_ext = 'png'
main_bg = 'bg1.jpg'
# Read and encode the logo image
with open(logo_path, "rb") as image_file:
encoded_logo = base64.b64encode(image_file.read()).decode()
# Custom CSS to style the logo above the sidebar
st.markdown(
f"""
<style>
/* Container for logo and text */
.logo-text-container {{
position: fixed;
top: 20px; /* Adjust vertical position */
left: 30px; /* Align with sidebar */
display: flex;
align-items: center;
gap: 5px;
width: 70%;
z-index:1000;
}}
/* Logo styling */
.logo-text-container img {{
width: 50px; /* Adjust logo size */
border-radius: 10px; /* Optional: round edges */
margin-top:-10px;
margin-left:-5px;
}}
/* Bold text styling */
.logo-text-container h1 {{
font-family: Nunito;
color: #0175C2;
font-size: 28px;
font-weight: bold;
margin-right :100px;
padding:0px;
}}
.logo-text-container i{{
font-family: Nunito;
color: orange;
font-size: 15px;
margin-right :10px;
padding:0px;
margin-left:-18.5%;
margin-top:1%;
}}
/* Sidebar styling */
section[data-testid="stSidebar"][aria-expanded="true"] {{
margin-top: 100px !important; /* Space for the logo */
border-radius: 0 60px 0px 60px !important; /* Top-left and bottom-right corners */
width: 200px !important; /* Sidebar width */
background:none; /* Gradient background */
/* box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); /* Shadow effect */
/* border: 1px solid #FFD700; /* Shiny golden border */
margin-bottom: 1px !important;
color:white !important;
}}
header[data-testid="stHeader"] {{
/*background: transparent !important;*/
background: white;
/*margin-right: 10px !important;*/
margin-top: 0.5px !important;
z-index: 1 !important;
color: orange; /* White text */
font-family: "Times New Roman " !important; /* Font */
font-size: 18px !important; /* Font size */
font-weight: bold !important; /* Bold text */
padding: 10px 20px; /* Padding for buttons */
border: none; /* Remove border */
border-radius: 1px; /* Rounded corners */
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2); /* Shadow effect */
transition: all 0.3s ease-in-out; /* Smooth transition */
align-items: left;
justify-content: center;
/*margin: 10px 0;*/
width:100%;
height:80px;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.4); /* Light border */
}}
div[data-testid="stDecoration"]{{
background-image:none;
}}
div[data-testid="stApp"]{{
/*background: grey;*/
background: rgba(255, 255, 255, 0.5); /* Semi-transparent white background */
height: 100vh; /* Full viewport height */
width: 99.5%;
border-radius: 2px !important;
margin-left:5px;
margin-right:5px;
margin-top:0px;
/* box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2); /* Shadow effect */
background: url(data:image/{main_bg_ext};base64,{base64.b64encode(open(main_bg, "rb").read()).decode()});
background-size: cover; /* Ensure the image covers the full page */
background-position: center;
overflow: hidden;
}}
.content-container {{
background-color: rgba(173, 216, 230, 0.5); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ border-radius: 1px;
width: 28%;
margin-left: 150px;
/* margin-top: -60px;*/
margin-bottom: 10px;
margin-right:10px;
padding:0;
/* border-radius:0px 0px 15px 15px ;*/
border:1px solid transparent;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 10%; /* Adjust top offset */
left: 60%; /* Adjust left offset */
height: 89.5vh; /* Full viewport height */
}}
.content-container2 {{
background-color: rgba(0, 0, 0, 0.1); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ border-radius: 1px;
width: 90%;
margin-left: 10px;
/* margin-top: -10px;*/
margin-bottom: 160px;
margin-right:10px;
padding:0;
border-radius:1px ;
border:1px solid transparent;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 3%; /* Adjust top offset */
left: 2.5%; /* Adjust left offset */
height: 78vh; /* Full viewport height */
}}
.content-container4 {{
background-color: rgba(0, 0, 0, 0.1); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ width: 40%;
margin-left: 10px;
margin-bottom: 160px;
margin-right:10px;
padding:0;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 60%; /* Adjust top offset */
left: 2.5%; /* Adjust left offset */
height: 10vh; /* Full viewport height */
}}
.content-container4 h3 ,p {{
font-family: "Times New Roman" !important; /* Elegant font for title */
font-size: 1rem;
font-weight: bold;
text-align:center;
}}
.content-container5 h3 ,p {{
font-family: "Times New Roman" !important; /* Elegant font for title */
font-size: 1rem;
font-weight: bold;
text-align:center;
}}
.content-container6 h3 ,p {{
font-family: "Times New Roman" !important; /* Elegant font for title */
font-size: 1rem;
font-weight: bold;
text-align:center;
}}
.content-container7 h3 ,p {{
font-family: "Times New Roman" !important; /* Elegant font for title */
font-size: 1rem;
font-weight: bold;
text-align:center;
}}
.content-container5 {{
background-color: rgba(0, 0, 0, 0.1); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ width: 40%;
margin-left: 180px;
margin-bottom: 130px;
margin-right:10px;
padding:0;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 60%; /* Adjust top offset */
left: 5.5%; /* Adjust left offset */
height: 10vh; /* Full viewport height */
}}
.content-container3 {{
background-color: rgba(216, 216, 230, 0.5); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ border-radius: 1px;
width: 92%;
margin-left: 10px;
/* margin-top: -10px;*/
margin-bottom: 160px;
margin-right:10px;
padding:0;
border: 10px solid white;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 3%; /* Adjust top offset */
left: 1.5%; /* Adjust left offset */
height: 40vh; /* Full viewport height */
}}
.content-container6 {{
background-color: rgba(0, 0, 0, 0.1); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ width: 40%;
margin-left: 10px;
margin-bottom: 160px;
margin-right:10px;
padding:0;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 80%; /* Adjust top offset */
left: 2.5%; /* Adjust left offset */
height: 10vh; /* Full viewport height */
}}
.content-container7 {{
background-color: rgba(0, 0, 0, 0.1); /* Light blue with 50% transparency */
backdrop-filter: blur(10px); /* Adds a slight blur effect */ width: 40%;
margin-left: 180px;
margin-bottom: 130px;
margin-right:10px;
padding:0;
overflow-y: auto; /* Enable vertical scrolling for the content */
position: fixed; /* Fix the position of the container */
top: 80%; /* Adjust top offset */
left: 5.5%; /* Adjust left offset */
height: 10vh; /* Full viewport height */
}}
.content-container2 img {{
width:99%;
height:50%;
}}
.content-container3 img {{
width:100%;
height:100%;
}}
div.stButton > button {{
background: rgba(255, 255, 255, 0.2);
color: blue; /* White text */
font-family: "Times New Roman " !important; /* Font */
font-size: 18px !important; /* Font size */
font-weight: bold !important; /* Bold text */
padding: 10px 20px; /* Padding for buttons */
border: none; /* Remove border */
border-radius: 15px; /* Rounded corners */
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2); /* Shadow effect */
transition: all 0.3s ease-in-out; /* Smooth transition */
display: flex;
align-items: center;
justify-content: center;
margin: 10px 0;
width:170px;
height:60px;
backdrop-filter: blur(10px);
}}
/* Hover effect */
div.stButton > button:hover {{
background: rgba(255, 255, 255, 0.2);
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.4); /* Enhanced shadow on hover */
transform: scale(1.05); /* Slightly enlarge button */
transform: scale(1.1); /* Slight zoom on hover */
box-shadow: 0px 4px 12px rgba(255, 255, 255, 0.4); /* Glow effect */
}}
.titles{{
margin-top:50px !important;
}}
/* Title styling */
.titles h1{{
/*font-family: "Times New Roman" !important; /* Elegant font for title */
/* font-size: 2.9rem;*/
/*font-weight: bold;*/
margin-left: 5px;
/* margin-top:-50px;*/
margin-bottom:50px;
padding: 0;
color: black; /* Neutral color for text */
}}
.titles > div{{
font-family: "Times New Roman" !important; /* Elegant font for title */
font-size: 1.2rem;
margin-left: 5px;
margin-bottom:1px;
padding: 0;
color:black; /* Neutral color for text */
}}
/* Recently viewed section */
.recently-viewed {{
display: flex;
align-items: center;
justify-content: flex-start; /* Align items to the extreme left */
margin-bottom: 10px;
margin-top: 20px;
gap: 10px; /* Add spacing between the elements */
padding-left: 20px; /* Add some padding if needed */
margin-left:35px;
height:100px;
}}
/* Style for the upload button */
[class*="st-key-upload-btn"] {{
position: absolute;
top: 100%; /* Position from the top of the inner circle */
left: -3%; /* Position horizontally at the center */
padding: 10px 20px;
color: red;
border: none;
border-radius: 20px;
cursor: pointer;
font-size: 35px !important;
width:30px;
height:20px;
}}
.upload-btn:hover {{
background-color: rgba(0, 123, 255, 1);
}}
div[data-testid="stFileUploader"] label > div > p {{
display:none;
color:white !important;
}}
section[data-testid="stFileUploaderDropzone"] {{
width:200px;
height: 60px;
background-color: white;
border-radius: 40px;
display: flex;
justify-content: center;
align-items: center;
margin-top:-10px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.3);
margin:20px;
background-color: rgba(255, 255, 255, 0.7); /* Transparent blue background */
color:white;
}}
div[data-testid="stFileUploaderDropzoneInstructions"] div > small{{
color:white !important;
display:none;
}}
div[data-testid="stFileUploaderDropzoneInstructions"] span{{
margin-left:65px;
color:orange;
}}
div[data-testid="stFileUploaderDropzoneInstructions"] div{{
display:none;
}}
section[data-testid="stFileUploaderDropzone"] button{{
display:none;
}}
div[data-testid="stMarkdownContainer"] p {{
font-family: "Times New Roman" !important; /* Elegant font for title */
color:white !important;
}}
.highlight {{
border: 4px solid lime;
font-weight: bold;
background: radial-gradient(circle, rgba(0,255,0,0.3) 0%, rgba(0,0,0,0) 70%);
box-shadow: 0px 0px 30px 10px rgba(0, 255, 0, 0.9),
0px 0px 60px 20px rgba(0, 255, 0, 0.6),
inset 0px 0px 15px rgba(0, 255, 0, 0.8);
transition: all 0.3s ease-in-out;
}}
.highlight:hover {{
transform: scale(1.05);
background: radial-gradient(circle, rgba(0,255,0,0.6) 0%, rgba(0,0,0,0) 80%);
box-shadow: 0px 0px 40px 15px rgba(0, 255, 0, 1),
0px 0px 70px 30px rgba(0, 255, 0, 0.7),
inset 0px 0px 20px rgba(0, 255, 0, 1);
}}
</style>
<div class="logo-text-container">
<img src="data:image/png;base64,{encoded_logo}" alt="Logo">
<h1>KidneyScan AI<br>
</h1>
<i>Empowering Early Diagnosis with AI</ai>
</div>
""", unsafe_allow_html=True
)
loading_html = """
<style>
.loader {
border: 8px solid #f3f3f3;
border-top: 8px solid #0175C2; /* Blue color */
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
<div class="loader"></div>
"""
page = "Home"
# Display content based on the selected page
# Define the page content dynamically
if page == "Home":
#components.html(html_string) # JavaScript works
#st.markdown(html_string, unsafe_allow_html=True)
image_path = "image.jpg"
st.container()
st.markdown(f"""
<div class="titles">
<h1>Kidney Disease Classfication</br> Using Transfer learning</h1>
<div> This web application utilizes deep learning to classify kidney ultrasound images</br>
into four categories: Normal, Cyst, Tumor, and Stone Class.
Built with Streamlit and powered by </br>a TensorFlow transfer learning
model based on <strong>VGG16</strong>
the app provides a simple and efficient way for users </br>
to upload kidney scans and receive instant predictions. The model analyzes the image
and classifies it based </br>on learned patterns, offering a confidence score for better interpretation.
</div>
</div>
""",
unsafe_allow_html=True,
)
uploaded_file = st.file_uploader("Choose a file", type=["png", "jpg", "jpeg"],key="upload-btn")
if uploaded_file is not None:
images = Image.open(uploaded_file)
# Rewind file pointer to the beginning
uploaded_file.seek(0)
file_content = uploaded_file.read() # Read file once
# Convert to base64 for HTML display
encoded_image = base64.b64encode(file_content).decode()
# Read and process image
pil_image = Image.open(uploaded_file).convert('RGB').resize((224, 224))
img_array = np.array(pil_image)
prediction = predict_image(images)
max_index = int(np.argmax(prediction[0]))
print(f"max index:{max_index}")
max_score = prediction[0][max_index]
predicted_class = np.argmax(prediction[0])
highlight_class = "highlight" # Special class for the highest confidence score
# Generate Grad-CAM
cam = generate_gradcam(pil_image, predicted_class)
# Create overlay
heatmap = cm.jet(cam)[..., :3]
heatmap = (heatmap * 255).astype(np.uint8)
overlayed_image = cv2.addWeighted(img_array, 0.6, heatmap, 0.4, 0)
# Convert to PIL
overlayed_pil = Image.fromarray(overlayed_image)
# Convert to base64
orig_b64 = convert_image_to_base64(pil_image)
overlay_b64 = convert_image_to_base64(overlayed_pil)
content = f"""
<div class="content-container">
<!-- Title -->
<!-- Recently Viewed Section -->
<div class="content-container2">
<div class="content-container3">
<img src="data:image/png;base64,{orig_b64}" alt="Uploaded Image">
</div>
<div class="content-container3">
<img src="data:image/png;base64,{overlay_b64}" class="result-image">
</div>
<div class="content-container4 {'highlight' if max_index == 0 else ''}">
<h3>{class_labels[0]}</h3>
<p>T Score: {prediction[0][0]:.2f}</p>
</div>
<div class="content-container5 {'highlight' if max_index == 1 else ''}">
<h3> {class_labels[1]}</h3>
<p>T Score: {prediction[0][1]:.2f}</p>
</div>
<div class="content-container6 {'highlight' if max_index == 2 else ''}">
<h3> {class_labels[2]}</h3>
<p>T Score: {prediction[0][2]:.2f}</p>
</div>
<div class="content-container7 {'highlight' if max_index == 3 else ''}">
<h3>{class_labels[3]}</h3>
<p>T Score: {prediction[0][3]:.2f}</p>
</div>
"""
# Close the gallery and content div
# Render the content
placeholder = st.empty() # Create a placeholder
placeholder.markdown(loading_html,unsafe_allow_html=True)
time.sleep(5) # Wait for 5 seconds
placeholder.empty()
st.markdown(content, unsafe_allow_html=True)
else:
default_image_path = "image.jpg"
with open(image_path, "rb") as image_file:
encoded_image = base64.b64encode(image_file.read()).decode()
st.markdown(f"""
<div class="content-container">
<!-- Title -->
<!-- Recently Viewed Section -->
<div class="content-container2">
<div class="content-container3">
<img src="data:image/png;base64,{encoded_image}" alt="Default Image">
</div>
</div>
""",
unsafe_allow_html=True,
)