|
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 |
|
|
|
|
|
|
|
MODEL_PATH = "knn_model.pkl" |
|
CLASS_NAMES_PATH = "class_names.pkl" |
|
TARGET_SIZE = (64, 64) |
|
|
|
|
|
def load_dataset(dataset_path, target_size): |
|
images = [] |
|
labels = [] |
|
class_names = sorted(os.listdir(dataset_path)) |
|
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() |
|
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 |
|
|
|
|
|
def train_and_save_model(dataset_path, target_size, model_path, class_names_path): |
|
|
|
X, y, class_names = load_dataset(dataset_path, target_size) |
|
|
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y) |
|
|
|
knn = KNeighborsClassifier(n_neighbors=3) |
|
knn.fit(X_train, y_train) |
|
|
|
y_pred = knn.predict(X_test) |
|
accuracy = accuracy_score(y_test, y_pred) |
|
print(f"KNN Model Accuracy: {accuracy * 100:.2f}%") |
|
|
|
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 |
|
|
|
|
|
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) |
|
|
|
|
|
def main(): |
|
st.title("Animal Classifier") |
|
st.write("Upload an image of an animal to predict its category.") |
|
|
|
|
|
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) |
|
|
|
|
|
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}") |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|