added qt gui with changeable parameters

master
Simon Pirkelmann 2020-11-28 19:57:22 +01:00
parent 9c1115d505
commit f9f4a2c1c6
1 changed files with 90 additions and 50 deletions

View File

@ -5,6 +5,7 @@ import os
import time import time
import math import math
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.parametertree import Parameter, ParameterTree
import pyqtgraph as pg import pyqtgraph as pg
@ -13,54 +14,105 @@ from queue import Queue
import aruco import aruco
class FPSCounter:
def __init__(self):
self.fps_start_time = time.time()
self.fps_counter = 0
self.fps_display_rate = 1.0
def get_fps(self):
self.fps_counter += 1
delta_t = time.time() - self.fps_start_time
if delta_t > self.fps_display_rate:
self.fps_counter = 0
self.fps_start_time = time.time()
return self.fps_counter / delta_t
class ArucoEstimator: class ArucoEstimator:
corner_marker_ids = {
'a': 0,
'b': 1,
'c': 2,
'd': 3
}
corner_estimates = {
'a': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'b': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'c': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'd': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
}
def __init__(self, robot_marker_ids=None, use_realsense=True, grid_columns=12, grid_rows=12): def __init__(self, robot_marker_ids=None, use_realsense=True, grid_columns=12, grid_rows=12):
self.app = QtGui.QApplication([]) self.app = QtGui.QApplication([])
## Create window with GraphicsView widget ## Create window with GraphicsView widget
self.win = pg.GraphicsLayoutWidget() self.win = QtGui.QWidget()
self.layout = QtGui.QGridLayout()
self.win.setLayout(self.layout)
self.win.keyPressEvent = self.handleKeyPressEvent self.win.keyPressEvent = self.handleKeyPressEvent
self.win.show() ## show widget alone in its own window
self.win.setWindowTitle('ArucoEstimator') self.win.setWindowTitle('ArucoEstimator')
self.view = self.win.addViewBox()
self.plotwidget = pg.PlotWidget()
self.layout.addWidget(self.plotwidget)
## lock the aspect ratio so pixels are always square ## lock the aspect ratio so pixels are always square
self.view.setAspectLocked(True) self.plotwidget.setAspectLocked(True)
self.plotwidget.getPlotItem().getAxis('left').hide()
self.plotwidget.getPlotItem().getAxis('bottom').hide()
## Create image item ## Create image item
self.img = pg.ImageItem(border='w') self.img = pg.ImageItem(border='w')
self.img.setLevels([[0, 255], [0, 255], [0, 255]]) self.img.setLevels([[0, 255], [0, 255], [0, 255]])
self.img.mouseClickEvent = self.handleMouseEvent self.img.mouseClickEvent = self.handleMouseEvent
self.view.addItem(self.img) self.plotwidget.addItem(self.img)
self.grid_columns = grid_columns # fps display
self.grid_rows = grid_rows self.fps_counter = FPSCounter()
self.fps_overlay = pg.TextItem('fps = 0', color=(255, 255, 0), anchor=(0,1))
self.plotwidget.addItem(self.fps_overlay)
self.invert_grayscale = False
self.draw_grid = False
self.draw_markers = True
self.draw_marker_coordinate_system = False
self.corner_marker_size = 0.075
self.corner_marker_ids = {
'a': 0,
'b': 1,
'c': 2,
'd': 3
}
self.corner_estimates = {
'a': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'b': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'c': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
'd': {'pixel_coordinate': None, 'x': None, 'y': None, 'n_estimates': 0},
}
self.robot_marker_size = 0.07
if robot_marker_ids is None: if robot_marker_ids is None:
robot_marker_ids = [] robot_marker_ids = []
self.robot_marker_ids = robot_marker_ids self.robot_marker_ids = robot_marker_ids
self.robot_marker_estimates = dict([(marker_id, {'t': None, 'x': None, 'y': None, 'angle': None}) self.robot_marker_estimates = dict([(marker_id, {'t': None, 'x': None, 'y': None, 'angle': None})
for marker_id in self.robot_marker_ids]) for marker_id in self.robot_marker_ids])
self.draw_grid = False
self.fps_start_time = time.time() # parameter
self.fps_counter = 0 params_spec = [
{'name': 'Corner marker size', 'type': 'float', 'value': self.corner_marker_size, 'siPrefix': True,
'suffix': 'm', 'limits': (0.01, 1), 'step': 0.001},
{'name': 'Robot marker size', 'type': 'float', 'value': self.robot_marker_size, 'siPrefix': True,
'suffix': 'm', 'limits': (0.01, 1), 'step': 0.001},
{'name': 'Draw markers', 'type': 'bool', 'value': self.draw_markers},
{'name': 'Draw marker coordinate system', 'type': 'bool', 'value': self.draw_marker_coordinate_system},
{'name': 'Invert grayscale', 'type': 'bool', 'value': self.invert_grayscale, 'tip': "Invert grayscale image before marker detection"},
{'name': 'Show FPS', 'type': 'bool', 'value': True, 'tip': "Display frames per second counter"},
{'name': 'Draw grid', 'type': 'bool', 'value': self.draw_grid, 'tip': "Draw grid spanned by the markers 0 - 3"},
{'name': 'Display mode', 'type': 'list', 'values': ['color', 'grayscale'], 'value': 'color', 'tip': "Display mode for the video"}
]
self.params = Parameter.create(name='params', type='group', children=params_spec)
self.params.param('Invert grayscale').sigValueChanged.connect(lambda _, v: self.__setattr__('invert_grayscale', v))
self.params.param('Draw markers').sigValueChanged.connect(lambda _, v: self.__setattr__('draw_markers', v))
self.params.param('Draw marker coordinate system').sigValueChanged.connect(lambda _, v: self.__setattr__('draw_marker_coordinate_system', v))
self.params.param('Draw grid').sigValueChanged.connect(lambda _, v: self.__setattr__('draw_grid', v))
self.params.param('Corner marker size').sigValueChanged.connect(lambda _, v: self.__setattr__('corner_marker_size', v))
self.params.param('Robot marker size').sigValueChanged.connect(lambda _, v: self.__setattr__('robot_marker_size', v))
self.params.param('Show FPS').sigValueChanged.connect(lambda _, v: self.fps_overlay.show() if v else self.fps_overlay.hide())
self.paramtree = ParameterTree()
self.paramtree.setParameters(self.params, showTop=False)
self.layout.addWidget(self.paramtree)
self.win.show() ## show widget alone in its own window
self.grid_columns = grid_columns
self.grid_rows = grid_rows
self.event_queue = Queue() self.event_queue = Queue()
@ -113,7 +165,6 @@ class ArucoEstimator:
self.drag_line_end = None self.drag_line_end = None
self.drag_line_start = None self.drag_line_start = None
self.previous_click = None self.previous_click = None
self.invert_grayscale = False
def compute_clicked_position(self, px, py): def compute_clicked_position(self, px, py):
if self.all_corners_detected(): if self.all_corners_detected():
@ -176,15 +227,10 @@ class ArucoEstimator:
self.drag_line_end = (px, py) self.drag_line_end = (px, py)
def process_frame(self): def process_frame(self):
draw_markers=True
draw_marker_coordinate_system=False
#cv2.setMouseCallback('RoboRally', self.mouse_callback)
fps_display_rate = 1 # displays the frame rate every 1 second
if self.pipeline: if self.pipeline:
frames = self.pipeline.wait_for_frames() frames = self.pipeline.wait_for_frames()
color_frame = frames.get_color_frame() color_frame = frames.get_color_frame()
# if not color_frame:
# continue
# Convert images to numpy arrays # Convert images to numpy arrays
color_image = np.asanyarray(color_frame.get_data()) color_image = np.asanyarray(color_frame.get_data())
else: else:
@ -206,16 +252,16 @@ class ArucoEstimator:
detected_marker_data[marker.id] = {'marker_center': marker.getCenter()} detected_marker_data[marker.id] = {'marker_center': marker.getCenter()}
if marker.id in self.corner_marker_ids.values(): if marker.id in self.corner_marker_ids.values():
marker.calculateExtrinsics(0.075, self.camparam) marker.calculateExtrinsics(self.corner_marker_size, self.camparam)
else: else:
marker.calculateExtrinsics(0.07, self.camparam) marker.calculateExtrinsics(self.robot_marker_size, self.camparam)
detected_marker_data[marker.id]['Rvec'] = marker.Rvec detected_marker_data[marker.id]['Rvec'] = marker.Rvec
detected_marker_data[marker.id]['Tvec'] = marker.Tvec detected_marker_data[marker.id]['Tvec'] = marker.Tvec
if draw_markers: if self.draw_markers:
marker.draw(color_image, np.array([255, 255, 255]), 2, True) marker.draw(color_image, np.array([255, 255, 255]), 2, True)
if draw_marker_coordinate_system: if self.draw_marker_coordinate_system:
aruco.CvDrawingUtils.draw3dAxis(color_image, self.camparam, marker.Rvec, marker.Tvec, .1) aruco.CvDrawingUtils.draw3dAxis(color_image, self.camparam, marker.Rvec, marker.Tvec, .1)
# store data # store data
@ -232,27 +278,22 @@ class ArucoEstimator:
color_image = cv2.line(color_image, self.drag_line_start, self.drag_line_end, color=(0, 0, 255), thickness=2) color_image = cv2.line(color_image, self.drag_line_start, self.drag_line_end, color=(0, 0, 255), thickness=2)
# compute frame rate # compute frame rate
self.fps_counter += 1 self.fps_overlay.setText(f"fps = {self.fps_counter.get_fps():.1f}")
delta_t = time.time() - self.fps_start_time
if delta_t > fps_display_rate:
self.fps_counter = 0
self.fps_start_time = time.time()
color_image = cv2.putText(color_image, f"fps = {(self.fps_counter / delta_t):.2f}", (10, 25), cv2.FONT_HERSHEY_PLAIN, 2,
(0, 255, 255),
thickness=2)
# Show images # Show images
color_image_rgb = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB) # convert to RGB color_image_rgb = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB) # convert to RGB
self.img.setImage(np.transpose(np.flipud(color_image_rgb), axes=(1, 0, 2))) display_mode = self.params.param('Display mode').value()
if display_mode == 'color':
self.img.setImage(np.transpose(np.flipud(color_image_rgb), axes=(1, 0, 2)))
elif display_mode == 'grayscale':
self.img.setImage(np.transpose(np.flipud(gray)))
QtCore.QTimer.singleShot(1, self.process_frame) QtCore.QTimer.singleShot(1, self.process_frame)
def handleKeyPressEvent(self, ev): def handleKeyPressEvent(self, ev):
key = ev.key() key = ev.key()
self.event_queue.put(('key', key)) self.event_queue.put(('key', key))
if key == QtCore.Qt.Key_G: if key == QtCore.Qt.Key_Q:
self.draw_grid = not self.draw_grid
elif key == QtCore.Qt.Key_Q:
if self.pipeline is not None: if self.pipeline is not None:
# Stop streaming # Stop streaming
self.pipeline.stop() self.pipeline.stop()
@ -268,6 +309,7 @@ class ArucoEstimator:
print("auto exposure ON") print("auto exposure ON")
elif key == QtCore.Qt.Key_I: elif key == QtCore.Qt.Key_I:
self.invert_grayscale = not self.invert_grayscale self.invert_grayscale = not self.invert_grayscale
def update_estimate(self, marker_id, pixel_coord_center, rvec, tvec, t_image): def update_estimate(self, marker_id, pixel_coord_center, rvec, tvec, t_image):
# update the marker estimate with new data # update the marker estimate with new data
if marker_id in self.corner_marker_ids.values(): if marker_id in self.corner_marker_ids.values():
@ -464,6 +506,4 @@ if __name__ == "__main__":
import sys import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_() QtGui.QApplication.instance().exec_()
#estimator.run_tracking(draw_markers=True, invert_grayscale=True)