我正在使用 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 的左上角。任何见解将不胜感激。谢谢!