Abdullah-Basar's picture
Update app.py
92cc97c verified
raw
history blame
3.8 kB
import os
import numpy as np
import joblib
from PIL import Image
import streamlit as st
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# Paths and global constants
#DATASET_PATH = "path_to_your_dataset" # Update with your dataset path
MODEL_PATH = "knn_model.pkl"
CLASS_NAMES_PATH = "class_names.pkl"
TARGET_SIZE = (64, 64)
# Helper function to load and preprocess dataset
def load_dataset(dataset_path, target_size):
images = []
labels = []
class_names = sorted(os.listdir(dataset_path)) # Sort for consistent class indexing
for idx, class_name in enumerate(class_names):
class_path = os.path.join(dataset_path, class_name)
if not os.path.isdir(class_path):
continue
for image_name in os.listdir(class_path):
image_path = os.path.join(class_path, image_name)
try:
img = Image.open(image_path).convert('RGB')
img = img.resize(target_size)
img_array = np.array(img).flatten() # Flatten to a single array
images.append(img_array)
labels.append(idx)
except Exception as e:
print(f"Error loading image {image_path}: {e}")
return np.array(images), np.array(labels), class_names
# Function to train and save KNN model
def train_and_save_model(dataset_path, target_size, model_path, class_names_path):
# Load data
X, y, class_names = load_dataset(dataset_path, target_size)
# Split dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Train KNN model
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
# Evaluate model
y_pred = knn.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"KNN Model Accuracy: {accuracy * 100:.2f}%")
# Save model and class names
joblib.dump(knn, model_path)
joblib.dump(class_names, class_names_path)
print(f"Model and class names saved to {model_path} and {class_names_path}")
return knn, class_names
# Preprocess image for prediction
def preprocess_image(image_path, target_size):
img = Image.open(image_path).convert('RGB')
img = img.resize(target_size)
img_array = np.array(img).flatten()
return img_array.reshape(1, -1) # Add batch dimension
# Main Streamlit app
def main():
st.title("Animal Classifier")
st.write("Upload an image of an animal to predict its category.")
# Load model and class names
if not os.path.exists(MODEL_PATH) or not os.path.exists(CLASS_NAMES_PATH):
st.error("Model or class names file not found. Please train the model first.")
return
knn = joblib.load(MODEL_PATH)
class_names = joblib.load(CLASS_NAMES_PATH)
# Upload image
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
if uploaded_file:
st.image(uploaded_file, caption="Uploaded Image", use_container_width=True)
try:
img_array = preprocess_image(uploaded_file, TARGET_SIZE)
if img_array.shape[1] != knn.n_features_in_:
st.error(f"Feature size mismatch: Model expects {knn.n_features_in_} features, but input has {img_array.shape[1]}.")
else:
prediction = knn.predict(img_array)
st.success(f"The predicted animal is: {class_names[prediction[0]]}")
except Exception as e:
st.error(f"Error processing image: {e}")
# Train and save model (Uncomment if running for the first time)
# train_and_save_model(DATASET_PATH, TARGET_SIZE, MODEL_PATH, CLASS_NAMES_PATH)
# Run Streamlit app
if __name__ == "__main__":
main()