「頑張れ宗谷本線」のモザイクアートを作る

ディープラーニングを申し訳程度に入れてモザイクアートの自動生成を行います。「頑張れ宗谷本線」のモザイクアートに触発されて作ったものです。

※この記事は趣味全開な内容です。過度なテクノロジーは期待しないでください。

## 宗谷本線
せっかくなので宗谷本線について簡単な解説をしましょう。宗谷本線とは北海道を走る「日本最北端」の鉄道路線です。

![souya_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/745dbd45-f190-22ed-fc6c-f4f6a91eea34.jpeg)

地図（[＊1]より）の赤で囲った部分が宗谷本線です。拡大してみましょう（[＊1]より）。

![souya_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/aff09f23-29b9-e43d-a4c8-be57e29bd87f.jpeg)

旭山動物園で有名な旭川駅から、日本最北端の駅である稚内駅までを結ぶのが宗谷本線です。ひとまず**日本最北端の駅＝稚内**であるというのを知っておいてください。沿線情報は書き出すと長くなってしまうので省略しますが、ほかには音威子府（おといねっぷ）というなんだかかっこいい名前の場所があるなぐらいに認識しておけばさらに良いです。

この地図を見ると「最果てに向かうなんだか寂しい路線だな」というイメージを持つかもしれません。しかし、つい35年ほど前まではもっと賑やかな路線でした。これは1983年の時刻表から([＊2])です。

![souya_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/ea90a901-5afb-8390-cc88-fa095ddfe050.jpeg)

つい35年ほど前は、道北には今は亡き鉄道網が網の目のように張り巡らされていました。宗谷本線の音威子府や名寄（なよろ）は交通の要衝であったのがわかります。これは道北に限った話ではなく、北海道全体でそうでした。1983年の北海道の路線図は次のとおりです。ぜひ最初の2019年の路線図と見比べてみてください。

![souya_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/9690f943-0ec9-96bd-4c34-e3d57643f28d.jpeg)

もはや同じ北海道と思えないぐらい、現在では消えた路線が大量にありました[^1]。

[^1]: これらの路線が消えてしまった原因はいろいろありますが、大きな要因としては、戦後国の政策により、国鉄が引き揚げ者や満鉄社員を引き受けたことで人件費が圧迫したこと[^2][^3]、その余波でローカル線の廃止が進められたこと、モータリゼーションの普及、北海道の成長を下支えした石炭産業が高度経済成長期に失速したこと、北海道全体の人口が日本全体よりもいち早く減少傾向になったこと[^4]などが挙げられます。これら以外にもあるでしょうが、複合的かつ根が深い問題となっているのが実情です。
[^2]: 中湧別にある名寄本線の資料にそのような記載あり　https://twitter.com/koshian2/status/1105462262959992839/photo/1
[^3]: 国土交通省の白書より。国鉄の損益状況の推移の資料あり。それによると、支出高騰の大部分が人件費と物価の高騰で、これが大きく収益を悪化させていたのがわかります　https://www.mlit.go.jp/hakusyo/transport/shouwa57/ind020101/001.html
[^4]: 北海道全体で人口減少が始まるのはおおよそ平成以降ですが、支庁単位で見れば石狩支庁（札幌近郊）以外は、1960～1980年代から人口減少が始まっていた点には留意すべきです。　https://pucchi.net/hokkaido/geo/population02.php

宗谷本線は、道北の大動脈ともいえる路線で、寝台列車が毎日運行されていたこともありました。1983年の時刻表（[＊2]）からです。

![souya_05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/a649498e-5316-b551-c1df-1eb7436fe669.jpeg)

一方で2019年現在の時刻表([＊1]より)は以下のとおりです。

![souya_06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/11123593-1f23-8433-5833-0745bb7e420e.jpeg)

旭川～名寄は若干今のほうが便利な感はありますが、名寄～稚内間は随分寂しくなりましたね。かつての急行列車はほとんど消滅しましたし、普通列車もかなりが姿を消しました。こんなに時刻表がスカスカで寂しい路線ではなかったのです。逆に言えば、現在の宗谷本線はかつて豪華な大動脈の面影が残っている路線、とも言うことができます。

