Problem fo wx.StaticBitmap.SetScaleMode

Backgournd:
(1) I apply the opencv with wx.StaticBitmap to get image frame stream from my webcam.
(2) It is works above to get image stream and show.

But, when I set “scale” function, it not works. The following shows the code in python:

color transfer

image1 = cv2.cvtColor(self.im_rd, cv2.COLOR_BGR2RGB)

image stream from buffer

pic = wx.Bitmap.FromBuffer(width, height, image1)

attach to the StaticBitmap

self.m_bmp01.SetBitmap(pic)

Set Scale, but not works

self.m_bmp01.SetScaleMode(wx.StaticBitmap.Scale_AspectFill)
print(self.m_bmp01.GetScaleMode()) # always printout 0

I have no idea to figure out, need your help
Thanks for your reply

According to the documentation:

Currently only the generic implementation supports all scaling modes. You may use generic implementation GenericStaticBitmap declared in <wx/generic/statbmpg.h> in all ports.

Have you tried:

from wx.lib.statbmp  import GenStaticBitmap as StaticBitmap

1 Like

When I was experimenting with opencv a while ago, I created the app below. This uses opencv’s resize() method to resize the images instead of using the StaticBitmap’s SetScaleMode().

When you resize the frame, the images are automatically resized while maintaining the original aspect ratio.

# Based on an example from:
# https://stackoverflow.com/questions/35009984/get-stream-from-webcam-with-opencv-and-wxpython
#
# To install cv2:
# pip install opencv-python
#

import cv2
import wx
from wx.lib.statbmp import GenStaticBitmap

INIT_SIZE = (640, 480)
FRAMES_PER_SECOND = 17
TIMER_INTERVAL = 1000 // FRAMES_PER_SECOND

class ViewWindow(wx.Frame):
    def __init__(self, parent, capture, title="Webcam Viewer"):
        super(ViewWindow, self).__init__(parent, title=title)
        self.capture = capture
        self.SetSize(INIT_SIZE)
        self.SetBackgroundColour(wx.BLACK)

        v_sizer = wx.BoxSizer(wx.VERTICAL)
        h_sizer = wx.BoxSizer(wx.HORIZONTAL)
        v_sizer.Add(h_sizer, 1, wx.ALIGN_CENTER_HORIZONTAL, 0)

        image = wx.Image(INIT_SIZE)
        bitmap = wx.Bitmap(image)
        self.static_bitmap = GenStaticBitmap(self, wx.ID_ANY, bitmap)
        h_sizer.Add(self.static_bitmap, 0, wx.ALIGN_CENTER_VERTICAL, 0)

        self.SetSizer(v_sizer)
        self.Layout()

        self.refreshView()

        self.timer = wx.Timer(self)
        self.timer.Start(TIMER_INTERVAL)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)


    def refreshView(self):
        res, video_frame = self.capture.read()
        if res:
            cv_image = cv2.cvtColor(video_frame, cv2.COLOR_BGR2RGB)
            ih, iw = video_frame.shape[:2]
            pw, ph = self.GetSize()
            p_ratio = ph / pw
            i_ratio = ih / iw
            if p_ratio == i_ratio:
                rw, rh = pw, ph
            else:
                if p_ratio > i_ratio:
                    rw = pw
                    rh = round(rw * i_ratio)
                else: # p_ratio < i_ratio:
                    rh = ph
                    rw = round(rh / i_ratio)
                cv_image = cv2.resize(cv_image, (rw, rh), interpolation=cv2.INTER_CUBIC)
            bitmap = wx.Bitmap.FromBuffer(rw, rh, cv_image)
            self.static_bitmap.SetBitmap(bitmap)
            self.Refresh()

        else:
            print("Failed to get video-frame from webcam")


    def OnTimer(self, _e):
        self.refreshView()


def main():
    app = wx.App()
    capture = cv2.VideoCapture(0)
    if capture.isOpened():
        frame = ViewWindow(None, capture)
        frame.Center()
        frame.Show()
        app.MainLoop()

    else:
        print("Failed to open the webcam.")


if __name__ == '__main__':
    main()

Tested on Python 3.10.4 + wxPython 4.2.0 gtk3 (phoenix) wxWidgets 3.2.0 + Linux Mint 21

1 Like

Hi, Richard,

Thanks for your information (including sample and concept), and it is works.
When I run this program and manual change the frame size, the captured frame also changed in the meanwhile