Ejemplo n.º 1
0
class BlockDiagramEditorView(QWidget):
    _size = 1_000

    def __init__(self):
        super().__init__()

        self.labeledSlider = VLabeledSlider()

        self._qscene = QGraphicsScene()
        self._qscene.setSceneRect(-self._size / 2, -self._size / 2, self._size,
                                  self._size)

        self._qview = BlockDiagramView(scene=self._qscene, parent=self)

        layout = QHBoxLayout()
        layout.addWidget(self.labeledSlider, 0)
        layout.addWidget(self._qview, 1)
        layout.setAlignment(Qt.AlignCenter)
        self.widgetLayout = layout

        groupBox = QGroupBox()
        groupBox.setTitle("Block diagram")
        groupBox.setLayout(layout)

        parentLayout = QVBoxLayout()
        parentLayout.addWidget(groupBox)
        self.setLayout(parentLayout)
Ejemplo n.º 2
0
class GraphicsView(QGraphicsView):
    def __init__(self, **kwargs):
        super(GraphicsView, self).__init__(**kwargs)
        self._scene = QGraphicsScene(parent=self)

        self.current_image = QGraphicsPixmapItem()
        self._scene.addItem(self.current_image)

        self.setScene(self._scene)
        self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setMouseTracking(True)
        self.setRenderHint(QPainter.Antialiasing)

    def update_image(self, img: np.ndarray):
        rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_image.shape
        bytes_per_line = ch * w
        qimg = QImage(rgb_image.data, w, h, bytes_per_line,
                      QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(qimg)
        self.current_image.setPixmap(pixmap)
        self._scene.setSceneRect(0, 0, w, h)
        self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)

    def resizeEvent(self, e):
        self.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)

    def wheelEvent(self, e):
        if e.angleDelta().y() > 0:
            self.scale(1.25, 1.25)
        elif e.angleDelta().y() < 0:
            self.scale(0.85, 0.85)

    def mousePressEvent(self, e):
        # シーン上のマウス位置を取得する
        pos = self.mapToScene(e.pos())
        if e.button() == Qt.LeftButton:
            if e.modifiers() == Qt.NoModifier:
                pass
            elif e.modifiers() == Qt.AltModifier:
                self.setDragMode(QGraphicsView.ScrollHandDrag)
        QGraphicsView.mousePressEvent(self, e)

    def mouseReleaseEvent(self, e):
        QGraphicsView.mouseReleaseEvent(self, e)
        if e.button() == Qt.LeftButton:
            self.setDragMode(QGraphicsView.NoDrag)

    def calc_offset(self, p: QPoint):
        offset_x = p.x() - int(self.viewport().width() / 2)
        offset_y = p.y() - int(self.viewport().height() / 2)
        return QPoint(offset_x, offset_y)