そんな宗谷本線ですがついに存続を問われる路線となりました。[JR北海道の資料](https://www.jrhokkaido.co.jp/pdf/161215-5.pdf)からです

![souya_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/2c10959b-1831-5c77-5bd8-13f1af346447.png)

日本最北の路線も、残念ながらいつまでもあり続ける保証はありません。

## 頑張れ宗谷本線
そんな宗谷本線ですが、今年に入って景気のいい話があります。「風っこそうや」というトロッコ列車が走るのです。（画像は[JR北海道のホームページ](https://www.jrhokkaido.co.jp/travel/kazekko-soya/index.html)より）

![souya_08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/d9f26d51-ea07-6546-d4f1-6eb4c7cf703d.jpeg)

以前から北海道ではノロッコなど、トロッコ列車の運行はありましたが、この「風っこそうや」の場合は、JR東日本から車両を借りて運行するという非常に珍しい試みなのです。

沿線の有志の方が行っている応援プロジェクトでは、クラウドファンディングで目標額80万円のところを、11日間で103万円を達成したとのことです。それだけ注目度が高いことであるのがわかります。（画像は[クラウドファンディングのサイト](https://readyfor.jp/projects/gogosoya)からです）

![a17c9aaa61e80a1bf71d0d850af4e5baa9800bbd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/16e7998f-e567-7abd-1efd-e3dbf6f4269a.png)


今回はこの「頑張れ宗谷本線」のようなイラスト（モザイクアートと言うそうです）を自分も作ってみることにしました。地元の方が愛を込めて作ったものには遠くは及びませんが、それっぽいものを作ることができました。

## モザイクアートの理論
ここから技術的な話に入ります。モザイクアートは実は機械的に作ることができます。モザイクアートのベースの画像を$B$とし、実際に貼り付ける参照画像を$R_k (k=1,\cdots,M)$とします。

モザイクアートの理論とは、ベース画像をいくつかのパッチ（四角形）に分割し、それに対して「どの参照画像を配置すればいいか」という問題を解くことです。これを定式化しましょう。

ベース画像を$(N_x, N_y)$というパッチに分割するとします。すると、ベース画像のパッチは、$B_{i, j} (i=1,\cdots,N_x, \quad j=1,\cdots,N_y)$という表記で表されます。$B_{i, j}$に対する最適な参照画像$R_{k^*}$の求め方は、

```math
\newcommand{\argmin}{\mathop{\rm arg~min}\limits}
k^*_{i,j}=\argmin_{k=1\to M}\mathcal{L}(\mathcal{M}(B_{i,j}), \mathcal{M}(R_k)) \tag{1}
```

を解くことです。ここで、$\mathcal{L}(\cdot)$は損失関数、$\mathcal{M}(\cdot)$は画像同士の近さを測る何らかの指標です。

損失関数$\mathcal{L}(\cdot)$は平均二乗誤差（L2ノルム）や、平均絶対値誤差（L1ノルム）などを使います。今回のケースでは、平均絶対値誤差を使います。

$\mathcal{M}(\cdot)$が直感的にわかりづらいですが、最も単純なのがピクセル同士の値を比較するということです。この場合は、ディープラーニングの**Mean absolute error**で最小化するのと同じです。

もう少し発展させたケースでは、$\mathcal{M}(\cdot)$に訓練済みモデルの特徴量を使うということです。つまり、例えば、訓練済みVGG16の中間層の値を取って、その値が近いもの同士を配置するという、スタイル変換における**[Perceptual loss](https://cs.stanford.edu/people/jcjohns/papers/eccv16/JohnsonECCV16.pdf)**と同じになります。ここらへんの発想は[Reframe Visualization](https://qiita.com/koshian2/items/89ada5223c18e930f801)にかなり近いです。

## 実装
ベース画像は、自分が名寄駅で撮ったキハ54を使います。参照画像は、画像処理で頻繁に使われる[ImageNet](http://www.image-net.org/)のValidationデータセット（5万枚）を使います。ベース画像は以下のとおりです。

![souya_09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/c2c7ceb3-d9a5-d5c9-adb2-5e74ba5fb062.jpeg)

この（元）画像の解像度は3968×2976ですが、縦93pixel×横124pixelを1つのパッチとし、32×32の合計1024枚のパッチに分割します。1024枚のパッチに対して、参照画像の最適な割り当てを計算します。

そして$\mathcal{M}(\cdot)$は以下の4ケースを使いました。

* ピクセル同士の差（Identity）
* 訓練済みVGG16のblock1_poolの値
* 訓練済みVGG16のblock2_poolの値
* 訓練済みVGG16のblock3_poolの値

VGG16は、ディープラーニングの伝統的なモデルですが、スタイル変換では未だに優位性があることが確認されています。VGG16は以下のような構成です（[VGGの論文](https://arxiv.org/pdf/1409.1556.pdf)より）。

![souya_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/7b363733-137d-e4f2-b236-2ef8c47bad2a.png)

## 結果
$\mathcal{M}(\cdot)$を変えてモザイクアートを作ると次のようになりました。ただし、block1_poolのケースではメモリ（RAM）の制約で参照画像の枚数を25000枚に減らしています。

![souya_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/c5f65e17-98f3-a3c0-db87-f5466715c2d4.jpeg)

ピクセル差の場合は、全体的にのっぺりとした印象（まだ写真っぽい）、**block1_poolは適度にゴツゴツしていて良さそう**（人間が作ったような感じ）受けます。モザイクアートの印象は、画像の拡大率によってかなり変わるので、いろいろなスケールで見てみるのをおすすめします。

残りの2ケース、特にblock3_poolは元の列車の形を認識するのが難しくなってしまいましたね。これは情報を落としすぎです。

最初の2ケースを拡大してみましょう。

### ピクセル差で最適化（Identity）
![collage_identity.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/86143dd2-5e1c-3b07-021b-ed36ed9a1619.jpeg)


### VGGのblock1_poolで最適化
![collage_block1pool_25000.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/7f21073a-f950-b240-32cc-b6f6f7784c1d.jpeg)

いずれのケースでも「普通」や「ワンマン」のような、文字や輪郭の部分が潰れてしまうのは致し方ないです。そこを入れたいのなら手動で再挿入するのが手っ取り早いかと思います。

## なぜこうなるのか
$\mathcal{M}(\cdot)$について、ピクセル差を取る場合は発想がわかりやすいのですが、なぜVGGの特徴量を取るのかということに補足しておきましょう。

この記事においてニューラルネットワーク（VGG16）の特徴量を取った理由とは、**再構成後の画像の粗さのコントロール**です。訓練済みVGG16のやっていることは、画像を入力して、どういう画像が映っているかという意味的な情報を出力します。したがって、深い層（例：block3_poolなど）を取るほど、元のピクセル情報は削ぎ落とされて、全体のぼんやりした情報を参照するようになります。block3_poolなどで最適化したときに、元の列車の形を認識しづらくなった理由の1つはこれです。

別の言い方をすれば、ニューラルネットワークの特徴量を使う、ディープラーニングのアプローチを使うことで、自動的に生成するモザイクアートの表現に幅を持たせることができます。

## 問題点
浅い層の特徴マップを取る場合、メモリをひたすら食いがちなので、そこでのargminの計算が時間がかかりました。何らかの次元削減か、昨日ツイッター上で見つけた[近似最近傍探索の最前線](https://speakerdeck.com/matsui_528/jin-si-zui-jin-bang-tan-suo-falsezui-qian-xian)などの手法を使うと計算時間を短縮できそうです。

## 感想
多分こんな感じでできるだろうと思って実装したら、そこそこ形になりました。ひとまず形になってよかったです。以前、[ディープラーニングのモザイク除去の薄くない薄い本を書いた](https://note.mu/koshian2/n/naa60d5c9ebba)のですが、このアート手法も「モザイクアート」ということで、何かと自分はモザイクに縁があるみたいです。

宗谷本線は非常に面白く楽しい場所なので、ぜひ遊びに行ってみてください。自分も近いうちに（この記事を書いた7/30時点）に風っこそうやに乗りに行くので楽しみです。

## コード
https://github.com/koshian2/DeepMosaicArt

おおよそKerasの実装です。Pythonで100行も行きません。

## 引用元
[＊1]:JTB小さな時刻表　春号, JTBパブリッシング, 2019年2月
[＊2]:国鉄監修時刻表, 日本交通公社 ,1983年8月