はじめに
この記事はJetson Nanoを使って解像度の低い画像から解像度の高い画像を作る「スーパーレゾリューション」を試したものである。いつも使っているboss.jpgの画像がピンボケしているのが気になっていたので実験。
ソースコードは下記のものを利用。
https://github.com/idealo/image-super-resolution
ディレクトリ構成
「$HOME/Documents/SuperResolution」以下に環境を構築する。最終的には下記のようになる。
├── Documents/
│ ├── SuperResolution/
│ │ ├── image-super-resolution/
│ │ ├── super_res.py
│ │ ├── Pipfile
│ │ └── Pipfile.lock
事前準備
「Jetson Nanoの実験環境のまとめ」でセットアップを行なった後、追加で次の作業を行う。
aptによる関連パッケージのインストール
まずはaptで関連パッケージのインストール。
-
git-lfs
がないとgit lfsのサブコマンドが使えず重みをダウンロードできない - 他のパッケージは
numpy
およびscipy
のために必要
apt install git-lfs libfreetype6-dev libblas-dev liblapack-dev libatlas-base-dev gfortran
Pipenvにより環境の構築
$HOME/Documents/SuperResolution以下にPipenvを使って環境を構築する。
yamamo-to@jetson-nano:~$ mkdir Documents/SuperResolution
yamamo-to@jetson-nano:~$ cd Documents/SuperResolution
yamamo-to@jetson-nano:~/Documents/SuperResolution$
「Jetson NanoにPipenvでTensorFlowをインストール」と同じように、~/Documents/SuperReoslution以下にPipfileを作成。ただし全く同じではなく指定されているバージョンを用いるよう微修正。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[[source]]
name = "nvidia"
url = "https://developer.download.nvidia.com/compute/redist/jp/v42"
verify_ssl = true
[dev-packages]
[packages]
numpy = {version="==1.16.2", index="pypi"}
grpcio = {version="*", index="pypi"}
absl-py = {version="*", index="pypi"}
py-cpuinfo = {version="*", index="pypi"}
psutil = {version="*", index="pypi"}
portpicker = {version="*", index="pypi"}
six = {version="*", index="pypi"}
mock = {version="*", index="pypi"}
requests = {version="*", index="pypi"}
gast = {version="*", index="pypi"}
h5py = {version="*", index="pypi"}
astor = {version="*", index="pypi"}
termcolor = {version="*", index="pypi"}
tensorflow_gpu = {version="==1.13.1+nv19.5", index="nvidia"}
imageio = {version="*", index="pypi"}
Keras = {version="==2.2.4", index="pypi"}
tqdm = {version="*", index="pypi"}
[requires]
python_version = "3.6"
[pipenv]
allow_prereleases = true
Pipfileを置いた後、pipenv install
で構築する。
yamamo-to@jetson-nano:~/Documents/SuperResolution$ pipenv install
ISRのインストール
Image Super Resolution(ISR)パッケージをインストールする。公式の手順ではpip install ISR
が推奨されているがTensorFlowのバージョンミスマッチにより失敗する。そのためソースコードからインストールする。
yamamo-to@jetson-nano:~/Documents/SuperResolution$ git clone https://github.com/idealo/image-super-resolution.git
yamamo-to@jetson-nano:~/Documents/SuperResolution$ cd image-super-resolution
yamamo-to@jetson-nano:~/Documents/SuperResolution/image-super-resolution$
重みをダウンロードする。
yamamo-to@jetson-nano:~/Documents/SuperResolution/image-super-resolution$ git lfs pull
setup.pyを編集してinstall_requiresから'tensorflow==1.13.1'を削除する。diffを取ると下記の通り。
$ git diff
diff --git a/setup.py b/setup.py
index df108a8..e49dd6c 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@ setup(
description='Image Super Resolution',
long_description=long_description,
license='Apache 2.0',
- install_requires=['imageio', 'Keras==2.2.4', 'numpy==1.16.2', 'tensorflow==1.13.1', 'tqdm'],
+ install_requires=['imageio', 'Keras==2.2.4', 'numpy==1.16.2', 'tqdm'],
extras_require={
'tests': ['pytest==4.3.0', 'pytest-cov==2.6.1'],
'docs': ['mkdocs==1.0.4', 'mkdocs-material==4.0.2'],
編集後、以下のようにインストールする。
yamamo-to@jetson-nano:~/Documents/SuperResolution/image-super-resolution$ pipenv run python3 setup.py install
実験
$HOME/Documents/SuperResolutionで作業を行う。
cd ~/Documents/SuperResolution
ソースコードの準備
以下のようなsuper_res.py
を作成する1。
import argparse
import numpy as np
from PIL import Image
from ISR.models import RDN
def main():
parser = argparse.ArgumentParser()
parser.add_argument('weights_hdf5')
parser.add_argument('input_image')
parser.add_argument('output_image')
args = parser.parse_args()
img = Image.open(args.input_image)
lr_img = np.array(img)
rdn = RDN(arch_params={'C':6, 'D':20, 'G':64, 'G0':64, 'x':2})
rdn.model.load_weights(args.weights_hdf5)
sr_img = rdn.predict(lr_img)
new_img = Image.fromarray(sr_img)
new_img.save(args.output_image)
if __name__ == '__main__':
main()
入力画像の準備
boss.jpgに対して実行するとOOM(Out Of Memory)エラーが発生するので、切り出して小さな画像 boss_crop.jpg を使う。
convert boss.jpg -crop 250x240+150+50 boss_crop.jpg
プログラムの実行
先ほど作成したsuper_res.py
を実行する。実行文が長くなっているのは重みファイルが深いところにあるため。
pipenv run python3 super_res.py image-super-resolution/weights/sample_weights/rdn-C6-D20-G64-G064-x2/ArtefactCancelling/rdn-C6-D20-G64-G064-x2_ArtefactCancelling_epoch219.hdf5 boss_crop.jpg boss_hires.jpg
実行ログに「メモリが足らないよ」という警告が散々出るがthis is not a failure
を信じることにする。
結果
成功すると入力画像の倍のサイズの画像が作成される。比較のためにオリジナル画像をImageMagickのconvertでresizeした画像も合わせて掲載する。
クロップ画像縦横2倍(500x480) by ImageMagick
差が分かりにくいので差分(スーパーレゾリューション - クロップ画像縦横2倍)を取る。
うん、それなりに違うようだ。
そもそも論
スーパーレゾリューションに期待してしていたのは(いつも使っているboss.jpgの)「ピンボケ画像が綺麗になる」ということであり、拡大して綺麗になることではない。ソリューションの選択ミスだったかも知れない。
それならば手動でオートエンコーダしてみよう、ということで画像を一旦半分にして、このスーパレゾリューションに掛けてみる。
(左)オリジナル画像 (右)画像を一旦半分にしてスーパーレゾリューション
細かい部分では「障子の模様が変わった」「カタカナが読めない」などあるものの、それなりに改善されたように見える。
まとめ
Jetson Nanoを使ってスーパーレゾリューションを行い、画像を一度半分にしてスーパーレゾリューションを適用することにより、ピンボケ画像の改善が見られた。
-
このプログラムは一度掴んだGPUのメモリが解放されない問題があるので、一回実行したら再起動が必要である。 ↩