ホームページ  >  記事  >  バックエンド開発  >  Python での画像スタイルの移行例

Python での画像スタイルの移行例

WBOY
WBOYオリジナル
2023-06-11 20:44:251322ブラウズ

画像スタイル転送は、ある画像のスタイルを別の画像に転送できるディープラーニングに基づくテクノロジーです。近年、画像スタイル転送技術は、芸術、映画、テレビの特殊効果の分野で広く使用されています。この記事では、Python言語を使用して画像スタイルの移行を実装する方法を紹介します。

1. 画像スタイル転送とは

画像スタイル転送では、ある画像のスタイルを別の画像に転送できます。スタイルは、アーティストの絵画スタイル、写真家の撮影スタイル、またはその他のスタイルにすることができます。画像スタイル転送の目的は、元の画像の内容を保持しながら、それに新しいスタイルを与えることです。

画像スタイル転送テクノロジーは、畳み込みニューラル ネットワーク (CNN) に基づく深層学習テクノロジーであり、その中心的なアイデアは、事前トレーニングされた CNN モデルを通じて画像のコンテンツとスタイル情報を抽出し、最適化手法を使用することです。 2 つを結合するか、新しい画像に合成します。通常、画像のコンテンツ情報は CNN の深い畳み込み層を通じて抽出され、画像のスタイル情報は CNN の畳み込みカーネル間の相関を通じて抽出されます。

2. 画像スタイルの移行を実装する

Python で画像スタイルの移行を実装する主な手順には、画像の読み込み、画像の前処理、モデルの構築、損失関数の計算、最​​適化メソッドを使用した反復処理と結果の出力が含まれます。 。次に、これらについて段階的に説明します。

  1. 画像のロード

まず、元の画像と参照画像をロードする必要があります。オリジナル画像はスタイルの転送が必要な画像であり、参照画像は転送の対象となるスタイル画像です。画像の読み込みは、Python の PIL (Python Imaging Library) モジュールを使用して実行できます。

from PIL import Image
import numpy as np

# 载入原始图像和参考图像
content_image = Image.open('content.jpg')
style_image = Image.open('style.jpg')

# 将图像转化为numpy数组,方便后续处理
content_array = np.array(content_image)
style_array = np.array(style_image)
  1. 画像の前処理

前処理には、元の画像と参照画像をニューラル ネットワークが処理できる形式に変換すること、つまり画像を Tensor に変換することが含まれます。標準化も同時に行います。ここでは、PyTorch が提供する前処理モジュールを使用して完了します。

import torch
import torch.nn as nn
import torchvision.transforms as transforms

# 定义预处理函数
preprocess = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 将图像进行预处理
content_tensor = preprocess(content_image).unsqueeze(0).to(device)
style_tensor = preprocess(style_image).unsqueeze(0).to(device)
  1. モデルの構築

画像スタイル転送モデルでは、大規模な画像データベースでトレーニングされたモデルを使用できます。一般的に使用されるモデルには、VGG19 や ResNet などがあります。ここでは VGG19 モデルを使用して完成させます。まず、事前トレーニングされた VGG19 モデルをロードし、最後の完全に接続された層を削除して、畳み込み層のみを残す必要があります。次に、畳み込み層の重みを変更することで、画像のコンテンツ情報とスタイル情報を調整する必要があります。

import torchvision.models as models

class VGG(nn.Module):
    def __init__(self, requires_grad=False):
        super(VGG, self).__init__()
        vgg19 = models.vgg19(pretrained=True).features
        self.slice1 = nn.Sequential()
        self.slice2 = nn.Sequential()
        self.slice3 = nn.Sequential()
        self.slice4 = nn.Sequential()
        self.slice5 = nn.Sequential()
        for x in range(2):
            self.slice1.add_module(str(x), vgg19[x])
        for x in range(2, 7):
            self.slice2.add_module(str(x), vgg19[x])
        for x in range(7, 12):
            self.slice3.add_module(str(x), vgg19[x])
        for x in range(12, 21):
            self.slice4.add_module(str(x), vgg19[x])
        for x in range(21, 30):
            self.slice5.add_module(str(x), vgg19[x])
        if not requires_grad:
            for param in self.parameters():
                param.requires_grad = False

    def forward(self, x):
        h_relu1 = self.slice1(x)
        h_relu2 = self.slice2(h_relu1)
        h_relu3 = self.slice3(h_relu2)
        h_relu4 = self.slice4(h_relu3)
        h_relu5 = self.slice5(h_relu4)
        return h_relu1, h_relu2, h_relu3, h_relu4, h_relu5

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = VGG().to(device).eval()
  1. 損失関数の計算

