# -*- coding: utf-8 -*- """Butterfly classification with CNN.ipynb Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/18Jo5pBel2xJCse_nNq61zkDnPN_zzg_u # Import Libraries and Load Data """ ## Remove Warnings ## import warnings warnings.filterwarnings("ignore") ## Data ## import numpy as np import pandas as pd import os ## Visualization ## import matplotlib.pyplot as plt import plotly.express as px import seaborn as sns import plotly.graph_objects as go ## Image ## import cv2 from tensorflow.keras.preprocessing.image import ImageDataGenerator ## Tensorflow ## from tensorflow.keras.models import Sequential, Model from tensorflow.keras.layers import Input, Dense , Conv2D , Dropout , Flatten , Activation, MaxPooling2D , GlobalAveragePooling2D from tensorflow.keras.optimizers import Adam , RMSprop from tensorflow.keras.layers import BatchNormalization from tensorflow.keras.callbacks import ReduceLROnPlateau , EarlyStopping , ModelCheckpoint , LearningRateScheduler from tensorflow.keras.applications import ResNet50V2 df = pd.read_csv('C:/Users/kamel/Documents/Image Classification/butterfly-dataset/butterflies and moths.csv') IMAGE_DIR = 'C:/Users/kamel/Documents/Image Classification/butterfly-dataset' df['filepaths'] = IMAGE_DIR + '/' + df['filepaths'] df.head() train_df = df.loc[df['data set'] == 'train'] val_df = df.loc[df['data set'] == 'valid'] test_df = df.loc[df['data set'] == 'test'] """# Exploratory Data Analysis""" label_counts = df['labels'].value_counts()[:10] fig = px.bar(x=label_counts.index, y=label_counts.values, color=label_counts.values, text=label_counts.values, color_continuous_scale='Blues') fig.update_layout( title_text='Labels Distribution', template='plotly_white', xaxis=dict( title='Label', ), yaxis=dict( title='Count', ) ) fig.update_traces(marker_line_color='black', marker_line_width=1.5, opacity=0.8) fig.show() """# Generate Image using ImageDataGenerator""" # only train data needs to be augmented train_gen = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rescale=1/255.) val_gen = ImageDataGenerator(rescale=1/255.) train_dir = 'C:/Users/kamel/Documents/Image Classification/butterfly-dataset/train' val_dir = 'C:/Users/kamel/Documents/Image Classification/butterfly-dataset/valid' BATCH_SIZE = 16 SEED = 56 IMAGE_SIZE = (244, 244) train_flow_gen = train_gen.flow_from_directory(directory=train_dir, class_mode='sparse', batch_size=BATCH_SIZE, target_size=IMAGE_SIZE, seed=SEED) val_flow_gen = val_gen.flow_from_directory(directory=val_dir, class_mode='sparse', batch_size=BATCH_SIZE, target_size=IMAGE_SIZE, seed=SEED) """# Create Model""" verbose=False input_tensor = Input(shape=(224, 224, 3)) base_model = ResNet50V2(input_tensor=input_tensor, include_top=False, weights='imagenet') bm_output = base_model.output x = GlobalAveragePooling2D()(bm_output) x = Dense(1024, activation='relu')(x) x = Dropout(rate=0.5)(x) output = Dense(100, activation='softmax')(x) model = Model(inputs=input_tensor, outputs=output) if verbose: model.summary() """# ResNet Modelling""" model.compile(optimizer=Adam(lr=0.001), loss='sparse_categorical_crossentropy', metrics=['accuracy']) rlr_cb = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=3, mode='min', verbose=0) early_cb = EarlyStopping(monitor='val_loss', patience=5, mode='min', verbose=0) model.fit(train_flow_gen, epochs=5, steps_per_epoch=int(np.ceil(train_df.shape[0]/BATCH_SIZE)), validation_data=val_flow_gen, validation_steps=int(np.ceil(val_df.shape[0]/BATCH_SIZE)), callbacks=[rlr_cb, early_cb]) test_dir = 'C:/Users/kamel/Documents/Image Classification/butterfly-dataset/test' test_gen = ImageDataGenerator(rescale=1/255.) test_flow_gen = test_gen.flow_from_directory(directory=test_dir, class_mode='sparse', batch_size=BATCH_SIZE, target_size=IMAGE_SIZE, seed=SEED) print('ResNet Test Data Accuracy: {0}'.format(model.evaluate(test_flow_gen)[1:][0])) # Save the current weights manually model.save('C:/Users/kamel/Documents/Image Classification/model_checkpoint_manual_effnet.h5') """# Deployment""" import gradio as gr import tensorflow as tf from tensorflow.keras.models import load_model import numpy as np import cv2 # Load the trained model model_path = 'C:/Users/kamel/Documents/Image Classification/model_checkpoint_manual_effnet.h5' model = load_model(model_path) class_names = ['ADONIS', 'AFRICAN GIANT SWALLOWTAIL', 'AMERICAN SNOOT', 'AN 88', 'APPOLLO', 'ARCIGERA FLOWER MOTH', 'ATALA', 'ATLAS MOTH', 'BANDED ORANGE HELICONIAN', 'BANDED PEACOCK'] # Define a function to preprocess the input image def preprocess_image(img): # Check if img is a file path or an image object if isinstance(img, str): # Load and preprocess the image img = cv2.imread(img) img = cv2.resize(img, (224, 224)) img = img / 255.0 # Normalize pixel values img = np.expand_dims(img, axis=0) # Add batch dimension elif isinstance(img, np.ndarray): # If img is already an image array, resize it img = cv2.resize(img, (224, 224)) img = img / 255.0 # Normalize pixel values img = np.expand_dims(img, axis=0) # Add batch dimension else: raise ValueError("Unsupported input type. Please provide a file path or a NumPy array.") return img # Define the classification function def classify_image(img): # Preprocess the image img = preprocess_image(img) # Make predictions predictions = model.predict(img) # Get the predicted class label predicted_class = np.argmax(predictions) # Get the predicted class name predicted_class_name = class_names[predicted_class] return f"Predicted Class: {predicted_class_name}" # Create a Gradio interface iface = gr.Interface(fn=classify_image, inputs="image", outputs="text", live=True) # Launch the Gradio app iface.launch()