iBrokeTheCode commited on
Commit
3f0ccc8
Β·
1 Parent(s): 8a45f7a

feat: Add UI for prediction app

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.jpeg filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.jpeg filter=lfs diff=lfs merge=lfs -text
37
+ *.jpg filter=lfs diff=lfs merge=lfs -text
assets/animal.jpg ADDED

Git LFS Details

  • SHA256: 27951d9cbfc6157813ac387bded60059f9bb7ba6f5ca335d8002d3e7b0e055fb
  • Pointer size: 130 Bytes
  • Size of remote file: 26.1 kB
assets/building.jpg ADDED

Git LFS Details

  • SHA256: cea2e1ba2b1d93349394b34a7419beba6fb22ffe6d46e5ae293c9e6c7b1839ff
  • Pointer size: 130 Bytes
  • Size of remote file: 35.8 kB
assets/object.jpg ADDED

Git LFS Details

  • SHA256: 5e6463241982b6c39d528ebb4e91bc056e9567d021b7cd39a4fd0da1d914e114
  • Pointer size: 130 Bytes
  • Size of remote file: 19.5 kB
assets/vehicle.jpg ADDED

Git LFS Details

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