import tensorflow.keras
from tensorflow.keras.utils import image_dataset_from_directory
print("Hello world")
path = 'E:\Semester 6\Machine Learning\machine-learning-techniques\Data\image1'
train_data, test_data = image_dataset_from_directory(
    path,
)
train_data
iterator = dataset.take(1).as_numpy_iterator()

images = iterator.next()
images
images[0][0]
images[1][0]
import matplotlib.pyplot as plt 

plt.imshow(images[0][0].astype('uint8'))
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
model = Sequential([
    Conv2D(16, (3, 3), activation='relu', input_shape=(256, 256, 3)),
    MaxPooling2D(),
    Flatten(), 
    Dense(128, activation='relu'),
    Dense(1, activation='sigmoid')
])
# Compile the model
model.compile(optimizer='adam',
              loss='binary_crossentropy', # Use 'categorical_crossentropy' for multi-class
              metrics=['accuracy'])
history = model.fit(train_data, epochs=10)

loss, accuracy = model.evaluate(test_data)
loss, accuracy
plt.plot(history.history['loss'])
images = []
classes = []
for image_batch, class_batch in test_data:
    _images = image_batch.numpy()
    _classes = class_batch.numpy()
    images.extend(_images)
    classes.extend(_classes)
classes



import numpy as np
image_batch = np.expand_dims(images[0],axis=0)

prediction = model.predict(image_batch)
prediction
np.round(prediction[0][0])
import numpy as np
import matplotlib.pyplot as plt

# Select the image to predict
image_to_predict = images[0]

# Display the image
plt.imshow(image_to_predict.astype('uint8'))
plt.title("Image to Predict")
plt.show()

# Add a batch dimension (shape becomes (1, 256, 256, 3))
image_batch = np.expand_dims(image_to_predict, axis=0)

# Make prediction
prediction = model.predict(image_batch)

# Assuming binary classification (sigmoid output), print the raw prediction
print(f"Raw prediction output: {prediction[0][0]}")

# Get class names (defined in cell 17, using train_data from cell 4)
class_names = train_data.class_names

# Determine predicted class
predicted_class_index = int(np.round(prediction[0][0])) # Round sigmoid output to 0 or 1
predicted_class_name = class_names[predicted_class_index]
print(f"Predicted class: {predicted_class_name} (Index: {predicted_class_index})")

# Get actual class (using 'classes' list from cell 15)
actual_class_index = classes[0]
actual_class_name = class_names[actual_class_index]
print(f"Actual class: {actual_class_name} (Index: {actual_class_index})")
import numpy as np

import matplotlib.pyplot as plt

# Get class names from the dataset
# train_data was created using image_dataset_from_directory which has a class_names attribute
class_names = train_data.class_names
num_classes = len(class_names)
print(f"Classes found: {class_names}")

# Dictionary to store one image per class index
class_images = {}
found_classes = set()

# Iterate through the training data to find one image per class
# We iterate through the dataset batch by batch
for images_batch, labels_batch in train_data:
    # Convert batch tensors to numpy arrays
    images_np = images_batch.numpy()
    labels_np = labels_batch.numpy()

    # Iterate through images and labels in the current batch
    for img, label_idx in zip(images_np, labels_np):
        # Check if we already found an image for this class
        if label_idx not in found_classes:
            # Store the image (convert to uint8 for display) and mark class as found
            class_images[label_idx] = img.astype(np.uint8)
            found_classes.add(label_idx)
            print(f"Found image for class: {class_names[label_idx]} (Index: {label_idx})")

        # Check if we have found an image for each class
        if len(found_classes) == num_classes:
            break # Stop searching within the batch

    # Check if we have found an image for each class after processing the batch
    if len(found_classes) == num_classes:
        break # Stop iterating through batches

# Display the images
if len(class_images) < num_classes:
    print(f"\nWarning: Only found images for {len(class_images)} out of {num_classes} classes.")
elif num_classes > 0:
    print(f"\nDisplaying one image per class:")
    plt.figure(figsize=(5 * num_classes, 5))
    i = 1
    # Sort items by class index for consistent display order
    sorted_items = sorted(class_images.items())
    for label_idx, img in sorted_items:
        plt.subplot(1, num_classes, i)
        plt.imshow(img)
        plt.title(f'Class: {class_names[label_idx]}')
        plt.axis('off')
        i += 1
    plt.show()
else:
    print("\nNo classes or images found in the dataset.")