louiecerv's picture
save changes
e67a6e7
import streamlit as st
import tensorflow as tf
import numpy as np
from PIL import Image
import os
from huggingface_hub import login
from tensorflow import keras
import requests
# Get Hugging Face token from environment variables
HF_TOKEN = os.environ.get("HF_TOKEN")
if not HF_TOKEN:
st.error("HF_TOKEN environment variable not set. Please set it before running the app.")
st.stop() # Stop execution if token is missing
# Authenticate with Hugging Face
try:
login(token=HF_TOKEN)
st.success("Successfully logged in to Hugging Face Hub!")
except Exception as e:
st.error(f"Hugging Face login failed: {e}")
st.stop()
model_url = "https://huggingface.co/louiecerv/cats_dogs_recognition_tf_cnn/resolve/main/cats_dogs_recognition_tf_cnn.keras"
model_filename = "cats_dogs_recognition_tf_cnn.keras" # Or any name you prefer
model_filepath = model_filename # Save in the current directory
try:
# 1. Download the model file
response = requests.get(model_url, stream=True)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
with open(model_filepath, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
# 2. Load the model from the local file
model = tf.keras.models.load_model(model_filepath)
st.success(f"Model loaded successfully from: {model_filepath}")
# Optional: Clean up the downloaded file (if desired)
# os.remove(model_filepath) # Uncomment if you want to delete the file after loading
except requests.exceptions.RequestException as e:
st.error(f"Error downloading model: {e}")
st.stop()
except Exception as e:
st.error(f"Error loading model: {e}")
st.stop()
# Image preprocessing function with cropping
def preprocess_image(image):
# 1. Crop to square aspect ratio
width, height = image.size
new_size = min(width, height)
left = (width - new_size) // 2
top = (height - new_size) // 2
right = (width + new_size) // 2
bottom = (height + new_size) // 2
image = image.crop((left, top, right, bottom))
# 2. Resize
image = image.resize((128, 128)) # Use PIL's resize for consistency
# 3. Convert to NumPy array if it's a PIL image
image_np = np.array(image)
# 4. Ensure 3 channels (RGB)
if image_np.ndim == 2 or image_np.shape[2] == 1:
image_np = np.stack([image_np] * 3, axis=-1)
# 5. Normalize
image_np = image_np.astype(np.float32) / 255.0
image_np = np.expand_dims(image_np, axis=0)
return image_np
# Streamlit app
st.title("Cat vs. Dog Image Classifier")
uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png", "jpeg"])
if uploaded_file is not None:
image = Image.open(uploaded_file)
st.image(image, caption="Uploaded Image.", use_container_width=True)
processed_image = preprocess_image(image) # Pass the PIL Image directly
# Display preprocessed image (optional, but helpful for debugging)
processed_image_display = tf.squeeze(processed_image, axis=0).numpy() * 255.0
processed_image_display = processed_image_display.astype(np.uint8)
processed_image_display = Image.fromarray(processed_image_display)
st.image(processed_image_display, caption="Preprocessed Image", use_container_width=True)
predictions = model.predict(processed_image)
class_index = np.argmax(predictions)
class_names = ["Cat", "Dog"]
predicted_class = class_names[class_index]
confidence = predictions[0][class_index] * 100
st.write(f"## Prediction: {predicted_class} (Confidence: {confidence:.2f}%)")