Search code examples
opencvwxpython

Why the SetBitmap function cannot run correctly without imshow function


I am building an wxPython app, when display every frame by changing the static bitmap image, I got a strange error, my application run normally if I have imshow() function in code, if I comment out it, this app only run 1-2 seconds and crash, no error message found, the command screen still show the elapsed time as I printed it. Here is my code

video_capture = VideoStream(0).start()
time.sleep(2.0)
fps = FPS().start()

count = 0;

while True:
    frame = video_capture.read()
    frame = imutils.resize(frame, width=720, height=480)

    t = time.time()

    output_rgb = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

    self.bitmap_1.SetBitmap(wx.Bitmap.FromBuffer(output_rgb.shape[1], output_rgb.shape[0], output_rgb.tostring()))
    self.Refresh()

    cv2.imshow('Video', output_rgb)
    fps.update()

    print('[INFO] elapsed time: {:.2f}'.format(time.time() - t))

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

fps.stop()

Here is initial of bitmap_1

self.bitmap_1 = wx.StaticBitmap(self, bitmap=wx.EmptyBitmap(720, 540))

Sorry for my bad English, I'm using python 3.6.2


Solution

  • The while-loop as used in your example will eat 100 % of the CPU time, leaving wxPython no chance to process any event. This is the reason why your app crashes.

    You have to get rid of the while and have to integrate this part into an event handler of your wxPython app. This example uses a wx.Timer to poll your frame-grabbing routine periodically.

    It would be better to put the OpenCV code in a separate thread and transfer the bitmap between the OpenCV thread and the wxPython main thread in a thread-safe manner.

    How to spin-off threads in wxPython in general, see LongRunningTasks,