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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -85
app.py CHANGED
@@ -8,97 +8,75 @@ 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):
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,29 +84,16 @@ tab1, tab2, tab3 = st.tabs(["πŸ“ Dataset Preview", "πŸ“Š Model Performance", "
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,37 +101,27 @@ with tab2:
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}")
 
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
  # πŸ“ 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
  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}")