File size: 3,797 Bytes
757ab9a
92cc97c
 
757ab9a
92cc97c
 
 
 
 
 
 
 
 
 
757ab9a
92cc97c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
757ab9a
92cc97c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
757ab9a
92cc97c
 
 
 
 
 
757ab9a
92cc97c
 
 
 
757ab9a
92cc97c
 
 
 
757ab9a
92cc97c
 
757ab9a
92cc97c
 
 
 
 
 
 
 
 
 
 
 
 
757ab9a
92cc97c
 
757ab9a
92cc97c
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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()