| | import streamlit as st |
| | from PIL import Image |
| |
|
| | from predictor import predict_image |
| |
|
| | |
| | st.set_page_config(page_title="Image Classifier App", page_icon="π€", layout="centered") |
| | st.html(""" |
| | <style> |
| | .stMainBlockContainer { |
| | max-width: 70rem; |
| | } |
| | </style> |
| | """) |
| |
|
| | |
| | |
| | if "selected_image" not in st.session_state: |
| | st.session_state["selected_image"] = None |
| | if "prediction_placeholder" not in st.session_state: |
| | st.session_state["prediction_placeholder"] = {"label": "A Dog", "score": 0.9558} |
| |
|
| | |
| | with st.container(): |
| | st.title( |
| | body="πΌοΈ Image Classifier with CNN", |
| | help="An interactive application to classify images into over 1000 categories.", |
| | ) |
| | st.html("<br>") |
| |
|
| | |
| | tab_app, tab_description = st.tabs(["**App**", "**Description**"]) |
| |
|
| | |
| | with tab_app: |
| | |
| | col_upload, col_results = st.columns(2, gap="large") |
| |
|
| | |
| | with col_upload: |
| | st.header("Upload an Image", divider=True) |
| |
|
| | |
| | uploaded_image = 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) |
| |
|
| | |
| | selected_example = st.segmented_control( |
| | label="Categories", |
| | options=["Animal", "Vehicle", "Object", "Building"], |
| | default="Animal", |
| | help="Select one of the pre-loaded examples", |
| | ) |
| |
|
| | st.html("<br>") |
| |
|
| | |
| | classify_button = st.button( |
| | label="Classify Image", |
| | key="classify_btn", |
| | type="primary", |
| | icon="β¨", |
| | ) |
| |
|
| | |
| | with col_results: |
| | st.header("Results", divider=True) |
| |
|
| | |
| | if st.session_state["selected_image"] is None and not classify_button: |
| | st.info("Choose an image to get a prediction.") |
| |
|
| | |
| | if classify_button: |
| | |
| | if uploaded_image is not None: |
| | |
| | |
| | st.session_state["selected_image"] = Image.open(uploaded_image) |
| | st.session_state["uploaded_file"] = uploaded_image |
| |
|
| | elif selected_example: |
| | |
| | try: |
| | img_path = f"./assets/{selected_example.lower()}.jpg" |
| | st.session_state["selected_image"] = Image.open(img_path) |
| | except FileNotFoundError: |
| | st.error( |
| | f"Error: The example image '{selected_example.lower()}.jpg' was not found." |
| | ) |
| | st.stop() |
| |
|
| | if st.session_state["selected_image"] is not None: |
| | st.image( |
| | st.session_state["selected_image"], |
| | caption="Image to be classified", |
| | ) |
| |
|
| | |
| | with st.spinner("Analyzing image..."): |
| | |
| | try: |
| | predicted_label, predicted_score = predict_image( |
| | st.session_state["selected_image"] |
| | ) |
| |
|
| | st.metric( |
| | label="Prediction", |
| | value=f"{predicted_label.replace('_', ' ').title()}", |
| | delta=f"{predicted_score * 100:.2f}%", |
| | help="The predicted category and its confidence score.", |
| | delta_color="normal", |
| | ) |
| | st.balloons() |
| | except Exception as e: |
| | st.error(f"An error occurred during prediction: {e}") |
| | else: |
| | st.error("Please upload an image or select an example to classify.") |
| |
|
| |
|
| | |
| | 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. |
| | """ |
| | ) |
| |
|