def pointAdd(self, scene: Qt.QGraphicsScene, xc: int, yc: int, col: int) -> Qt.QGraphicsScene: colour = Qt.QBrush() colour.setStyle(QtCore.Qt.SolidPattern) if col == 0: colour.setColor(Qt.QColor(255, 0, 0, 255)) elif col == 1: colour.setColor(Qt.QColor(0, 255, 0, 255)) else: colour.setColor(Qt.QColor(0, 0, 255, 255)) return scene.addEllipse(xc, yc, 23, 23, Qt.QPen(), colour)
class CameraInspectorCore(QGraphicsView): _w = setting.camera_resolution[0] _h = setting.camera_resolution[1] def __init__(self): super().__init__() self._zoom = 0 self._scene = None self._image = None self._last_rect = None self._info = None self._require_fit_map = False self._disconnect_map = None self._loading_map = None self._setup_ui() def _generate_loading_map(self): text = 'Loading...' pixmap = QPixmap(self._w, self._h) pixmap.fill(self.palette().dark().color()) painter = QPainter(pixmap) painter.setRenderHint(QPainter.TextAntialiasing) font = QFont() font.setPixelSize(60) painter.setFont(font) painter.setPen(self.palette().text().color()) text_size = painter.fontMetrics().size(0, text) painter.drawText((self._w - text_size.width()) / 2, (self._h - text_size.height()) / 2, text_size.width(), text_size.height(), Qt.AlignCenter, text) painter.end() return pixmap def _setup_ui(self): self.setRenderHint(QPainter.Antialiasing) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setFrameShape(QFrame.NoFrame) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._loading_map = self._generate_loading_map() self._scene = QGraphicsScene(self) self._scene.setBackgroundBrush(QBrush(self.palette().dark().color())) self._image = QGraphicsPixmapItem() self._scene.addItem(self._image) # hud hud_color = self.palette().highlight().color().lighter(150) self._overlay = self._scene.addEllipse(QRectF(), QPen(hud_color, 4), QBrush(Qt.NoBrush)) self._crosshair = self._scene.addEllipse(QRectF(), QPen(hud_color, 2), QBrush(Qt.NoBrush)) rect = QRectF(0, 0, self._w, self._h) cx = rect.center().x() cy = rect.center().y() r = min(rect.width(), rect.height()) * 0.7 self._overlay.setRect(QRectF(cx - r / 2, cy - r / 2, r, r)) rc = min(rect.width(), rect.height()) * 0.05 self._crosshair.setRect(QRectF(cx - rc / 2, cy - rc / 2, rc, rc)) self._overlay.setVisible(False) self._crosshair.setVisible(False) # scene self.setScene(self._scene) self._info = CameraInspectorInfo() self.setLayout(self._info) def toggle_overlay(self, toggle): self._overlay.setVisible(toggle) self._crosshair.setVisible(toggle) def change_camera(self, serial): self._info.update_info(serial=serial) self.set_map(self._loading_map) self._require_fit_map = True def set_map(self, pixmap): if pixmap and pixmap.width() == self._w: self._image.setPixmap(pixmap) if self._require_fit_map: self._fit_map() self._require_fit_map = False else: self._image.setPixmap(self._loading_map) if self._zoom != 0: self._fit_map() def _fit_map(self): self.setDragMode(QGraphicsView.NoDrag) rect = QRectF(self._image.pixmap().rect()) self.setSceneRect(rect) # 取得目前 scale,歸回 scale 1 m = self.transform().mapRect(QRectF(0, 0, 1, 1)) self.scale(1 / m.width(), 1 / m.height()) # 縮放成適合圖像大小 scenerect = self.transform().mapRect(rect) factor = min(self.width() / scenerect.width(), self.height() / scenerect.height()) self.scale(factor, factor) self._zoom = 0 self._info.update_info(zoom=self.transform().m11()) def wheelEvent(self, event): if event.angleDelta().y() > 0: factor = 1.25 self._zoom += 1 else: factor = 0.8 self._zoom -= 1 if self._zoom > 0: self.scale(factor, factor) self.setDragMode(QGraphicsView.ScrollHandDrag) elif self._zoom == 0: self._fit_map() else: self._zoom = 0 self._info.update_info(zoom=self.transform().m11()) def resizeEvent(self, event): if not self.isVisible(): return if self._zoom == 0: if not self._image.pixmap().isNull(): self._fit_map() elif self._last_rect is not None: la = self._last_rect.center() c = self.rect().center() self.translate(c.x() - la.x(), c.y() - la.y()) self._last_rect = self.rect()
class MatplotTinderUI(QWidget, UI): def __init__(self, parent=None): super().__init__(parent) matplot_widget = FigureCanvas(Figure()) self._ax = matplot_widget.figure.subplots() self._scene = QGraphicsScene() self.matplot_graphics_widget = self._scene.addWidget(matplot_widget) self.matplot_graphics_widget.setParent(self) self.red_brush = QBrush(Qt.SolidPattern) self.red_brush.setColor(QColor(255, 0, 0, 50)) self.pen = QPen() self.pen.setColor(QColor(0, 0, 0, 0)) self._scene.addEllipse(0, self.height()/2, self.height()/2, self.height(), QPen(Qt.NoPen), self.red_brush) self._view = QGraphicsView(self._scene) self._view.setGeometry(250, 250, 500, 500) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._view) self.setLayout(layout) id = QGestureRecognizer.registerRecognizer(PanGestureRecognizer()) self.grabGesture(id) def show_image(self, img, cmap=Defaults.cmap, interpolation='gaussian'): self._ax.clear() self._ax.axis('off') self._ax.imshow(img.data, cmap=cmap, interpolation=interpolation) self._ax.figure.canvas.draw() def connect_multi_classification_listener(self, action): pass def connect_single_classification_listener(self, action): pass def connect_skip_classification_listener(self, action): self.skip = action def event(self, event): if event.type() == QEvent.Gesture and event.gesture(Qt.PanGesture): self.pan_triggered(event.gesture(Qt.PanGesture)) else: super().event(event) return True def pan_triggered(self, pan_gesture): delta = pan_gesture.delta() self.matplot_graphics_widget.setPos(self.matplot_graphics_widget.x() + delta.x(), self.matplot_graphics_widget.y() + delta.y()) if pan_gesture.state() == Qt.GestureFinished: # self._check_if_classified() self.reset() def mouseDoubleClickEvent(self, a0): # self.reset() print('mouseclick') self.skip() def reset(self): self.animation = QPropertyAnimation(self.matplot_graphics_widget, b'pos') self.animation.setStartValue(self.matplot_graphics_widget.pos()) self.animation.setEndValue(QPointF(100, 100)) self.animation.setDuration(100) self.animation.start() def paintEvent(self, event): self.matplot_graphics_widget.setRotation(self.get_rotation()) self.update() def get_rotation(self): pic = [self.matplot_graphics_widget.x(), -self.matplot_graphics_widget.y()] pivot = [0, -500] v1 = np.subtract(pic, pivot) v2 = np.subtract([0, 0], pivot) a = np.arccos(np.divide(np.abs(np.dot(v1, v2)), (np.linalg.norm(v1) * np.linalg.norm(v2)))) if self.matplot_graphics_widget.x() < 0: return -a * 10 return a * 10