chiichann commited on
Commit
665a66c
Β·
verified Β·
1 Parent(s): 65a1a68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -57
app.py CHANGED
@@ -1,77 +1,80 @@
1
- import streamlit as st
2
  import tensorflow as tf
3
  import numpy as np
4
  import os
5
  import pandas as pd
6
  import altair as alt
7
  from PIL import Image
 
8
  import zipfile
9
  import io
10
  import shutil
11
 
12
- # 🎨 App Styling
13
- st.set_page_config(page_title="Cat vs Dog Classifier", page_icon="🐢🐱", layout="wide")
14
- st.markdown("""
15
- <style>
16
- .stApp { background-color: #f4f4f4; }
17
- .stTitle { color: #333; text-align: center; }
18
- .stMarkdown h2 { color: #555; }
19
- </style>
20
- """, unsafe_allow_html=True)
21
-
22
- # 🎯 App Title
23
  st.title("🐢🐱 Cat vs Dog Classifier")
24
 
25
  # πŸ“– About the App
26
- st.markdown(
27
  """
28
  ## About This App
29
- This machine learning application classifies images into two categories: **Cats 🐱** and **Dogs 🐢**.
30
- It is powered by **Streamlit** for an interactive user experience and **TensorFlow** for image classification.
31
-
32
- ### πŸ”₯ Features:
33
- - πŸ“ **Dataset Overview**: Displays dataset statistics and image distribution.
34
- - πŸ“Š **Model Performance**: Shows accuracy and loss metrics.
35
- - πŸ“· **Image Classification**: Upload an image, and the model predicts the category with confidence.
36
- - πŸ“¦ **Download Test Folder**: Option to download a ZIP of test images.
37
- """,
38
- unsafe_allow_html=True
 
39
  )
40
 
41
- # βœ… Set Dataset Path
42
- BASE_DIR = "dataset"
43
- ZIP_PATH = "dataset.zip"
 
44
  TRAIN_DIR = os.path.join(BASE_DIR, "train")
45
  TEST_DIR = os.path.join(BASE_DIR, "test")
46
- MODEL_PATH = "cats_dogs_model.h5"
47
- IMG_SIZE = (150, 150)
48
- BATCH_SIZE = 32
49
 
50
- # βœ… Extract Dataset if Needed
51
- if ZIP_PATH and os.path.exists(ZIP_PATH) and not os.path.exists(BASE_DIR):
52
- with zipfile.ZipFile(ZIP_PATH, "r") as zip_ref:
53
- zip_ref.extractall(BASE_DIR)
 
54
  st.success("βœ… Dataset extracted!")
55
 
56
- # πŸ“Œ Verify Dataset
57
- cat_dir, dog_dir = os.path.join(TRAIN_DIR, "cats"), os.path.join(TRAIN_DIR, "dogs")
 
 
 
 
 
 
 
58
  if not os.path.exists(cat_dir) or not os.path.exists(dog_dir):
59
- st.error("❌ Missing 'cats' or 'dogs' folders in 'train'. Check your dataset.")
60
  st.stop()
61
 
 
 
 
 
 
62
  # 🎯 Load Model
63
  if os.path.exists(MODEL_PATH):
64
  model = tf.keras.models.load_model(MODEL_PATH)
65
  else:
66
- st.error("⚠ No trained model found. Upload 'cats_dogs_model.h5'.")
67
  st.stop()
68
 
69
  # πŸ“· Image Preprocessing
70
- @st.cache_resource
71
  def preprocess_image(image):
72
  image = image.convert('RGB').resize(IMG_SIZE)
73
  img_array = np.array(image, dtype=np.float32) / 255.0
74
- return np.expand_dims(img_array, axis=0)
 
75
 
76
  # 🐢🐱 Classify Image
77
  def classify_image(image):
@@ -83,63 +86,87 @@ def classify_image(image):
83
 
84
  # πŸ“Š Model Evaluation
85
  def evaluate_model():
86
- datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1.0 / 255, validation_split=0.2)
87
- test_data = datagen.flow_from_directory(TRAIN_DIR, target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='binary', subset='validation')
 
 
 
 
 
 
 
 
88
  loss, accuracy = model.evaluate(test_data, verbose=0)
 
89
  return accuracy, loss
90
 
91
  # πŸŽ› Streamlit Tabs
92
  tab1, tab2, tab3 = st.tabs(["πŸ“ Dataset Preview", "πŸ“Š Model Performance", "🐢🐱 Image Classification"])
93
 
94
- # πŸ“ Tab 1: Dataset Overview
95
  with tab1:
96
  st.write("### Dataset Overview")
 
97
  dataset_info = {
98
  "Total Images": len(os.listdir(cat_dir)) + len(os.listdir(dog_dir)),
99
  "Cat Images": len(os.listdir(cat_dir)),
100
  "Dog Images": len(os.listdir(dog_dir))
101
  }