Ejemplo n.º 3
0
class DataGraphWidget(QGraphicsView):

    selection_changed = Signal()

    def __init__(self, parent=None):

        super(DataGraphWidget, self).__init__(parent=parent)

        # Set up scene

        self.scene = QGraphicsScene(self)
        self.scene.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.scene.setSceneRect(0, 0, 800, 300)

        self.setScene(self.scene)

        self.setWindowTitle("Glue data graph")

        self.setRenderHint(QPainter.Antialiasing)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)

        self.selection_level = 0

    def resizeEvent(self, event):
        self.scene.setSceneRect(0, 0, self.width(), self.height())
        self.relayout(reorder=False)

    def relayout(self, reorder=True):

        # Update radius
        for node in self.nodes:
            node.radius = self.height() / 30.

        layout_simple_circle(self.nodes,
                             self.edges,
                             center=(self.width() / 2, self.height() / 2),
                             radius=self.height() / 3,
                             reorder=reorder)

        # Update edge positions
        for edge in self.background_edges + self.edges:
            edge.update_position()

        # Set up labels
        self.left_nodes = [
            node for node in self.nodes
            if node.node_position[0] < self.width() / 2
        ]
        self.left_nodes = sorted(self.left_nodes,
                                 key=lambda x: x.node_position[1],
                                 reverse=True)

        self.right_nodes = [
            node for node in self.nodes if node not in self.left_nodes
        ]
        self.right_nodes = sorted(self.right_nodes,
                                  key=lambda x: x.node_position[1],
                                  reverse=True)

        for i, node in enumerate(self.left_nodes):
            y = self.height() - (i + 1) / (len(self.left_nodes) +
                                           1) * self.height()
            node.label_position = self.width() / 2 - self.height() / 2, y

        for i, node in enumerate(self.right_nodes):
            y = self.height() - (i + 1) / (len(self.right_nodes) +
                                           1) * self.height()
            node.label_position = self.width() / 2 + self.height() / 2, y

    def set_data_collection(self,
                            data_collection,
                            old_links=None,
                            new_links=None):

        # Get data and initialize nodes
        self.data_to_nodes = OrderedDict(
            (data, DataNode(data)) for data in data_collection)
        self.nodes = list(self.data_to_nodes.values())

        # Get links and set up edges

        if old_links:
            self.background_edges = [
                Edge(self.data_to_nodes[data1],
                     self.data_to_nodes[data2],
                     linewidth=1,
                     zindex=1) for data1, data2 in get_connections(
                         data_collection.external_links)
            ]
        else:
            self.background_edges = []

        if new_links:
            self.edges = [
                Edge(self.data_to_nodes[data1], self.data_to_nodes[data2])
                for data1, data2 in get_connections(new_links)
            ]
        else:
            self.edges = []

        # Figure out positions
        self.relayout()

        # Add nodes and edges to graph

        for node in self.nodes:
            node.add_to_scene(self.scene)

        for edge in self.background_edges + self.edges:
            edge.add_to_scene(self.scene)

        self.text_adjusted = False

        self.selected_edge = None
        self.selected_node1 = None
        self.selected_node2 = None

    def set_links(self, links):

        for edge in self.edges:
            edge.remove_from_scene(self.scene)

        self.edges = [
            Edge(self.data_to_nodes[data1], self.data_to_nodes[data2])
            for data1, data2 in get_connections(links)
        ]

        for edge in self.edges:
            edge.update_position()

        for edge in self.edges:
            edge.add_to_scene(self.scene)

        self._update_selected_edge()

        self._update_selected_colors()

    def paintEvent(self, event):

        super(DataGraphWidget, self).paintEvent(event)

        if not self.text_adjusted:

            for node in self.nodes:

                width = node.label.boundingRect().width()
                height = node.label.boundingRect().height()

                transform = QTransform()
                if node in self.left_nodes:
                    transform.translate(-width, -height / 2)
                else:
                    transform.translate(0, -height / 2)

                node.label.setTransform(transform)

            self.text_adjusted = True

    def manual_select(self, data1=None, data2=None):
        if data1 is None and data2 is not None:
            data1, data2 = data2, data1
        if data2 is not None:
            self.selection_level = 2
        elif data1 is not None:
            self.selection_level = 1
        else:
            self.selection_level = 0
        self.selected_node1 = self.data_to_nodes.get(data1, None)
        self.selected_node2 = self.data_to_nodes.get(data2, None)
        self._update_selected_edge()
        self._update_selected_colors()

    def find_object(self, event):
        for obj in list(self.nodes) + self.edges:
            if obj.contains(event.localPos()):
                return obj

    def mouseMoveEvent(self, event):

        # TODO: Don't update until the end
        # TODO: Only select object on top

        selected = self.find_object(event)

        if selected is None:

            if self.selection_level == 0:
                self.selected_node1 = None
                self.selected_node2 = None
                self._update_selected_edge()
            elif self.selection_level == 1:
                self.selected_node2 = None
                self._update_selected_edge()

        elif isinstance(selected, DataNode):

            if self.selection_level == 0:
                self.selected_node1 = selected
                self.selected_node2 = None
            elif self.selection_level == 1:
                if selected is not self.selected_node1:
                    self.selected_node2 = selected
                    self._update_selected_edge()

        elif isinstance(selected, Edge):

            if self.selection_level == 0:
                self.selected_edge = selected
                self.selected_node1 = selected.node_source
                self.selected_node2 = selected.node_dest

        self._update_selected_colors()

        self.selection_changed.emit()

    def mousePressEvent(self, event):

        # TODO: Don't update until the end
        # TODO: Only select object on top

        selected = self.find_object(event)

        if selected is None:

            self.selection_level = 0
            self.selected_node1 = None
            self.selected_node2 = None

            self._update_selected_edge()

        elif isinstance(selected, DataNode):

            if self.selection_level == 0:
                self.selected_node1 = selected
                self.selection_level += 1
            elif self.selection_level == 1:
                if selected is self.selected_node1:
                    self.selected_node1 = None
                    self.selection_level = 0
                else:
                    self.selected_node2 = selected
                    self.selection_level = 2
            elif self.selection_level == 2:
                if selected is self.selected_node2:
                    self.selected_node2 = None
                    self.selection_level = 1
                else:
                    self.selected_node1 = selected
                    self.selected_node2 = None
                    self.selection_level = 1

            self._update_selected_edge()

        elif isinstance(selected, Edge):

            if self.selected_edge is selected and self.selection_level == 2:
                self.selected_edge = None
                self.selected_node1 = None
                self.selected_node2 = None
                self.selection_level = 0
            else:
                self.selected_edge = selected
                self.selected_node1 = selected.node_source
                self.selected_node2 = selected.node_dest
                self.selection_level = 2

        self.mouseMoveEvent(event)

    def _update_selected_edge(self):
        for edge in self.edges:
            if (edge.node_source is self.selected_node1
                    and edge.node_dest is self.selected_node2
                    or edge.node_source is self.selected_node2
                    and edge.node_dest is self.selected_node1):
                self.selected_edge = edge
                break
        else:
            self.selected_edge = None

    def _update_selected_colors(self):

        colors = {}

        if self.selected_node1 is not None and self.selection_level < 2:

            direct, indirect = find_connections(self.selected_node1,
                                                self.nodes, self.edges)

            for node in self.nodes:
                if node in direct or node in indirect:
                    colors[node] = COLOR_CONNECTED
                else:
                    colors[node] = COLOR_DISCONNECTED

            for edge in self.edges:
                if (edge.node_source is self.selected_node1
                        or edge.node_dest is self.selected_node1):
                    colors[edge] = COLOR_CONNECTED

        if self.selected_edge is not None:
            colors[self.selected_edge] = COLOR_SELECTED

        if self.selected_node1 is not None:
            colors[self.selected_node1] = COLOR_SELECTED

        if self.selected_node2 is not None:
            colors[self.selected_node2] = COLOR_SELECTED

        self.set_colors(colors)

    def set_colors(self, colors):

        for obj in list(self.nodes) + self.edges:
            default_color = '0.8' if isinstance(obj, DataNode) else '0.5'
            obj.color = colors.get(obj, default_color)
            obj.update()
