{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport imageio\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Input, Conv2D, Flatten, Dense, Reshape, Conv2DTranspose, concatenate, Embedding\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nimport cv2\n\n# Define constants\nIMAGE_SIZE = (256, 256, 3)\nLATENT_DIM = 100\nNUM_CLASSES = 2  # Number of classes (e.g., artists)\nEPOCHS = 1000\nBATCH_SIZE = 16\nSAMPLE_INTERVAL = 100\n\n# Define the generator model\ndef build_generator():\n    input_layer = Input(shape=(LATENT_DIM,))\n    input_label = Input(shape=(1,), dtype='int32')\n    \n    # Embedding layer for label\n    label_embedding = Embedding(NUM_CLASSES, LATENT_DIM)(input_label)\n    label_embedding = Flatten()(label_embedding)\n    \n    # Concatenate the noise and label\n    combined = concatenate([input_layer, label_embedding])\n    x = Dense(64 * 64 * 64, activation=\"relu\")(combined)\n    x = Reshape((64, 64, 64))(x)\n    x = Conv2DTranspose(64, kernel_size=3, strides=2, padding=\"same\", activation=\"relu\")(x)\n    x = Conv2DTranspose(32, kernel_size=3, strides=2, padding=\"same\", activation=\"relu\")(x)\n    x = Conv2DTranspose(3, kernel_size=3, strides=1, padding=\"same\", activation=\"sigmoid\")(x)\n    model = Model([input_layer, input_label], x)\n    return model\n\n# Define the discriminator model\ndef build_discriminator():\n    input_layer = Input(shape=IMAGE_SIZE)\n    input_label = Input(shape=(1,), dtype='int32')\n    \n    # Embedding layer for label\n    label_embedding = Embedding(NUM_CLASSES, np.prod(IMAGE_SIZE))(input_label)\n    label_embedding = Reshape(IMAGE_SIZE)(label_embedding)\n    \n    # Concatenate the image and label\n    combined = concatenate([input_layer, label_embedding])\n    \n    x = Conv2D(32, kernel_size=3, strides=2, padding=\"same\", activation=\"relu\")(combined)\n    x = Conv2D(64, kernel_size=3, strides=2, padding=\"same\", activation=\"relu\")(x)\n    x = Conv2D(128, kernel_size=3, strides=2, padding=\"same\", activation=\"relu\")(x)\n    x = Flatten()(x)\n    x = Dense(1, activation=\"sigmoid\")(x)\n    model = Model([input_layer, input_label], x)\n    return model\n    \n# Load images\ndef load_images(image1_path, image2_path):\n    try:\n        image1 = cv2.imread(image1_path)\n        if image1 is None:\n            print(f\"Failed to load image1 from {image1_path}\")\n            return None, None\n        image1 = cv2.resize(image1, (IMAGE_SIZE[1], IMAGE_SIZE[0]))\n        image1 = image1 / 255.0\n\n        image2 = cv2.imread(image2_path)\n        if image2 is None:\n            print(f\"Failed to load image2 from {image2_path}\")\n            return None, None\n        image2 = cv2.resize(image2, (IMAGE_SIZE[1], IMAGE_SIZE[0]))\n        image2 = image2 / 255.0\n\n        return image1, image2\n    except Exception as e:\n        print(\"Error loading images:\", e)\n        return None, None\n\n# Combine images using the generator\ndef combine_images(generator, latent_dim, image1, image2, label):\n    latent_noise = np.random.normal(0, 1, (1, latent_dim))\n    label = np.array([[label]])\n    generated_image = generator.predict([latent_noise, label])[0]\n\n    combined_image = generated_image * image1 + (1 - generated_image) * image2\n    combined_image = (combined_image * 255).astype(np.uint8)\n    return combined_image\n\n# Train the GAN\ndef train_gan(generator, discriminator, combined_model, images, labels):\n    combined_model.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))\n    for epoch in range(EPOCHS):\n        idx = np.random.randint(0, images.shape[0], BATCH_SIZE)\n        real_images = images[idx]\n        real_labels = labels[idx]\n        latent_noise = np.random.normal(0, 1, (BATCH_SIZE, LATENT_DIM))\n        generated_images = generator.predict([latent_noise, real_labels])\n\n        # Train the discriminator\n        discriminator.trainable = True\n        d_loss_real = discriminator.train_on_batch([real_images, real_labels], np.ones((BATCH_SIZE, 1)))\n        d_loss_fake = discriminator.train_on_batch([generated_images, real_labels], np.zeros((BATCH_SIZE, 1)))\n        d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)\n\n        # Train the generator\n        discriminator.trainable = False\n        g_loss = combined_model.train_on_batch([latent_noise, real_labels], np.ones((BATCH_SIZE, 1)))\n\n        print(f\"Epoch {epoch}, D Loss: {d_loss}, G Loss: {g_loss}\")\n        if(epoch==20):\n            break\n\ndef main(image1_path, image2_path, output_path):\n    try:\n        # Load images\n        image1, image2 = load_images(image1_path, image2_path)\n\n        # Generate labels for the images (e.g., artist labels)\n        label1 = 0  # Label for image1\n        label2 = 1  # Label for image2\n\n        # Build and compile the discriminator\n        discriminator = build_discriminator()\n        discriminator.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5), metrics=['accuracy'])\n\n        # Build and compile the generator\n        generator = build_generator()\n\n        # Combine discriminator and generator to form the GAN\n        discriminator.trainable = False\n        gan_input = Input(shape=(LATENT_DIM,))\n        gan_label = Input(shape=[1,], dtype='int32')\n        combined_output = discriminator([generator([gan_input, gan_label]), gan_label])\n        combined_model = Model([gan_input, gan_label], combined_output)\n        combined_model.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))\n\n        # Train GAN\n        images = np.array([image1, image2])\n        labels = np.array([[label1], [label2]])\n        train_gan(generator, discriminator, combined_model, images, labels)\n\n        # Generate combined image\n        combined_image = combine_images(generator, LATENT_DIM, image1, image2, label1)\n\n        # Save combined image\n        cv2.imwrite(output_path, combined_image)\n\n        return True, \"Combined image generated successfully.\"\n\n    except Exception as e:\n        return False, f\"An error occurred: {str(e)}\"\n\nif __name__ == \"__main__\":\n    import argparse\n\n    # Parse command-line arguments\n    parser = argparse.ArgumentParser(description=\"Combine two images using GAN\")\n    parser.add_argument(\"image1_path\", type=str, help=\"Path to the first image\")\n    parser.add_argument(\"image2_path\", type=str, help=\"Path to the second image\")\n    parser.add_argument(\"output_path\", type=str, help=\"Path to save the combined image\")\n    args = parser.parse_args()\n\n    # Call main function with provided paths\n    success, message = main(args.image1_path, args.image2_path, args.output_path)\n    if success:\n        print(message)\n    else:\n        print(\"Error:\", message)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-18T15:13:21.023Z","iopub.execute_input":"2025-04-18T15:13:21.023335Z","iopub.status.idle":"2025-04-18T15:13:40.113508Z","shell.execute_reply.started":"2025-04-18T15:13:21.023303Z","shell.execute_reply":"2025-04-18T15:13:40.112002Z"}},"outputs":[],"execution_count":null}]}