StaticBitmap.SetBitmap()でbitmapを表示したい
以下の環境にて、wxPythonで動画を表示させるStaticBitmapの拡張クラスを作ろうとしています。
・Python 3.6.8
・wxPython 4.0.6
・OpenCV 4.1.1
・ubuntu 18.06
OpenCVはapp.MainLoop()でループさせる必要があるため、StaticBitmapを継承したクラスを作って、その中で別スレッドを作り、その中でループさせてフレームを読み込み、bitmapに変換して自身に再セットする、といった処理を考えています。
おおむね上手くいったのですが、なぜかbitmapの再セットをSetBitmap()で行うと、画像が表示されず、真っ白になります。
スレッド操作が悪いのか、StaticBitmapの使い方が悪いのか、原因の切り分けができずに困っています。
どなたか、wxPython+OpenCVでStaticBitmapを使って動画再生をしたことがあるかたがいらっしゃったら、アドバイスを頂けると助かります。
該当のソースコード
import wx import cv2 import numpy as np import threading class VideoBitmap(wx.StaticBitmap): def __init__(self, parent, file_name, pos=(0, 0), size=(100, 100)): self.video = cv2.VideoCapture(file_name) self.width = size[0] ret, frame = self.video.read() bmp = self.create_wx_bitmap_from_cv2_image(frame) bmp = self.scale_bitmap_keep_ratio(bmp, 300) super().__init__(parent, wx.ID_ANY, bmp, pos, size, style=0, name='') def create_wx_bitmap_from_cv2_image(self, cv2_image): height, width = cv2_image.shape[:2] cv2_image_rgb = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB) return wx.BitmapFromBuffer(width, height, cv2_image_rgb) def scale_bitmap_keep_ratio(self, bitmap, width): image = wx.ImageFromBitmap(bitmap) rate = bitmap.Height / bitmap.Width height = width * rate image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH) result = wx.BitmapFromImage(image) return result def video_run(self): frame_count = int(self.video.get(cv2.CAP_PROP_FRAME_COUNT)) frame_rate = int(self.video.get(cv2.CAP_PROP_FPS)) test_bmp = wx.Bitmap('icons/save.png') for i in range(frame_count): is_read, frame = self.video.read() if not is_read: break bmp = self.create_wx_bitmap_from_cv2_image(frame) bmp = self.scale_bitmap_keep_ratio(bmp, 300) self.SetBitmap(bmp) print('%d' % i) if __name__ == "__main__": app = wx.App(False) file_name = "video/video.mp4" frame = wx.Frame(None, wx.ID_ANY, "テスト", size=(800,625)) panel = wx.Panel(frame, size=(800,625)) layout = wx.FlexGridSizer(rows=2, cols=2, gap=(0,0)) panel.SetSizer(layout) video = VideoBitmap(panel, file_name, pos=(10, 10), size=(300, 300)) layout.Add(video) frame.Show(True) thread = threading.Thread(target=video.video_run) thread.start() app.MainLoop()
試したこと
上記コードのメソッド「video_run」内にある「self.SetBitmap(bmp)」がうまく機能していないと思われるため、以下を試しました。
・初期表示の画像(コンストラクタで作成したbmpをself.init_bmpとして保持)を、bmpの代わりにself.SetBitmap(self.init_bmp)として表示してみたが、やはり真っ白になった。
・適当なアイコン画像をwx.Bitmap()で生成してSetBitmapに入れてみたところ、最初の1フレームループの時だけ表示され、2巡目からはやはり真っ白になる。
・self.Update()で即時描画更新を試したが、コアダンプで落ちる。
コンストラクタでセットした画像だけ(つまり初手)は表示されます。
アドバイスを頂けると幸いです。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/24 03:29
2019/09/24 12:57
2019/09/25 11:25