{"id":2147,"date":"2023-06-13T12:43:36","date_gmt":"2023-06-13T11:43:36","guid":{"rendered":"https:\/\/laserphotonics.uk\/?p=2147"},"modified":"2023-06-13T12:45:26","modified_gmt":"2023-06-13T11:45:26","slug":"neural-style-transfer-nst-test-success","status":"publish","type":"post","link":"https:\/\/laserphotonics.uk\/?p=2147","title":{"rendered":"Neural style transfer (NST) test &#8211; success"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"1024\" height=\"351\" src=\"https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-1024x351.png\" alt=\"\" class=\"wp-image-2148\" srcset=\"https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-1024x351.png 1024w, https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-300x103.png 300w, https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-768x263.png 768w, https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-1536x526.png 1536w, https:\/\/laserphotonics.uk\/wp-content\/uploads\/2023\/06\/Zengbo2-2048x701.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\n\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\nimport torchvision.transforms as transforms\nimport torchvision.models as models\n\nimport copy\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Define the fixed size\ntarget_size = (512, 512)\n\nloader = transforms.Compose(&#91;\n    transforms.Resize(target_size),\n    transforms.ToTensor()])\n\ndef image_loader(image_name):\n    image = Image.open(image_name)\n    image = loader(image).unsqueeze(0)\n    return image.to(device, torch.float)\n\nstyle_img = image_loader(\"style_fanGao.jpg\")\ncontent_img = image_loader(\"Zengbo.jpg\")\n\n# Resize the images to the same size\nstyle_img = F.interpolate(style_img, size=target_size, mode='bilinear', align_corners=False)\ncontent_img = F.interpolate(content_img, size=target_size, mode='bilinear', align_corners=False)\n\nassert style_img.size() == content_img.size(), \"Style and content images must be of the same size.\"\n\nunloader = transforms.ToPILImage()\n\nplt.ion()\n\ndef imshow(tensor, title=None):\n    image = tensor.cpu().clone()\n    image = image.squeeze(0)\n    image = unloader(image)\n    plt.imshow(image)\n    if title is not None:\n        plt.title(title)\n    plt.pause(0.001)\n\ndef gram_matrix(input):\n    a, b, c, d = input.size()  # a=batch size(=1)\n    features = input.view(a * b, c * d)  # resise F_XL into \\hat F_XL\n\n    G = torch.mm(features, features.t())  # compute the gram product\n\n    # normalization factor\n    return G.div(a * b * c * d)\n\nclass ContentLoss(nn.Module):\n    def __init__(self, target):\n        super(ContentLoss, self).__init__()\n        self.target = target.detach()\n\n    def forward(self, input):\n        self.loss = F.mse_loss(input, self.target)\n        return input\n\nclass StyleLoss(nn.Module):\n    def __init__(self, target_feature):\n        super(StyleLoss, self).__init__()\n        self.target = gram_matrix(target_feature).detach()\n\n    def forward(self, input):\n        G = gram_matrix(input)\n        self.loss = F.mse_loss(G, self.target)\n        return input\n\nclass Normalization(nn.Module):\n    def __init__(self, mean, std):\n        super(Normalization, self).__init__()\n        self.mean = mean.view(-1, 1, 1)\n        self.std = std.view(-1, 1, 1)\n\n    def forward(self, img):\n        return (img - self.mean) \/ self.std\n\ncnn = models.vgg19(pretrained=True).features.to(device).eval()\n\ncnn_normalization_mean = torch.tensor(&#91;0.485, 0.456, 0.406]).to(device)\ncnn_normalization_std = torch.tensor(&#91;0.229, 0.224, 0.225]).to(device)\n\ncontent_layers_default = &#91;'conv_4']\nstyle_layers_default = &#91;'conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5']\n\ndef get_style_model_and_losses(cnn, normalization_mean, normalization_std,\n                               style_img, content_img,\n                               content_layers=content_layers_default,\n                               style_layers=style_layers_default):\n    normalization = Normalization(normalization_mean, normalization_std).to(device)\n\n    content_losses = &#91;]\n    style_losses = &#91;]\n\n    model = nn.Sequential(normalization)\n\n    i = 0\n    for layer in cnn.children():\n        if isinstance(layer, nn.Conv2d):\n            i += 1\n            name = 'conv_{}'.format(i)\n        elif isinstance(layer, nn.ReLU):\n            name = 'relu_{}'.format(i)\n            layer = nn.ReLU(inplace=False)\n        elif isinstance(layer, nn.MaxPool2d):\n            name = 'pool_{}'.format(i)\n        elif isinstance(layer, nn.BatchNorm2d):\n            name = 'bn_{}'.format(i)\n        else:\n            raise RuntimeError('Unrecognized layer: {}'.format(layer.__class__.__name__))\n\n        model.add_module(name, layer)\n\n        if name in content_layers:\n            target = model(content_img).detach()\n            content_loss = ContentLoss(target)\n            model.add_module(\"content_loss_{}\".format(i), content_loss)\n            content_losses.append(content_loss)\n\n        if name in style_layers:\n            target_feature = model(style_img).detach()\n            style_loss = StyleLoss(target_feature)\n            model.add_module(\"style_loss_{}\".format(i), style_loss)\n            style_losses.append(style_loss)\n\n    for i in range(len(model) - 1, -1, -1):\n        if isinstance(model&#91;i], ContentLoss) or isinstance(model&#91;i], StyleLoss):\n            break\n\n    model = model&#91;:(i + 1)]\n\n    return model, style_losses, content_losses\n\ndef get_input_optimizer(input_img):\n    optimizer = optim.LBFGS(&#91;input_img])\n    return optimizer\n\ndef run_style_transfer(cnn, normalization_mean, normalization_std,\n                       content_img, style_img, input_img, num_steps=300,\n                       style_weight=1000000, content_weight=1):\n    model, style_losses, content_losses = get_style_model_and_losses(cnn,\n                                                                      normalization_mean, normalization_std,\n                                                                      style_img, content_img)\n\n    input_img.requires_grad_(True)\n    model.requires_grad_(False)\n\n    optimizer = get_input_optimizer(input_img)\n\n    run = &#91;0]\n    while run&#91;0] &lt;= num_steps:\n\n        def closure():\n            with torch.no_grad():\n                input_img.clamp_(0, 1)\n\n            optimizer.zero_grad()\n            model(input_img)\n            style_score = 0\n            content_score = 0\n\n            for sl in style_losses:\n                style_score += sl.loss\n            for cl in content_losses:\n                content_score += cl.loss\n\n            style_score *= style_weight\n            content_score *= content_weight\n\n            loss = style_score + content_score\n            loss.backward()\n\n            run&#91;0] += 1\n            if run&#91;0] % 50 == 0:\n                print(\"run {}:\".format(run))\n                print('Style Loss : {:4f} Content Loss: {:4f}'.format(\n                    style_score.item(), content_score.item()))\n                print()\n\n            return style_score + content_score\n\n        optimizer.step(closure)\n\n    with torch.no_grad():\n        input_img.clamp_(0, 1)\n\n    return input_img\n\ndef save_output_image(image, output_path):\n    try:\n        image.save(output_path)\n        print(f\"Output image saved successfully at {output_path}\")\n    except Exception as e:\n        print(f\"An error occurred while saving the output image: {str(e)}\")\n\ndef convert_to_pil_image(tensor):\n    image = tensor.squeeze(0).cpu().clone().detach().numpy().transpose(1, 2, 0)\n    image = image.clip(0, 1)\n    image = (image * 255).astype('uint8')\n    return Image.fromarray(image)\n\nnum_steps = 500\nstyle_weight = 1000000000\ncontent_weight = 1\n\ninput_img = content_img.clone()\n\noutput = run_style_transfer(cnn, cnn_normalization_mean, cnn_normalization_std,\n                            content_img, style_img, input_img, num_steps=num_steps,\n                            style_weight=style_weight, content_weight=content_weight)\n\noutput_image = convert_to_pil_image(output)\n\noutput_path = \"output_image.jpg\"\nsave_output_image(output_image, output_path)\n\n# Display content, style, and output images in a single row\nfig, axes = plt.subplots(1, 3, figsize=(15, 5))\naxes&#91;0].imshow(content_img.squeeze(0).permute(1, 2, 0).cpu().numpy())\naxes&#91;0].set_title('Content Image')\naxes&#91;0].axis('off')\naxes&#91;1].imshow(style_img.squeeze(0).permute(1, 2, 0).cpu().numpy())\naxes&#91;1].set_title('Style Image')\naxes&#91;1].axis('off')\naxes&#91;2].imshow(output_image)\naxes&#91;2].set_title('Output Image')\naxes&#91;2].axis('off')\nplt.tight_layout()\nplt.show()\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/2147"}],"collection":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2147"}],"version-history":[{"count":2,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/2147\/revisions"}],"predecessor-version":[{"id":2150,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=\/wp\/v2\/posts\/2147\/revisions\/2150"}],"wp:attachment":[{"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/laserphotonics.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}