txtファイルとして出力した画像ファイルを、Pythonを用いて3Dプロットで可視化してみます。
はじめに
こんにちは、@bioerrorlogです。
先日、画像ファイルというものは所詮数値に過ぎないと改めて実感する出来事がありました。 画像解析ソフトFiji1で画像解析をしていると、面白いものを見つけたのです。 名前をつけて保存"Save as"の欄に、"Text Image"というファイル形式がありました。
画像ファイルの保存形式としてはJPEGやPNGなどを使っていましたが、"Text Image"形式とはどういうことでしょうか。 試してみると、0から255までの数値で各ピクセルが表現されたtxtファイルが出力されました(Fig. 1)。
ひとつ思いついたのは、このtxtファイルをもとにして、3Dグラフを描画したいということです。 画像ファイルが数値の連なりに過ぎない、ということを実感できるいい経験になると思います。
それではPythonを使ってやっていきます。
作業環境
Pythonバージョン:
$ python3 --version Python 3.6.7
Ubuntu18.04.1 LTS を
Windows10の上に、VMwareによって構築した仮想環境で起動しています。
www.bioerrorlog.work
画像をtxtファイルから3Dグラフで可視化する
txtファイルの読み込み | pd.read_csv()
まずは、Fijiで出力したtxtファイル"peterpan_syndrome.txt"をpandasのread_csv()で読み込んで、行数と列数を出力してみます。 正しく読み込めていれば、画像のピクセル数"796 800"が表示されるはずです。
import pandas as pd img_txt = pd.read_csv('peterpan_syndrome.txt',sep='\t',header=None) row_count = img_txt.shape[0] col_count = img_txt.shape[1]
print(col_count,row_count) 796 800#出力
予想通りの出力が得られ、正しく読み込めたのがわかります。
ちなみに、txtファイルだからといってread_table()で読み込もうとすると、
FutureWarning: read_table is deprecated, use read_csv instead, passing sep='\t'. img_txt = pd.read_table('peterpan_syndrome.txt',header=None)
read_table()は良くないからread_csv()でsep='\t'を使いなさいと怒られてしまいました。
XYの用意 | np.arange() / np.meshgrid()
私が描画しようとしている3Dグラフは、X軸とY軸がそれぞれ画像のwidthとHeightに相当し、Z軸が格子状にtxtファイルの値を示すものです。
そこでX軸とY軸を得るために、xyに1間隔でそれぞれのピクセル数を上限とした配列を与え、そこから格子列XYを生成します。
import numpy as np x = np.arange(0, col_count, 1) y = np.arange(0, row_count, 1) X, Y = np.meshgrid(x, y)
これで、必要なXYを規定できました。
ここからは、3Dグラフにプロットしていきます。
3Dグラフプロット | mplot3d
ModuleNotFoundError: No module named 'tkinter'
しかし、3dグラフの描画に必要なモジュールのひとつmatplotlibをインポートをした際に、エラーを吐かれてしまいました。
from matplotlib import pyplot as plt
~ ModuleNotFoundError: No module named 'tkinter'
'tkinter'モジュールがない、と怒られてしまった訳です。 しかしここで、'tkinter'モジュールをインストールしようとしても、上手くいきませんでした。
解決策を探すと、同じ問題に当たった人を見つけました。
これによると、'python3-tk'をインストールすればいいようです。
$ sudo apt install python3-tk
私もこれで、上記のエラーが解消されました。
mplot3dで3Dグラフを描画する
それでは、ついに3Dグラフを描画します。
3Dグラフの描画には、mplot3 Toolkitという便利なライブラリがあるようです。
https://matplotlib.org/tutorials/toolkits/mplot3d.html#sphx-glr-tutorials-toolkits-mplot3d-pymatplotlib.org
このmplot3 Toolkitドキュメントにしたがって、3Dグラフの描画処理を書いていきます。 今回は、きれいなグラフになりそうなFilled contour plots "contourf()"を用いて描画しました。
from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = Axes3D(fig) ax.contourf(X,Y,img_txt) plt.show()
これで、上手くいくはずです。 ここまでのコードをすべてまとめます。
import pandas as pd from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np img_txt = pd.read_csv('peterpan_syndrome.txt',sep='\t',header=None) row_count = img_txt.shape[0] col_count = img_txt.shape[1] x = np.arange(0,col_count,1) y = np.arange(0,row_count,1) X, Y = np.meshgrid(x, y) fig = plt.figure() ax = Axes3D(fig) ax.contourf(X,Y,img_txt) plt.show()
これを実行すると、じつに美しい3Dプロットが得られました(Fig. 2)。
お見事です。
おわりに
今回は、画像をtxtファイルで出力し、それをもとにPythonで3Dプロットを行いました(Fig. 3)。
このように、私のような経験の浅いものでも簡単にプロットを行えるのが、Pythonのいいところでしょう。 今回使用したmplot3dも、公式のチュートリアルドキュメントが大変充実していました。
ところで、今回使ったFilled contour plots以外にも、mplot3には多くの描画形式がありました。 また、カラーなどの多くのオプションもあり、まだまだそれらも使いこなせていません。
Pythonでのデータ可視化というのも、いろいろ遊んで慣れていきたいものです。
[関連記事]
-
Fiji: ImageJ, with "Batteries Included" - 生物系では広く利用されているオープンソースの画像解析ソフトです。↩