| import streamlit as st |
| from PIL import 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"] = 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", |
| ) |
| st.markdown("---") |
| st.subheader("Prediction") |
|
|
| |
| with st.spinner("Analyzing image..."): |
| |
| try: |
| predicted_label, predicted_score = predict_image( |
| st.session_state["selected_image"] |
| ) |
|
|
| st.metric( |
| label="Prediction", |
| value=f"Prediction: {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. |
| """ |
| ) |
|
|