Google Colaboratoryで画像表示してみる

Google Colaboratoryで画像表示してみる

最近、やっているGoogle Colaboratory関連のエントリーの続きです。

uepon.hatenadiary.com

uepon.hatenadiary.com

Google ColaboratoryOpenCVを使おうと思っていましたが、このあたりの書き方がJupyter Notebookとはちょっと違うようだったのでメモ。

作業を始めてわかったのですが

f:id:ueponx:20180328194454p:plain

ファイルを確認すると「空」でした!

このように、前回のエントリーでインスタンスに接続したGoogle Driveのマウントは消えています。またファイルアップロードを過去に行っていても そのファイルもなくなるようです。つまり、インスタンス起動の制限時間内に収まらなかった場合、最後の状態が保持されるわけではないようです。 過去のエントリーにも追加が必要ですね。(初期インスタンスイメージをロードする感じなんでしょうね)

マウント処理は毎回やらないとダメそうですね…

ファイルをアップロードして表示を行う

では、前回のエントリー同様にファイルアップロードを行ってみます。

from google.colab import files
uploaded = files.upload()

f:id:ueponx:20180328195529p:plain

これでapple.jpgという画像ファイルをアップロードすることができました。 では、画像ファイルを表示してみます。

notebookで単純に画像を表示するならIPython.displayモジュールのdisplay_*メソッドが使えるようです。

IPythonとは、Pythonの対話型インタプリタを強力に拡張したもののようです。

  • 強力なインタラクティブシェル
  • Jupyterのカーネル
  • インタラクティブなデータの視覚化とGUIツールキットの使用をサポート
  • フレキシブルで埋め込み可能な通訳者が自分のプロジェクトに読み込み
  • 使いやすい、並列コンピューティングのための高性能ツール

以上のような機能があります。notebook上で保管がモジュールの保管が聞くのもこのおかげのようです。

ドキュメントをみると

f:id:ueponx:20180328203445p:plain

こんなふうな感じです。jpegの他にもHTML、pdf、pngSVGmarkdownなんかも表示ができるようです。 では実行してみましょう。

from IPython.display import Image,display_jpeg
display_jpeg(Image('apple.jpg'))

f:id:ueponx:20180328204610p:plain

無事に画像が表示されました。 pngの場合にはdisplay_jpeg()の代わりにdisplay_png()とするような感じです。

from IPython.display import Image,display_png
display_png(Image('Lenna.png'))

f:id:ueponx:20180328205307p:plain

こんな感じで実行できます。

透過色があっても問題ありません!

f:id:ueponx:20180328205547p:plain

背景が黒だとこんな風に見えます。

f:id:ueponx:20180328205739p:plain

SVGファイルもこのような感じで表示できます。

from IPython.display import *
display_svg(SVG('svg.svg'))

SVGの場合にはImageオブジェクトではなくSVGオブジェクトを引数にする必要があります。

f:id:ueponx:20180328232838p:plain

pdfとmarkdownはうまく行かなかったみいです。(純粋なJupyterNotebookでは動くかもですが…ちょっと自信ないです)

f:id:ueponx:20180328234512p:plain

そんなことをやりたかったわけではない

そうでした。本当にやりたかったのはOpenCVで処理した結果をGoogle Colabで表示したいのでした。 ということで、OpenCVで使ったサンプルをGoogleColabで実行してみると…

import cv2

img = cv2.imread('Lenna.png', 0)

cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

おや?

f:id:ueponx:20180328235539p:plain

インスタンスの異常終了をして、再起動までされてしまいました。うお。 調べてみるとNotebookで実行するのであればインライン(コマンドの出力)での出力にしないとまずいようです。 つまり先程のサンプルでは別ウインドウで画像を開こうとしているという点が失敗の原因になっていたということです。

今回はグラフなどの描画でもちいるmatplotlibOpenCVの結果を渡すことで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)

f:id:ueponx:20180329000846p:plain

修正点としては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)

f:id:ueponx:20180329002042p:plain

ファイルの書き込みも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)

f:id:ueponx:20180329002427p:plain

では画像を加工していくつかの表示を行いたい場合にはどうすればいいでしょうか。 いくつかの手法はあるのですが、今回は一つの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()

f:id:ueponx:20180330181005p:plain

ポイントとなるのは以下の部分です。

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()

f:id:ueponx:20180330182209p:plain

こんな感じになりました。パラメータ次第で以下のようにも表示可能です。

f:id:ueponx:20180330182337p:plain

おわりに

これで目的は達成できたかなと思います。

おまけですが、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)

f:id:ueponx:20180330184350p:plain

Google Colab上でOpenCVを使って画像処理(画像表示)ができるようになりました。 Googleスプレッドシートに画像のURLを指定して画像を保存、加工、表示するところまでは比較的簡単にできそうですね。 次はGoogleスプレッドシートの読み込みですかね。

関連エントリー

uepon.hatenadiary.com uepon.hatenadiary.com