Ejemplo n.º 4
0
class CroppableCameraView(QGraphicsView):
    rectChanged = Signal(QRect)
    imageDisplayed = Signal(np.ndarray)
    videoStarted = Signal()
    mouseMoved = Signal(QMouseEvent)
    mousePressed = Signal(QMouseEvent)
    mouseReleased = Signal(QMouseEvent)

    def __init__(self, camera, **settings):
        super(CroppableCameraView, self).__init__()
        self.setRenderHint(QPainter.Antialiasing)
        self.cam = camera
        self.is_live = False
        self._cmin = 0
        self._cmax = None
        self.settings = settings
        self._selecting = False
        self.needs_resize = False
        self.latest_array = None

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene()
        #self.setFrameStyle(QFrame.NoFrame)
        self.setScene(self.scene)
        self.pixmapitem = self.scene.addPixmap(QPixmap())
        self._uncropped_pixmap = None

        self.setMouseTracking(True)

        self.start = None
        c1 = QColor(0, 100, 220, 150)
        self.c2 = QColor(0, 100, 220, 50)
        self.c3 = QColor(0, 100, 220, 0)
        pen = QPen(c1, 2)

        self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3)
        self.selrect.setZValue(100)
        self.selrect.hide()

    def enable_selecting(self):
        print("Selection enabled")
        self._selecting = True

    def disable_selecting(self):
        self._selecting = False

    def mousePressEvent(self, event):
        if self._selecting:
            print("Mouse pressed")
            if not self.selrect.isVisible():
                self.selrect.show()

            if event.button() == Qt.LeftButton:
                sp = self.mapToScene(event.pos())
                self.start = (sp.x(), sp.y())
                self.selrect.setRect(sp.x(), sp.y(), 0, 0)
                self.selrect.setBrush(self.c2)

        self.mousePressed.emit(event)

    def mouseMoveEvent(self, event):
        if self.start:
            x1, y1 = self.start
            sp = self.mapToScene(event.pos())

            # Image width, height in scene coords
            ir = self.pixmapitem.boundingRect()
            sr = self.pixmapitem.sceneTransform().mapRect(ir)

            size = self.pixmapitem.pixmap().size()
            x2 = max(sr.left(), min(sr.right() - 1, sp.x()))
            y2 = max(sr.top(), min(sr.bottom() - 1, sp.y()))
            x1, x2 = sorted((x1, x2))
            y1, y2 = sorted((y1, y2))
            self.selrect.setRect(x1, y1, x2 - x1, y2 - y1)

        self.mouseMoved.emit(event)

    def mouseReleaseEvent(self, event):
        if self.start and event.button() == Qt.LeftButton:
            self.start = None
            self.selrect.setBrush(self.c3)
            self.rectChanged.emit(self.selrect.rect().toRect())

        self.mouseReleased.emit(event)

    def update_rect(self, x, y, w, h):
        self.selrect.setRect(x, y, w, h)
        self.rectChanged.emit(self.selrect.rect().toRect())

    def hideRect(self):
        self.selrect.hide()

    def showRect(self):
        self.selrect.show()

    def setRectVisible(self, visible):
        self.selrect.setVisible(visible)

    def isRectVisible(self):
        return self.selrect.isVisible()

    def rect(self):
        """QRect of the selection in camera coordinates"""
        # selrect in _image_ (pixmap) coordinates
        i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect(
            self.selrect.rect())
        current_left = self.settings.get('left', 0)
        current_top = self.settings.get('top', 0)
        return i_selrect.toRect().translated(current_left, current_top)

    def crop_to_rect(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        self.hideRect()

        rect = self.rect()
        self.settings['left'] = rect.left()
        self.settings['right'] = rect.right()
        self.settings['top'] = rect.top()
        self.settings['bot'] = rect.bottom()

        if was_live:
            self.start_video()
        else:
            if not self._uncropped_pixmap:
                self._uncropped_pixmap = self.pixmapitem.pixmap()
            self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect))
            self.setFixedSize(rect.width(), rect.height())

    def uncrop(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        for key in ['left', 'right', 'top', 'bot']:
            if key in self.settings:
                del self.settings[key]

        if was_live:
            self.start_video()
        else:
            pixmap = self._uncropped_pixmap
            self.pixmapitem.setPixmap(pixmap)

        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        self.setFixedSize(sr.width(), sr.height())

    def mapSceneToPixmap(self, pt):
        transform = self.pixmapitem.sceneTransform().inverted()[0]
        return transform.mapRect(pt) if isinstance(
            pt, (QRect, QRectF)) else transform.map(pt)

    def mapViewToPixmap(self, view_pt):
        scene_pt = self.mapToScene(view_pt)
        return self.mapSceneToPixmap(scene_pt)

    def mapPixmapToScene(self, pixmap_pt):
        transform = self.pixmapitem.sceneTransform()
        map_func = transform.mapRect if isinstance(pixmap_pt,
                                                   (QRect,
                                                    QRectF)) else transform.map
        return map_func(pixmap_pt)

    def mapSceneToCamera(self, sc_pt):
        px_pt = self.mapSceneToPixmap(sc_pt)
        return QPoint(px_pt.x() + self.settings.get('left', 0),
                      px_pt.y() + self.settings.get('top', 0))

    def set_image(self, image_arr):
        pixmap = QPixmap(self._array_to_qimage(image_arr))
        if not self.pixmapitem:
            self.pixmapitem = self.scene.addPixmap(pixmap)
        else:
            self.pixmapitem.setPixmap(pixmap)

        if self.needs_resize:
            self._autoresize_viewport()
            self.needs_resize = False

    def _autoresize_viewport(self):
        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        #self.setFixedSize(sr.width(), sr.height())
        self.resize(sr.width(), sr.height())
        #self.viewport().setMaximumSize(sr.width(), sr.height())
        d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        self.setMaximumSize(sr.width() + 2 * d, sr.height() + 2 * d)

    def grab_image(self):
        arr = self.cam.grab_image(**self.settings)
        self.set_image(arr)
        self.latest_array = arr
        self.imageDisplayed.emit(arr)

    def start_video(self):
        timer = QTimer()
        self.timer = timer
        timer.timeout.connect(self._wait_for_frame)
        self.cam.start_live_video(**self.settings)
        timer.start(0)  # Run full throttle
        self.is_live = True
        self.needs_resize = True
        self.videoStarted.emit()

    def stop_video(self):
        self.timer.stop()
        self.cam.stop_live_video()
        self.is_live = False

    def _wait_for_frame(self):
        frame_ready = self.cam.wait_for_frame(timeout='0 ms')
        if frame_ready:
            arr = self.cam.latest_frame(copy=True)
            self.set_image(arr)
            self.latest_array = arr
            self.imageDisplayed.emit(arr)

    def _scale_image(self, arr):
        """Return a bytescaled copy of the image array"""
        if not self._cmax:
            self._cmax = arr.max()  # Set cmax once from first image
        return scipy.misc.bytescale(arr, self._cmin, self._cmax)

    def _lut_scale_image(self, arr):
        if not self._cmax:
            self._cmax = arr.max()
        lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax)
        return lut[arr]

    def _create_lut(self, k):
        A = 2**15
        B = 100  # k's scaling factor
        g = lambda i, k: A * ((k - B) * i) / ((2 * k) * x - (k + B) * A)

    def _array_to_qimage(self, arr):
        bpl = arr.strides[0]
        is_rgb = len(arr.shape) == 3

        if is_rgb and arr.dtype == np.uint8:
            format = QImage.Format_RGB32
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl,
                           format)
        elif not is_rgb and arr.dtype == np.uint8:
            # TODO: Somehow need to make sure data is ordered as I'm assuming
            format = QImage.Format_Indexed8
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl,
                           format)
            self._saved_img = arr
        elif not is_rgb and arr.dtype == np.uint16:
            arr = self._scale_image(arr)
            format = QImage.Format_Indexed8
            w, h = self.cam.width, self.cam.height
            image = QImage(arr.data, w, h, w, format)
            self._saved_img = arr  # Save a reference to keep Qt from crashing
        else:
            raise Exception("Unsupported color mode")

        return image