102
- df_info = pd.DataFrame(dataset_info.items(), columns=["Category", "Count"])
103
- st.dataframe(df_info, width=500)
104
 
 
 
 
 
105
  st.write("### Image Distribution")
106
- chart = alt.Chart(df_info).mark_bar().encode(x="Category", y="Count", color="Category")
 
 
107
  st.altair_chart(chart, use_container_width=True)
108
 
109
  # πŸ“Š Tab 2: Model Performance
110
  with tab2:
111
  st.write("### Model Evaluation")
 
112
  accuracy, loss = evaluate_model()
113
- st.metric(label="Validation Accuracy", value=f"{accuracy*100:.2f}%")
114
- st.metric(label="Validation Loss", value=f"{loss:.4f}")
 
115
 
116
  # 🐢🐱 Tab 3: Image Classification
117
  with tab3:
118
  st.write("### Upload an Image for Classification")
119
  uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png", "jpeg"])
120
-
121
  if uploaded_file:
122
  image = Image.open(uploaded_file)
123
  st.image(image, caption="Uploaded Image", use_container_width=True)
124
-
125
  with st.spinner("Classifying..."):
126
  label, confidence = classify_image(image)
127
-
128
- st.success(f"Prediction: **{label}** with **{confidence*100:.2f}%** confidence.")
129
-
 
130
  # **New Feature: Download the 'test' folder as a ZIP**
131
  def zip_folder(folder_path):
 
132
  zip_buffer = io.BytesIO()
133
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
134
- for root, _, files in os.walk(folder_path):
135
  for file in files:
136
  zip_file.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), folder_path))
137
- zip_buffer.seek(0)
138
  return zip_buffer
139
-
 
140
  if os.path.exists(TEST_DIR):
141
  st.write("### Download Test Folder")
142
  zip_buffer = zip_folder(TEST_DIR)
143
- st.download_button("Download Test Folder as ZIP", data=zip_buffer, file_name="test_folder.zip", mime="application/zip")
 
 
 
 
 
144
  else:
145
- st.warning("❌ Test folder not found.")
 
1
+ import streamlit as st
2
  import tensorflow as tf
3
  import numpy as np
4
  import os
5
  import pandas as pd
6
  import altair as alt
7
  from PIL import Image
8
+ from tensorflow.keras.preprocessing.image import ImageDataGenerator
9
  import zipfile
10
  import io
11
  import shutil
12
 
13
+ # 🎨 App Title
 
 
 
 
 
 
 
 
 
 
14
  st.title("🐢🐱 Cat vs Dog Classifier")
15
 
16
  # πŸ“– About the App
17
+ st.write(
18
  """
19
  ## About This App
20
+ This is a machine learning application that classifies images into two categories:
21
+ **Cats 🐱** and **Dogs 🐢**. The model is trained using a deep learning architecture
22
+ called Convolutional Neural Networks (CNNs) and is able to distinguish between images
23
+ of cats and dogs with high accuracy.
24
+ ### Features:
25
+ - **Dataset Overview**: View the number of images in the dataset, categorized by "Cats" and "Dogs".
26
+ - **Model Evaluation**: Check the model's performance on the validation set, including accuracy and loss.
27
+ - **Image Classification**: Upload an image, and the model will predict whether it's a cat or a dog, along with the confidence level.
28
+ - **Download Test Folder**: Download a ZIP file containing the test images.
29
+ The app is powered by **Streamlit** for an interactive user interface and **TensorFlow** for image classification.
30
+ """
31
  )
32
 
33
+ # βœ… Detect Environment & Set Dataset Path
34
+ BASE_DIR = "dataset" # In Hugging Face Spaces, the dataset folder should be at the root of the Space
35
+ ZIP_PATH = "dataset.zip" # If dataset is uploaded as a ZIP (make sure it's in the same directory as app.py)
36
+
37
  TRAIN_DIR = os.path.join(BASE_DIR, "train")
38
  TEST_DIR = os.path.join(BASE_DIR, "test")
 
 
 
39
 
40
+ # βœ… Extract Dataset if Needed (Hugging Face)
41
+ if ZIP_PATH and os.path.exists(ZIP_PATH):
42
+ if not os.path.exists(BASE_DIR): # Avoid re-extracting
43
+ with zipfile.ZipFile(ZIP_PATH, "r") as zip_ref:
44
+ zip_ref.extractall(BASE_DIR) # Extract into dataset folder
45
  st.success("βœ… Dataset extracted!")
46
 
47
+ # πŸ“Œ Check if dataset exists
48
+ if not os.path.exists(TRAIN_DIR):
49
+ st.error(f"❌ Dataset folder 'train' not found at {TRAIN_DIR}. Please upload the dataset.")
50
+ st.stop()
51
+
52
+ # πŸ“Œ Verify Cats & Dogs Folders
53
+ cat_dir = os.path.join(TRAIN_DIR, "cats")
54
+ dog_dir = os.path.join(TRAIN_DIR, "dogs")
55
+
56
  if not os.path.exists(cat_dir) or not os.path.exists(dog_dir):
