まんぼう日記

takataka's diary

OpenCV と wxPython の連係

夏休みに某「ぐにゃぐにゃカメラ」の改良をすることにしました.いままでC言語でOpenCV使って書いたプログラムやったんを,Python + OpenCV で一から書き直します.ついでにGUIもちゃんとしたくなって,wxPython 使うことにしました.その勉強過程のメモです.

 

目次

 

Step1  wxPython で画像を表示

 もう何年も wxPython 使ったプログラム書いてなかったので,復習をかねて,まずは画像ファイルを読み込んで表示するだけのものを作ります.こちらを参考にしました: wxStaticBitmap - wxPyWiki

 

ファイル名を指定して wx.Bitmap のインスタンスを生成し,それを wx.StaticBitmap に渡す,と.こんな感じでできました: wx160813.py · GitHub

f:id:takatakamanbou:20160814150148p:plain 

Step2  OpenCV で作った画像を wxPython で表示

次は,OpenCV で作った画像を wx.Bitmap に変換して表示させるプログラムを作ります.将来的な野望は 「OpenCV でキャプチャした動画を wxPython のウィンドウ上に表示させる」っちうことなので,適当なタイミングで画像を切り換える処理も必要.そこで,ボタンを押すたびに画素値を反転させるようにしてみました.こんなんでけました:  cv2wx160813.py · GitHub

f:id:takatakamanbou:20160814150147p:plain

みそは,ImagePanel クラスの redraw() メソッドの部分.

# img は NumPy の NDArray. shape は (height, width, depth), dtype は uint8
# その画素値の並び順を変更
buf = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# buf から wx.Bitmap のインスタンスを生成
bmp = wx.BitmapFromBuffer(img.shape[1], img.shape[0], buf)

# stbmp は wx.StaticBitmap のインスタンス. bmp をセット
self.stbmp.SetBitmap(bmp)

BitmapFromBuffer() についてはこちら: https://wxpython.org/docs/api/wx-module.html#BitmapFromBuffer

 

Step3 イベント処理を使って画像を切りかえ表示

さて,上記の野望の実現へのステップとして,1秒ごとに画像を切りかえ表示するプログラムを作ります.

  1. 画像を作る処理を wxPython による描画とは別スレッドにして,
  2. 画像が用意できる度にイベントを発生させて画像を切りかえる,

ということにしました.1. については,Python の threading モジュール( 16.2. threading — 高水準のスレッドインタフェース — Python 2.7.x ドキュメント )を使います.2. については,以下の文書の ``Custom Event Summary'' の項を参考にしました.

 Events and Event Handling — wxPython Phoenix 3.0.3 documentation

 

できたプログラムはこちら: imageviewer160813.py · GitHub.1秒ごとに画素値が反転します.ImageSetterのインスタンスが定期的に画像を投げて,ImageViewerのインスタンスがそれを受け取ったらredraw()する,ということになってます.

 

ウィンドウを閉じた時の処理とかまだちゃんとできてないとか,画像まるごとイベントオブジェクトとして投げて効率はどないやねんとか,2つのクラスが絡み合ってて使いにくいとか,いろいろありますが,とりあえず…

 

「やったー! うまくいったよ!!」

 

……SQ5のボウケンシャーにしか通じないネタ (^^)