夏休みに某「ぐにゃぐにゃカメラ」の改良をすることにしました.いままでC言語でOpenCV使って書いたプログラムやったんを,Python + OpenCV で一から書き直します.ついでにGUIもちゃんとしたくなって,wxPython 使うことにしました.その勉強過程のメモです.
目次
Step1 wxPython で画像を表示
もう何年も wxPython 使ったプログラム書いてなかったので,復習をかねて,まずは画像ファイルを読み込んで表示するだけのものを作ります.こちらを参考にしました: wxStaticBitmap - wxPyWiki
ファイル名を指定して wx.Bitmap のインスタンスを生成し,それを wx.StaticBitmap に渡す,と.こんな感じでできました: wx160813.py · GitHub
Step2 OpenCV で作った画像を wxPython で表示
次は,OpenCV で作った画像を wx.Bitmap に変換して表示させるプログラムを作ります.将来的な野望は 「OpenCV でキャプチャした動画を wxPython のウィンドウ上に表示させる」っちうことなので,適当なタイミングで画像を切り換える処理も必要.そこで,ボタンを押すたびに画素値を反転させるようにしてみました.こんなんでけました: cv2wx160813.py · GitHub
みそは,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秒ごとに画像を切りかえ表示するプログラムを作ります.
- 画像を作る処理を wxPython による描画とは別スレッドにして,
- 画像が用意できる度にイベントを発生させて画像を切りかえる,
ということにしました.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のボウケンシャーにしか通じないネタ (^^)