|
|
|
|
|
import cv2
|
|
|
import h5py
|
|
|
import numpy as np
|
|
|
import pandas as pd
|
|
|
import seaborn as sns
|
|
|
import matplotlib.pyplot as plt
|
|
|
from sklearn.metrics import confusion_matrix, classification_report
|
|
|
|
|
|
|
|
|
def load_signs_dataset():
|
|
|
"""
|
|
|
Loads the hand signs dataset from HDF5 files.
|
|
|
|
|
|
Returns:
|
|
|
train_set_x_orig (numpy.ndarray): Training set features (images).
|
|
|
train_set_y_orig (numpy.ndarray): Training set labels, reshaped to (1, number_of_samples).
|
|
|
test_set_x_orig (numpy.ndarray): Test set features (images).
|
|
|
test_set_y_orig (numpy.ndarray): Test set labels, reshaped to (1, number_of_samples).
|
|
|
classes (numpy.ndarray): Array containing the list of class labels.
|
|
|
"""
|
|
|
|
|
|
|
|
|
train_dataset = h5py.File('datasets/train_signs.h5', "r")
|
|
|
|
|
|
|
|
|
train_set_x_orig = np.array(train_dataset["train_set_x"][:])
|
|
|
|
|
|
|
|
|
train_set_y_orig = np.array(train_dataset["train_set_y"][:])
|
|
|
|
|
|
|
|
|
test_dataset = h5py.File('datasets/test_signs.h5', "r")
|
|
|
|
|
|
|
|
|
test_set_x_orig = np.array(test_dataset["test_set_x"][:])
|
|
|
|
|
|
|
|
|
test_set_y_orig = np.array(test_dataset["test_set_y"][:])
|
|
|
|
|
|
|
|
|
classes = np.array(test_dataset["list_classes"][:])
|
|
|
|
|
|
|
|
|
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
|
|
|
|
|
|
|
|
|
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
|
|
|
|
|
|
|
|
|
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
|
|
|
|
|
|
def dataset_preprocessing(img_data, img_label):
|
|
|
"""
|
|
|
Preprocesses image data and labels for model training or testing.
|
|
|
|
|
|
Args:
|
|
|
img_data (numpy.ndarray): The input image data array.
|
|
|
img_label (numpy.ndarray): The corresponding labels for the image data.
|
|
|
|
|
|
Returns:
|
|
|
norm_data (numpy.ndarray): Normalized image data with pixel values scaled between 0 and 1.
|
|
|
one_hot_label (numpy.ndarray): Labels converted to one-hot encoded vectors.
|
|
|
"""
|
|
|
|
|
|
|
|
|
norm_data = img_data / 255.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
one_hot_label = np.eye(6)[img_label.reshape(-1)]
|
|
|
|
|
|
|
|
|
|
|
|
return norm_data, one_hot_label
|
|
|
|
|
|
def visualize_sign(data, label, max_indx):
|
|
|
"""
|
|
|
Visualizes a random selection of hand sign images along with their predicted labels.
|
|
|
|
|
|
Args:
|
|
|
data (numpy.ndarray): The dataset containing image data.
|
|
|
Shape is expected to be (num_samples, height, width, channels).
|
|
|
label (numpy.ndarray): The predicted labels corresponding to the dataset.
|
|
|
Shape should be (1, num_samples).
|
|
|
max_indx (int): The number of images to display in the visualization.
|
|
|
|
|
|
Returns:
|
|
|
None: Displays the images and their labels using Matplotlib.
|
|
|
"""
|
|
|
|
|
|
|
|
|
fig, axs = plt.subplots(1, max_indx)
|
|
|
|
|
|
|
|
|
arr = list(np.random.randint(0, data.shape[0], size=max_indx))
|
|
|
|
|
|
|
|
|
for i, value in enumerate(arr):
|
|
|
|
|
|
axs[i].imshow(data[value])
|
|
|
|
|
|
|
|
|
axs[i].set_title(f'It is {label[0, value]}')
|
|
|
|
|
|
|
|
|
axs[i].axis('off')
|
|
|
|
|
|
|
|
|
plt.show()
|
|
|
|
|
|
def visualize_metrics(history):
|
|
|
"""
|
|
|
Visualizes the training metrics (accuracy and loss) over epochs.
|
|
|
|
|
|
Args:
|
|
|
history (tensorflow.keras.callbacks.History): The history object returned by the
|
|
|
model's `fit` method. Contains training metrics.
|
|
|
|
|
|
Returns:
|
|
|
None: Displays the accuracy and loss plots.
|
|
|
"""
|
|
|
|
|
|
df = pd.DataFrame(history.history)
|
|
|
|
|
|
|
|
|
fig, axs = plt.subplots(1, 2, figsize=(12, 4))
|
|
|
|
|
|
|
|
|
axs[0].plot(df['accuracy'], label='Training Accuracy')
|
|
|
if 'val_accuracy' in df.columns:
|
|
|
axs[0].plot(df['val_accuracy'], label='Validation Accuracy', linestyle='--')
|
|
|
axs[0].set_title('Accuracy')
|
|
|
axs[0].set_xlabel('Epochs')
|
|
|
axs[0].set_ylabel('Accuracy')
|
|
|
axs[0].legend()
|
|
|
|
|
|
|
|
|
axs[1].plot(df['loss'], label='Training Loss')
|
|
|
if 'val_loss' in df.columns:
|
|
|
axs[1].plot(df['val_loss'], label='Validation Loss', linestyle='--')
|
|
|
axs[1].set_title('Loss')
|
|
|
axs[1].set_xlabel('Epochs')
|
|
|
axs[1].set_ylabel('Loss')
|
|
|
axs[1].legend()
|
|
|
|
|
|
|
|
|
plt.tight_layout()
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
def evaluate_model(model, test_data, test_labels, class_names):
|
|
|
"""
|
|
|
Evaluates a trained model on test data and visualizes metrics.
|
|
|
|
|
|
Args:
|
|
|
model: The trained model to evaluate.
|
|
|
test_data (numpy.ndarray): Normalized test data used for predictions.
|
|
|
test_labels (numpy.ndarray): One-hot encoded true labels of the test data.
|
|
|
class_names (list of str): List of class names corresponding to the classes.
|
|
|
|
|
|
Returns:
|
|
|
None: Displays a confusion matrix and classification report.
|
|
|
"""
|
|
|
class_names = list(class_names.astype(str))
|
|
|
|
|
|
y_pred = model.predict(test_data)
|
|
|
y_pred_classes = np.argmax(y_pred, axis=1)
|
|
|
|
|
|
|
|
|
test_labels_classes = np.argmax(test_labels, axis=1)
|
|
|
|
|
|
|
|
|
conf_matrix = confusion_matrix(test_labels_classes, y_pred_classes)
|
|
|
|
|
|
|
|
|
print("\nClassification Report:")
|
|
|
print(classification_report(test_labels_classes, y_pred_classes, target_names=class_names))
|
|
|
|
|
|
|
|
|
plt.figure(figsize=(8, 6))
|
|
|
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
|
|
|
xticklabels=class_names, yticklabels=class_names)
|
|
|
plt.title("Confusion Matrix")
|
|
|
plt.xlabel("Predicted Labels")
|
|
|
plt.ylabel("True Labels")
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
def predictor(model, image_array, input_size=(64, 64), class_names=None):
|
|
|
"""
|
|
|
Makes a prediction on a single image using the given model and visualizes the result.
|
|
|
|
|
|
Args:
|
|
|
model: The trained model to use for prediction.
|
|
|
image_array (numpy.ndarray): The input image array (e.g., loaded using OpenCV).
|
|
|
input_size (tuple): The expected input size of the model (default is (64, 64)).
|
|
|
class_names (list of str, optional): List of class names corresponding to the model's output.
|
|
|
|
|
|
Returns:
|
|
|
None: Displays the input image with the predicted class as the title.
|
|
|
"""
|
|
|
|
|
|
if class_names is not None:
|
|
|
class_names = [str(cls) for cls in class_names]
|
|
|
|
|
|
|
|
|
img = cv2.resize(image_array, input_size)
|
|
|
|
|
|
|
|
|
img = img / 255.0
|
|
|
|
|
|
|
|
|
img = np.expand_dims(img, axis=0)
|
|
|
|
|
|
|
|
|
pred = model.predict(img)
|
|
|
|
|
|
|
|
|
pred = np.squeeze(pred)
|
|
|
|
|
|
|
|
|
print("Predicted Probabilities:", pred)
|
|
|
|
|
|
|
|
|
predicted_class_idx = np.argmax(pred, axis=0)
|
|
|
|
|
|
|
|
|
print("Predicted Class Index:", predicted_class_idx)
|
|
|
|
|
|
|
|
|
predicted_class_name = class_names[predicted_class_idx] if class_names else str(predicted_class_idx)
|
|
|
|
|
|
|
|
|
rgb_image = cv2.cvtColor(image_array, cv2.COLOR_BGR2RGB)
|
|
|
|
|
|
|
|
|
plt.imshow(rgb_image)
|
|
|
plt.title(f'Predicted: {predicted_class_name}')
|
|
|
plt.axis('off')
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
|