WxPython 中的 GetPosition 没有返回正确的位置

问题描述 投票:0回答:0

我正在使用 WxPython 开发用户界面,我需要记录在 StaticBitmap 上手动选择的两个点。这是在下面的函数

on_left_click()
中。

import wx
import cv2
import numpy as np

class main_frame(wx.Frame):
    # Whether a new frame be displayed.
    _update_frame = True
    # A point on the image.
    _new_pt = wx.Point(0, 0)

    # The latest frame, used for shaft length measurement
    _current_frame = None
    # shaft shaft points.
    _shaft_pts = [wx.Point(0,0), wx.Point(0,0)]
    # shaft shaft point index
    _shaft_pts_idx = -1

    # Frame initialisation.
    def __init__(self, parent, title):
        super(main_frame, self).__init__(parent,
                                         title=title,
                                         size=(800, 600),
                                         style= wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX )

        # create a panel to hold the image and buttons
        panel = wx.Panel(self)

        # Statusbar for displaying information.
        self.statusbar = self.CreateStatusBar()

        # Main horizontal sizer.
        hbox_main = wx.BoxSizer(wx.HORIZONTAL)

        # create a static bitmap to display the webcam image
        self.bmp = wx.StaticBitmap(panel, wx.ID_ANY, wx.NullBitmap)
        hbox_main.Add(self.bmp, 1, wx.EXPAND | wx.ALL, 5)

        # create the controls.
        self.shaft_box = wx.CheckBox(panel, label="Shaft detection")
        self.shaft_box.SetToolTip("Select two points to measure the shaft length. "
                                   "Left click to select point, "
                                   "middle click to delete last point")

        # Vertical sizer of buttons/displays.
        vbox_inputs = wx.BoxSizer(wx.VERTICAL)
        vbox_inputs.Add(self.shaft_box, 0, wx.EXPAND | wx.ALL, 5)
        hbox_main.Add(vbox_inputs, 0, wx.EXPAND)

        # Add the horizontal sizer to the panel.
        panel.SetSizer(hbox_main)

        # Event bindings.
        # quit_button.Bind(wx.EVT_BUTTON, self.on_quit_button_click)
        self.shaft_box.Bind(wx.EVT_CHECKBOX, self.on_shaft_check)

        # Bitmap mouse click events.
        self.bmp.Bind(wx.EVT_LEFT_DOWN, self.on_left_click)
        self.bmp.Bind(wx.EVT_MIDDLE_DOWN, self.on_middle_click)

        ########################################################################
        self.cap = cv2.VideoCapture(0)

        # start a timer to update the image every x milliseconds.
        fps = 20
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update_image)
        self.timer.Start(int(1000/fps)) # [ms]

        # show the frame.
        self.Show(True)

    # Left mouse click on the image.
    def on_left_click(self, event):
        # FIXME the position is off
        self._new_pt = event.GetPosition()

        if self.shaft_box.IsChecked():
            self.update_shaft(new_pt=True)

    # Middle mouse click on the image.
    def on_middle_click(self, event):
        if self.shaft_box.IsChecked():
            self.update_shaft(delete_pt=True)

    # "shaft Detection" clicked.
    def on_shaft_check(self, event):
        self._update_frame = not event.IsChecked()
        if event.IsChecked():
            self._shaft_pts_idx = 0
            self._current_frame = self.image.copy()
            self.update_shaft()
        else:
            self._shaft_pts_idx = -1
            self.statusbar.SetStatusText("")

    # Timer event, all processing to go in here and updates the image.
    def update_image(self, event):
        # Get frame.
        if (self._update_frame):

            _, frame = self.cap.read()
            self.image = np.uint8(frame)
            height, width = self.image.shape[:2]
            bitmap = wx.Bitmap.FromBuffer(width, height, self.image)
            self.bmp.SetBitmap(bitmap)
            self.bmp.Update()

    # Select two points on the image which define the shaft.
    def update_shaft(self, new_pt=False, delete_pt=False):
        # Delete points.
        if delete_pt:
            if self._shaft_pts_idx > 0:
                self._shaft_pts_idx -= 1

        # Add new points.
        if (self._shaft_pts_idx >= 0) and (self._shaft_pts_idx < 2):
            # Add a new point.
            if new_pt:
                self._shaft_pts[self._shaft_pts_idx] = self._new_pt
                self._shaft_pts_idx += 1

            # Update the statusbar.
            if self._shaft_pts_idx == 0:
                self.statusbar.SetStatusText("Select two points on the image")
            elif self._shaft_pts_idx == 1:
                self.statusbar.SetStatusText(f"Point 1: {self._shaft_pts[0]}, "
                                             f" select another point")
            else:
                self.statusbar.SetStatusText(f"Point 1: {self._shaft_pts[0]}, "
                                             f"Point 2: {self._shaft_pts[1]}")

        # Draw points on image.
        img = self._current_frame.copy()
        height, width = img.shape[:2]
        for i in range(0, self._shaft_pts_idx):
            # img, loc, colour, marker type, size, thickness
            cv2.drawMarker(img,
                           (self._shaft_pts[i].x, self._shaft_pts[i].y),
                           (0,255,0),
                           cv2.MARKER_CROSS,
                           11,
                           2)
            cv2.putText(img,
                        f"Pt {i+1}",
                        (self._shaft_pts[i].x + 10,
                         self._shaft_pts[i].y),
                        cv2.FONT_HERSHEY_SIMPLEX,
                        0.5,
                        (0,255,0),
                        2)
        bitmap = wx.Bitmap.FromBuffer(width, height, img)
        self.bmp.SetBitmap(bitmap)


def main():
    app = wx.App()
    frame = main_frame(None, title="Fine-Tuned Demo")
    frame.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

代码最初运行良好,但我发现如果我调整窗口大小,返回的坐标是错误的。调整大小后,原点似乎是窗口的左上角,而不是 StaticBitmap 的左上角。任何见解将不胜感激。谢谢!

wxpython
© www.soinside.com 2019 - 2024. All rights reserved.