画像スタイルの移行の目的は、元の画像の内容を保持しながら新しいスタイルを与えることであるため、次のことを定義する必要があります。この目標を達成するための損失関数。損失関数は 2 つの部分で構成され、1 つはコンテンツの損失、もう 1 つはスタイルの損失です。

コンテンツ損失は、畳み込み層の特徴マップで元の画像と生成された画像の間の平均二乗誤差を計算することで定義できます。スタイル損失は、生成された画像の特徴マップと畳み込み層内のスタイル画像の間のグラム行列間の平均二乗誤差を計算することによって定義されます。ここでのグラム行列は、特徴マップの畳み込みカーネル間の相関行列です。

def content_loss(content_features, generated_features):
    return torch.mean((content_features - generated_features)**2)

def gram_matrix(input):
    batch_size , h, w, f_map_num = input.size()
    features = input.view(batch_size * h, w * f_map_num)
    G = torch.mm(features, features.t())
    return G.div(batch_size * h * w * f_map_num)

def style_loss(style_features, generated_features):
    style_gram = gram_matrix(style_features)
    generated_gram = gram_matrix(generated_features)
    return torch.mean((style_gram - generated_gram)**2)

content_weight = 1
style_weight = 1000

def compute_loss(content_features, style_features, generated_features):
    content_loss_fn = content_loss(content_features, generated_features[0])
    style_loss_fn = style_loss(style_features, generated_features[1])
    loss = content_weight * content_loss_fn + style_weight * style_loss_fn
    return loss, content_loss_fn, style_loss_fn
  1. 最適化メソッドを使用した反復

損失関数を計算した後、最適化メソッドを使用して、生成された画像のピクセル値を調整して、損失関数。一般的に使用される最適化手法には、勾配降下法や L-BFGS アルゴリズムなどがあります。ここでは、PyTorch が提供する LBFGS オプティマイザーを使用してイメージの移行を完了します。反復回数は必要に応じて調整できますが、通常は 2000 回反復するとより良い結果が得られます。

from torch.optim import LBFGS

generated = content_tensor.detach().clone().requires_grad_(True).to(device)

optimizer = LBFGS([generated])

for i in range(2000):

    def closure():
        optimizer.zero_grad()
        generated_features = model(generated)
        loss, content_loss_fn, style_loss_fn = compute_loss(content_features, style_features, generated_features)
        loss.backward()
        return content_loss_fn + style_loss_fn

    optimizer.step(closure)

    if i % 100 == 0:
        print('Iteration:', i)
        print('Total loss:', closure().tolist())
  1. 出力結果

最後に、生成された画像をローカルに保存し、画像スタイルの移行の効果を観察できます。

import matplotlib.pyplot as plt

generated_array = generated.cpu().detach().numpy()
generated_array = np.squeeze(generated_array, 0)
generated_array = generated_array.transpose(1, 2, 0)
generated_array = np.clip(generated_array, 0, 1)

plt.imshow(generated_array)
plt.axis('off')
plt.show()

Image.fromarray(np.uint8(generated_array * 255)).save('generated.jpg')

3. 概要

この記事では、Python 言語を使用して画像スタイル転送テクノロジを実装する方法を紹介します。画像をロードし、画像を前処理し、モデルを構築し、損失関数を計算し、最適化メソッドを繰り返し実行して結果を出力することで、ある画像のスタイルを別の画像に転送できます。実際のアプリケーションでは、より良い結果を得るために、さまざまなニーズに応じて参照画像や反復回数などのパラメーターを調整できます。

以上がPython での画像スタイルの移行例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。