Ejemplo n.º 5
0
class DataGraphWidget(QGraphicsView):

    selection_changed = Signal()

    def __init__(self, parent=None):

        super(DataGraphWidget, self).__init__(parent=parent)

        # Set up scene

        self.scene = QGraphicsScene(self)
        self.scene.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.scene.setSceneRect(0, 0, 800, 300)

        self.setScene(self.scene)

        self.setWindowTitle("Glue data graph")

        self.setRenderHint(QPainter.Antialiasing)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)

        self.selection_level = 0

    def resizeEvent(self, event):
        self.scene.setSceneRect(0, 0, self.width(), self.height())
        self.relayout(reorder=False)

    def relayout(self, reorder=True):

        # Update radius
        for node in self.nodes:
            node.radius = self.height() / 30.

        layout_simple_circle(self.nodes, self.edges,
                             center=(self.width() / 2, self.height() / 2),
                             radius=self.height() / 3, reorder=reorder)

        # Update edge positions
        for edge in self.edges:
            edge.update_position()

        # Set up labels
        self.left_nodes = [node for node in self.nodes if node.node_position[0] < self.width() / 2]
        self.left_nodes = sorted(self.left_nodes, key=lambda x: x.node_position[1], reverse=True)

        self.right_nodes = [node for node in self.nodes if node not in self.left_nodes]
        self.right_nodes = sorted(self.right_nodes, key=lambda x: x.node_position[1], reverse=True)

        for i, node in enumerate(self.left_nodes):
            y = self.height() - (i + 1) / (len(self.left_nodes) + 1) * self.height()
            node.label_position = self.width() / 2 - self.height() / 2, y

        for i, node in enumerate(self.right_nodes):
            y = self.height() - (i + 1) / (len(self.right_nodes) + 1) * self.height()
            node.label_position = self.width() / 2 + self.height() / 2, y

    def set_data_collection(self, data_collection):

        # Get data and initialize nodes
        self.data_to_nodes = dict((data, DataNode(data)) for data in data_collection)
        self.nodes = list(self.data_to_nodes.values())

        # Get links and set up edges
        self.edges = [Edge(self.data_to_nodes[data1], self.data_to_nodes[data2])
                      for data1, data2 in get_connections(data_collection.external_links)]

        # Figure out positions
        self.relayout()

        # Add nodes and edges to graph

        for node in self.nodes:
            node.add_to_scene(self.scene)

        for edge in self.edges:
            edge.add_to_scene(self.scene)

        self.text_adjusted = False

        self.selected_edge = None
        self.selected_node1 = None
        self.selected_node2 = None

    def set_links(self, links):

        for edge in self.edges:
            edge.remove_from_scene(self.scene)

        self.edges = [Edge(self.data_to_nodes[data1], self.data_to_nodes[data2])
                      for data1, data2 in get_connections(links)]

        for edge in self.edges:
            edge.update_position()

        for edge in self.edges:
            edge.add_to_scene(self.scene)

        self._update_selected_edge()

        self._update_selected_colors()

    def paintEvent(self, event):

        super(DataGraphWidget, self).paintEvent(event)

        if not self.text_adjusted:

            for node in self.nodes:

                width = node.label.boundingRect().width()
                height = node.label.boundingRect().height()

                transform = QTransform()
                if node in self.left_nodes:
                    transform.translate(-width, -height / 2)
                else:
                    transform.translate(0, -height / 2)

                node.label.setTransform(transform)

            self.text_adjusted = True

    def manual_select(self, data1=None, data2=None):
        if data1 is None and data2 is not None:
            data1, data2 = data2, data1
        if data2 is not None:
            self.selection_level = 2
        elif data1 is not None:
            self.selection_level = 1
        else:
            self.selection_level = 0
        self.selected_node1 = self.data_to_nodes.get(data1, None)
        self.selected_node2 = self.data_to_nodes.get(data2, None)
        self._update_selected_edge()
        self._update_selected_colors()

    def find_object(self, event):
        for obj in list(self.nodes) + self.edges:
            if obj.contains(event.localPos()):
                return obj

    def mouseMoveEvent(self, event):

        # TODO: Don't update until the end
        # TODO: Only select object on top

        selected = self.find_object(event)

        if selected is None:

            if self.selection_level == 0:
                self.selected_node1 = None
                self.selected_node2 = None
                self._update_selected_edge()
            elif self.selection_level == 1:
                self.selected_node2 = None
                self._update_selected_edge()

        elif isinstance(selected, DataNode):

            if self.selection_level == 0:
                self.selected_node1 = selected
                self.selected_node2 = None
            elif self.selection_level == 1:
                if selected is not self.selected_node1:
                    self.selected_node2 = selected
                    self._update_selected_edge()

        elif isinstance(selected, Edge):

            if self.selection_level == 0:
                self.selected_edge = selected
                self.selected_node1 = selected.node_source
                self.selected_node2 = selected.node_dest

        self._update_selected_colors()

        self.selection_changed.emit()

    def mousePressEvent(self, event):

        # TODO: Don't update until the end
        # TODO: Only select object on top

        selected = self.find_object(event)

        if selected is None:

            self.selection_level = 0
            self.selected_node1 = None
            self.selected_node2 = None

            self._update_selected_edge()

        elif isinstance(selected, DataNode):

            if self.selection_level == 0:
                self.selected_node1 = selected
                self.selection_level += 1
            elif self.selection_level == 1:
                if selected is self.selected_node1:
                    self.selected_node1 = None
                    self.selection_level = 0
                else:
                    self.selected_node2 = selected
                    self.selection_level = 2
            elif self.selection_level == 2:
                if selected is self.selected_node2:
                    self.selected_node2 = None
                    self.selection_level = 1
                else:
                    self.selected_node1 = selected
                    self.selected_node2 = None
                    self.selection_level = 1

            self._update_selected_edge()

        elif isinstance(selected, Edge):

            if self.selected_edge is selected and self.selection_level == 2:
                self.selected_edge = None
                self.selected_node1 = None
                self.selected_node2 = None
                self.selection_level = 0
            else:
                self.selected_edge = selected
                self.selected_node1 = selected.node_source
                self.selected_node2 = selected.node_dest
                self.selection_level = 2

        self.mouseMoveEvent(event)

    def _update_selected_edge(self):
        for edge in self.edges:
            if (edge.node_source is self.selected_node1 and edge.node_dest is self.selected_node2 or
                    edge.node_source is self.selected_node2 and edge.node_dest is self.selected_node1):
                self.selected_edge = edge
                break
        else:
            self.selected_edge = None

    def _update_selected_colors(self):

        colors = {}

        if self.selected_node1 is not None and self.selection_level < 2:

            direct, indirect = find_connections(self.selected_node1, self.nodes, self.edges)

            for node in self.nodes:
                if node in direct or node in indirect:
                    colors[node] = COLOR_CONNECTED
                else:
                    colors[node] = COLOR_DISCONNECTED

            for edge in self.edges:
                if (edge.node_source is self.selected_node1 or
                        edge.node_dest is self.selected_node1):
                    colors[edge] = COLOR_CONNECTED

        if self.selected_edge is not None:
            colors[self.selected_edge] = COLOR_SELECTED

        if self.selected_node1 is not None:
            colors[self.selected_node1] = COLOR_SELECTED

        if self.selected_node2 is not None:
            colors[self.selected_node2] = COLOR_SELECTED

        self.set_colors(colors)

    def set_colors(self, colors):

        for obj in list(self.nodes) + self.edges:
            default_color = '0.8' if isinstance(obj, DataNode) else '0.5'
            obj.color = colors.get(obj, default_color)
            obj.update()
