Python
機械学習
DeepLearning

pythonで○べひろしを回す

○べひろしさんを回したいと思ったことありませんか?

○べひろしさんといえば、彫りの深さが魅力ですよね?
でも、写真ではどうしても2次元になってしまい、良さも半減してしまいます。がっかりですね。

そんなあなたにぴったりな、いい論文を見つけました。

中身は、CNNで2次元の顔写真を3次元に復元するというもの。
しかも、彫りの深い外国人でチューニングされているため、○べひろしさんにぴったりですよね。

online demoでは素早く3次元に復元してくれます。

screenshot.png

これだけでも十分楽しめるのですが、今回は緑のボタンでダウンロード出来るOBJファイルというので遊んでみようと思いました。

OBJ ファイルとは

obj fileは3Dモデル用のファイル形式でWavefrontという会社のAdvanced Visualizerというソフト用に出来たものらしいです。
開けてみると今回は

v 51.639737 50.000000 42.500000 0.086275 0.070588 0.058824
v 51.641337 50.000000 43.000000 0.086275 0.070588 0.058824
v 51.664167 50.000000 42.000000 0.086275 0.070588 0.058824
...
f 13709 13414 13711
f 13578 13711 13414
f 13578 13414 13415
f 13578 13415 13417

みたいなテキストファイルでした。
よくわからないファイル形式には慣れているのと深夜テンションとでpythonでいじってみることに。

ファイルの中身は、1列目はvとfの2種類があることがわかりました。
本当はもっと種類があるみたいですが、今回は

v:頂点(色付き)
x座標 y座標 z座標 R G B
f:面
頂点1 頂点2 頂点3

という構成でした。
fの頂点はvの行番号。(1始まり)

pythonで回す。

とりあえずpandasで読んで可視化してみました。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D, art3d
from tqdm import tqdm_notebook
%matplotlib inline

# 頂点データを取り出す。
df_obj_v = pd.read_csv('abe.obj.txt', sep=' ', header=None)
df_obj_v.columns = ['data', 'x', 'y', 'z', 'r', 'g', 'b']
df_obj_v = df_obj_v[df_obj_v['data'] == 'v']
df_obj_v = df_obj_v[['x', 'y', 'z', 'r', 'g', 'b']].astype(np.float64)

# 面データを取り出す。(実は使ってない)
df_obj_f = pd.read_csv('abe.obj.txt', sep=' ', header=None, usecols=[0,1,2,3])
df_obj_f.columns = ['data', 'v1', 'v2', 'v3']
df_obj_f = df_obj_f[df_obj_f['data'] == 'f']
df_obj_f = df_obj_f[['v1', 'v2', 'v3']].astype(np.int)
df_obj_f = df_obj_f.reset_index(drop=True)

# zが低い点を消す。
df_obj_v_u = df_obj_v[df_obj_v.z > 40]

for i in tqdm_notebook(range(120)):
    e = 30
    azim = 90 + 3 * i

    fig = plt.figure(dpi=100)
    ax = Axes3D(fig, aspect='equal')

    ax.scatter(df_obj_v_u['x'], df_obj_v_u['y'], df_obj_v_u['z'], s=0.5, facecolors=df_obj_v_u[['r', 'g', 'b']])
    ax.view_init(elev = e, azim=azim)
    # 数字を0詰めにしないとImageMagickがうまく行かない。
    plt.savefig('for_gif_dot/{}.png'.format(str(i).zfill(3)), bbox_inches='tight')
    plt.close()

大量に出力しておいてImageMagickでgifにする。
ここでImageMagickを使うときは0詰のファイル名にしないとうまくいかない事に注意してください。

$ cd for_gif_dot
$ convert -delay 5 -loop 0 *.png movie.gif

回りました。

movie.gif

よかったですね。

最後に

ポリゴン化はノイズが多くて出来ませんでしたが、詳しい内容や、ポリゴン化のことはこちらに書いておきました。
もしよければご覧下さい。

pythonで○べひろしを回す(はてなブログ)