chiichann commited on
Commit
2c202de
Β·
verified Β·
1 Parent(s): e0e82a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -40
app.py CHANGED
@@ -8,75 +8,97 @@ from PIL import Image
8
  from tensorflow.keras.preprocessing.image import ImageDataGenerator
9
  import zipfile
10
  import io
 
11
 
12
  # 🎨 App Title
13
  st.title("🐢🐱 Cat vs Dog Classifier")
14
 
15
  # πŸ“– About the App
16
- st.write("""
 
17
  ## About This App
18
  This is a machine learning application that classifies images into two categories:
19
- **Cats 🐱** and **Dogs 🐢**. The model is trained using Convolutional Neural Networks (CNNs)
20
- and distinguishes between images with high accuracy.
21
-
22
  ### Features:
23
- - **Dataset Overview**: View image counts for "Cats" and "Dogs".
24
- - **Model Evaluation**: Check accuracy and loss on the validation set.
25
- - **Image Classification**: Upload an image to classify it.
26
- - **Download Test Folder**: Get test images as a ZIP file.
27
- """)
28
-
29
- # βœ… Set Dataset Path
30
- BASE_DIR = "dataset"
31
- ZIP_PATH = "dataset.zip"
 
 
 
32
  TRAIN_DIR = os.path.join(BASE_DIR, "train")
33
  TEST_DIR = os.path.join(BASE_DIR, "test")
34
- MODEL_PATH = "cats_dogs_model.h5"
35
- IMG_SIZE = (150, 150)
36
- BATCH_SIZE = 32
37
 
38
- # βœ… Extract Dataset if Needed
39
- if ZIP_PATH and os.path.exists(ZIP_PATH) and not os.path.exists(BASE_DIR):
40
- with zipfile.ZipFile(ZIP_PATH, "r") as zip_ref:
41
- zip_ref.extractall(BASE_DIR)
 
42
  st.success("βœ… Dataset extracted!")
43
 
44
- # πŸ“Œ Check dataset existence
45
  if not os.path.exists(TRAIN_DIR):
46
- st.error(f"❌ Dataset folder 'train' not found at {TRAIN_DIR}.")
47
  st.stop()
48
 
49
- cat_dir, dog_dir = os.path.join(TRAIN_DIR, "cats"), os.path.join(TRAIN_DIR, "dogs")
 
 
 
50
  if not os.path.exists(cat_dir) or not os.path.exists(dog_dir):
51
- st.error("❌ Missing 'cats' or 'dogs' folders inside 'train'.")
52
  st.stop()
53
 
 
 
 
 
 
54
  # 🎯 Load Model
55
  if os.path.exists(MODEL_PATH):
56
  model = tf.keras.models.load_model(MODEL_PATH)
57
  else:
58
- st.error("⚠ No trained model found. Upload 'cats_dogs_model.h5'.")
59
  st.stop()
60
 
61
  # πŸ“· Image Preprocessing
62
  def preprocess_image(image):
63
  image = image.convert('RGB').resize(IMG_SIZE)
64
  img_array = np.array(image, dtype=np.float32) / 255.0
65
- return np.expand_dims(img_array, axis=0)
 
66
 
67
  # 🐢🐱 Classify Image
68
  def classify_image(image):
69
- prediction = model.predict(preprocess_image(image))[0][0]
 
70
  label = "Dog 🐢" if prediction > 0.5 else "Cat 🐱"
71
- confidence = max(prediction, 1 - prediction)
72
  return label, confidence
73
 
74
  # πŸ“Š Model Evaluation
75
  def evaluate_model():
76
- test_data = ImageDataGenerator(rescale=1.0 / 255, validation_split=0.2).flow_from_directory(
77
- TRAIN_DIR, target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='binary', subset='validation'
 
 
 
 
 
 
78
  )
79
- return model.evaluate(test_data, verbose=0)
 
 
 
80
 
81
  # πŸŽ› Streamlit Tabs
82
  tab1, tab2, tab3 = st.tabs(["πŸ“ Dataset Preview", "πŸ“Š Model Performance", "🐢🐱 Image Classification"])
@@ -84,16 +106,29 @@ tab1, tab2, tab3 = st.tabs(["πŸ“ Dataset Preview", "πŸ“Š Model Performance", "
84
  # πŸ“ Tab 1: Dataset Preview
85
  with tab1:
86
  st.write("### Dataset Overview")
87
- dataset_info = {"Total Images": len(os.listdir(cat_dir)) + len(os.listdir(dog_dir)),
88
- "Cat Images": len(os.listdir(cat_dir)), "Dog Images": len(os.listdir(dog_dir))}
89
- df_info = pd.DataFrame(dataset_info.items(), columns=["Category", "Count"])
 
 
 
 
 
90
  st.dataframe(df_info)
91
- st.altair_chart(alt.Chart(df_info).mark_bar().encode(x="Category", y="Count", color="Category"), use_container_width=True)
 
 
 
 
 
 
92
 
93
  # πŸ“Š Tab 2: Model Performance
94
  with tab2:
95
  st.write("### Model Evaluation")
 
96
  accuracy, loss = evaluate_model()
 
97
  st.write(f"βœ… **Validation Accuracy:** {accuracy*100:.2f}%")
98
  st.write(f"βœ… **Validation Loss:** {loss:.4f}")
99
 
@@ -101,27 +136,37 @@ with tab2:
101
  with tab3:
102
  st.write("### Upload an Image for Classification")
103
  uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png", "jpeg"])
 
104
  if uploaded_file:
105
  image = Image.open(uploaded_file)
106
  st.image(image, caption="Uploaded Image", use_container_width=True)
 
107
  with st.spinner("Classifying..."):
108
  label, confidence = classify_image(image)
 
109
  st.subheader("Prediction:")
110
  st.write(f"This is a **{label}** with **{confidence*100:.2f}%** confidence.")
111
 
112
- # **Download Test Folder as ZIP**
113
  def zip_folder(folder_path):
 
114
  zip_buffer = io.BytesIO()
115
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
116
- for root, _, files in os.walk(folder_path):
117
  for file in files:
118
  zip_file.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), folder_path))
119
- zip_buffer.seek(0)
120
  return zip_buffer
121
 
 
122
  if os.path.exists(TEST_DIR):
123
  st.write("### Download Test Folder")
124
  zip_buffer = zip_folder(TEST_DIR)
125
- st.download_button("Download Test Folder as ZIP", data=zip_buffer, file_name="test_folder.zip", mime="application/zip")
 
 
 
 
 
126
  else:
127
- st.warning(f"❌ Test folder not found at {TEST_DIR}")
 
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):
81
+ processed_img = preprocess_image(image)
82
+ prediction = model.predict(processed_img)[0][0]
83
  label = "Dog 🐢" if prediction > 0.5 else "Cat 🐱"
84
+ confidence = prediction if label == "Dog 🐢" else 1 - prediction
85
  return label, confidence
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"])
 
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
 
 
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}")