Ejemplo n.º 6
0
class CroppableCameraView(QGraphicsView):
    rectChanged = Signal(QRect)
    imageDisplayed = Signal(np.ndarray)
    videoStarted = Signal()
    mouseMoved = Signal(QMouseEvent)
    mousePressed = Signal(QMouseEvent)
    mouseReleased = Signal(QMouseEvent)

    def __init__(self, camera, **settings):
        super(CroppableCameraView, self).__init__()
        self.setRenderHint(QPainter.Antialiasing)
        self.cam = camera
        self.is_live = False
        self._cmin = 0
        self._cmax = None
        self.settings = settings
        self._selecting = False
        self.needs_resize = False
        self.latest_array = None

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene()
        #self.setFrameStyle(QFrame.NoFrame)
        self.setScene(self.scene)
        self.pixmapitem = self.scene.addPixmap(QPixmap())
        self._uncropped_pixmap = None

        self.setMouseTracking(True)

        self.start = None
        c1 = QColor(0, 100, 220, 150)
        self.c2 = QColor(0, 100, 220, 50)
        self.c3 = QColor(0, 100, 220, 0)
        pen = QPen(c1, 2)

        self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3)
        self.selrect.setZValue(100)
        self.selrect.hide()

    def enable_selecting(self):
        print("Selection enabled")
        self._selecting = True

    def disable_selecting(self):
        self._selecting = False

    def mousePressEvent(self, event):
        if self._selecting:
            print("Mouse pressed")
            if not self.selrect.isVisible():
                self.selrect.show()

            if event.button() == Qt.LeftButton:
                sp = self.mapToScene(event.pos())
                self.start = (sp.x(), sp.y())
                self.selrect.setRect(sp.x(), sp.y(), 0, 0)
                self.selrect.setBrush(self.c2)

        self.mousePressed.emit(event)

    def mouseMoveEvent(self, event):
        if self.start:
            x1, y1 = self.start
            sp = self.mapToScene(event.pos())

            # Image width, height in scene coords
            ir = self.pixmapitem.boundingRect()
            sr = self.pixmapitem.sceneTransform().mapRect(ir)

            size = self.pixmapitem.pixmap().size()
            x2 = max(sr.left(), min(sr.right()-1, sp.x()))
            y2 = max(sr.top(), min(sr.bottom()-1, sp.y()))
            x1, x2 = sorted((x1, x2))
            y1, y2 = sorted((y1, y2))
            self.selrect.setRect(x1, y1, x2-x1, y2-y1)

        self.mouseMoved.emit(event)

    def mouseReleaseEvent(self, event):
        if self.start and event.button() == Qt.LeftButton:
            self.start = None
            self.selrect.setBrush(self.c3)
            self.rectChanged.emit(self.selrect.rect().toRect())

        self.mouseReleased.emit(event)

    def update_rect(self, x, y, w, h):
        self.selrect.setRect(x, y, w, h)
        self.rectChanged.emit(self.selrect.rect().toRect())

    def hideRect(self):
        self.selrect.hide()

    def showRect(self):
        self.selrect.show()

    def setRectVisible(self, visible):
        self.selrect.setVisible(visible)

    def isRectVisible(self):
        return self.selrect.isVisible()

    def rect(self):
        """QRect of the selection in camera coordinates"""
        # selrect in _image_ (pixmap) coordinates
        i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect(self.selrect.rect())
        current_left = self.settings.get('left', 0)
        current_top = self.settings.get('top', 0)
        return i_selrect.toRect().translated(current_left, current_top)

    def crop_to_rect(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        self.hideRect()

        rect = self.rect()
        self.settings['left'] = rect.left()
        self.settings['right'] = rect.right()
        self.settings['top'] = rect.top()
        self.settings['bot'] = rect.bottom()

        if was_live:
            self.start_video()
        else:
            if not self._uncropped_pixmap:
                self._uncropped_pixmap = self.pixmapitem.pixmap()
            self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect))
            self.setFixedSize(rect.width(), rect.height())

    def uncrop(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        for key in ['left', 'right', 'top', 'bot']:
            if key in self.settings:
                del self.settings[key]

        if was_live:
            self.start_video()
        else:
            pixmap = self._uncropped_pixmap
            self.pixmapitem.setPixmap(pixmap)

        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        self.setFixedSize(sr.width(), sr.height())

    def mapSceneToPixmap(self, pt):
        transform = self.pixmapitem.sceneTransform().inverted()[0]
        return transform.mapRect(pt) if isinstance(pt, (QRect, QRectF)) else transform.map(pt)

    def mapViewToPixmap(self, view_pt):
        scene_pt = self.mapToScene(view_pt)
        return self.mapSceneToPixmap(scene_pt)

    def mapPixmapToScene(self, pixmap_pt):
        transform = self.pixmapitem.sceneTransform()
        map_func = transform.mapRect if isinstance(pixmap_pt, (QRect, QRectF)) else transform.map
        return map_func(pixmap_pt)

    def mapSceneToCamera(self, sc_pt):
        px_pt = self.mapSceneToPixmap(sc_pt)
        return QPoint(px_pt.x() + self.settings.get('left', 0),
                      px_pt.y() + self.settings.get('top', 0))

    def set_image(self, image_arr):
        pixmap = QPixmap(self._array_to_qimage(image_arr))
        if not self.pixmapitem:
            self.pixmapitem = self.scene.addPixmap(pixmap)
        else:
            self.pixmapitem.setPixmap(pixmap)

        if self.needs_resize:
            self._autoresize_viewport()
            self.needs_resize = False

    def _autoresize_viewport(self):
        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        #self.setFixedSize(sr.width(), sr.height())
        self.resize(sr.width(), sr.height())
        #self.viewport().setMaximumSize(sr.width(), sr.height())
        d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        self.setMaximumSize(sr.width() + 2*d, sr.height() + 2*d)

    def grab_image(self):
        arr = self.cam.grab_image(**self.settings)
        self.set_image(arr)
        self.latest_array = arr
        self.imageDisplayed.emit(arr)

    def start_video(self):
        timer = QTimer()
        self.timer = timer
        timer.timeout.connect(self._wait_for_frame)
        self.cam.start_live_video(**self.settings)
        timer.start(0)  # Run full throttle
        self.is_live = True
        self.needs_resize = True
        self.videoStarted.emit()

    def stop_video(self):
        self.timer.stop()
        self.cam.stop_live_video()
        self.is_live = False

    def _wait_for_frame(self):
        frame_ready = self.cam.wait_for_frame(timeout='0 ms')
        if frame_ready:
            arr = self.cam.latest_frame(copy=True)
            self.set_image(arr)
            self.latest_array = arr
            self.imageDisplayed.emit(arr)

    def _scale_image(self, arr):
        """Return a bytescaled copy of the image array"""
        if not self._cmax:
            self._cmax = arr.max()  # Set cmax once from first image
        return scipy.misc.bytescale(arr, self._cmin, self._cmax)

    def _lut_scale_image(self, arr):
        if not self._cmax:
            self._cmax = arr.max()
        lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax)
        return lut[arr]

    def _create_lut(self, k):
        A = 2**15
        B = 100  # k's scaling factor
        g = lambda i, k: A*((k-B)*i) / ((2*k)*x - (k+B)*A)

    def _array_to_qimage(self, arr):
        bpl = arr.strides[0]
        is_rgb = len(arr.shape) == 3

        if is_rgb and arr.dtype == np.uint8:
            format = QImage.Format_RGB32
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format)
        elif not is_rgb and arr.dtype == np.uint8:
            # TODO: Somehow need to make sure data is ordered as I'm assuming
            format = QImage.Format_Indexed8
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format)
            self._saved_img = arr
        elif not is_rgb and arr.dtype == np.uint16:
            arr = self._scale_image(arr)
            format = QImage.Format_Indexed8
            w, h = self.cam.width, self.cam.height
            image = QImage(arr.data, w, h, w, format)
            self._saved_img = arr  # Save a reference to keep Qt from crashing
        else:
            raise Exception("Unsupported color mode")

        return image
