Google Colaboratoryで画像表示してみる
最近、やっているGoogle Colaboratory
関連のエントリーの続きです。
Google Colaboratory
でOpenCV
を使おうと思っていましたが、このあたりの書き方がJupyter Notebook
とはちょっと違うようだったのでメモ。
作業を始めてわかったのですが
ファイルを確認すると「空」でした!
このように、前回のエントリーでインスタンスに接続したGoogle Driveのマウントは消えています。またファイルアップロードを過去に行っていても そのファイルもなくなるようです。つまり、インスタンス起動の制限時間内に収まらなかった場合、最後の状態が保持されるわけではないようです。 過去のエントリーにも追加が必要ですね。(初期インスタンスイメージをロードする感じなんでしょうね)
マウント処理は毎回やらないとダメそうですね…
ファイルをアップロードして表示を行う
では、前回のエントリー同様にファイルアップロードを行ってみます。
from google.colab import files uploaded = files.upload()
これでapple.jpg
という画像ファイルをアップロードすることができました。
では、画像ファイルを表示してみます。
notebookで単純に画像を表示するならIPython.displayモジュールのdisplay_*メソッドが使えるようです。
IPythonとは、Pythonの対話型インタプリタを強力に拡張したもののようです。
- 強力なインタラクティブシェル
- Jupyterのカーネル
- インタラクティブなデータの視覚化とGUIツールキットの使用をサポート
- フレキシブルで埋め込み可能な通訳者が自分のプロジェクトに読み込み
- 使いやすい、並列コンピューティングのための高性能ツール
以上のような機能があります。notebook上で保管がモジュールの保管が聞くのもこのおかげのようです。
ドキュメントをみると
こんなふうな感じです。jpegの他にもHTML、pdf、png、SVG、markdownなんかも表示ができるようです。 では実行してみましょう。
from IPython.display import Image,display_jpeg display_jpeg(Image('apple.jpg'))
無事に画像が表示されました。 pngの場合にはdisplay_jpeg()の代わりにdisplay_png()とするような感じです。
from IPython.display import Image,display_png display_png(Image('Lenna.png'))
こんな感じで実行できます。
透過色があっても問題ありません!
背景が黒だとこんな風に見えます。
SVGファイルもこのような感じで表示できます。
from IPython.display import * display_svg(SVG('svg.svg'))
SVGの場合にはImageオブジェクトではなくSVGオブジェクトを引数にする必要があります。
pdfとmarkdownはうまく行かなかったみいです。(純粋なJupyterNotebookでは動くかもですが…ちょっと自信ないです)
そんなことをやりたかったわけではない
そうでした。本当にやりたかったのはOpenCVで処理した結果をGoogle Colabで表示したいのでした。 ということで、OpenCVで使ったサンプルをGoogleColabで実行してみると…
import cv2 img = cv2.imread('Lenna.png', 0) cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows()
おや?
インスタンスの異常終了をして、再起動までされてしまいました。うお。 調べてみるとNotebookで実行するのであればインライン(コマンドの出力)での出力にしないとまずいようです。 つまり先程のサンプルでは別ウインドウで画像を開こうとしているという点が失敗の原因になっていたということです。
今回はグラフなどの描画でもちいるmatplotlib
にOpenCVの結果を渡すことでNotebook環境(インライン)で表示することにします。
%matplotlib inline
を指定(出力先をインラインに指定)しないとだめそうなのですがうまく行っています。
import cv2 import matplotlib.pyplot as plt import os.path file = 'apple.jpg' if os.path.exists(file): img = cv2.imread(file) show_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(show_img)
修正点としてはcv2
からmatplotlib.pyplot
に変更した点が大きく違います。ちゃんと設定をすれば座標軸などは消すことはできますので安心してください。
import cv2 import matplotlib.pyplot as plt import os.path # 座標軸の削除処理 fig,ax = plt.subplots() ax.tick_params(labelbottom="off",bottom="off") ax.tick_params(labelleft="off",left="off") ax.set_xticklabels([]) ax.axis('off') file = 'apple.jpg' if os.path.exists(file): img = cv2.imread(file) show_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(show_img)
ファイルの書き込みもOpenCVの‘‘‘imwrite()‘‘‘メソッドでOKです。
import cv2 as cv import matplotlib.pyplot as plt fig,ax = plt.subplots() ax.tick_params(labelbottom="off",bottom="off") ax.tick_params(labelleft="off",left="off") ax.set_xticklabels([]) ax.axis('off') img = cv.imread('Lenna.png', cv.IMREAD_GRAYSCALE) cv.imwrite('Lenna_Gray.png', img) plt.imshow(img)
では画像を加工していくつかの表示を行いたい場合にはどうすればいいでしょうか。 いくつかの手法はあるのですが、今回は一つのfigure(枠)に複数のaxes(グラフ)をはりつけるという方法で実現をしようと思います。 OpenCVでタイル状に合成するのもいいですが、見た目がわかりにくいこともあるのでこちらの手法にしました。
今回はカラー画像とグレースケール化画像を並べて表示してみます。
import cv2 as cv import matplotlib.pyplot as plt import os.path def clearLabel(_ax): _ax.tick_params(labelbottom="off",bottom="off") _ax.tick_params(labelleft="off",left="off") _ax.set_xticklabels([]) _ax.axis('off') return _ax def readImage(_filename): if os.path.exists(_filename): img = cv.imread(_filename) return img img = readImage('Lenna.png') fig = plt.figure() ax1 = fig.add_subplot(1, 2, 1) clearLabel(ax1) show_img1 = cv.cvtColor(img, cv.COLOR_BGR2RGB) plt.imshow(show_img1) ax2 = fig.add_subplot(1, 2, 2) clearLabel(ax2) show_img2 = cv.cvtColor(img, cv.COLOR_BGR2GRAY) plt.imshow(show_img2) plt.show()
ポイントとなるのは以下の部分です。
fig = plt.figure() # figureの作成 ax1 = fig.add_subplot(1, 2, 1) # 1 rows 2 columnsの1columns目のaxes(向かって左側に表示される画像)をax1に代入 … ax2 = fig.add_subplot(1, 2, 2) # 1 rows 2 columnsの2columns目のaxes(向かって右側に表示される画像)をax2に代入
今回はfigure(枠)に2つの画像(axes(グラフ))を左右に並べるので1 rows 2 columns(1行2列)のfigureを作成して画像を配置することになります。 今回は左右に並べましたが、上下にするのであればパラメータを少し変更して
import cv2 as cv import matplotlib.pyplot as plt import os.path def clearLabel(_ax): _ax.tick_params(labelbottom="off",bottom="off") _ax.tick_params(labelleft="off",left="off") _ax.set_xticklabels([]) _ax.axis('off') return _ax def readImage(_filename): if os.path.exists(_filename): img = cv.imread(_filename) return img img = readImage('Lenna.png') fig = plt.figure() ax1 = fig.add_subplot(2, 1, 1) #変更 clearLabel(ax1) show_img1 = cv.cvtColor(img, cv.COLOR_BGR2RGB) plt.imshow(show_img1) ax2 = fig.add_subplot(2, 1, 2) #変更 clearLabel(ax2) show_img2 = cv.cvtColor(img, cv.COLOR_BGR2GRAY) plt.imshow(show_img2) plt.show()
こんな感じになりました。パラメータ次第で以下のようにも表示可能です。
おわりに
これで目的は達成できたかなと思います。
おまけですが、URLを指定して画像をダウンロードし、表示をさせる場合にはrequests
モジュールを使用すれば可能です。
以下のような感じで一応できました(もっときれいに書いたほうがいいけど)
import requests import cv2 as cv import matplotlib.pyplot as plt import os.path def clearLabel(_ax): _ax.tick_params(labelbottom="off",bottom="off") _ax.tick_params(labelleft="off",left="off") _ax.set_xticklabels([]) _ax.axis('off') return _ax def readImage(_filename): if os.path.exists(_filename): img = cv.imread(_filename) return img response = requests.get('https://upload.wikimedia.org/wikipedia/commons/e/e1/Harvest_of_MIKAN.jpg', allow_redirects=False) if response.status_code != 200: e = Exception("HTTP status: " + response.status_code) raise e content_type = response.headers["content-type"] if 'image' not in content_type: e = Exception("Content-Type: " + content_type) raise e with open('mikan.jpg', "wb") as fout: fout.write(response.content) img = readImage('mikan.jpg') fig = plt.figure() ax = fig.add_subplot(1, 1, 1) clearLabel(ax) show_img = cv.cvtColor(img, cv.COLOR_BGR2RGB) plt.imshow(show_img)
Google Colab上でOpenCVを使って画像処理(画像表示)ができるようになりました。 Googleのスプレッドシートに画像のURLを指定して画像を保存、加工、表示するところまでは比較的簡単にできそうですね。 次はGoogleスプレッドシートの読み込みですかね。
【関連エントリー】