import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

def load_model():
    model = tf.keras.applications.InceptionV3(weights='imagenet', include_top=False)
    model.trainable = False
    return model

def deep_dream(image, model, iterations=10, step_size=0.01):
    image = tf.convert_to_tensor(image)
    image = tf.expand_dims(image, axis=0)
    for _ in range(iterations):
        with tf.GradientTape() as tape:
            tape.watch(image)
            features = model(image)
            loss = tf.reduce_mean(features)
        gradients = tape.gradient(loss, image)
        gradients /= tf.math.reduce_std(gradients) + 1e-8
        image = image + gradients * step_size
        image = tf.clip_by_value(image, -1.0, 1.0)
    return image.numpy().squeeze()

# Load and preprocess image
img_path = 'input_image.jpg'  # Replace with your image path
img = tf.keras.preprocessing.image.load_img(img_path, target_size=(224, 224))
img = tf.keras.preprocessing.image.img_to_array(img)
img = (img / 255.0) * 2.0 - 1.0

# Load model and run DeepDream
model = load_model()
dream_img = deep_dream(img, model, iterations=50, step_size=0.01)

# Save and display the result
dream_img = (dream_img + 1.0) / 2.0
plt.imshow(dream_img)
plt.axis('off')
plt.savefig('deepdream_image.png')
plt.show()