6_1_1:p5.jsを使った画像の画風変換(Style Transfer) ml5.js JavaScript

本稿は「ml5-examples/p5js/StyleTransfer/StyleTransfer_Image」で公開されているサンプルの解説です。

次のリンクをクリックすると、実際の動作が確認できます。「p5.jsを使った画像の画風変換

これは、入力画像を、葛飾北斎風タッチで描くとこうなり、ピカビア風タッチで描くとこうなる、というようなことです。

HTML

<p id="statusMsg">モデルの読み込み中...</p>
<button id="transferBtn">変換</button>
<p>入力画像:</p>
<img src="img/patagonia.jpg" alt="input img" id="inputImg">
<div id="styleA">
  <p>スタイルA:神奈川沖浪裏(かながわおきなみうら), 1829 - 葛飾北斎</p>
  <img src="img/wave.jpg" alt="style one">
</div>
<div id="styleB">
  <p>スタイル B:ウドニ―(若いアメリカの少女:ダンス), 1913 - フランシス・ピカビア</p>
  <img src="img/udnie.jpg" alt="style two">
</div>

CSS:入力画像はこのCSSによって、全部正方形として扱われます。

img {
    width: 250px;
    height: 250px;
    display: inline;
}

sketch.js

let inputImg;
let statusMsg;
let transferBtn;
let style1;
let style2;

function setup() {
    noCanvas();
    // ステータスメッセージを取得
    statusMsg = select('#statusMsg');

    // 入力イメージを取得
    inputImg = select('#inputImg');

    // [変換]ボタン
    transferBtn = select('#transferBtn')

    // ml5.styleTransfer(model, ?callback)
    // 別個の訓練済みモデルを使って、2つのスタイルを作成する
    style1 = ml5.styleTransfer('models/wave', modelLoaded);
    style2 = ml5.styleTransfer('models/udnie', modelLoaded);
}

// モデルが読み込まれたときに呼び出される関数
function modelLoaded() {
    // モデルが両方とも読み込まれたことを確認
    if (style1.ready && style2.ready) {
        statusMsg.html('準備完了');
        transferBtn.mousePressed(transferImages);
    }
}

// 変換を両方の画像に適用
function transferImages() {
    statusMsg.html('画風変換を適用中...');

    // 画風変換をinputに適用
    // .transfer(input, ?callback)
    style1.transfer(inputImg, function(err, result) {
        //console.log(result)
        // resultは<img src=​"data:​image/​png;​base64,iVBORw..."> src値にデータURIが使われている
        // resultは<img> HTML要素

        // 与えられたsrcとalternateテキストで、DOMに<img>要素を作成する。
        // createImg(src, [alt], [successCallback])
        // https://p5js.org/reference/#/p5/createImg

        // 指定された親に、要素を割り当てる
        // https://p5js.org/reference/#/p5.Element
        createImg(result.src).parent('styleA');
    });

    style2.transfer(inputImg, function(err, result) {
        createImg(result.src).parent('styleB');
    });

    statusMsg.html('終了');
}

HTML要素で本来的に必要なのは、入力のimg要素と、変換結果を表示する要素だけです。

<img src="img/patagonia.jpg" alt="input img" id="inputImg">
<div id="styleA">
<div id="styleB">

ml5.styleTransfer()には、画風変換モデルへのパスと、モデルが読み込まれたときに呼び出すコールバック関数を与えます。すると、StyleTransferオブジェクトが得られます(style1)


style1 = ml5.styleTransfer('models/wave', modelLoaded);

変換は、StyleTransferオブジェクトのtranfer()メソッドに、入力イメージとコールバック関数を渡して実行します。ただしこれは、モデルの読み込みが終わってから行う必要があります。

style1.transfer(inputImg, function (err, result) {...

コールバック関数には変換結果(result)が、<img src=​"data:​image/​png;​base64,iVBORw...">という形式で渡されます。これは、data:が頭についたデータURIという形式で、画像データはBASE64という方法でエンコードされています。この<img>要素のsrcプロパティをp5.jsのcreateImg()に渡すと変換結果の画像を作成することができます。

createImg(result.src).parent('styleA');

舞台裏ではかなり面倒なことが行われているはずなのですが、ml5.jsのおかげでJavaScriptコードは簡単です。試しに下図の左の写真を入力画像として与えると、右の葛飾北斎風タッチの画像が得られました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA