個人的にPythonでOpenCVを使って画像処理をする機会が多くなってきました。ライブラリに備わる関数も充実しており、短い記述で簡単に、凝った処理が記述出来て重宝しています。その際に必要となるのが、確認やデバッグ用途での画像表示です。そこで、
楽ちんなOpenCVを用いた表示
ちょっと便利なmatplotlibを用いた表示
凝った事もできそうなtkinterを用いた表示
の3種類の画像表示の方法を試して比較してみます。
OpenCVを用いた画像表示(cv2.imshow)
CでOpenCVを使っていたころから長いこと使っていました。imshow関数です。OpenCVのimread関数で読み込んだ画像の表示にはこれしかないと思い込んでいました。以下のような簡単な記述でウィンドウに画像を表示してくれます。楽ちんです。
1 2 3 4 5 | import cv2 img = cv2.imread( 'lena.jpg' ) cv2.imshow( "aaa" ,img) key = cv2.waitKey( 0 ) |
これだけの記述で

これがポップアップするので、文句はありません。
ちなみに3行目のwaitKey(0)はキーボード入力を待っています。引数は入力待ち時間でミリ秒単位で指定します。この関数は、指定された時間だけキーボード入力を待ちます。入力待ちの間に何かのキーを打てば、返り値(今回の場合にはkey)にそのキーコードが返ってきます。引数に 0 を指定した時は、キー入力を無限に待ち続けます。今回の場合は表示しっぱなしで、何かキーによって操作をすることは想定しないので、waitは0です。
ただ、このimshowですが、画像をディスプレイにバイピクセルの等倍表示がデフォルトだし、表示後のその表示画像の拡大縮小も受け付けてくれません。色々そのWindowに対して操作もできるようですが、いまいち使いづらいです。詳細はこちら。
ただimreadで読んだ画像の表示としては一番手軽。 書式も簡単だし なんだかんだで使ってます。imwriteと引数が似てるのも覚えやすい。
matplotlibを用いた画像表示(plt.imshow)
matplotlibにも同じ関数名で画像を表示してくれる関数があります。matplotlibは主にグラフを書いてもらうのに使うことが多いですが、画像もちゃんと表示してくれます。ただし表示のための画像のフォーマットが、OpenCVのそれと異なります。残念。
そのため、例えば以下のコード。直感的にはこれでよさそうですが
1 2 3 4 5 6 | import cv2 from matplotlib import pyplot as plt img = cv2.imread( 'lena2.jpg' ) plt.imshow(img) plt.show() |
OpenCVで読み込んだ画像をそのまま表示すると、こんなになります。

OpenCVはなぜが画素順がBGR順、対して表示はRGB順なので、入れ替えてやる必要があります。
1 | plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) |
これでキレイに以下の様に表示されます。
このウィンドウのいいところは、拡大縮小から、軸の表示、保存までGUI操作までできちゃいます。レポートを作るときに挿入する画像を用意する時にはとても重宝します。 画像サイズもウィンドウにフィッティングしてくれますので、ディスプレイサイズを大きく超えるような画像の表示も見やすいです。
ただし、これもグラフ表示をメインとしているせいか、1チャンネルしかないグレースケールの画像表示にも難があります。普通に表示させるとおかしなことになります。
1 2 3 | img = cv2.imread( 'lenag.jpg' , cv2.IMREAD_GRAYSCALE) plt.imshow(img) plt.show() |
これで一見OKに見えますが、表示は

となります。おかしいです。これはgrayの明度値をいわゆる明るさを示す値とみなさず、異なるカラーマップに割り当てている事が理由のようです。matplotlib カラーマップでググると色々情報が出てきます。が、ここではグレースケール表示ができればよいので、
1 | plt.imshow(img,cmap = plt.cm.gray) |
としてあげると以下の様に解決します。

このようにOpenCVの画像を表示するには少し煩わしいですが、この癖を理解して使えば表示後は便利です。
ただ、Spyderを使っていると別ウィンドウへ飛び出してくれないので、以下の設定をした上で活用ください。
tkinterを用いた画像表示(canvas)
最後に試すのが、ちょっとトリッキーな表示方法。Python の Tkinter で 画像を表示です。GUIを自分で加えることを想定するとこの表示方法が便利です。が、ちょっとしたデバッグ用途といった感じではなくなります。単純な表示だけではなく、処理のパラメータを画像を見ながらGUIを使って調整したいとき、などの表示用です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import cv2 import tkinter as tk from PIL import ImageTk, Image img = cv2.imread( 'lena2.jpg' ) root = tk.Tk() canvas = tk.Canvas() image_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) image_pil = Image.fromarray(image_rgb) image_Tk = ImageTk.PhotoImage(image_pil, master = canvas) canvas.create_image( 0 , 0 ,image = image_Tk,anchor = 'nw' ) canvas.grid() root.mainloop() |
煩わしいです。が今後使えるので我慢します。表示させるための画像フォーマットへの変換に一度PIL(python image library)をはさみます。なので、opencvで読む。rgb順へ変換させる。pilフォーマットへ変換する。tk用フォーマットへ変換する。と3回変換します。その後canvasへ適用させ、windowへレイアウト。という過程を経てやっと表示できます。がこの記述だと画像の一部しか表示されない全く行けてない表示です。
今回は表示だけで、GUIまでは付けていませんが、今後それも試してみようと思います。
まとめ
今回OpenCVで画像処理する人には必須となるであろう画像処理の結果画像を表示する方法を3種類試してみました。どれがいいとか悪いではなく、用途によって使い分けることができると便利だなと思います。
特に最後のtkinterに関しては、もともとGUI用途です。なので今回表示だけというのは機能の一部を見せているだけで、実はもっとすごいポテンシャルを秘めてそうです。今後勉強していきたいです。
コメント