search
LoginSignup
3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

ubiregiUbiregi Advent Calendar 2019 Day 5

posted at

updated at

Organization

葛飾北斎になりたい

Ubiregi Advent Calendar 2019 5日目です。

またまたフロントエンドエンジニアのコジャが担当します。

流石にそろそろ疲れてきました。今回のアドベントカレンダー、3記事目です。仕事中もコード書いて、仕事終わったら記事を書くためにコード書いて、すごいななんか。

もうコードを書くのは疲れた……。文章を書くのもめんどくさい。ああ……ああ……

絵を描こう。すげー絵を、描こう……

葛飾北斎

葛飾北斎ってみなさんご存知でしょうか。私は存じております。富士山書いた人です。多分もっと色々すごい。私は教養がない……。

葛飾北斎 - Wikipedia

葛飾 北斎(かつしか ほくさい、葛飾 北齋、宝暦10年9月23日〈1760年10月31日〉? - 嘉永2年4月18日〈1849年5月10日〉)は、江戸時代後期の浮世絵師。化政文化を代表する一人。
代表作に『富嶽三十六景』や『北斎漫画』があり、世界的にも著名な画家である。森羅万象を描き、生涯に3万点を超える作品を発表した。

すげぇ……なりてえ……。

ml5jsを使う

落ち着いた。

私は絵を描くのが別に嫌いでも好きでも上手くも下手でもないのですが、javascriptの力を借りて葛飾北斎のような絵を作り出していこうと思います。

使用するのはml5jsです。

ml5jsはwebで簡単に機械学習を利用できるよ!っていうライブラリです。内部ではtensorflowのモデルを利用しているようですね。私は絵だけでなく、機械学習もそこまでわからないのですが、今回はStyleTransferを使用します。

StyleTransfer?

StyleTransferはある画像に別の画像のスタイルを適用するといった技術です。

StyleTransferを行うにはまずスタイルを提供する画像を学習するといったプロセスが必要なのですが、超有名な葛飾北斎に関しては必要ありません。ml5jsには最初から富嶽三十六景(覚えた)を学習したモデルが標準搭載されています。

なにはともあれ

やっていきます。

まず公式のexampleからモデルを拝借しましょう。ここにあります。

ml5jsは変換時にこのモデルを参照するのですが、http://{domain}/models/wave/といったリクエストを投げてくるので、まぁpublic配下とかブラウザから見えるところにディレクトリごと置いておきましょう。

今回reactを使うので、reactとreact-domを依存パッケージに追加していますが、本来はml5jsだけでOKです。バージョンは現在(20191207)で最新の0.4.3です。

yarn add react react-dom ml5

以下はコードです。

import React, { useRef } from 'react'
import ml5 from 'ml5';

const StyleTrans = () => {
    const newImage = useRef(null);
    const srcImage = useRef(null);
    const file = useRef(null)
    return (
        <>
            <input ref={file} type="file" name="imageFile" onChange={(e) => {
                const reader = new FileReader()
                reader.onloadend = (e) => {
                    srcImage.current.src = e.target.result;
                }
                srcImage.current.onload = () => {
                    ml5.styleTransfer('models/wave')
                    .then(styleWave => styleWave.transfer(srcImage.current))
                    .then(result => {
                        newImage.current.src = result.src;
                    })
                }
                reader.readAsDataURL(file.current.files[0])
            }} />
            <img ref={srcImage} width={400} height={279} src="" alt="変換前の画像" />
            <img ref={newImage} src="" alt="変換後の画像" />
        </>
    )
}

色々ゴタゴタ書いてますが。大事な箇所は下記の部分です。models/waveというのがモデルの場所を示しています。
result.srcに変換後の画像が入っているので、それを出力して終わりです。簡単。

ml5.styleTransfer('models/wave')
.then(styleWave => styleWave.transfer(srcImage.current))
.then(result => {
    newImage.current.src = result.src;
})

変換元の画像は?

この辺はちゃんと調べられてないのですが。どうも画像のサイズ(容量)ではなく、解像度によって上手く変換できなかったりするようです。
解像度が高いとメモリリークを起こしてしまうので、今回はだいたい400*400に収まるくらいの画像を使用しました。

変換してみる

フジテレビ

iphoneの写真を漁っていると見つけたフジテレビです。
IMG_9954.JPG

なぜか後ろに雪山が見えます。
fuji.png

知らないガンダム

知らないガンダムです。ガンダムじゃないかもしれない。私はガンダムもあまりよく知りません。すいません。
IMG_0427.JPG

なんか溶けた。
gundom.png

中学生の頃の私

これは中学生の頃の私です。なぜか古き良き昭和を感じさせる。この写真は2005年(平成17年)の頃のはずなんですが、
mukashinoore.png

昭和を通り越してコンテンポラリーなアート作品のようになりました。すごい。
after.png

最後に

今回は葛飾北斎の富嶽三十六景を学習したモデルを利用しましたが、勿論、自身で学習させたモデルを作成することもできます。いつかやってみたいですね。

あとこの記事はアドベントカレンダー5日目に登録されていますが、今現在、2019年12月7日午前00:55です。遅刻したわ。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3
Help us understand the problem. What are the problem?