Ejemplo n.º 7
0
class GraphicsView(QGraphicsView):

    def __init__(self, parent=None):

        super(GraphicsView, self).__init__(parent)

        self.scene = QGraphicsScene()
        self.pixmapItem = QGraphicsPixmapItem()
        self.scene.setSceneRect(0, 0, 500, 500)
        self.setScene(self.scene)
        self.scene.addItem(self.pixmapItem)
        #would eventually make this fit to size of screen, waiting cause it's annoying.

        self.buildingParams = []
        self.scalef = [1, 1]

        self.Buildings()
    
    def Buildings(self):
        
        filename = os.getcwd() + "\examplebuildings.png"
        img = cv2.imread(filename)
        imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        ret,thresh = cv2.threshold(imgray, 250, 255, 0)
        contours , h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

        MinCntArea = 5000.
        MaxCntArea = 100000.

        for cnt in contours:
            
            if cv2.contourArea(cnt) > MinCntArea and cv2.contourArea(cnt) < MaxCntArea:
                
                cv2.drawContours(img, cnt, -1, (0, 255, 0), 3) # this is a green rectangle which shows the found contour

                #cv2.circle(img, (min(cnt.T[0][0]), min(cnt.T[1][0])), 4, 4) #makes a circle around the upper left corner

                #np.set_printoptions(threshold=np.inf) #this is to make it so that the whole numpy array prints to the terminal

                self.buildingParams.append([min(cnt.T[0][0]), min(cnt.T[1][0]), max(cnt.T[0][0])-min(cnt.T[0][0]), max(cnt.T[1][0])-min(cnt.T[1][0])]) # x, y, height, width
                
        # copy and paste these three lines if you would like to see what an opencv images looks like anywhere in the program
        #cv2.imshow('img', img)
        #cv2.waitKey(0)
        #cv2.destroyAllWindows()

        #cv2.rectangle(img, (self.buildingParams[0][0], self.buildingParams[0][1]), 
        #                   (self.buildingParams[0][0] + self.buildingParams[0][2], self.buildingParams[0][1] + self.buildingParams[0][3]),
        #                   (255, 0, 0), -1) # draws a blue filled in rectangle - did this to make sure I had the indicies correct for x, y, width, and height

        height, width, channel = img.shape
        bytesPerLine = 3*width
        qimg = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped()

        ##### need to add not null checks here

        self.ogimage = QPixmap.fromImage(qimg)
        self.image = self.ogimage.scaled(self.scene.width(), self.scene.height())
        self.pixmapItem.setPixmap(self.image)

        self.updateScalef()
        self.buildingParams += self.scalef

        for i in range(len(self.buildingParams)-2):

            parameters = self.buildingParams
            rect = GraphicsRectItem(QRectF(QPointF(parameters[i][0] * parameters[4],
                                                                parameters[i][1] * parameters[5]),
                                                                QPointF((parameters[i][0] + parameters[i][2]) * parameters[4],
                                                                (parameters[i][1] + parameters[i][3]) * parameters[5])))
            
            rect.setAcceptHoverEvents(True)
            self.scene.addItem(rect)

        

    def updateScalef(self):

        self.scalef[0] = self.image.width()/self.ogimage.width()
        self.scalef[1] = self.image.height()/self.ogimage.height()

    def mousePressEvent(self, e):
        print(e.pos())