File size: 6,247 Bytes
aee8033 29f6ccc 3f0ccc8 29f6ccc af98bbd aee8033 3f0ccc8 aee8033 3f0ccc8 aee8033 3f0ccc8 a2c2878 3f0ccc8 a2c2878 3f0ccc8 a2c2878 aee8033 3f0ccc8 a2c2878 3f0ccc8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
import os
import streamlit as st
from PIL import Image
from predictor import predict_image
APP_DIR = os.path.dirname(os.path.abspath(__file__))
ASSETS_DIR = os.path.join(APP_DIR, "assets")
# π PAGE SETUP
st.set_page_config(page_title="Image Classifier App", page_icon="π€", layout="centered")
st.html("""
<style>
.stMainBlockContainer {
max-width: 70rem;
}
</style>
""")
# π INITIALIZE SESSION STATE
if "uploaded_image" not in st.session_state:
st.session_state["uploaded_image"] = None
if "example_selected" not in st.session_state:
st.session_state["example_selected"] = False
if "prediction_result" not in st.session_state:
st.session_state["prediction_result"] = None
# π MAIN APP LAYOUT
with st.container():
st.title(
body="πΌοΈ Image Classifier with CNN",
help="An interactive application to classify images into over 1000 categories.",
)
st.html("<br>")
# Use tabs for different sections of the app
tab_app, tab_description = st.tabs(["**App**", "**Description**"])
# π APP TAB
with tab_app:
# Create a two-column layout for the app interface
col_upload, col_results = st.columns(2, gap="large")
# π IMAGE UPLOAD & EXAMPLE SELECTION
with col_upload:
st.header("Upload an Image", divider=True)
# File uploader widget
uploaded_file = st.file_uploader(
label="Drag and drop an image here or click to browse",
type=["jpg", "jpeg", "png"],
help="Maximum file size is 200MB",
key="image_uploader",
)
st.html("<br>")
st.subheader("Or Try an Example", divider=True)
# Segmented control for selecting example images
selected_example = st.segmented_control(
label="Categories",
options=["Animal", "Vehicle", "Object", "Building"],
default=None,
help="Select one of the pre-loaded examples",
)
st.html("<br>")
# --- THE SINGLE CLASSIFY BUTTON ---
classify_button = st.button(
label="Classify Image",
key="classify_btn",
type="primary",
icon="β¨",
)
# --- LOGIC FOR IMAGE SELECTION & PREDICTION ---
# Clear the previous prediction result if a new input is selected
if uploaded_file or selected_example:
st.session_state.prediction_result = None
image_to_process = None
if uploaded_file:
image_to_process = Image.open(uploaded_file)
elif selected_example:
try:
img_path = os.path.join(
APP_DIR, "assets", f"{selected_example.lower()}.jpg"
)
image_to_process = Image.open(img_path)
except FileNotFoundError:
st.error(
f"Error: The example image '{selected_example.lower()}.jpg' was not found."
)
st.stop()
# π PREDICTION RESULTS
with col_results:
st.header("Results", divider=True)
# Display a "get started" message if no image is selected
if not image_to_process and not st.session_state.prediction_result:
st.info("Choose an image or an example to get a prediction.")
# Display the image if one is selected
if image_to_process:
st.image(image_to_process, caption="Image to be classified")
# If the button is clicked, run the prediction logic
if classify_button and image_to_process:
with st.spinner("Analyzing image..."):
try:
from predictor import predict_image
predicted_label, predicted_score = predict_image(
image_to_process
)
st.session_state.prediction_result = {
"label": predicted_label.replace("_", " ").title(),
"score": predicted_score,
}
except Exception as e:
st.error(f"An error occurred during prediction: {e}")
# Display the prediction result if available in session state
if st.session_state.prediction_result:
st.metric(
label="Prediction",
value=st.session_state.prediction_result["label"],
delta=f"{st.session_state.prediction_result['score'] * 100:.2f}%",
help="The predicted category and its confidence score.",
delta_color="normal",
)
st.balloons()
elif image_to_process:
st.info("Click 'Classify Image' to see the prediction.")
# π DESCRIPTION TAB
with tab_description:
st.header("About This Project", divider=True)
st.markdown(
"""
This project showcases a Convolutional Neural Network (CNN) model that automatically
classifies images into over 1000 different categories.
### Original Architecture
The original project was built as a multi-service architecture, featuring:
* **Streamlit:** For the web user interface.
* **FastAPI:** As a RESTful API to handle image processing and model serving.
* **Redis:** A message broker for communication between the services.
### Portfolio Adaptation
For a live and cost-effective demo, this application has been adapted into a single-service
solution. The core logic of the FastAPI backend has been integrated directly into
the Streamlit app. This demonstrates the ability to adapt a solution for
specific deployment and resource constraints.
### Technologies Used
* **Streamlit:** For the interactive web interface.
* **TensorFlow:** For loading and running the pre-trained CNN model.
* **Pre-trained Model:** ResNet50 with weights trained on the ImageNet dataset.
"""
)
|