57
+ st.error("❌ Missing 'cats' or 'dogs' folders inside 'train'. Please check your dataset.")
58
  st.stop()
59
 
60
+ # πŸ“Œ Constants
61
+ IMG_SIZE = (150, 150)
62
+ BATCH_SIZE = 32
63
+ MODEL_PATH = "cats_dogs_model.h5" # Ensure the model is uploaded to Hugging Face Space
64
+
65
  # 🎯 Load Model
66
  if os.path.exists(MODEL_PATH):
67
  model = tf.keras.models.load_model(MODEL_PATH)
68
  else:
69
+ st.error("⚠ No trained model found. Please upload 'cats_dogs_model.h5' to your Hugging Face repository.")
70
  st.stop()
71
 
72
  # πŸ“· Image Preprocessing
 
73
  def preprocess_image(image):
74
  image = image.convert('RGB').resize(IMG_SIZE)
75
  img_array = np.array(image, dtype=np.float32) / 255.0
76
+ img_array = np.expand_dims(img_array, axis=0)
77
+ return img_array
78
 
79
  # 🐢🐱 Classify Image
80
  def classify_image(image):
 
86
 
87
  # πŸ“Š Model Evaluation
88
  def evaluate_model():
89
+ datagen = ImageDataGenerator(rescale=1.0 / 255, validation_split=0.2)
90
+
91
+ test_data = datagen.flow_from_directory(
92
+ TRAIN_DIR,
93
+ target_size=IMG_SIZE,
94
+ batch_size=BATCH_SIZE,
95
+ class_mode='binary',
96
+ subset='validation'
97
+ )
98
+
99
  loss, accuracy = model.evaluate(test_data, verbose=0)
100
+
101
  return accuracy, loss
102
 
103
  # πŸŽ› Streamlit Tabs
104
  tab1, tab2, tab3 = st.tabs(["πŸ“ Dataset Preview", "πŸ“Š Model Performance", "🐢🐱 Image Classification"])
105
 
106
+ # πŸ“ Tab 1: Dataset Preview
107
  with tab1:
108
  st.write("### Dataset Overview")
109
+
110
  dataset_info = {
111
  "Total Images": len(os.listdir(cat_dir)) + len(os.listdir(dog_dir)),
112
  "Cat Images": len(os.listdir(cat_dir)),
113
  "Dog Images": len(os.listdir(dog_dir))
114
  }
 
 
115
 
116
+ df_info = pd.DataFrame(list(dataset_info.items()), columns=["Category", "Count"])
117
+ st.dataframe(df_info)
118
+
119
+ # Visualization
120
  st.write("### Image Distribution")
121
+ chart = alt.Chart(df_info).mark_bar().encode(
122
+ x="Category", y="Count", color="Category"
123
+ )
124
  st.altair_chart(chart, use_container_width=True)
125
 
126
  # πŸ“Š Tab 2: Model Performance
127
  with tab2:
128
  st.write("### Model Evaluation")
129
+
130
  accuracy, loss = evaluate_model()
131
+
132
+ st.write(f"βœ… **Validation Accuracy:** {accuracy*100:.2f}%")
133
+ st.write(f"βœ… **Validation Loss:** {loss:.4f}")
134
 
135
  # 🐢🐱 Tab 3: Image Classification
136
  with tab3:
137
  st.write("### Upload an Image for Classification")
138
  uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png", "jpeg"])
139
+
140
  if uploaded_file:
141
  image = Image.open(uploaded_file)
142
  st.image(image, caption="Uploaded Image", use_container_width=True)
143
+
144
  with st.spinner("Classifying..."):
145
  label, confidence = classify_image(image)
146
+
147
+ st.subheader("Prediction:")
148
+ st.write(f"This is a **{label}** with **{confidence*100:.2f}%** confidence.")
149
+
150
  # **New Feature: Download the 'test' folder as a ZIP**
151
  def zip_folder(folder_path):
152
+ # Create an in-memory zip file
153
  zip_buffer = io.BytesIO()
154
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
155
+ for root, dirs, files in os.walk(folder_path):
156
  for file in files:
157
  zip_file.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), folder_path))
158
+ zip_buffer.seek(0) # Go to the beginning of the file
159
  return zip_buffer
160
+
161
+ # Button to download 'test' folder
162
  if os.path.exists(TEST_DIR):
163
  st.write("### Download Test Folder")
164
  zip_buffer = zip_folder(TEST_DIR)
165
+ st.download_button(
166
+ label="Download Test Folder as ZIP",
167
+ data=zip_buffer,
168
+ file_name="test_folder.zip",
169
+ mime="application/zip"
170
+ )
171
  else:
172
+ st.warning(f"❌ Test folder not found at {TEST_DIR}")