예제 #1
0
파일: game.py 프로젝트: spacejump163/ai2
class Tank(GameObject):
    FIRE_CD = 1.0
    MAX_MOVE_SPEED = UNIT * 2
    MAX_CANNON_ROTATION_SPEED = math.pi / 1.0
    MAX_BODY_ROTATION_SPEED = math.pi / 4.0
    MISSILE_SPEED = 2.5 * UNIT

    def __init__(self, color, group):
        super(Tank, self).__init__()
        self.graphics = QGraphicsItemGroup()
        self.body_graphics = TankGraphics(color)
        self.graphics.addToGroup(self.body_graphics)
        self.cannon_graphics = CannonGraphics(color)
        self.graphics.addToGroup(self.cannon_graphics)

        self.cannon_rotation = 0
        self.cannon_rotate_speed = 0
        self.group = group
        self.hp = 50

        self.fire_cd = 0

    def start(self):
        pass

    def update_logic(self):
        super(Tank, self).update_logic()
        self.cannon_rotation += self.cannon_rotate_speed * self.arena.dt
        self.fire_cd -= self.arena.dt

    def update_graphics(self):
        super(Tank, self).update_graphics()
        a = math.degrees(self.cannon_rotation)
        self.cannon_graphics.setRotation(a)

    def get_world_aiming(self):
        return self.rotation + self.cannon_rotation

    def adjust_aim_clockwise(self, w):
        self.cannon_rotate_speed = w

    def open_fire(self):
        if self.fire_cd <= 0:
            self.fire_cd = self.FIRE_CD
            orient = self.get_world_aiming()
            dv = QPointF(math.cos(orient), math.sin(orient)) * 0.6 * UNIT
            pos = self.position + dv
            m = Missile(pos, orient, self.MISSILE_SPEED)
            self.arena.add(m)
            return True
        else:
            return False

    def update(self):
        super(Tank, self).update()

    def take_damage(self, dmg):
        self.hp -= dmg
        if self.hp <= 0:
            self.cleanup()
예제 #2
0
    def visualize(self):
        """
        called when user clicks draw lsystem. This visualizes the lsystem to allow setup
        before the actual lsystification takes place
        """
        self.getdata()
        self.run_lsystem()

        old_group = self.layersModel.itemFromIndex(
            self.parent.layersList.currentIndex()).get_graphics_items_group()
        if old_group:
            self.parent.scene.removeItem(old_group)

        group = QGraphicsItemGroup()
        path = QPainterPath()
        for idx, point in enumerate(
                self.lsysteminterpreter.globalstate["pts"]):
            x = point[0][0][0]
            y = point[0][1][0]
            direction = point[1]
            x = x * self.xscale + self.xoffs
            y = y * self.yscale + self.yoffs
            if idx == 0:
                path.moveTo(x, y)
            else:
                path.lineTo(x, y)
        item = QGraphicsPathItem(path)
        pen = QPen()
        pen.setWidth(self.strokeWidth)
        item.setPen(pen)
        group.addToGroup(item)
        self.addNewGraphicsItems(group)
예제 #3
0
파일: game.py 프로젝트: spacejump163/ai2
class Tank(GameObject):
    FIRE_CD = 1.0
    MAX_MOVE_SPEED = UNIT * 2
    MAX_CANNON_ROTATION_SPEED = math.pi / 1.0
    MAX_BODY_ROTATION_SPEED = math.pi / 4.0
    MISSILE_SPEED = 2.5 * UNIT

    def __init__(self, color, group):
        super(Tank, self).__init__()
        self.graphics = QGraphicsItemGroup()
        self.body_graphics = TankGraphics(color)
        self.graphics.addToGroup(self.body_graphics)
        self.cannon_graphics = CannonGraphics(color)
        self.graphics.addToGroup(self.cannon_graphics)

        self.cannon_rotation = 0
        self.cannon_rotate_speed = 0
        self.group = group
        self.hp = 50

        self.fire_cd = 0

    def start(self):
        pass

    def update_logic(self):
        super(Tank, self).update_logic()
        self.cannon_rotation += self.cannon_rotate_speed * self.arena.dt
        self.fire_cd -= self.arena.dt

    def update_graphics(self):
        super(Tank, self).update_graphics()
        a = math.degrees(self.cannon_rotation)
        self.cannon_graphics.setRotation(a)

    def get_world_aiming(self):
        return self.rotation + self.cannon_rotation

    def adjust_aim_clockwise(self, w):
        self.cannon_rotate_speed = w

    def open_fire(self):
        if self.fire_cd <= 0:
            self.fire_cd = self.FIRE_CD
            orient = self.get_world_aiming()
            dv = QPointF(math.cos(orient), math.sin(orient)) * 0.6 * UNIT
            pos = self.position + dv
            m = Missile(pos, orient, self.MISSILE_SPEED)
            self.arena.add(m)
            return True
        else:
            return False

    def update(self):
        super(Tank, self).update()

    def take_damage(self, dmg):
        self.hp -= dmg
        if self.hp <= 0:
            self.cleanup()
예제 #4
0
    def __drawPoint(self, x, y, index):
        #横线
        line1 = QGraphicsLineItem()
        line1.setPen(self.pen)
        line1.setLine(x - self.lineRadius, y, x + self.lineRadius, y)

        #竖线
        line2 = QGraphicsLineItem()
        line2.setPen(self.pen)
        line2.setLine(x, y - self.lineRadius, x, y + self.lineRadius)

        #文字说明
        text = QGraphicsTextItem()
        text.setDefaultTextColor(Qt.blue)
        text.setFont(self.font)

        text.setPlainText(self.pointsName[index])
        text.setPos(x, y)

        #放到组中
        pointGroup = QGraphicsItemGroup()
        pointGroup.addToGroup(line1)
        pointGroup.addToGroup(line2)
        pointGroup.addToGroup(text)

        #显示
        if self.pointsItem[index] is not None:
            self.scene.removeItem(self.pointsItem[index])

        #保存到字典
        self.pointsItem[index] = pointGroup
        #显示该点
        self.scene.addItem(self.pointsItem[index])
예제 #5
0
class ReviewView(QGraphicsView):
    """Simple extension of QGraphicsView
    - containing an image and click-to-zoom/unzoom
    """
    def __init__(self, fnames):
        QGraphicsView.__init__(self)
        self.initUI(fnames)

    def initUI(self, fnames):
        # Make QGraphicsScene
        self.scene = QGraphicsScene()
        # TODO = handle different image sizes.
        self.images = {}
        self.imageGItem = QGraphicsItemGroup()
        self.scene.addItem(self.imageGItem)
        self.updateImage(fnames)
        self.setBackgroundBrush(QBrush(Qt.darkCyan))

    def updateImage(self, fnames):
        """Update the image with that from filename"""
        for n in self.images:
            self.imageGItem.removeFromGroup(self.images[n])
            self.images[n].setVisible(False)
        if fnames is not None:
            x = 0
            n = 0
            for fn in fnames:
                self.images[n] = QGraphicsPixmapItem(QPixmap(fn))
                self.images[n].setTransformationMode(Qt.SmoothTransformation)
                self.images[n].setPos(x, 0)
                self.images[n].setVisible(True)
                self.scene.addItem(self.images[n])
                x += self.images[n].boundingRect().width() + 10
                self.imageGItem.addToGroup(self.images[n])
                n += 1

        # Set sensible sizes and put into the view, and fit view to the image.
        br = self.imageGItem.boundingRect()
        self.scene.setSceneRect(
            0,
            0,
            max(1000, br.width()),
            max(1000, br.height()),
        )
        self.setScene(self.scene)
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)

    def mouseReleaseEvent(self, event):
        """Left/right click to zoom in and out"""
        if (event.button() == Qt.RightButton) or (
                QGuiApplication.queryKeyboardModifiers() == Qt.ShiftModifier):
            self.scale(0.8, 0.8)
        else:
            self.scale(1.25, 1.25)
        self.centerOn(event.pos())

    def resetView(self):
        """Reset the view to its reasonable initial state."""
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)
class TaxiRouteItem(QGraphicsItem):
	'''
	Draws a set of edges that turn on/off together, each possibly labelled.
	Call prepareGeometryChange after building to initialise correctly.
	'''
	def __init__(self, parentItem, segments, colour):
		QGraphicsItem.__init__(self, parent=parentItem)
		self.colour_name = colour
		self.shape = QPainterPath()
		self.labels = QGraphicsItemGroup(self)
		self.bbox = QRectF(0, 0, 0, 0)
		for (p1, p2), label in segments:
			lvect = QVector2D(p2 - p1)
			lpath = QPainterPath()
			m = TWY_line_margin
			l = lvect.length()
			plst = [QPointF(-m, 0), QPointF(-m/3, -m), QPointF(l + m/3, -m), QPointF(l + m, 0), QPointF(l + m/3, m), QPointF(-m/3, m)]
			lpath.addPolygon(QPolygonF(plst))
			lrot = QTransform()
			lrot.rotateRadians(atan2(lvect.y(), lvect.x()))
			lpath = lrot.map(lpath)
			lpath.translate(p1)
			self.shape.addPath(lpath)
			rect = QRectF(p1, p2).normalized()
			if label != None:
				self.labels.addToGroup(TaxiwayLabelItem(label, rect.center(), self))
			self.bbox |= rect
		self.shape.setFillRule(Qt.WindingFill)
		self.mouse_highlight = False
		self.labels.setVisible(False)
	
	def hoverEnterEvent(self, event):
		self.mouse_highlight = self.scene().mouseover_highlights_groundnet_edges
		if self.mouse_highlight and not self.labels.isVisible():
			self.labels.setVisible(True)
		self.setVisible(False)
		self.setVisible(True)
	
	def hoverLeaveEvent(self, event):
		self.mouse_highlight = False
		self.labels.setVisible(self.scene().show_taxiway_names)
		self.setVisible(False)
		self.setVisible(True)
	
	def boundingRect(self):
		return withMargins(self.bbox, TWY_line_margin)
	
	def shape(self):
		return self.shape

	def paint(self, painter, option, widget):
		if self.mouse_highlight or self.scene().show_ground_networks:
			painter.setPen(QPen(Qt.NoPen))
			brushcol = settings.colour(self.colour_name)
			brushcol.setAlpha(96 if self.mouse_highlight else 64)
			painter.setBrush(QBrush(brushcol))
			painter.drawPath(self.shape)
예제 #7
0
def build_tiles_level(level, tile_size, slide_helper: SlideHelper):
    level_size = slide_helper.get_level_size(level)
    tiles_rects = slice_rect(level_size, tile_size)
    tiles_graphics_group = QGraphicsItemGroup()
    downsample = slide_helper.get_downsample_for_level(level)
    for tile_rect in tiles_rects:
        item = TileGraphicsItem(tile_rect, slide_helper.slide_path, level,
                                downsample)
        item.moveBy(tile_rect[0], tile_rect[1])
        tiles_graphics_group.addToGroup(item)

    return tiles_graphics_group
예제 #8
0
    def __loadGraphicItem(self,
                          shapes,
                          images,
                          condition_variables=None,
                          default_color=Qt.blue):

        if not images:
            return ObjectGraphicsItem(shapes, color=default_color)

        gitem = QGraphicsItemGroup()

        for image in images:
            gitem.addToGroup(
                self.__loadGraphicItemImagePart(image, condition_variables))

        return gitem
예제 #9
0
 def addToGroup(self, item, name):
     '''
     Määrittää saman ryhmänimen omaaville yhteisen ryhmän ja palauttaa sen
     '''
     if name.strip() == 'None':
         return None
     elif name not in self.groups:
         group = QGraphicsItemGroup()
         self.piirtoalusta.scene.addItem(group)
         group.setFlag(QGraphicsItem.ItemIsSelectable)
         group.setFlag(QGraphicsItem.ItemIsMovable)
         group.addToGroup(item)
         self.groups.update({name: group})
     else:
         group = self.groups[name]
         group.addToGroup(item)
예제 #10
0
    def makeLines(self, image):
        # remove existing data on this layer
        self.removeOldGraphicsItems()

        group = QGraphicsItemGroup()

        sections = 4
        coordinates = []
        bounds = [
            self.parent.region1Linify.value(),
            self.parent.region2Linify.value(),
            self.parent.region3Linify.value(),
            self.parent.region3Linify.value()
        ]

        for y in range(0, image.height(), 4):
            drawing = False
            for linetype in range(sections):
                if linetype >= 1:
                    qt_y = y + linetype  # / sections
                    for x in range(image.width()):
                        grayvalue = qGray(image.pixel(x, y))
                        start_drawing = (grayvalue <
                                         bounds[linetype]) and not drawing
                        if start_drawing:
                            coordinates.append([[x, qt_y]])
                            drawing = True
                        stop_drawing = ((grayvalue >= bounds[linetype]) or
                                        (x == (image.width() - 1))) and drawing
                        if stop_drawing:
                            coordinates[-1].append([x, qt_y])
                            drawing = False

        group = QGraphicsItemGroup()
        for lineseg in coordinates:
            if len(lineseg) != 2 or len(lineseg[0]) != 2 or len(
                    lineseg[1]) != 2:
                print("Unexpected lineseg: ", lineseg)
            else:
                lineitem = QGraphicsLineItem(lineseg[0][0], lineseg[0][1],
                                             lineseg[1][0], lineseg[1][1])
                pen = QPen()
                pen.setWidth(1 / sections)
                lineitem.setPen(pen)
                group.addToGroup(lineitem)

        self.addNewGraphicsItems(group)
예제 #11
0
def paint_screenshot_image(
        painter: QPainter,
        scene: QGraphicsScene,
        image_size: QSize,
        scene_rect: QRectF = QRectF(),
        transparent_background=False,
) -> QImage:
    # with elapsed_timer() as elapsed:
    painter.fillRect(QRect(QPoint(0, 0), image_size),
                     painter.background().color())
    scene_items = scene.items(scene_rect, Qt.IntersectsItemBoundingRect)
    only_leaf_items = [
        item for item in scene_items if len(item.childItems()) == 0
    ]
    item_parents = {}
    item_groups = {}
    for item in only_leaf_items:
        if item.group():
            item_groups[item] = item.group()
            item.group().setVisible(False)
        elif item.parentItem():
            item_parents[item] = item.parentItem()
            item.parentItem().setVisible(False)
    group_for_screenshot = QGraphicsItemGroup()
    for item in only_leaf_items:
        group_for_screenshot.addToGroup(item)
    scene.addItem(group_for_screenshot)
    group_for_screenshot.setVisible(True)
    # scene_items2 = scene.items(scene_rect, Qt.IntersectsItemBoundingRect)
    # print(scene_items2)
    # print("before render==========================================")
    rendered_size = scene_rect.size().scaled(QSizeF(image_size),
                                             Qt.KeepAspectRatio)
    dsize = QSizeF(image_size) - rendered_size
    top_left = QPointF(dsize.width() / 2, dsize.height() / 2)
    scene.render(painter, QRectF(top_left, rendered_size), scene_rect,
                 Qt.KeepAspectRatio)
    scene.destroyItemGroup(group_for_screenshot)

    for item in item_parents:
        parent = item_parents[item]
        item.setParentItem(parent)
        parent.setVisible(True)
    for item in item_groups:
        group = item_groups[item]
        group.addToGroup(item)
        group.setVisible(True)
예제 #12
0
    def hatchify(self, image):
        """
        actual calculations
        :param image: bitmap to squigglify
        :return:
        """
        #print("image width = {0}, image height = {1}".format(image.width(), image.height()))
        ctimage = ImageOps.autocontrast(
            qimage_to_pil_image(image).convert("L"), 10)
        draw_contours = self.parent.includeContoursHatchify.checkState(
        ) == Qt.Checked
        draw_hatch = self.parent.includeHatchingHatchify.checkState(
        ) == Qt.Checked
        contour_simplify = self.parent.contourSimplificationHatchify.value()
        hatch_size = self.parent.hatchSizeHatchify.value()
        resolution = image.width()
        w, h = image.width(), image.height()
        aspect_ratio = h / w

        lines = []
        inv_resize_factor = (1, 1)
        if draw_contours:
            lines += self.getcontours(ctimage, contour_simplify)
        if draw_hatch:
            lines += self.hatch(ctimage, hatch_size)

        lines = self.sortlines(lines)

        self.removeOldGraphicsItems()
        group = QGraphicsItemGroup()
        for line in lines:
            path = QPainterPath()
            for point_idx, point in enumerate(line):
                if point_idx == 0:
                    path.moveTo(point[0], point[1])
                else:
                    path.lineTo(point[0], point[1])
            item = QGraphicsPathItem(path)
            group.addToGroup(item)

        self.addNewGraphicsItems(group)
예제 #13
0
    def on_actGroup_triggered(self):  # 组合
        cnt = len(self.scene.selectedItems())
        if cnt > 1:
            # group=self.scene.createItemGroup(self.scene.selectedItems())
            group = QGraphicsItemGroup()  # 创建组合
            self.scene.addItem(group)  # 组合添加到场景中

            for i in range(0, cnt):
                item = self.scene.selectedItems()[0]
                item.setSelected(False)  # 清除选择虚线框
                item.clearFocus()
                group.addToGroup(item)  # 添加到组合
            group.setFlags(QGraphicsItem.ItemIsMovable
                           | QGraphicsItem.ItemIsSelectable
                           | QGraphicsItem.ItemIsFocusable)

            self.view.frontZ = self.view.frontZ + 1
            group.setZValue(self.view.frontZ)
            # group.clearFocus()
            self.scene.clearSelection()
            group.setSelected(True)
예제 #14
0
파일: my0806.py 프로젝트: falomsc/pyqtStudy
    def on_qAction8_triggered(self):  # 组合
        items = self.scene.selectedItems()
        cnt = len(items)
        if cnt <= 1:
            return
        group = QGraphicsItemGroup()
        self.scene.addItem(group)
        for i in range(cnt):
            item = items[i]
            item.setSelected(False)
            item.clearFocus()
            group.addToGroup(item)

        group.setFlag(QGraphicsItem.ItemIsFocusable)
        group.setFlag(QGraphicsItem.ItemIsMovable)
        group.setFlag(QGraphicsItem.ItemIsSelectable)

        self.__frontZ += 1
        group.setZValue(self.__frontZ)
        self.scene.clearSelection()
        group.setSelected(True)
예제 #15
0
   def on_actGroup_triggered(self):
      items=self.scene.selectedItems()    # QGraphicsItem的列表
      cnt=len(items)  #选中的图形项个数
      if (cnt<=1):
        return 

      group =QGraphicsItemGroup() #创建组合
      self.scene.addItem(group)   #组合添加到场景中
      for i in range(cnt):
         item=items[i]
         item.setSelected(False)    #清除选择虚线框
         item.clearFocus()
         group.addToGroup(item)     #添加到组合

      group.setFlag(QGraphicsItem.ItemIsFocusable)
      group.setFlag(QGraphicsItem.ItemIsMovable)
      group.setFlag(QGraphicsItem.ItemIsSelectable)

      self.__frontZ=1+self.__frontZ
      group.setZValue(self.__frontZ)
      self.scene.clearSelection()
      group.setSelected(True)
예제 #16
0
    def addCircle(self, index, points, r):
        (x, y) = points

        circleItem = QGraphicsEllipseItem(x - r, y - r, 2 * r, 2 * r)
        circleItem.setPen(self.pen)

        # self.scene.addItem(circleItem)

        #横线
        line1 = QGraphicsLineItem()
        line1.setPen(self.pen)
        line1.setLine(x - self.lineRadius, y, x + self.lineRadius, y)

        #竖线
        line2 = QGraphicsLineItem()
        line2.setPen(self.pen)
        line2.setLine(x, y - self.lineRadius, x, y + self.lineRadius)

        #文字说明
        text = QGraphicsTextItem()
        text.setDefaultTextColor(Qt.blue)
        text.setFont(self.font)

        text.setPlainText(str(self.names[index]))
        text.setPos(x, y)

        #放到组中
        pointGroup = QGraphicsItemGroup()
        pointGroup.addToGroup(line1)
        pointGroup.addToGroup(line2)
        pointGroup.addToGroup(text)
        pointGroup.addToGroup(circleItem)

        #显示该点
        self.scene.addItem(pointGroup)

        self.pointsItem.append(pointGroup)
예제 #17
0
class BoardGUI(QWidget):
    """cointain the graphical representation of the Board"""

    # ratio of bordersize compared to the size of one base square
    borderRatio = 0.8
    baseRectRatio = 14 / 15  # 12/13 for normal ratio but looks weird
    stoneScale = 0.46

    # siganl
    stoneClicked = pyqtSignal(tuple)

    def __init__(self, parent, game):
        super().__init__()

        self.initUI(game)

    def initUI(self, game):
        self.board = game.currentBoard
        self.game = game

        self.showCoords = True
        self.scene = QGraphicsScene()

        # grid containing coordinates for the scene
        self.grid = []
        self.drawGrid()

        # initialize and set layout + view
        self.view = QGraphicsView(self.scene)
        self.view.setMouseTracking(True)
        self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        self.setMouseTracking(True)
        box = QHBoxLayout()
        box.addWidget(self.view)
        self.setLayout(box)

        # stones for all positions are created and listed in self.pos dict
        self.createPosition()
        self.makeCoords()  # has to be called after drawGrid!

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

    def boardWidth(self):
        """returns the max width fitting into widget"""
        width = self.contentsRect().width() * 0.95
        height = self.contentsRect().height() * 0.95

        return min(width, height * self.baseRectRatio)

    def boardHeight(self):
        """returns the max width fitting into widget """
        return self.boardWidth() * (1 / self.baseRectRatio)

    def makeGrid(self):
        """
        returns coords [[(x, y)]] for the Grid according
         to current window mesures
        """
        # set scenesize to window size
        self.scene.setSceneRect(0, 0, self.boardWidth(), self.boardHeight())
        denom = self.board.size + 2 * self.borderRatio
        baseWidth = self.boardWidth() / denom
        baseHeight = self.boardHeight() / denom

        leftOffset = 0.5 * baseWidth  # (self.contentsRect().width()-self.boardWidth())/2
        topOffset = 0  # (self.contentsRect().height()-self.boardHeight())/2

        partionWidth = [
            leftOffset + (self.borderRatio + x) * baseWidth
            for x in range(self.board.size)
        ]
        partionHeight = [
            topOffset + (self.borderRatio + x) * baseHeight
            for x in range(self.board.size)
        ]

        grid = [[(x, y) for x in partionWidth] for y in partionHeight]
        self.grid = grid
        self.baseWidth = baseWidth

    def drawGrid(self):
        """draws the background grid"""
        self.makeGrid()
        for line in self.grid:
            self.scene.addLine(*line[0], *line[-1])
        for (pointT, pointB) in zip(self.grid[0], self.grid[-1]):
            self.scene.addLine(*pointT, *pointB)
        self.drawHoshis()

    def makeCoords(self):
        """ draws Coordinates """
        xLabels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
        yLabels = list(range(1, 26))
        botGrid = []
        leftGrid = []
        # generate pixel coordinates grids
        for n in range(self.board.size):
            (xBot, yBot) = self.grid[self.board.size - 1][n]
            yBot += self.baseWidth * 0.4 / self.baseRectRatio
            xBot -= self.baseWidth * 0.1
            botGrid.append((xBot, yBot))
            (xLeft, yLeft) = self.grid[n][0]
            xLeft -= self.baseWidth * 1.2
            yLeft -= self.baseWidth * 0.3 / self.baseRectRatio
            leftGrid.append((xLeft, yLeft))
        # generate Text items and add them to group
        self.coordGroup = QGraphicsItemGroup()
        for n in range(self.board.size):
            leftText = QGraphicsSimpleTextItem(str(yLabels[n]))
            leftText.setPos(*leftGrid[n])
            self.coordGroup.addToGroup(leftText)
            bottomText = QGraphicsSimpleTextItem(xLabels[n])
            bottomText.setPos(*botGrid[n])
            self.coordGroup.addToGroup(bottomText)
        # draw coordinates and update visibility according to self.showCoords
        self.scene.addItem(self.coordGroup)
        self.updateCoords()

    def updateCoords(self):
        """ slot that updates the visibility os the coordiantes. """
        self.coordGroup.setVisible(self.showCoords)

    def setCoordVis(self, visibility):
        """ set the self.showCoords boolean """
        self.showCoords = visibility
        self.updateCoords()

    def drawHoshis(self):
        """ Draws Hoshi dots"""
        hoshis = []
        rad = self.baseWidth * 0.15
        for (x, y) in self.board.getHoshis():
            hoshis.append(self.grid[x][y])
        for point in hoshis:
            (x, y) = point
            self.scene.addEllipse(x - rad, y - rad, rad * 2.0, rad * 2.0,
                                  QPen(), QBrush(Qt.SolidPattern))

    def updatePosition(self):
        """
        sets the colors for all stones in self.pos according
        to the status in self.board
        """
        for (x, y) in self.pos:
            color = self.game.currentBoard.getPosition(x, y)
            self.pos[(x, y)].setMark(None)
            self.pos[(x, y)].setColor(color)
        lastMove = self.game.currentBoard.lastMove
        if lastMove:
            self.pos[lastMove].setMark(GoMarks.circel)
        ko = self.game.currentBoard.ko
        if ko:
            self.pos[ko].setMark(GoMarks.square)

    def createPosition(self):
        """
        Creates the self.pos dictionary containing all possible stones on the
        board initialized as empty stones

        also connects a signal form each stone to ???
        """
        self.pos = {}
        radius = self.stoneScale * self.baseWidth
        for row in range(self.board.size):
            for col in range(self.board.size):
                (x, y) = self.grid[row][col]
                newStone = Stone(x, y, radius)
                self.pos[(row, col)] = newStone
                self.scene.addItem(newStone)
        self.updatePosition()
        self.connecting()

    def connecting(self):
        for key in self.pos:
            self.pos[key].clicked.connect(lambda key=key: self.resend(key))

    def resend(self, pos):
        """
        emits the captured signal again,
        with (int, in) parameter for stone clicked
        """
        self.stoneClicked.emit(pos)
예제 #18
0
class Ui_MainWindow(QtWidgets.QMainWindow, Ui_MainWindowBase):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setupUi(self)

        self.videoPlaybackInit()
        self.imgInit()
        self.menuInit()

        self.df = None
        self.trackingPathGroup = None
        self.drawingFlag = False
        self.handInputSystem = None
        self.handInputSystem = HandInputSystem()
        self.handInputSystem.setRect(self.inputScene.sceneRect())
        self.inputScene.addItem(self.handInputSystem)
        self.handInputSystem.addNewDataFrame()
        self.currentFrameNo = 0
            
        self.colors = []

        self.circleCheckBox.stateChanged.connect(self.polyLineCheckBoxStateChanged)
        self.lineCheckBox.stateChanged.connect(self.polyLineCheckBoxStateChanged)
        self.overlayCheckBox.stateChanged.connect(self.overlayCheckBoxStateChanged)
        self.radiusSpinBox.valueChanged.connect(self.radiusSpinBoxValueChanged)

        self.frameNoSpinBox.valueChanged.connect(self.frameNoSpinBoxValueChanged)
        self.groupBox_2.hide()
        

        self.inputGraphicsView.viewport().setCursor(QtCore.Qt.ArrowCursor)
        #
        self.optionViewButton.pressed.connect(self.optionViewButtonPressed)
        self.zoomedGraphicsView.hide()

        self.dataFrameWidget.dataFrameChanged.connect(self.dataFrameChanged)
        self.dataFrameWidget.hide()
        self.handInputSystem.setColor(self.dataFrameWidget.getColor())
        
        #self.processDropedFile("/Users/ymnk/temp/Dast/2016/01/hoge.avi")
        #self.processDropedFile("./a.csv")        
    def dataFrameChanged(self,addedFrameFlag,editingNo,color):
        if addedFrameFlag:
            self.handInputSystem.addNewDataFrame()
        self.handInputSystem.setEditingNo(editingNo)
        self.handInputSystem.setColor(color)
        print(addedFrameFlag,color,editingNo)

    def optionViewButtonPressed(self):
        if self.groupBox_2.isVisible():
            self.optionViewButton.setText("<")
            self.groupBox_2.hide()
        else:
            self.optionViewButton.setText(">")
            self.groupBox_2.show()

    def overlayCheckBoxStateChanged(self, s):
        if self.overlayCheckBox.isChecked():
            self.frameBufferItemGroup.show()
        else:
            self.frameBufferItemGroup.hide()

        self.updateInputGraphicsView()

    def polyLineCheckBoxStateChanged(self, s):
        overlayFrameNo = self.frameNoSpinBox.value()

        min_value = max(self.currentFrameNo-overlayFrameNo,0)
        current_pos = self.currentFrameNo - min_value

        if self.handInputSystem is not None:
            self.handInputSystem.setDrawItem(current_pos, self.circleCheckBox.isChecked())
            self.handInputSystem.setDrawLine(self.lineCheckBox.isChecked())
            self.updateInputGraphicsView()

    def radiusSpinBoxValueChanged(self, value):
        if self.handInputSystem is not None:
            self.handInputSystem.setRadius(self.radiusSpinBox.value())
            self.updateInputGraphicsView()

    def frameNoSpinBoxValueChanged(self, value):
        if self.handInputSystem is not None:
            self.handInputSystem.setOverlayFrameNo(self.frameNoSpinBox.value())
            self.updateInputGraphicsView()
    def dragEnterEvent(self,event):
        event.acceptProposedAction()

    def dropEvent(self,event):
        # event.setDropAction(QtCore.Qt.MoveAction)
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            if len(urls) > 0:
                self.processDropedFile(urls[0].toLocalFile())

        event.acceptProposedAction()

    def processDropedFile(self,filePath):
        root,ext = os.path.splitext(filePath)
        if ext == ".filter":
            # Read Filter
            self.openFilterFile(filePath=filePath)
            return
        elif ext == ".csv":
            self.openCSVFile(filePath=filePath)
        elif self.openImageFile(filePath=filePath):
            return
        elif self.openVideoFile(filePath=filePath):
            return

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.hide()
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame, Qt.QueuedConnection)

    def setFrame(self, frame, frameNo):
        if frame is not None:
            self.cv_img = frame
            self.currentFrameNo = frameNo
            self.updateInputGraphicsView()
            if self.videoInitialFlag == True:
                 self.graphicsViewResized()
                 self.videoInitialFlag = False
            self.evaluate()

    def imgInit(self):
        self.cv_img = cv2.imread(os.path.join(sampleDataPath,"color_filter_test.png"))


        self.frameBuffer = Queue()
        self.frameBufferItemGroup = QGraphicsItemGroup()
        self.frameBufferItemGroup.hide()
        self.inputPixmapRenderScene = QGraphicsScene()
        self.inputPixmapRenderScene.addItem(self.frameBufferItemGroup)

        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.graphicsViewResized
        # self.inputScene.addItem(self.frameBufferItemGroup)

        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)
        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.mousePressEvent = self.inputGraphicsViewMousePressEvent
        self.inputGraphicsView.mouseMoveEvent = self.inputGraphicsViewMouseMoveEvent
        self.inputGraphicsView.mouseReleaseEvent = self.inputGraphicsViewMouseReleaseEvent
        self.inputGraphicsView.keyPressEvent = self.inputGraphicsViewKeyPressEvent
        self.inputGraphicsView.keyReleaseEvent = self.inputGraphicsViewKeyReleaseEvent
        self.inputGraphicsView.wheelEvent = self.inputGraphicsViewwheelEvent
        #self.inputGraphicsView.focusInEvent = self.inputGraphicsViewfocusInEvent
        self.inputGraphicsView.viewport().installEventFilter(self)

        self.inputGraphicsView.setMouseTracking(True)
        self.overlayScene = QGraphicsScene()
        self.inputGraphicsView.setOverlayScene(self.overlayScene)
    def inputGraphicsViewfocusInEvent(self,event):
        #
        QGraphicsView.focusInEvent(self.inputGraphicsView, event)
    def inputGraphicsViewMousePressEvent(self, event):
        if event.modifiers() == QtCore.Qt.ShiftModifier:
            # Comment out to permit the view for sending the event to the child scene.
            QGraphicsView.mousePressEvent(self.inputGraphicsView, event)
        else:
            self.drawingFlag = True
            if not self.videoPlaybackWidget.isPlaying():
                self.videoPlaybackWidget.playButtonClicked()
            
    def inputGraphicsViewMouseMoveEvent(self, event):
        if event.modifiers() == QtCore.Qt.ShiftModifier:
            # Comment out to permit the view for sending the event to the child scene.
            QGraphicsView.mouseMoveEvent(self.inputGraphicsView, event)
        elif self.drawingFlag == True:
            pass
            #self.videoPlaybackWidget.moveNextButtonClicked()
        #self.handInputSystem.inputMouseMoveEvent(mousePosition,self.currentFrameNo)
        #print(self.currentFrameNo)
        #self.positionStack.append(mousePosition)
        #self.handInputSystem.inputMouseMoveEvent(mousePosition)
        
    def inputGraphicsViewMouseReleaseEvent(self, event):
        if self.drawingFlag == True:
            self.drawingFlag = False
            self.videoPlaybackWidget.playButtonClicked()
        self.handInputSystem.inputMouseReleaseEvent()
        self.handInputSystem.setPoints()
        # Comment out to permit the view for sending the event to the child scene.
        QGraphicsView.mouseReleaseEvent(self.inputGraphicsView, event)
        self.inputGraphicsView.viewport().setCursor(QtCore.Qt.ArrowCursor)
        
    def inputGraphicsViewKeyPressEvent(self,event):
        mousePosition = QCursor().pos()
        mousePosition = self.inputGraphicsView.mapFromGlobal(mousePosition)
        if event.type() == QtCore.QEvent.KeyPress:
            key = event.key()
            if key == QtCore.Qt.Key_Space:
                self.videoPlaybackWidget.playButtonClicked()
            elif key == QtCore.Qt.Key_A:
                self.videoPlaybackWidget.movePrevButtonClicked()
            elif key == QtCore.Qt.Key_D:
                self.videoPlaybackWidget.moveNextButtonClicked()
            elif key == QtCore.Qt.Key_Down:
                self.inputGraphicsViewScaleDown()
            elif key == QtCore.Qt.Key_Up:
                self.inputGraphicsViewScaleUp()
                pass
            elif key == QtCore.Qt.Key_R:
                self.graphicsViewResized()
            elif key == QtCore.Qt.Key_P:
                pass
                #self.handInputSystem.nextDataFrame()
            elif key == QtCore.Qt.Key_O:
                pass
                #self.handInputSystem.previousDataFrame()
            elif key == QtCore.Qt.Key_J:
                frameNo = self.handInputSystem.getLastInputedFrameIndex()
                self.videoPlaybackWidget.moveToFrame(frameNo)
            elif key == QtCore.Qt.Key_S:
                self.handInputSystem.saveCSV("./a.csv")
        QGraphicsView.keyPressEvent(self.inputGraphicsView, event)
        
    def inputGraphicsViewKeyReleaseEvent(self,event):
        
        QGraphicsView.keyReleaseEvent(self.inputGraphicsView, event)
        
    def inputGraphicsViewwheelEvent(self,event):
        scaleFactor = 1.15
        if event.delta() > 0:
            # Zoom in
            self.inputGraphicsView.scale(scaleFactor, scaleFactor)
        else:
            # Zooming out
            self.inputGraphicsView.scale(1.0 / scaleFactor, 1.0 / scaleFactor)
        QGraphicsView.wheelEvent(self.inputGraphicsView, event)

    def inputGraphicsViewScaleDown(self):
        scaleFactor = 1.15
        self.inputGraphicsView.scale(1.0 / scaleFactor, 1.0 / scaleFactor)
    def inputGraphicsViewScaleUp(self):
        scaleFactor = 1.15
        self.inputGraphicsView.scale(scaleFactor, scaleFactor)
        
    def menuInit(self):
        self.actionSaveCSVFile.triggered.connect(self.saveCSVFile)
        self.actionOpenCSVFile.triggered.connect(self.openCSVFile)

    def openVideoFile(self, activated=False, filePath = None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Video File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False
            self.videoInitialFlag = True
            self.videoPlaybackWidget.show()
            self.dataFrameWidget.show()
            # self.evaluate()

            return True
        else:
            return False

    def openImageFile(self, activated=False, filePath = None):
        if filePath == None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Image File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            img = cv2.imread(filePath)
            if img is None:
                return False

            self.cv_img = img
            self.videoPlaybackWidget.hide()
            self.updateInputGraphicsView()

            self.evaluate()

            return True
        else:
            return False

    def openCSVFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open CSV File', userDir, 'CSV files (*.csv)')

        if len(filePath) is not 0:
            self.df = pd.read_csv(filePath, index_col=0)
            if self.handInputSystem is not None:
                self.inputScene.removeItem(self.handInputSystem)
            self.handInputSystem = HandInputSystem()
            self.handInputSystem.setRect(self.inputScene.sceneRect())
            self.inputScene.addItem(self.handInputSystem)
            self.handInputSystem.setDataFrame(self.df)
            self.handInputSystem.setPoints()

            self.dataFrameWidget.clear()
            self.dataFrameWidget.dataFrameNo = self.handInputSystem.dataFrameNo
            self.dataFrameWidget.editingNo = 0
            for item in range(self.handInputSystem.dataFrameNo+1):
                color = self.handInputSystem.itemList[item].getColor()
                print(item,color)
                self.dataFrameWidget.colorList.append(color)
            self.dataFrameWidget.setUniqueIDLabel()

            self.evaluate()

    def saveCSVFile(self, activated=False, filePath = None):
        #if self.df is not None:
        if self.handInputSystem.isDataFrame():
            filePath, _ = QFileDialog.getSaveFileName(None, 'Save CSV File', userDir, "CSV files (*.csv)")

            if len(filePath) is not 0:
                logger.debug("Saving CSV file: {0}".format(filePath))
                self.handInputSystem.saveCSV(filePath)

    def updateInputGraphicsView(self):
        # print("update")
        # self.inputScene.clear()
        self.inputScene.removeItem(self.inputPixmapItem)
        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)

        p = QPainter(self.inputPixmap)
        sourceRect = self.inputPixmapRenderScene.sceneRect()
        self.inputPixmapRenderScene.render(p, QRectF(sourceRect), QRectF(sourceRect), QtCore.Qt.IgnoreAspectRatio)

        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        rect = QtCore.QRectF(self.inputPixmap.rect())
        self.inputScene.setSceneRect(rect)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.viewport().update()
        # self.graphicsViewResized()

    def eventFilter(self, obj, event):
        if obj is self.inputGraphicsView.viewport() and event.type()==QEvent.Wheel:
            return True
        else:
            return False

    def graphicsViewResized(self, event=None):
        # print("resize")
        # print(self.inputScene)
        self.inputGraphicsView.fitInView(QtCore.QRectF(self.inputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def evaluate(self):
        if not self.videoPlaybackWidget.isOpened():
            return

        qimg = misc.cvMatToQImage(self.cv_img)
        pixmapItem = QGraphicsPixmapItem(QPixmap.fromImage(qimg))
        pixmapItem.setOpacity(0.2)

        self.frameBuffer.put(pixmapItem)
        self.frameBufferItemGroup.addToGroup(pixmapItem)
        if self.frameBuffer.qsize() > 10:
            item = self.frameBuffer.get()
            self.frameBufferItemGroup.removeFromGroup(item)
        """
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setPoints(self.currentFrameNo)
        """

        if self.handInputSystem is not None:
            self.handInputSystem.setPoints(self.currentFrameNo)
            if self.drawingFlag is True:
                mousePosition = QCursor().pos()
                mousePosition = self.inputGraphicsView.mapFromGlobal(mousePosition)
                mousePosition = self.inputGraphicsView.mapToScene(mousePosition)
                pos = [mousePosition.x(),mousePosition.y()]
                self.handInputSystem.appendPosition(pos,self.currentFrameNo)
예제 #19
0
파일: aman.py 프로젝트: pdanneels/bluesky
class AMANDisplay(QGraphicsView):
    def __init__(self):
        super(AMANDisplay, self).__init__()
        self.setGeometry(0, 0, 500, 600)
        self.setStyleSheet("background-color:#233370")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene(0, 0, 500, 600)

        # Timeline boundaries
        pen = QPen(QColor("white"))
        brush = QBrush(QColor("#233370"))
        self.scene.addLine(220, 0, 220, 600, pen)
        self.scene.addLine(280, 0, 280, 600, pen)
        self.scene.addLine(0, 30, 500, 30, pen)

        timelinebox = self.scene.addRect(220, 30, 60, 540, pen, brush)
        timelinebox.setFlag(timelinebox.ItemClipsChildrenToShape, True)

        # Timeline scale
        self.timeline = QGraphicsItemGroup()
        self.timeline.setParentItem(timelinebox)
        self.timeticks = []
        for i in range(40):
            y = 15 * i
            w = 6
            if i % 5 == 0:
                w = 10
                self.timeticks.append(self.scene.addText("%02d" % (40 - i), QFont("Courier", 10)))
                self.timeticks[-1].setPos(240, y - 10)
                self.timeticks[-1].setDefaultTextColor(QColor("white"))
                self.timeline.addToGroup(self.timeticks[-1])
            self.timeline.addToGroup(self.scene.addLine(220, y, 220 + w, y, pen))
            self.timeline.addToGroup(self.scene.addLine(280 - w, y, 280, y, pen))

        self.lrwy = self.scene.addText("18R", QFont("Arial", 20, 50))
        self.lrwy.setPos(1, 1)
        self.lrwy.setDefaultTextColor(QColor("white"))
        # Finalize
        self.setScene(self.scene)
        self.show()

    def update(self, simt, data):
        # data has: ids, iafs, eats, etas, delays, rwys, spdratios

        # First delete old labels
        for (key,) in self.aircraft.keys:
            if key not in data.ids:
                # del label
                del self.aircraft[key]

        for i in len(data.ids):
            if data.ids[i] not in self.aircraft:
                # self.aircraft[data.ids[i]] = QLabel()
                pass

            # Generate the new label text and position
            newtext = "<font color=Red>bla</font>"  # veranderen
            lbl = self.aircraft[data.ids[i]]
            lbl.setText(newtext)
            lbl.move(posx, posy)  # move in pixels
예제 #20
0
    def makeBubbles(self, image):
        """
        helper method for bubblification (contains the actual calculations)
        :param image:
        :return:
        """
        self.parent.progressBarBubblify.setVisible(True)
        self.parent.application.processEvents()

        minBrightness = self.parent.minBrightnessBubblify.value()
        maxBrightness = self.parent.maxBrightnessBubblify.value()
        minCircleRadius = self.parent.minRadiusBubblify.value()
        maxCircleRadius = self.parent.maxRadiusBubblify.value()
        invertColors = self.parent.invertColorsBubblify.checkState(
        ) == Qt.Checked
        minProbability = self.parent.minProbabilityBubblify.value()
        maxProbablity = self.parent.maxProbabilityBubblify.value()
        radiustolerance = self.parent.radiusToleranceBubblify.value()
        strokeWidth = 1

        # remove existing data on this layer
        self.removeOldGraphicsItems()

        # first add seeding points
        print("Seeding points")
        spots = []
        circles = []
        for x in range(image.width()):
            for y in range(image.height()):
                grayvalue = qGray(image.pixel(x, y))
                if invertColors:
                    grayvalue = 255 - grayvalue
                if minBrightness < grayvalue < maxBrightness:
                    probability = Mapping.linexp(grayvalue, 0, 255,
                                                 maxProbablity / 100,
                                                 minProbability / 100)
                    addNow = random() < probability
                    if addNow:
                        spots.append([x, y])

        print("Optimizing {0} points".format(len(spots)))
        # next find out radii we can use that avoid overlap
        print("Analyzing radii")
        if len(spots):
            tree = spatial.KDTree(spots)
            for center in spots:
                x = center[0]
                y = center[1]
                grayvalue = qGray(image.pixel(x, y))
                proposed_radius = Mapping.linexp(grayvalue, minBrightness,
                                                 maxBrightness,
                                                 minCircleRadius,
                                                 maxCircleRadius)
                nearest_neighbor = tree.query(np.array([[x, y]]), 2)
                # print("{0} nearest to {1}".format(nearest_neighbor, [x,y]))
                if nearest_neighbor:
                    try:
                        distance = nearest_neighbor[0][0][1]
                        maxradius = np.floor(distance / 2)
                        minimum = min(proposed_radius, maxradius)
                        # print("Using minimum of proposed {0} and max {1}".format(proposed_radius, maxradius))
                        if minimum >= proposed_radius * radiustolerance:
                            circles.append((x, y, minimum))
                    except:
                        print("weird nearest neighbor: ", nearest_neighbor)

            print("Visualize")
            # next, visualize
            group = QGraphicsItemGroup()
            for c in circles:
                x = c[0]
                y = c[1]
                r = c[2]
                item = QGraphicsEllipseItem(x - r, y - r, r * 2, r * 2)
                pen = QPen()
                pen.setWidth(strokeWidth)
                item.setPen(pen)
                group.addToGroup(item)

            self.addNewGraphicsItems(group)

            self.parent.progressBarBubblify.setVisible(False)
class CursorGraphicsView(QGraphicsView):
    coords = None

    def __init__(self, *__args):
        super().__init__(*__args)
        self.num = -1
        self.scale = QPointF(1, 1)

    def mouseReleaseEvent(self, event):
        if not self.scene(): return

        # the event's position is relative to the CursorGraphicsView, but we need it relative to the image
        pos_x = event.x() - (self.width() - self.scene().width() - 1) / 2
        pos_y = event.y() - (self.height() - self.scene().height() - 1) / 2

        # if the position of the click event is on the image, we convert the pixel position on screen to a voxel
        # position in the image, and then update all CursorGraphicsViews to show the corresponding slice as well as a
        # cursor pointing at the clicked voxel
        if pos_x >= 0 and pos_x < self.scene().width(
        ) and pos_y >= 0 and pos_y < self.scene().height():
            slider_values = [
                floor(pos_x / self.scale.x()),
                floor((self.scene().height() - pos_y) / self.scale.y())
            ]
            CursorGraphicsView.coords = self.get_coords(slider_values)

            for i, slider in enumerate(self.sliders):
                slider.setValue(self.coords[i])
            for viewer in self.viewers:
                viewer.show_cursor(self.coords)

    def set_num(self, num: int):
        self.num = num

    def set_scale(self, scale: float):
        self.scale = scale

    def set_viewers(self, viewers):
        self.viewers = viewers

    def set_sliders(self, sliders):
        self.sliders = sliders

    def get_coords(self, pos):
        return [(s.value() if i == self.num else pos.pop(0))
                for i, s in enumerate(self.sliders)]

    def make_cursor(self):
        pen = QPen(QColor(0, 255, 0))
        h_line = QGraphicsLineItem(-10, 0, 10, 0)
        v_line = QGraphicsLineItem(0, -10, 0, 10)

        pen.setWidth(1)
        h_line.setPen(pen)
        v_line.setPen(pen)

        self.point_cursor = QGraphicsItemGroup()
        self.point_cursor.addToGroup(h_line)
        self.point_cursor.addToGroup(v_line)
        self.point_cursor.setZValue(1)
        self.point_cursor.setVisible(False)
        self.scene().addItem(self.point_cursor)

    def show_cursor(self, values):
        pos = values.copy()
        pos.pop(self.num)

        self.point_cursor.setVisible(True)
        self.point_cursor.setPos(
            pos[0] * self.scale.x(),
            self.scene().height() - pos[1] * self.scale.y())
예제 #22
0
class CircleMethod(object):
    """
    class to represent how an lsystem overlayed on a bitmap is converted to a list of circles
    """
    def __init__(self, minBrightness, maxBrightness, minRadius, maxRadius,
                 minStepSize, maxStepSize, clipToBitmap, strokeWidth,
                 imageWidth, imageHeight):
        self.group = QGraphicsItemGroup()
        self.minBrightness = minBrightness
        self.maxBrightness = maxBrightness
        self.minRadius = minRadius
        self.maxRadius = maxRadius
        self.minStepSize = minStepSize
        self.maxStepSize = maxStepSize
        self.clipToBitmap = clipToBitmap
        self.strokeWidth = strokeWidth
        self.width = imageWidth
        self.height = imageHeight

    def step(self, x, y, direction, brightness):
        """
        step is called many times while iterating over the loaded bitmap
        in each step we calculate a circle based on position x,y with given brightness
        in the bitmap. direction is a direction vector indicating what direction we are
        moving in.

        calculate a new circle in the circle generation process
        :param x: x pos in bitmap that calculation should be based on
        :param y: y pos in bitmap that calculation should be based on
        :param direction: in what direction are we moving?
        :param brightness: gray value in the bitmap at x,y
        :return: potentially modified step size
        """
        r = Mapping.linexp(brightness, self.minBrightness, self.maxBrightness,
                           self.maxRadius, self.minRadius)
        if not r:
            r = self.minRadius
        stepsize = int(
            Mapping.linlin(brightness, self.minBrightness, self.maxBrightness,
                           self.minStepSize, self.maxStepSize))
        if not self.clipToBitmap or (self.clipToBitmap and not Circle(
                x, y, r).edges(self.width, self.height)):
            item = QGraphicsEllipseItem(x - r, y - r, r * 2, r * 2)
            pen = QPen()
            pen.setWidth(self.strokeWidth)
            item.setPen(pen)
            self.group.addToGroup(item)
        return max(int(stepsize), 1)

    def skip(self, x, y, direction, brightness):
        """
        similar to step, but explicitly asking to skip generation of a circle (e.g. because brightness constraints are not met)
        this allows the method to update its internal state to keep track of what is happening

        :param x: x pos in bitmap that the calculation should be based on
        :param y: x pos in bitmap that the calculation should be based on
        :param direction: direction we were moving in
        :param brightness: gray value of x,y in bitmap
        :return: potentially modified step size
        """
        stepsize = int(
            Mapping.linlin(brightness, self.minBrightness, self.maxBrightness,
                           self.minStepSize, self.maxStepSize))
        return max(int(stepsize), 1)

    def finish(self):
        """
        return the wrapped up result of the calculations
        :return: qgraphicsitemgroup
        """
        return self.group
예제 #23
0
    def randomWalk(self, image):
        """
        actual calculations
        :param image: bitmap to squigglify
        :return:
        """
        self.removeOldGraphicsItems()
        group = QGraphicsItemGroup()
        no_of_walks = self.parent.noOfWalksWalkify.value()
        coordinates = {}
        self.applyThreshold(image)
        for w in range(no_of_walks):
            x, y = self.find_darkest(image)
            x, y, color = self.find_darkest_neighbor(image, x, y)
            coordinates[w] = np.array([[x, y]])
            no_of_line_segments = self.parent.noOfLineSegmentsWalkify.value()
            adjustbrightness = self.parent.localBrightnessAdjustmentWalkify.value(
            )
            stroke_width = self.parent.lineWidthWalkify.value()
            for s in range(0, no_of_line_segments):
                dx, dy, dc = self.find_darkest_neighbor(image, x, y)
                self.lighten_area_around(image, adjustbrightness, dx, dy)
                x, y = dx, dy
                coordinates[w] = np.append(coordinates[w], [[x, y]], axis=0)

        for w in range(no_of_walks):
            coordinates[w] = simplify_coords(
                coordinates[w],
                self.parent.polylineSimplificationToleranceWalkify.value())

        for w in range(no_of_walks):
            path = QPainterPath()
            in_the_middle_of_a_quad = False
            for idx, c in enumerate(coordinates[w]):
                quad = self.parent.useSmootherShapesWalkify.checkState(
                ) == Qt.Checked
                if not quad:
                    if idx == 0:
                        path.moveTo(coordinates[w][idx][0],
                                    coordinates[w][idx][1])
                    else:
                        path.lineTo(coordinates[w][idx][0],
                                    coordinates[w][idx][1])
                else:
                    if idx == 0:
                        path.moveTo(coordinates[w][idx][0],
                                    coordinates[w][idx][1])
                    elif idx % 2 == 1:
                        middlex, middley = coordinates[w][idx][0], coordinates[
                            w][idx][1]
                        in_the_middle_of_a_quad = True
                    else:
                        path.quadTo(middlex, middley, coordinates[w][idx][0],
                                    coordinates[w][idx][1])
                        in_the_middle_of_a_quad = False

            if in_the_middle_of_a_quad:
                path.lineTo(middlex, middley)

            item = QGraphicsPathItem(path)
            pen = QPen()
            pen.setWidth(stroke_width)
            item.setPen(pen)
            group.addToGroup(item)

        self.addNewGraphicsItems(group)
예제 #24
0
class SquiggleMethod(object):
    """
    class to represent how to convert LSystem overlayed on bitmap to squiggles
    """
    def __init__(self, minBrightness, maxBrightness, strength, detail,
                 minStepSize, maxStepSize, clipToBitmap, strokeWidth,
                 imageWidth, imageHeight):
        self.group = QGraphicsItemGroup()
        self.path = QPainterPath()
        self.minBrightness = minBrightness
        self.maxBrightness = maxBrightness
        self.strength = strength
        self.detail = detail
        self.minStepSize = minStepSize
        self.maxStepSize = maxStepSize
        self.clipToBitmap = clipToBitmap
        self.strokeWidth = strokeWidth
        self.width = imageWidth
        self.height = imageHeight
        self.prevPos = None
        self.disturbance_direction = 1
        self.previous_stepsize = 1

    def step(self, x, y, direction, brightness):
        """
        step is called many times while iterating over the loaded bitmap
        in each step we calculate a squiggle based on position x,y with given brightness
        in the bitmap. direction is a direction vector indicating what direction we are
        moving in.

        calculate a new squiggle in the circle generation process
        :param x: x pos in bitmap that calculation should be based on
        :param y: y pos in bitmap that calculation should be based on
        :param direction: in what direction are we moving?
        :param brightness: gray value in the bitmap at x,y
        :return: potentially modified step size
        """
        stepSize = Mapping.linexp(brightness, 0, 255, self.minStepSize,
                                  self.maxStepSize)
        stepSize = Mapping.linlin(stepSize, 1, 10, 1, 10 / self.detail)
        self.previous_stepsize = stepSize
        amplitudeSize = Mapping.linlin(brightness, 0, 255, self.strength, 0)
        if self.prevPos is None:
            self.path = QPainterPath()
            self.path.moveTo(x, y)
            self.prevPos = np.array([[
                x,
            ], [
                y,
            ]])
        else:
            newPos = np.array([[
                x,
            ], [
                y,
            ]])
            dirx = direction[0][0]
            diry = direction[1][0]
            ortho_dir = np.array([[-diry], [dirx]
                                  ]) * self.disturbance_direction
            disturbance = ortho_dir * amplitudeSize
            disturbedPos = (self.prevPos + newPos) / 2 + disturbance
            if not self.clipToBitmap or (self.clipToBitmap and not Circle(
                    x, y, amplitudeSize).edges(self.width, self.height)):
                self.path.quadTo(disturbedPos[0][0], disturbedPos[1][0],
                                 newPos[0][0], newPos[1][0])
            else:
                self.path.moveTo(newPos[0][0], newPos[1][0])
            self.prevPos = newPos
        self.disturbance_direction = -self.disturbance_direction
        return max(int(stepSize), 1)

    def skip(self, x, y, direction, brightness):
        """
        similar to step, but explicitly asking to skip generation of a squiggle (e.g. because brightness constraints are not met)
        this allows the method to update its internal state to keep track of what is happening

        :param x: x pos in bitmap that the calculation should be based on
        :param y: x pos in bitmap that the calculation should be based on
        :param direction: direction we were moving in
        :param brightness: gray value of x,y in bitmap
        :return: potentially modified step size
        """
        if self.prevPos is None:
            self.path = QPainterPath()
            self.path.moveTo(x, y)
        else:
            self.path.moveTo(x, y)
        self.prevPos = np.array([[
            x,
        ], [
            y,
        ]])
        return int(self.previous_stepsize)

    def finish(self):
        """
        return the wrapped up result of the calculations
        :return: qgraphicsitemgroup
        """
        item = QGraphicsPathItem(self.path)
        pen = QPen()
        pen.setWidth(self.strokeWidth)
        item.setPen(pen)
        self.group.addToGroup(item)
        self.prevPos = None
        return self.group
class Ui_MainWindow(QtWidgets.QMainWindow, Ui_MainWindowBase):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setupUi(self)

        self.videoPlaybackInit()
        self.imgInit()
        self.menuInit()

        self.df = {}
        self.trackingPathGroup = None
        self.movableArrowGroup = None

        self.line_data_dict = {}
        self.line_item_dict = {}

        self.file_name_dict = {}

        self.currentFrameNo = 0

        self.colors = None

        self.overlayCheckBox.stateChanged.connect(
            self.overlayCheckBoxStateChanged)
        self.radiusSpinBox.valueChanged.connect(self.radiusSpinBoxValueChanged)
        self.frameNoSpinBox.valueChanged.connect(
            self.frameNoSpinBoxValueChanged)
        self.markDeltaSpinBox.valueChanged.connect(
            self.markDeltaSpinBoxValueChanged)

    def overlayCheckBoxStateChanged(self, s):
        if self.overlayCheckBox.isChecked():
            self.frameBufferItemGroup.show()
        else:
            self.frameBufferItemGroup.hide()

        self.updateInputGraphicsView()

    def markDeltaSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setMarkDelta(self.markDeltaSpinBox.value())
            self.updateInputGraphicsView()

    def radiusSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setRadius(self.radiusSpinBox.value())
            self.updateInputGraphicsView()

    def frameNoSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setOverlayFrameNo(
                self.frameNoSpinBox.value())
            self.updateInputGraphicsView()

    def dragEnterEvent(self, event):
        event.acceptProposedAction()

    def dropEvent(self, event):
        # event.setDropAction(QtCore.Qt.MoveAction)
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            if len(urls) > 0:
                self.processDropedFile(urls[0].toLocalFile())

        event.acceptProposedAction()

    def processDropedFile(self, filePath):
        root, ext = os.path.splitext(filePath)
        if ext == ".filter":
            # Read Filter
            self.openFilterFile(filePath=filePath)
            return
        elif ext == ".csv":
            self.openCSVFile(filePath=filePath)
        elif ext == ".json":
            self.openJSONFile(filePath=filePath)
        elif ext == ".color":
            self.openColorFile(filePath=filePath)
        elif self.openImageFile(filePath=filePath):
            return
        elif self.openVideoFile(filePath=filePath):
            return

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.hide()
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame,
                                                      Qt.QueuedConnection)

    def setFrame(self, frame, frameNo):
        if frame is not None:
            self.cv_img = frame
            self.currentFrameNo = frameNo
            self.updateInputGraphicsView()
            self.evaluate()

    def imgInit(self):
        self.cv_img = cv2.imread(
            os.path.join(sampleDataPath, "color_filter_test.png"))

        self.frameBuffer = Queue()
        self.frameBufferItemGroup = QGraphicsItemGroup()
        self.frameBufferItemGroup.hide()
        self.inputPixmapRenderScene = QGraphicsScene()
        self.inputPixmapRenderScene.addItem(self.frameBufferItemGroup)

        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.graphicsViewResized
        # self.inputScene.addItem(self.frameBufferItemGroup)

        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)
        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputScene.addItem(self.inputPixmapItem)

        self.rubberBand = QtWidgets.QRubberBand(
            QtWidgets.QRubberBand.Rectangle, self.inputGraphicsView)
        self.inputGraphicsView.mousePressEvent = self.inputGraphicsViewMousePressEvent
        self.inputGraphicsView.mouseMoveEvent = self.inputGraphicsViewMouseMoveEvent
        self.inputGraphicsView.mouseReleaseEvent = self.inputGraphicsViewMouseReleaseEvent

        self.inputGraphicsView.viewport().installEventFilter(self)

        self.inputGraphicsView.setMouseTracking(True)
        self.overlayScene = QGraphicsScene()
        self.inputGraphicsView.setOverlayScene(self.overlayScene)

        self.zoomedGraphicsView.setScene(self.inputScene)
        self.zoomedGraphicsView.setOverlayScene(self.overlayScene)

    def inputGraphicsViewMousePressEvent(self, event):
        self.origin = QPoint(event.pos())
        self.rubberBand.setGeometry(QtCore.QRect(self.origin, QtCore.QSize()))
        self.rubberBand.show()

        # Comment out to permit the view for sending the event to the child scene.
        # QGraphicsView.mousePressEvent(self.inputGraphicsView, event)

    def inputGraphicsViewMouseMoveEvent(self, event):
        if self.rubberBand.isVisible():
            self.rubberBand.setGeometry(
                QtCore.QRect(self.origin, event.pos()).normalized())
        # Comment out to permit the view for sending the event to the child scene.
        # QGraphicsView.mouseMoveEvent(self.inputGraphicsView, event)

    def inputGraphicsViewMouseReleaseEvent(self, event):
        if self.rubberBand.isVisible():
            self.rubberBand.hide()
            rect = self.rubberBand.geometry()
            sceneRect = self.inputGraphicsView.mapToScene(rect).boundingRect()
            self.zoomedGraphicsView.fitInView(QRectF(sceneRect))
            self.zoomedGraphicsView.viewport().update()
        # Comment out to permit the view for sending the event to the child scene.
        self.inputGraphicsView.viewport().update()
        # QGraphicsView.mouseReleaseEvent(self.inputGraphicsView, event)

    def menuInit(self):
        self.actionSaveDataFiles.triggered.connect(self.saveDataFiles)
        self.actionOpenCSVFile.triggered.connect(self.openCSVFile)
        self.actionOpenCSVFile.triggered.connect(self.openJSONFile)
        self.actionOpenCSVFile.triggered.connect(self.openJSONFile)

        self.actionPath.triggered.connect(self.actionPathTriggered)
        self.actionCircle.triggered.connect(self.actionCircleTriggered)
        self.actionIntervalMark.triggered.connect(
            self.actionIntervalMarkTriggered)
        self.actionShape.triggered.connect(self.actionShapeTriggered)
        self.actionSkeleton.triggered.connect(self.actionSkeletonTriggered)
        self.actionArrow.triggered.connect(self.actionArrowTriggered)

        self.actionChangeOrderOfNum.triggered.connect(
            self.actionChangeOrderOfNumTriggered)

        self.actionTrackingPathColor.triggered.connect(
            self.openTrackingPathColorSelectorDialog)

    def actionPathTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawLine(checked)
            if not checked or self.actionIntervalMark.isChecked():
                self.trackingPathGroup.setDrawMarkItem(checked)
            self.updateInputGraphicsView()

    def actionCircleTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawItem(checked)
            self.updateInputGraphicsView()

    def actionIntervalMarkTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawMarkItem(checked)
            self.updateInputGraphicsView()

    def actionShapeTriggered(self, checked):
        if 'shape' in self.line_item_dict.keys():
            line_item = self.line_item_dict['shape']
            if checked:
                line_item.show()
            else:
                line_item.hide()

    def actionSkeletonTriggered(self, checked):
        if 'skeleton' in self.line_item_dict.keys():
            line_item = self.line_item_dict['skeleton']
            if checked:
                line_item.show()
            else:
                line_item.hide()

    def actionArrowTriggered(self, checked):
        if self.movableArrowGroup is not None:
            if checked:
                self.movableArrowGroup.show()
            else:
                self.movableArrowGroup.hide()

    def actionChangeOrderOfNumTriggered(self, checked):
        if len(self.df.keys()) != 0 or len(self.line_data_dict.keys()) != 0:
            self.videoPlaybackWidget.stop()

            dialog = DataSwapDialog(self)
            dialog.setWindowModality(Qt.WindowModal)
            dialog.setData(self.df, self.line_data_dict)
            dialog.swapAccepted.connect(self.evaluate)

            res = dialog.exec()

    def openTrackingPathColorSelectorDialog(self, activated=False):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.openColorSelectorDialog(self)

    def openVideoFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Video File',
                                                      userDir)

        if len(filePath) is not 0:
            self.filePath = filePath

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False

            self.videoPlaybackWidget.show()
            self.cv_img = self.videoPlaybackWidget.getCurrentFrame()

            self.initialize()

            return True
        else:
            return False

    def openImageFile(self, activated=False, filePath=None):
        if filePath == None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Image File',
                                                      userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            img = cv2.imread(filePath)
            if img is None:
                return False

            self.cv_img = img
            self.videoPlaybackWidget.hide()
            self.updateInputGraphicsView()

            self.evaluate()

            return True
        else:
            return False

    def openCSVFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open CSV File',
                                                      userDir,
                                                      'CSV files (*.csv)')

        if len(filePath) is not 0:
            df = pd.read_csv(filePath, index_col=0)
            name = df.index.name

            if name is None:
                name = 'position'

            self.df[name] = df
            self.file_name_dict[name] = filePath

            if name is None or name == 'position':
                if self.trackingPathGroup is not None:
                    self.inputScene.removeItem(self.trackingPathGroup)

                self.trackingPathGroup = TrackingPathGroup()
                self.trackingPathGroup.setRect(self.inputScene.sceneRect())
                self.inputScene.addItem(self.trackingPathGroup)

                self.trackingPathGroup.setDrawLine(self.actionPath.isChecked())
                self.trackingPathGroup.setDrawItem(
                    self.actionCircle.isChecked())
                self.trackingPathGroup.setDrawMarkItem(
                    self.actionIntervalMark.isChecked())

                shape = self.df['position'].shape
                self.num_items = int(shape[1] / 2)
                index = (np.repeat(range(self.num_items),
                                   2).tolist(), [0, 1] * self.num_items)
                self.df['position'].columns = pd.MultiIndex.from_tuples(
                    tuple(zip(*index)))

                self.trackingPathGroup.setDataFrame(self.df['position'])

                delta = self.df['position'].index[1] - self.df[
                    'position'].index[0]
                self.videoPlaybackWidget.setPlaybackDelta(delta)
                self.videoPlaybackWidget.setMaxTickableFrameNo(
                    self.df['position'].index[-1])
            elif name == 'arrow':
                if self.movableArrowGroup is not None:
                    self.inputScene.removeItem(self.movableArrowGroup)

                self.movableArrowGroup = MovableArrowGroup()
                self.inputScene.addItem(self.movableArrowGroup)
                self.movableArrowGroup.edited.connect(self.arrowEdited)

                if not self.actionArrow.isChecked():
                    self.movableArrowGroup.hide()

            if 'arrow' in self.df.keys() and 'position' in self.df.keys():
                self.movableArrowGroup.setDataFrame(self.df['arrow'],
                                                    self.df['position'])

            self.initialize()

    def openColorFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Color File',
                                                      userDir,
                                                      'Color files (*.color)')

        if len(filePath) is not 0:
            self.colors = pd.read_csv(filePath, index_col=0).values.tolist()
            self.colors = [QColor(*rgb) for rgb in self.colors]
            self.setColorsToGraphicsObjects()

    def openJSONFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open JSON File',
                                                      userDir,
                                                      'JSON files (*.json)')

        if len(filePath) is not 0:
            with open(filePath) as f_p:
                data = json.load(f_p)

            name = data['name']
            self.line_data_dict[name] = data
            self.file_name_dict[name] = filePath

            if name in self.line_item_dict.keys():
                self.inputScene.removeItem(self.line_item_dict[name])

            lines = MovableLineGroup()
            lines.setData(data)
            lines.setRect(self.inputScene.sceneRect())

            if name == 'shape' and not self.actionShape.isChecked():
                lines.hide()

            if name == 'skeleton' and not self.actionSkeleton.isChecked():
                lines.hide()

            self.line_item_dict[name] = lines
            self.inputScene.addItem(lines)

            self.initialize()

    def saveDataFiles(self, activated=False, filePath=None):
        if len(self.df.keys()) != 0:
            for k, v in self.df.items():
                f_name, f_ext = os.path.splitext(self.file_name_dict[k])
                candidate_file_path = '{0}-fixed{1}'.format(f_name, f_ext)
                filePath, _ = QFileDialog.getSaveFileName(
                    None, 'Save CSV File', candidate_file_path,
                    "CSV files (*.csv)")

                if len(filePath) is not 0:
                    logger.debug("Saving CSV file: {0}".format(filePath))
                    df = v.copy()
                    col_n = df.values.shape[1] / 2

                    col_names = np.array([('x{0}'.format(i), 'y{0}'.format(i))
                                          for i in range(int(round(col_n)))
                                          ]).flatten()
                    df.columns = pd.Index(col_names)
                    df.index.name = k
                    df.to_csv(filePath)

        for k, v in self.line_data_dict.items():
            f_name, f_ext = os.path.splitext(self.file_name_dict[k])
            candidate_file_path = '{0}-fixed{1}'.format(f_name, f_ext)
            filePath, _ = QFileDialog.getSaveFileName(None, 'Save JSON File',
                                                      candidate_file_path,
                                                      "JSON files (*.json)")

            if len(filePath) is not 0:
                logger.debug("Saving JSON file: {0}".format(filePath))
                with open(filePath, 'w') as f_p:
                    json.dump(v, f_p)

    def updateInputGraphicsView(self):
        self.inputScene.removeItem(self.inputPixmapItem)
        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)

        p = QPainter(self.inputPixmap)
        sourceRect = self.inputPixmapRenderScene.sceneRect()
        self.inputPixmapRenderScene.render(p, QRectF(sourceRect),
                                           QRectF(sourceRect),
                                           QtCore.Qt.IgnoreAspectRatio)

        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        rect = QtCore.QRectF(self.inputPixmap.rect())
        self.inputScene.setSceneRect(rect)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.viewport().update()
        self.graphicsViewResized()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.Wheel:
            self.videoPlaybackWidget.wheelEvent(event)
            return True

        if event.type() == QEvent.KeyPress:
            if Qt.Key_Home <= event.key() <= Qt.Key_PageDown:
                self.videoPlaybackWidget.keyPressEvent(event)
                return True

        return False

    def graphicsViewResized(self, event=None):
        self.inputGraphicsView.fitInView(
            QtCore.QRectF(self.inputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def setColorsToGraphicsObjects(self):
        # FIXME: データセットと色リストのサイズ整合性チェックが必要
        if self.colors is not None:
            if self.trackingPathGroup is not None:
                self.trackingPathGroup.setColors(self.colors)

            for k, v in self.line_item_dict.items():
                v.setColors(self.colors)

    def initialize(self):
        if not self.videoPlaybackWidget.isOpened():
            return

        if self.trackingPathGroup is not None:
            r = self.trackingPathGroup.autoAdjustRadius(self.cv_img.shape)
            self.radiusSpinBox.setValue(r)
            self.trackingPathGroup.autoAdjustLineWidth(self.cv_img.shape)

            self.trackingPathGroup.setItemsAreMovable(True)

            if self.movableArrowGroup is not None:
                pass

        for k, v in self.line_item_dict.items():
            v.autoAdjustLineWidth(self.cv_img.shape)
            v.autoAdjustMarkSize(self.cv_img.shape)

        self.setColorsToGraphicsObjects()

        self.evaluate()

    def evaluate(self):
        if not self.videoPlaybackWidget.isOpened():
            return

        qimg = misc.cvMatToQImage(self.cv_img)
        pixmapItem = QGraphicsPixmapItem(QPixmap.fromImage(qimg))
        pixmapItem.setOpacity(0.2)

        self.frameBuffer.put(pixmapItem)
        self.frameBufferItemGroup.addToGroup(pixmapItem)
        if self.frameBuffer.qsize() > 10:
            item = self.frameBuffer.get()
            self.frameBufferItemGroup.removeFromGroup(item)

        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setPoints(self.currentFrameNo)

            if self.movableArrowGroup is not None:
                self.movableArrowGroup.setPositions(self.currentFrameNo)

        for k, v in self.line_item_dict.items():
            v.setPolyline(self.currentFrameNo)

    @pyqtSlot(object)
    def arrowEdited(self, name):
        # TODO: 方向の再推定機能の実装
        # quit_msg = "Arrow {} edited.\nRe-estimate the direction in following frames?".format(name)
        # reply = QtWidgets.QMessageBox.question(
        #         self,
        #         'Question',
        #         quit_msg,
        #         QtWidgets.QMessageBox.Yes,
        #         QtWidgets.QMessageBox.No
        #         )
        #
        # if reply == QtWidgets.QMessageBox.Yes:
        #     pass
        # else:
        #     pass
        pass
예제 #26
0
파일: nodeitems.py 프로젝트: bucaneer/flint
class NodeItem(QGraphicsItem):
    def __init__ (self, nodeobj, parent=None, view=None, state=1):
        super().__init__()
        self.edge = None
        self.linkIDs = None
        self.children = None
        self.childpos = None
        self.nodeobj = nodeobj
        self.style = FlGlob.mainwindow.style
        self.view = weakref.proxy(view)
        self.refID = parent.realid() if parent is not None else None
        self.state = state
        self.setrank(parent)
        self.setCursor(Qt.ArrowCursor)
        self.yoffset = 0
        self.graphicsetup()
        self.setstate(state)
    
    def id (self):
        return (self.refID, self.nodeobj.ID)
    
    def realid (self):
        return self.nodeobj.ID
    
    def childlist (self, generate=False):
        ID = self.nodeobj.ID
        itemtable = self.view.itemtable
        if self.state == 1 and ID in itemtable and not self.iscollapsed():
            if self.children and self.nodeobj.linkIDs == self.linkIDs and None not in [c() for c in self.children]:
                ret = self.children
            else:
                children = []
                for child in self.nodeobj.linkIDs:
                    if child in itemtable[ID]:
                        item = itemtable[ID][child]
                    else:
                        continue
                    children.append(weakref.ref(item))
                self.linkIDs = self.nodeobj.linkIDs.copy()
                self.children = children
                ret = children
        else:
            ret = []
        if generate:
            x = self.x()
            y = self.y()
            self.childpos = []
            for target in ret:
                t = target()
                self.childpos.append((t.x()+t.boundingRect().left()-self.style.activemargin-x, t.y()-y))
            if self.edge:
                if self.childpos != self.edge.childpos:
                    self.edge.prepareGeometryChange()
                    self.edge.sourceright = self.boundingRect().right()
                    self.edge.update(self.edge.boundingRect())
        return ret
    
    def setedge (self, edge):
        self.edge = edge
        edge.setX(self.x())
    
    def setactive (self, active):
        if active:
            self.activebox.show()
            self.mainbox.setBrush(QBrush(self.altcolor))
        else:
            self.activebox.hide()
            self.mainbox.setBrush(QBrush(self.maincolor))
    
    def setselected (self, selected):
        if selected:
            self.selectbox.show()
        else:
            self.selectbox.hide()
    
    def setstate (self, state):
        self.state = state
        if state == 1: # normal
            self.show()
            self.graphgroup.setOpacity(1)
            self.shadowbox.show()
        elif state == 0: # ghost
            self.show()
            self.graphgroup.setOpacity(0.7)
            self.shadowbox.hide()
        elif state == -1: # hidden
            self.hide()
    
    def setplaymode (self, playmode):
        if playmode:
            self.setOpacity(0.5)
        else:
            self.setOpacity(1)
    
    def setY (self, y):
        parent = self.view.itembyID(self.refID)
        y += self.getyoffset()
        if self.edge is not None:
            self.edge.setY(y)
        super().setY(y)
    
    def setrank (self, parent):
        if parent is None:
            return
        if self.issubnode():
            x = parent.x()
            self.setX(x)
        else:
            x = parent.x()+self.style.rankwidth
            self.setX(x)
            self.nudgechildren()
        if self.edge is not None:
            self.edge.setX(x)
    
    def nudgechildren (self):
        for child in self.childlist():
            child().setrank(self)
    
    def getyoffset (self):
        if self.nodeobj.nodebank == -1:
            return self.yoffset
        else:
            return self.view.itembyID(self.refID).getyoffset() + self.yoffset
    
    def hide (self):
        super().hide()
        if self.edge:
            self.edge.hide()
    
    def show (self):
        super().show()
        if self.edge:
            self.edge.show()
    
    def issubnode (self):
        return self.nodeobj.nodebank is not -1
    
    def isghost (self):
        return not self.state
    
    def realnode (self):
        return self.view.itembyID(self.nodeobj.ID)
    
    def isactive (self):
        return self.view.activenode is self
    
    def isselected (self):
        return self.view.selectednode is self
    
    def iscollapsed (self):
        return self.id() in self.view.collapsednodes
    
    def y_top (self):
        return self.y() - self.boundingRect().height()//2
    
    def y_bottom (self):
        return self.y() + self.boundingRect().height()//2
    
    def bulkshift (self, children, diff):
        self.setY(self.y() + diff)
        if children is None:
            children = [c() for c in self.childlist()]
        for child in children:
            child.bulkshift(None, diff)
    
    def treeposition (self, ranks=None):
        if ranks is None:
            ranks = dict()
        localranks = dict()
        children = [c() for c in self.childlist()]
        for child in children:
            localranks = child.treeposition(localranks)
        rank = self.x() // self.style.rankwidth
        if children:
            top = children[0].y_top()
            bottom = children[-1].y_bottom()
            self.setY((top+bottom)//2)
        localranks[rank] = [self.y_top, self.y_bottom]
        streeshift = None
        for r in localranks:
            if r in ranks:
                rankshift = ranks[r][1]() + self.style.rowgap - localranks[r][0]()
                if streeshift is None or rankshift > streeshift:
                    streeshift = rankshift
                ranks[r][1] = localranks[r][1]
            else:
                ranks[r] = localranks[r]
        if streeshift:
            self.bulkshift(children, streeshift)
        return ranks
    
    def siblings (self):
        if self.refID is None:
            return None
        parent = self.view.nodecontainer.nodes[self.refID]
        if self.issubnode():
            return parent.subnodes
        else:
            return parent.linkIDs
    
    def siblingabove (self):
        sibs = self.siblings()
        if sibs is None or self.nodeobj.ID not in sibs:
            return None
        myindex = sibs.index(self.nodeobj.ID)
        if myindex:
            sibID = (self.refID, sibs[myindex-1])
            return self.view.itembyfullID(sibID)
        else:
            return None
    
    def siblingbelow (self):
        sibs = self.siblings()
        if sibs is None or self.nodeobj.ID not in sibs:
            return None
        myindex = sibs.index(self.nodeobj.ID)
        if len(sibs) > myindex+1:
            sibID = (self.refID, sibs[myindex+1])
            return self.view.itembyfullID(sibID)
        else:
            return None
    
    def subtreesize (self, depth=-1):
        """Find vertical extents of a subtree.
        
        Returns min/max y coordinates up to given depth (negative depth means
        whole subtree)."""

        # calculate child positions for EgdeItem only once when calculating scenerect
        if depth<0:
            generate = True
        else:
            generate = False
        
        children = [c() for c in self.childlist(generate=generate)]
        maxdepth = abs(depth)
        if children and depth:
            nextdepth = depth-1
            ymin = self.y_top()
            ymax = self.y_bottom()
            for child in children:
                top, bottom, depth = child.subtreesize(nextdepth)
                ymin = min(ymin, top)
                ymax = max(ymax, bottom)
                maxdepth = max(maxdepth, depth)
        else:
            ymin = self.y_top()
            ymax = self.y_bottom()
        return ymin, ymax, maxdepth
        
    def boundingRect (self):
        return self.rect
    
    def paint (self, painter, style, widget):
        pass
    
    def pixmap (self, path):
        return QPixmap(path).scaledToWidth(self.style.boldheight, Qt.SmoothTransformation)
    
    def graphicsetup (self):
        lightbrush = QBrush(FlPalette.light)
        mainbrush = QBrush(self.maincolor)
        altbrush = QBrush(self.altcolor)
        nopen = QPen(0)
        viewport = self.view.viewport()
        
        self.graphgroup = QGraphicsItemGroup(self)
        self.fggroup = QGraphicsItemGroup(self)
        
        self.shadowbox = QGraphicsRectItem(self)
        self.shadowbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        self.shadowbox.setBrush(FlPalette.dark)
        self.shadowbox.setPen(nopen)
        self.shadowbox.setPos(*(self.style.shadowoffset,)*2)
        self.graphgroup.addToGroup(self.shadowbox)
        
        self.activebox = QGraphicsRectItem(self)
        self.activebox.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        activepen = QPen(self.maincolor, self.style.selectmargin, join=Qt.MiterJoin)
        self.activebox.setPen(activepen)
        self.activebox.hide()
        self.graphgroup.addToGroup(self.activebox)
        
        self.selectbox = QGraphicsRectItem(self)
        self.selectbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        selectpen = QPen(FlPalette.light, self.style.selectmargin, join=Qt.MiterJoin)
        self.selectbox.setPen(selectpen)
        self.selectbox.hide()
        self.graphgroup.addToGroup(self.selectbox)
        
        self.mainbox = QGraphicsRectItem(self)
        self.mainbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        self.mainbox.setBrush(mainbrush)
        self.mainbox.setPen(nopen)
        self.graphgroup.addToGroup(self.mainbox)
        
        self.nodelabel = QGraphicsSimpleTextItemCond(self, viewport)
        self.nodelabel.setBrush(lightbrush)
        self.nodelabel.setFont(self.style.boldfont)
        self.nodelabel.setText(self.label % self.realid())
        self.nodelabel.setPos(self.style.itemmargin, self.style.itemmargin)
        self.fggroup.addToGroup(self.nodelabel)
        
        self.icon = self.pixmap("images/blank.png")
        self.iwidth = self.icon.width()
        self.iconx = self.style.nodetextwidth
        
        self.condicon = QGraphicsPixmapItemCond(self.icon, self, viewport)
        self.condicon.setPos(self.iconx-self.iwidth, self.style.itemmargin)
        self.iconx = self.condicon.x()
        self.fggroup.addToGroup(self.condicon)
        
        self.randicon = QGraphicsPixmapItemCond(self.icon, self, viewport)
        self.randicon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin)
        self.iconx = self.randicon.x()
        self.fggroup.addToGroup(self.randicon)
        
        self.exiticon = QGraphicsPixmapItemCond(self.icon, self, viewport)
        self.exiticon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin)
        self.iconx = self.exiticon.x()
        self.fggroup.addToGroup(self.exiticon)
        
        self.entericon = QGraphicsPixmapItemCond(self.icon, self, viewport)
        self.entericon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin)
        self.iconx = self.entericon.x()
        self.fggroup.addToGroup(self.entericon)
        
        self.persisticon = QGraphicsPixmapItemCond(self.icon, self, viewport)
        self.persisticon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin)
        self.iconx = self.persisticon.x()
        self.fggroup.addToGroup(self.persisticon)
        
        self.comment = QGraphicsTextItemCond(self, viewport)
        self.comment.setTextWidth(self.style.nodetextwidth)
        self.comment.setDefaultTextColor(FlPalette.light)
        self.comment.setPos(0, self.nodelabel.y()+self.nodelabel.boundingRect().height()+self.style.itemmargin)
        self.fggroup.addToGroup(self.comment)
        
        self.graphgroup.addToGroup(self.fggroup)
        
        self.view.nodedocs[self.realid()]["comment"].contentsChanged.connect(self.updatecomment)
        self.updatecondition()
        self.updateenterscripts()
        self.updateexitscripts()
        self.updaterandweight()
        self.updatepersistence()
        
        # Never call updatelayout() from here (or any inheritable reimplementation)!
    
    def collapse (self, collapse):
        for item in self.fggroup.childItems():
            if item is not self.nodelabel:
                if collapse:
                    item.hide()
                else:
                    item.show()
        self.updatelayout()
    
    def updatecondition (self):
        icons = {True: "key", False: "blank"}
        pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hascond()])
        self.condicon.setPixmap(pixmap)
        if self.nodeobj.hascond():
            self.condicon.setToolTip("Condition")
        else:
            self.condicon.setToolTip("")
    
    def updateenterscripts (self):
        icons = {True: "script-enter", False: "blank"}
        pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hasenterscripts()])
        self.entericon.setPixmap(pixmap)
        if self.nodeobj.hasenterscripts():
            self.entericon.setToolTip("Enter Scripts")
        else:
            self.entericon.setToolTip("")
    
    def updateexitscripts (self):
        icons = {True: "script-exit", False: "blank"}
        pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hasexitscripts()])
        self.exiticon.setPixmap(pixmap)
        if self.nodeobj.hasexitscripts():
            self.exiticon.setToolTip("Exit Scripts")
        else:
            self.exiticon.setToolTip("")
    
    def updaterandweight (self):
        icons = {True: "dice", False: "blank"}
        pixmap = self.pixmap("images/%s.png" % icons[bool(self.nodeobj.randweight)])
        self.randicon.setPixmap(pixmap)
        if self.nodeobj.randweight:
            self.randicon.setToolTip("Random Weight: %s" % self.nodeobj.randweight)
        else:
            self.randicon.setToolTip("")
    
    def updatepersistence (self):
        icons = {"Mark": "mark", "OncePerConv": "once", "OnceEver": "onceever", "": "blank"}
        pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.persistence])
        self.persisticon.setPixmap(pixmap)
        if self.nodeobj.persistence:
            self.persisticon.setToolTip("Persistence: %s" % self.nodeobj.persistence)
        else:
            self.persisticon.setToolTip("")
    
    def updatecomment (self):
        self.fggroup.removeFromGroup(self.comment)
        contents = self.view.nodedocs[self.realid()]["comment"].toPlainText()
        if not contents:
            self.comment.hide()
        else:
            self.comment.show()
            self.comment.setPlainText(contents)
            self.fggroup.addToGroup(self.comment)
        self.updatelayout()
    
    def updatelayout (self):
        if self.iscollapsed():
            rect = self.nodelabel.mapRectToParent(self.nodelabel.boundingRect())
        else:
            rect = self.fggroup.childrenBoundingRect()
        mainrect = rect.marginsAdded(self.style.nodemargins)
        self.mainbox.setRect(mainrect)
        self.shadowbox.setRect(mainrect)
        self.selectbox.setRect(mainrect.marginsAdded(self.style.selectmargins))
        activerect = mainrect.marginsAdded(self.style.activemargins)
        self.activebox.setRect(activerect)
        self.graphgroup.setPos(-activerect.width()//2-activerect.x(), -activerect.height()//2-activerect.y())
        self.prepareGeometryChange()
        self.rect = self.graphgroup.mapRectToParent(mainrect)
        self.view.updatelayout()
    
    def mouseDoubleClickEvent (self, event):
        super().mouseDoubleClickEvent(event)
        event.accept()
        if event.button() == Qt.LeftButton:
            self.view.setactivenode(self)
    
    def mousePressEvent (self, event):
        super().mousePressEvent(event)
        if event.button() & (Qt.LeftButton | Qt.RightButton) :
            self.view.setselectednode(self)
            event.accept()
    
    def __repr__ (self):
        return "<%s %s>" % (type(self).__name__, self.id())
예제 #27
0
class MapWidget(QDialog):
    def __init__(self):
        QDialog.__init__(self)
    
        self.__mapWidgetUi = Ui_MapWidget()
        self.__mapWidgetUi.setupUi(self)
        
        self.__view = self.__mapWidgetUi.graphicsView
        self.__view.setObjectName("ACS_Map_View")
        self.__scene = QGraphicsScene()
                
        self.__view.setScene(self.__scene)

        self.__current_lat = 35.720428
        self.__current_lon = -120.769924
        self.__current_ground_width = 41000000. #meters(start w/ view of whole earth)
        #TODO: don't hard code location
        self.__tiler = acs_map_tiler.ACS_MapTiler(35.720428, -120.769924)

        self.__current_detail_layer = 0 #corresponds to "zoom" in map_tiler module
        self.__detail_layers = []
        self.__rect_tiles = OrderedDict() #see rectKey method for how key works

        #detail layers are various levels of raster detail for the map.
        #0 is lowest level of detail, 20 highest.  0 loads fast and the 
        #entire world can fit on a single tile.  20 loads slow, and it is unwise
        #to try to show the entire world due to the number of tiles required 
        #(higher numbered detail layers are intended for "zooming in")
        self.setupDetailLayers()

        self.__plane_layer = QGraphicsItemGroup()
        self.__scene.addItem(self.__plane_layer)
        self.__plane_icons = {}
        self.__plane_labels = {}
        self.__plane_icon_pixmaps = {}
        img_bytes = pkg_resources.resource_stream("acs_dashboards", "data/images/flyingWingTiny.png").read()
        self.__plane_icon_pixmaps[0] = QPixmap()
        self.__plane_icon_pixmaps[0].loadFromData(img_bytes)
        img_bytes2 = pkg_resources.resource_stream("acs_dashboards", "data/images/flyingWingTiny2.png").read()
        self.__plane_icon_pixmaps[1] = QPixmap()
        self.__plane_icon_pixmaps[1].loadFromData(img_bytes2)

        #for drawing waypoints:
        self.__mission_layer = QGraphicsItemGroup()
        self.__scene.addItem(self.__mission_layer)
        self.__wp_diameter = 0.0001
        self.__prev_drawn_nav_wp = None  #needed when drawing lines between wps
        self.__wp_loiter_radius = None #NOTE: this is in meters; the map itself
                                       #is in degrees

        #for drawing fence:
        self.__fence_layer = QGraphicsItemGroup()
        self.__scene.addItem(self.__fence_layer)

        #slots
        self.__view.just_zoomed.connect(self.onZoom)
        self.__mapWidgetUi.zoom_sb.valueChanged.connect(self.onZoomSBValueChanged)
        self.__view.just_panned.connect(self.onPan)
        
    def getView(self):
        return self.__view
    
    def rectKey(self, x, y):
        '''rect_tiles key'''
        return (self.__current_detail_layer, x, y)

    #returns (min_lat, max_lat, min_lon, max_lon) as a tuple
    def extentsOfVisibleWorld(self):
        topLeft = self.__view.mapToScene(0,0)
        bottomRight = self.__view.mapToScene(self.__view.width(), 
                                             self.__view.height())

        return (-topLeft.y(), -bottomRight.y(), topLeft.x(), bottomRight.x())

    #returns a list of TileInfos that are currently visible
    def tilesInVisibleWorld(self):
        (latTop, latBottom, lonLeft, lonRight) = self.extentsOfVisibleWorld()
        #print("Extents:", latTop, latBottom, lonLeft, lonRight, "\n")
        tile_info_list = self.__tiler.area_to_tile_list_lat_lon(latTop, latBottom,
                lonLeft, lonRight, self.__current_detail_layer)

        return tile_info_list

    def setupDetailLayers(self):
        #setup detail layers 0-20
        for i in range(0,21):
            self.__detail_layers.append(QGraphicsItemGroup())
            #add layer to scene:
            self.__scene.addItem(self.__detail_layers[i])            
            #hide all detail layers until it's time to show one:
            self.__detail_layers[i].hide()

        #show only the current detail layer
        self.setCurrentDetailLayer(0)

    def setCurrentDetailLayer(self, layerNum):
        self.__detail_layers[self.__current_detail_layer].hide()
        self.__detail_layers[layerNum].show()
        self.__current_detail_layer = layerNum

        self.__tiler.set_max_zoom(self.__current_detail_layer+1)
        #self.__tiler.prefetch()

        self.addTilesToCurrentDetailLayer()

    def createRectFromTileInfo(self, tile_info):
        #if Rectangle already exists, don't create it again
        key = self.rectKey(tile_info.x, tile_info.y)
        if key in self.__rect_tiles:
            return self.__rect_tiles[key]

        (y, x) = tile_info.coord()
        #TODO: do something about the hard coded 256s
        (end_y, end_x) = tile_info.coord((256, 256))
        
        #y values need to reflect across the equator due to the origin in scene space
        #being on the top right (as opposed to bottom left in tile space) 
        y = -y
        end_y = -end_y

        #keep things simple at the edges of the map:
        if y < -85.0:
            y = -85.0
        if end_y > 85.0:
            end_y = 85.0

        width = end_x - x
        height = end_y - y

        #create rectangle for the TileInfo and put it into the scene
        self.__rect_tiles[key] = QGraphicsRectItem(x, y, width, height, self.__detail_layers[self.__current_detail_layer])

        #add raster data to the rect tile
        self.__tiler.load_tile(tile_info)
        #no border
        self.__rect_tiles[key].setPen(QPen(Qt.NoPen))

        #remember the tiling data
        self.__rect_tiles[key].setData(0, tile_info)

        #attempt to add tile texture to rectangle:
        self.textureRect(self.__rect_tiles[key])

        return self.__rect_tiles[key]

    def addTilesToCurrentDetailLayer(self):
        tile_info_list = self.tilesInVisibleWorld()

        for next_tile_info in tile_info_list:
            next_rect = self.createRectFromTileInfo(next_tile_info)

            #add rect tile to appropriate detail layer
            self.__detail_layers[self.__current_detail_layer].addToGroup(next_rect)

    #returns True if texture successfully applied, False otherwise
    #depth applies to how many zoom levels (or detail layers) we have traveled
    #while attempting to get a lower resolution texture
    def textureRect(self, rect_tile):
        tile_info = rect_tile.data(0)

        if tile_info is None:
            return False

        pm = QPixmap(self.__tiler.tile_to_path(tile_info))  
        if pm.width() != 256:
            #print("Probably didn't get tile:", next_tile_info.x, next_tile_info.y, "\n")
            #TODO: Attempt to texture with a lower res tile
            #Bear in mind that you will have to take Mercator projection into
            #account on the lower res tile.
            
            #First Attempt: didn't work
            #if tile_info.zoom <= self.__tiler.get_min_zoom():
            #    return False
            #
            #find colocated lower res tile
            #(lat,lon) = tile_info.coord()
            #tile_info2 = self.__tiler.coord_to_tile(lat,lon, tile_info.zoom-1)
            #rect_tile.setData(0, tile_info2)
            #print("prev tile: ", tile_info.tile, tile_info.coord())
            #return self.textureRect(rect_tile, depth + 1)

            #until such time as we can pull lower res tiles and figure out
            #which area to render on a rectangle, skip:
            return False

        topLeft = rect_tile.boundingRect().topLeft()
        bottomRight = rect_tile.boundingRect().bottomRight()   
       
        width = bottomRight.x() - topLeft.x()
        height = bottomRight.y() - topLeft.y()

        brush_trans = QTransform()        
        brush_trans.translate(topLeft.x(), topLeft.y())
        brush_trans.scale(width/256.0, height/256.0)

        qb = QBrush(pm)
        qb.setTransform(brush_trans)
        rect_tile.setBrush(qb)
   
        return True

    def checkForNewTextures(self):
        #ONLY care about rects in the current view:
        tile_info_list = self.tilesInVisibleWorld()

        for next_tile_info in tile_info_list:
            key = self.rectKey(next_tile_info.x, next_tile_info.y)
            # make sure key exists in self.__rect_tiles
            if key not in self.__rect_tiles:
                self.createRectFromTileInfo(next_tile_info)
            
            if self.__rect_tiles[key].brush().texture().width() != 256:
                self.textureRect(self.__rect_tiles[key])
             
            #TODO: this code becomes applicable when lower res tiles become
            #available to higher zoom levels.
            #if self.__rect_tiles[key].data(0).zoom < self.__current_detail_layer:
                #lower res in there, try to get higher res 
                #(remove tile info of the lower res tile):
            #    del self.__rect_tiles[key]

    def clearFencePoints(self):
        children = self.__fence_layer.childItems()
        for child in children:
            self.__fence_layer.removeFromGroup(child)

    def clearWPs(self):
        children = self.__mission_layer.childItems()
        for child in children:
            self.__mission_layer.removeFromGroup(child)
        
        self.__prev_drawn_nav_wp = None

    def addWP(self, wp):
        if wp.command in [mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
                          mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
                          mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT,
                          mavutil.mavlink.MAV_CMD_NAV_LOITER_TURNS,
                          mavutil.mavlink.MAV_CMD_NAV_LOITER_TIME,
                          mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM,
                          mavutil.mavlink.MAV_CMD_NAV_LAND]:
            

            #point
            rad = self.__wp_diameter * 0.5
            ellipse = QGraphicsEllipseItem(wp.y - rad, -wp.x - rad, 
                self.__wp_diameter, self.__wp_diameter, self.__mission_layer)
            ellipse.setBrush(QBrush(QColor(255, 255, 255)))
            e_pen = QPen(QColor(255, 255, 255))
            e_pen.setWidth(0)
            ellipse.setPen(e_pen)
            self.__mission_layer.addToGroup(ellipse)

            #label
            label = QGraphicsTextItem(str(wp.seq), self.__mission_layer)
            label.setZValue(2)
            label.setDefaultTextColor(Qt.white)
            label.setPos(wp.y + rad, -wp.x - rad)
            label.setScale(0.00002)  #bit hacky --  really should scale based on
                                 #current zoom, but I'm in a hurry.
            self.__mission_layer.addToGroup(label)
            label.show()

    #argument is a dictionary of waypoints (keys = ids)
    def drawNewMission(self, wps):
        self.clearWPs()

        self.drawMissionLines(wps)        
                
    def drawWPLine(self, wp1, wp2):
        if wp1 is None or wp2 is None:
            print("Error: Can't draw line for Null endpoint")
            return
    
        rad = self.__wp_diameter * 0.5
        mapped_wp1_x = wp1.y - rad
        mapped_wp1_y = -wp1.x
        #tangential approach?
        if (wp1.command == mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT
                and wp1.param1 == 1.0):
            l_rad = abs(self.__wp_loiter_radius)
            if l_rad is not None:
                dis = acs_math.gps_distance(wp1.x, wp1.y, wp2.x, wp2.y)
                theta = math.degrees(math.atan(l_rad / dis))

                #sign of self.__wp_loiter_radius indicates the direction of the
                #loiter (negative is counter-clockwise, postive is clockwise)
                #Also, the waypoint itself can override the default setting
                #via param2
                if ((wp1.param2 == 0 and self.__wp_loiter_radius > 0.0) or
                     wp1.param2 > 0.0):
                    theta = -theta

                tan_dis = math.sqrt( dis * dis - l_rad * l_rad)
                bearing = acs_math.gps_bearing(wp2.x, wp2.y, wp1.x, wp1.y)

                (tan_wp_x, tan_wp_y) = acs_math.gps_newpos(wp2.x, wp2.y,
                    bearing - theta, tan_dis)

                mapped_wp1_x = tan_wp_y - rad
                mapped_wp1_y = -tan_wp_x

        next_line = QGraphicsLineItem(mapped_wp1_x, mapped_wp1_y,
                            wp2.y - rad, -wp2.x, self.__mission_layer)
        l_pen = QPen(QColor(255, 255, 255))
        l_pen.setWidth(0.00002)
        next_line.setPen(l_pen)
        self.__mission_layer.addToGroup(next_line)

    def setWPLoiterRad(self, rad):
        self.__wp_loiter_radius = rad

    def drawWPCircle(self, wp):
        if self.__wp_loiter_radius is None:
            print("Can't draw WP loiter circles; wp_loiter_radius not set.")
            return

        rad_deg = acs_math.gps_meters_to_degrees_lat(abs(self.__wp_loiter_radius), wp.x, wp.y)
        diameter = rad_deg * 2.0
        ellipse = QGraphicsEllipseItem(wp.y - rad_deg, -wp.x - rad_deg, 
            diameter, diameter, self.__mission_layer)
        #ellipse.setBrush(QBrush(QColor(255, 255, 255)))
        e_pen = QPen(QColor(255, 255, 255))
        e_pen.setWidth(0.00002)
        ellipse.setPen(e_pen)
        self.__mission_layer.addToGroup(ellipse)

    def drawMissionLines(self, wps):
        for i in range(1, len(wps)):
            self.addWP(wps[i])

            if wps[i].command in [mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
                                  mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
                                  mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT,
                                  mavutil.mavlink.MAV_CMD_NAV_LOITER_TURNS,
                                  mavutil.mavlink.MAV_CMD_NAV_LOITER_TIME,
                                  mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM]:

                if self.__prev_drawn_nav_wp is not None:
                    self.drawWPLine(self.__prev_drawn_nav_wp, wps[i])
            
                if wps[i].command in [mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM,
                                      mavutil.mavlink.MAV_CMD_NAV_LOITER_TURNS,
                                      mavutil.mavlink.MAV_CMD_NAV_LOITER_TIME,
                                    mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT]:
                    self.drawWPCircle(wps[i])

                self.__prev_drawn_nav_wp = wps[i]

            elif wps[i].command == mavutil.mavlink.MAV_CMD_DO_JUMP:
                wp_id = wps[i].param1
                if self.__prev_drawn_nav_wp is not None:
                    self.drawWPLine(self.__prev_drawn_nav_wp, wps[wp_id])
                self.__prev_drawn_nav_wp = None
    
    def drawNewFence(self, fps):
        self.clearFencePoints()

        prev_fp = None
        for i in range(1, len(fps)):
            if prev_fp is not None:
                prev_x = prev_fp.lon
                prev_y = -prev_fp.lat
                mapped_x = fps[i].lon
                mapped_y = -fps[i].lat

                next_line = QGraphicsLineItem(prev_x, prev_y, 
                    mapped_x, mapped_y, self.__fence_layer)
                l_pen = QPen(QColor(0, 255, 0))
                l_pen.setWidth(0.1)
                next_line.setPen(l_pen)
                self.__fence_layer.addToGroup(next_line)

            prev_fp = fps[i]

    def updateIcon(self, id, uav_state, image_num=0):
        if uav_state.get_lon() == 0.0:
            #haven't received a Pose message yet
            return

        if id not in self.__plane_icons:
            #make the plane's label first
            label = QGraphicsTextItem(str(id), self.__plane_layer)
            label.setZValue(2)
            label.setDefaultTextColor(Qt.red)
            self.__plane_layer.addToGroup(label) 
            label.show()
            self.__plane_labels[id] = label

            self.__plane_icons[id] = MapGraphicsIcon(id, label,
                                                    self.__plane_layer)
            self.__plane_icons[id].centerIconAt(uav_state.get_lon(),
                                               -uav_state.get_lat())
            self.__plane_icons[id].textureIcon(self.__plane_icon_pixmaps[image_num])

            #plane icons need to be drawn on top of map tiles:
            self.__plane_icons[id].setZValue(1)
            self.__plane_layer.addToGroup(self.__plane_icons[id])

            #key 0 = last update time
            self.__plane_icons[id].setData(0, 0)

            #refresh:
            #HACK: don't know why zooming works to refresh. Couldn't
            #get scene.invalidate() nor scene.update() to work
            self.onZoom(self.__current_detail_layer)
        #end if

        now = time.time()

        #if we don't have new pose data, then we don't update the plane icon
        if (self.__plane_icons[id].data(0) is None 
         or self.__plane_icons[id].data(0) >= uav_state.get_last_pose_update()):
            return

        #place icon
        self.__plane_icons[id].centerIconAt(uav_state.get_lon(), -uav_state.get_lat())
        #give correct heading:
        quat = uav_state.get_quat()
        heading = acs_math.yaw_from_quat(quat[0], quat[1], quat[2], quat[3])
        self.__plane_icons[id].setHeading(heading)
          
        #set last update time
        self.__plane_icons[id].setData(0, now)
     
    def zoomTo(self, zoomLevel, lat = 0, lon = 0):
        self.__view.zoomTo(zoomLevel, lat, lon)

    def onZoom(self, zoom_level):
        self.setCurrentDetailLayer(zoom_level)
        self.__mapWidgetUi.zoom_sb.setValue(zoom_level)
        for id, nextPlaneIcon in self.__plane_icons.items():
            nextPlaneIcon.scaleByViewAndTexture(self.__view)

    def onZoomSBValueChanged(self, new_zoom):
        if (int(self.__view.getCurrentZoom()) != new_zoom):
            self.__view.zoomTo(new_zoom)

    def onPan(self, new_lat, new_lon):
        lat_lon_str = str(new_lat) + ", " + str(new_lon) 
        self.__mapWidgetUi.coords_lb.setText(lat_lon_str)

    def hideUAVIcon(self, id):
        if id in self.__plane_icons:
            self.__plane_icons[id].hide()
            self.__plane_labels[id].hide()

    def showUAVIcon(self, id):
        if id in self.__plane_icons:
            self.__plane_icons[id].show()
            self.__plane_labels[id].show()
예제 #28
0
class BoardGUI(QWidget):
    """cointain the graphical representation of the Board"""

    # ratio of bordersize compared to the size of one base square
    borderRatio = 0.8
    baseRectRatio = 14/15  # 12/13 for normal ratio but looks weird
    stoneScale = 0.46

    # siganl
    stoneClicked = pyqtSignal(tuple)

    def __init__(self, parent, game):
        super().__init__()

        self.initUI(game)

    def initUI(self, game):
        self.board = game.currentBoard
        self.game = game

        self.showCoords = True
        self.scene = QGraphicsScene()

        # grid containing coordinates for the scene
        self.grid = []
        self.drawGrid()

        # initialize and set layout + view
        self.view = QGraphicsView(self.scene)
        self.view.setMouseTracking(True)
        self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        self.setMouseTracking(True)
        box = QHBoxLayout()
        box.addWidget(self.view)
        self.setLayout(box)

        # stones for all positions are created and listed in self.pos dict
        self.createPosition()
        self.makeCoords()  # has to be called after drawGrid!

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

    def boardWidth(self):
        """returns the max width fitting into widget"""
        width = self.contentsRect().width()*0.95
        height = self.contentsRect().height()*0.95

        return min(width, height*self.baseRectRatio)

    def boardHeight(self):
        """returns the max width fitting into widget """
        return self.boardWidth()*(1/self.baseRectRatio)

    def makeGrid(self):
        """
        returns coords [[(x, y)]] for the Grid according
         to current window mesures
        """
        # set scenesize to window size
        self.scene.setSceneRect(0, 0, self.boardWidth(), self.boardHeight())
        denom = self.board.size + 2*self.borderRatio
        baseWidth = self.boardWidth() / denom
        baseHeight = self.boardHeight() / denom

        leftOffset = 0.5*baseWidth  # (self.contentsRect().width()-self.boardWidth())/2
        topOffset = 0  # (self.contentsRect().height()-self.boardHeight())/2

        partionWidth = [leftOffset+(self.borderRatio+x)*baseWidth
                        for x in range(self.board.size)]
        partionHeight = [topOffset+(self.borderRatio+x)*baseHeight
                         for x in range(self.board.size)]

        grid = [[(x, y) for x in partionWidth] for y in partionHeight]
        self.grid = grid
        self.baseWidth = baseWidth

    def drawGrid(self):
        """draws the background grid"""
        self.makeGrid()
        for line in self.grid:
            self.scene.addLine(*line[0], *line[-1])
        for (pointT, pointB) in zip(self.grid[0], self.grid[-1]):
            self.scene.addLine(*pointT, *pointB)
        self.drawHoshis()

    def makeCoords(self):
        """ draws Coordinates """
        xLabels = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
        yLabels = list(range(1, 26))
        botGrid = []
        leftGrid = []
        # generate pixel coordinates grids
        for n in range(self.board.size):
            (xBot, yBot) = self.grid[self.board.size-1][n]
            yBot += self.baseWidth*0.4/self.baseRectRatio
            xBot -= self.baseWidth*0.1
            botGrid.append((xBot, yBot))
            (xLeft, yLeft) = self.grid[n][0]
            xLeft -= self.baseWidth*1.2
            yLeft -= self.baseWidth*0.3/self.baseRectRatio
            leftGrid.append((xLeft, yLeft))
        # generate Text items and add them to group
        self.coordGroup = QGraphicsItemGroup()
        for n in range(self.board.size):
            leftText = QGraphicsSimpleTextItem(str(yLabels[n]))
            leftText.setPos(*leftGrid[n])
            self.coordGroup.addToGroup(leftText)
            bottomText = QGraphicsSimpleTextItem(xLabels[n])
            bottomText.setPos(*botGrid[n])
            self.coordGroup.addToGroup(bottomText)
        # draw coordinates and update visibility according to self.showCoords
        self.scene.addItem(self.coordGroup)
        self.updateCoords()

    def updateCoords(self):
        """ slot that updates the visibility os the coordiantes. """
        self.coordGroup.setVisible(self.showCoords)

    def setCoordVis(self, visibility):
        """ set the self.showCoords boolean """
        self.showCoords = visibility
        self.updateCoords()

    def drawHoshis(self):
        """ Draws Hoshi dots"""
        hoshis = []
        rad = self.baseWidth*0.15
        for (x, y) in self.board.getHoshis():
            hoshis.append(self.grid[x][y])
        for point in hoshis:
            (x, y) = point
            self.scene.addEllipse(x-rad, y-rad, rad*2.0, rad*2.0,
                                  QPen(), QBrush(Qt.SolidPattern))

    def updatePosition(self):
        """
        sets the colors for all stones in self.pos according
        to the status in self.board
        """
        for (x, y) in self.pos:
            color = self.game.currentBoard.getPosition(x, y)
            self.pos[(x, y)].setMark(None)
            self.pos[(x, y)].setColor(color)
        lastMove = self.game.currentBoard.lastMove
        if lastMove:
            self.pos[lastMove].setMark(GoMarks.circel)
        ko = self.game.currentBoard.ko
        if ko:
            self.pos[ko].setMark(GoMarks.square)

    def createPosition(self):
        """
        Creates the self.pos dictionary containing all possible stones on the
        board initialized as empty stones

        also connects a signal form each stone to ???
        """
        self.pos = {}
        radius = self.stoneScale*self.baseWidth
        for row in range(self.board.size):
            for col in range(self.board.size):
                (x, y) = self.grid[row][col]
                newStone = Stone(x, y, radius)
                self.pos[(row, col)] = newStone
                self.scene.addItem(newStone)
        self.updatePosition()
        self.connecting()

    def connecting(self):
        for key in self.pos:
            self.pos[key].clicked.connect(lambda key=key: self.resend(key))

    def resend(self, pos):
        """
        emits the captured signal again,
        with (int, in) parameter for stone clicked
        """
        self.stoneClicked.emit(pos)
예제 #29
0
class Image_widget(QWidget):
    param_user_modified = pyqtSignal(object) # (px1, py1, px2, px2)
    # zoom_params = ["x", "y", "dx", "xy_ratio"]

    def __init__(self, parent, view_presenter): # im=None):#, xy_ratio=None):
        super().__init__(parent)
        # self.setWindowFlags(Qt.BypassGraphicsProxyWidget)
        self._model = view_presenter._model
        self._mapping = view_presenter._mapping
        self._presenter = view_presenter# model[func_keys]
            
#        if xy_ratio is None:
#            self._im = parent._im
#        else:
#            self._im = im
            
        
        # sets graphics scene and view
        self._scene = QGraphicsScene()
        self._group = QGraphicsItemGroup()
        self._view = QGraphicsView()
        self._scene.addItem(self._group)
        self._view.setScene(self._scene)
        self._view.setFrameStyle(QFrame.Box)
        

        
#        # always scrollbars
#        self._view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
#        self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        # special sursor
        self._view.setCursor(QtGui.QCursor(Qt.CrossCursor))
        
        # sets property widget
        self._labels = QDict_viewer(self,
            {"Image metadata": None, "px": None, "py": None, "zoom": None})

        # sets layout
        self._layout = QVBoxLayout(self)
        self.setLayout(self._layout)
        self._layout.addWidget(self._view, stretch=1)
        #self._layout.addStretch(1)
        self._layout.addWidget(self._labels, stretch=0)

        # Zoom rectangle disabled
        self._rect = None
        self._drawing_rect = False
        self._dragging_rect = False

        # Sets Image
        self._qim = None
        self.reset_im()

        # zooms anchors for wheel events - note this is only active 
        # when the 
        self._view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self._view.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
        self._view.setAlignment(Qt.AlignCenter)

        # events filters
        self._view.viewport().installEventFilter(self)
        self._scene.installEventFilter(self)
        
        # Publish / subscribe signals with the submodel
        # self.zoom_user_modified.connect(self._model.)
        self._model.model_event.connect(self.model_event_slot)

#        self._view.setContextMenuPolicy(Qt.ActionsContextMenu)
#        self._scene.customContextMenuRequested.connect(self.useless)
#        useless_action = QAction("DoNothing", self)
#        self._scene.addAction(useless_action)
#        useless_action.triggered.connect(self.useless)


        
    
    def on_context_menu(self, event):
        menu = QMenu(self)
        NoAction = QAction("Does nothing", self)
        menu.addAction(NoAction)
        NoAction.triggered.connect(self.doesnothing)
        menu.popup(self._view.viewport().mapToGlobal(event.pos()))
        return True

    def doesnothing(self, event):
        print("voili voilou")

    @property
    def zoom(self):
        view = self._view
        pc = 100. * math.sqrt(view.transform().determinant())
        return "{0:.2f} %".format(pc)

    @property
    def xy_ratio(self):
        return self._presenter["xy_ratio"]

#        return self.parent().xy_ratio


    def reset_im(self):
        image_file = os.path.join((self._presenter["fractal"]).directory, 
                                   self._presenter["image"] + ".png")
        valid_image = True
        try:
            with PIL.Image.open(image_file) as im:
                info = im.info
                nx, ny = im.size
                # print("info debug", info["debug"])
        except FileNotFoundError:
            valid_image = False
            info = {"x": None, "y": None, "dx": None, "xy_ratio": None}
            nx = None
            ny = None

        # Storing the "initial" zoom info
        self._fractal_zoom_init = {k: info[k] for k in 
                                   ["x", "y", "dx", "xy_ratio"]}
        self._fractal_zoom_init["nx"] = nx
        self._fractal_zoom_init["ny"] = ny
        self.validate()

#        if self._qim is not None:
#            self._group.removeFromGroup(self._qim)
        for item in [self._qim, self._rect]:
            if item is not None:
                self._group.removeFromGroup(item)

        if valid_image:
            self._qim = QGraphicsPixmapItem(QtGui.QPixmap.fromImage(
                    QtGui.QImage(image_file)))#QtGui.QImage()))#imqt)) # QtGui.QImage(self._im)))
            self._qim.setAcceptHoverEvents(True)
            self._group.addToGroup(self._qim)
            self.fit_image()
        else:
            self._qim = None
        
        self._rect = None
        self._drawing_rect = False

    @staticmethod
    def cast(val, example):
        """ Casts value to the same type as example """
        return type(example)(val)

    def check_zoom_init(self):
        """ Checks if the image 'zoom init' matches the parameters ;
        otherwise, updates """
        ret = 0
        for key in ["x", "y", "dx", "xy_ratio"]:#, "dps"]: # TODO : or precision ??
            expected = self._presenter[key]
            value = self._fractal_zoom_init[key]
            if value is None:
                ret = 2
            else:
                casted = self.cast(value, expected)
                # Send a model modification request
                self._presenter[key] = casted
                if casted != str(expected) and (ret != 2):
                    ret = 1
                    self._fractal_zoom_init[key] = casted
        return ret

    def validate(self):
        """ Sets Image metadata message """
        self.validated = self.check_zoom_init()
        message = {0: "OK, matching",
                   1: "OK, zoom params updated",
                   2: "No image found"}
        self._labels.values_update({"Image metadata": 
            message[self.validated]})

    def fit_image(self):
        if self._qim is None:
            return
        rect = QtCore.QRectF(self._qim.pixmap().rect())
        if not rect.isNull():
            #        # always scrollbars off
            self._view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            
            view = self._view
            view.setSceneRect(rect)
            unity = view.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
            view.scale(1 / unity.width(), 1 / unity.height())
            viewrect = view.viewport().rect()
            scenerect = view.transform().mapRect(rect)
            factor = min(viewrect.width() / scenerect.width(),
                         viewrect.height() / scenerect.height())
            view.scale(factor, factor)
            
            self._view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            
            self._labels.values_update({"zoom": self.zoom})

    def eventFilter(self, source, event):
        # ref: https://doc.qt.io/qt-5/qevent.html
        if source is self._scene:
            if type(event) is QtWidgets.QGraphicsSceneMouseEvent:
                return self.on_viewport_mouse(event)
            elif type(event) is QtGui.QEnterEvent:
                return self.on_enter(event)
            elif (event.type() == QtCore.QEvent.Leave):
                return self.on_leave(event)

        elif source is self._view.viewport():
            # Catch context menu
            if type(event) == QtGui.QContextMenuEvent:
                return self.on_context_menu(event)
            elif event.type() == QtCore.QEvent.Wheel:
                return self.on_wheel(event)
            elif event.type() == QtCore.QEvent.ToolTip:
                return True

        return False

    def on_enter(self, event):
#        print("enter")
        return False

    def on_leave(self, event):
#        print("leave")
        return False

    def on_wheel(self, event):
        if self._qim is not None:
            view = self._view
            if event.angleDelta().y() > 0:
                factor = 1.25
            else:
                factor = 0.8
            view.scale(factor, factor)
            self._labels.values_update({"zoom": self.zoom})
        return True


    def on_viewport_mouse(self, event):

        if event.type() == QtCore.QEvent.GraphicsSceneMouseMove:
            # print("viewport_mouse")
            self.on_mouse_move(event)
            return True

        elif (event.type() == QtCore.QEvent.GraphicsSceneMousePress
              and event.button() == Qt.LeftButton):
            self.on_mouse_left_press(event)
            return True

        elif (event.type() == QtCore.QEvent.GraphicsSceneMouseRelease
              and event.button() == Qt.LeftButton):
            self.on_mouse_left_release(event)
            return True

        elif (event.type() == QtCore.QEvent.GraphicsSceneMouseDoubleClick
              and event.button() == Qt.LeftButton):
            self.on_mouse_double_left_click(event)
            return True

        else:
            # print("Uncatched mouse event", event.type())
            return False

    def on_mouse_left_press(self, event):
        self._drawing_rect = True
        self._dragging_rect = False
        self._rect_pos0 = event.scenePos()

    def on_mouse_left_release(self, event):
        if self._drawing_rect:
            self._rect_pos1 = event.scenePos()
            if (self._rect_pos0 == self._rect_pos1):
                self._group.removeFromGroup(self._rect)
                self._rect = None
                print("cancel drawing RECT")
                self.cancel_drawing_rect()
            else:
                print("finish drawing RECT", self._rect_pos0, self._rect_pos1)
                self.publish_drawing_rect()
            self._drawing_rect = False
            
    def cancel_drawing_rect(self, dclick=False):
        if self._qim is None:
            return
        keys = ["x", "y", "dx"]
        if dclick:
            keys = ["x", "y", "dx", "xy_ratio"]
        # resets everything except the zoom ratio 
        for key in keys: #, "xy_ratio"]:
            value = self._fractal_zoom_init[key]
            if value is not None:
                # Send a model modification request
                # TODO: avoid update cancel xy_ratio 1.0 <class 'str'>
                print("update cancel", key, value, type(value))
                self._presenter[key] = value

    def publish_drawing_rect(self):
        print("------*----- publish zoom")
        if self._qim is None:
            return
#        print("publish", self._rect_pos0, self._rect_pos1)
#        print("fractal", self._presenter["fractal"])
#        print("fractal", self._presenter["image"])
        nx = self._fractal_zoom_init["nx"]
        ny = self._fractal_zoom_init["ny"]
        # new center offet in pixel
        center_off_px = 0.5 * (self._rect_pos0.x() + self._rect_pos1.x() - nx)
        center_off_py = 0.5 * (ny - self._rect_pos0.y() - self._rect_pos1.y())
        dx_pix = abs(self._rect_pos0.x() - self._rect_pos1.x())
#        print("center px", center_off_px)
#        print("center py", center_off_py)
        ref_zoom = self._fractal_zoom_init.copy()
        # str -> mpf as needed
        to_mpf = {k: isinstance(self._fractal_zoom_init[k], str) for k in
                  ["x", "y", "dx"]}
        # We may need to increase the dps to hold sufficent digits
        if to_mpf["dx"]:
            ref_zoom["dx"] = mpmath.mpf(ref_zoom["dx"])
        pix = ref_zoom["dx"] / float(ref_zoom["nx"])
        with mpmath.workdps(6):
            # Sets the working dps to 10e-8 x pixel size
            ref_zoom["dps"] = int(-mpmath.log10(pix * dx_pix / nx) + 8)
        print("------*----- NEW dps from zoom", ref_zoom["dps"])

#        if ref_zoom["dps"] > mpmath.dps:
#        zoom_dps = max(ref_zoom["dps"], mpmath.mp.dps)
        with mpmath.workdps(ref_zoom["dps"]):
            for k in ["x", "y"]:
                if to_mpf[k]:
                    ref_zoom[k] = mpmath.mpf(ref_zoom[k])
    
    #        print("is_mpf", to_mpf, ref_zoom)
    
            ref_zoom["x"] += center_off_px * pix
            ref_zoom["y"] += center_off_py * pix
            ref_zoom["dx"] = dx_pix * pix
    
            
            
            #  mpf -> str (back)
            for (k, v) in to_mpf.items():
                if v:
                    if k == "dx":
                        ref_zoom[k] = mpmath.nstr(ref_zoom[k], 16)
                    else:
                        ref_zoom[k] = str(ref_zoom[k])

        for key in ["x", "y", "dx", "dps"]:
            self._presenter[key] = ref_zoom[key]
        

        
        
#        keys = ["x", "y", "dx"]
#        if dclick:
#            keys = ["x", "y", "dx", "xy_ratio"]
#        # resets everything except the zoom ratio 
#        for key in keys: #, "xy_ratio"]:
#            value = self._fractal_zoom_init[key]
#            if value is not None:
#                # Send a model modification request
#                # TODO: avoid update cancel xy_ratio 1.0 <class 'str'>
#                print("update cancel", key, value, type(value))
#                self._presenter[key] = value


    def on_mouse_double_left_click(self, event):
        self.fit_image()
        self.cancel_drawing_rect(dclick=True)

    def on_mouse_move(self, event):
        scene_pos = event.scenePos()
        self._labels.values_update({"px": scene_pos.x(),
                                    "py": scene_pos.y()})
        if self._drawing_rect:
            self._dragging_rect = True
            self._rect_pos1 = event.scenePos()
            self.draw_rect(self._rect_pos0, self._rect_pos1)
            

    def draw_rect(self, pos0, pos1):
        """ Draws the selection rectangle """
        # Enforce the correct ratio
        diffx = pos1.x() - pos0.x()
        diffy = pos1.y() - pos0.y()
        radius_sq = diffx ** 2 + diffy ** 2
        diffx0 = math.sqrt(radius_sq / (1. + self.xy_ratio ** 2))
        diffy0 = diffx0 * self.xy_ratio
        diffx0 = math.copysign(diffx0, diffx)
        diffy0 = math.copysign(diffy0, diffy)
        pos1 = QtCore.QPointF(pos0.x() + diffx0, pos0.y() + diffy0)

        topleft = QtCore.QPointF(min(pos0.x(), pos1.x()),
                                 min(pos0.y(), pos1.y()))
        bottomRight = QtCore.QPointF(max(pos0.x(), pos1.x()),
                                     max(pos0.y(), pos1.y()))
        rectF = QtCore.QRectF(topleft, bottomRight)
        if self._rect is not None:
            self._rect.setRect(rectF)
        else:
            self._rect = QGraphicsRectItem(rectF)
            self._rect.setPen(QtGui.QPen(QtGui.QColor("red"), 0, Qt.DashLine))
            self._group.addToGroup(self._rect)


    def model_event_slot(self, keys, val):
        """ A model item has been modified - will it impact the widget ? """
        # Find the mathching "mapping" - None if no match
        mapped = next((k for k, v in self._mapping.items() if v == keys), None)
        if mapped in ["image", "fractal"]:
            self.reset_im()
        elif mapped in ["x", "y", "dx", "xy_ratio", "dps"]:
            pass
        else:
            if mapped is not None:
                raise NotImplementedError("Mapping event not implemented: " 
                                          + "{}".format(mapped))
예제 #30
0
class IDView(QGraphicsView):
    """Simple extension of QGraphicsView
    - containing an image and click-to-zoom/unzoom
    """
    def __init__(self, parent, fnames):
        QGraphicsView.__init__(self)
        self.parent = parent
        self.initUI(fnames)

    def initUI(self, fnames):
        # Make QGraphicsScene
        self.scene = QGraphicsScene()
        # TODO = handle different image sizes.
        self.images = {}
        self.imageGItem = QGraphicsItemGroup()
        self.scene.addItem(self.imageGItem)
        self.updateImage(fnames)
        self.setBackgroundBrush(QBrush(Qt.darkCyan))
        self.parent.tool = "zoom"

        self.boxFlag = False
        self.originPos = QPointF(0, 0)
        self.currentPos = self.originPos
        self.boxItem = QGraphicsRectItem()
        self.boxItem.setPen(QPen(Qt.darkCyan, 1))
        self.boxItem.setBrush(QBrush(QColor(0, 255, 0, 64)))

    def updateImage(self, fnames):
        """Update the image with that from filename"""
        for n in self.images:
            self.imageGItem.removeFromGroup(self.images[n])
            self.images[n].setVisible(False)
        if fnames is not None:
            x = 0
            n = 0
            for fn in fnames:
                self.images[n] = QGraphicsPixmapItem(QPixmap(fn))
                self.images[n].setTransformationMode(Qt.SmoothTransformation)
                self.images[n].setPos(x, 0)
                self.images[n].setVisible(True)
                self.scene.addItem(self.images[n])
                x += self.images[n].boundingRect().width() + 10
                self.imageGItem.addToGroup(self.images[n])
                n += 1

        # Set sensible sizes and put into the view, and fit view to the image.
        br = self.imageGItem.boundingRect()
        self.scene.setSceneRect(
            0,
            0,
            max(1000, br.width()),
            max(1000, br.height()),
        )
        self.setScene(self.scene)
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)

    def deleteRect(self):
        if self.boxItem.scene() is None:
            return
        self.scene.removeItem(self.boxItem)
        self.parent.rectangle = None

    def mousePressEvent(self, event):
        if self.parent.tool == "rect":
            self.originPos = self.mapToScene(event.pos())
            self.currentPos = self.originPos
            self.boxItem.setRect(QRectF(self.originPos, self.currentPos))
            if self.boxItem.scene() is None:
                self.scene.addItem(self.boxItem)
            self.boxFlag = True
        else:
            super(IDView, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.parent.tool == "rect" and self.boxFlag:
            self.currentPos = self.mapToScene(event.pos())
            if self.boxItem is None:
                return
            else:
                self.boxItem.setRect(QRectF(self.originPos, self.currentPos))
        else:
            super(IDView, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if self.boxFlag:
            self.boxFlag = False
            self.parent.rectangle = self.boxItem.rect()
            self.parent.whichFile = self.parent.vTW.currentIndex()
            return
        """Left/right click to zoom in and out"""
        if (event.button() == Qt.RightButton) or (
                QGuiApplication.queryKeyboardModifiers() == Qt.ShiftModifier):
            self.scale(0.8, 0.8)
        else:
            self.scale(1.25, 1.25)
        self.centerOn(event.pos())

    def resetView(self):
        """Reset the view to its reasonable initial state."""
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)
예제 #31
0
class Ui_MainWindow(QtWidgets.QMainWindow, Ui_MainWindowBase):

    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setupUi(self)

        self.videoPlaybackInit()
        self.imgInit()
        self.menuInit()

        self.df = {}
        self.trackingPathGroup = None
        self.movableArrowGroup = None

        self.line_data_dict = {}
        self.line_item_dict = {}

        self.file_name_dict = {}

        self.currentFrameNo = 0

        self.colors = None

        self.overlayCheckBox.stateChanged.connect(self.overlayCheckBoxStateChanged)
        self.radiusSpinBox.valueChanged.connect(self.radiusSpinBoxValueChanged)
        self.frameNoSpinBox.valueChanged.connect(self.frameNoSpinBoxValueChanged)
        self.markDeltaSpinBox.valueChanged.connect(self.markDeltaSpinBoxValueChanged)

    def overlayCheckBoxStateChanged(self, s):
        if self.overlayCheckBox.isChecked():
            self.frameBufferItemGroup.show()
        else:
            self.frameBufferItemGroup.hide()

        self.updateInputGraphicsView()

    def markDeltaSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setMarkDelta(self.markDeltaSpinBox.value())
            self.updateInputGraphicsView()

    def radiusSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setRadius(self.radiusSpinBox.value())
            self.updateInputGraphicsView()

    def frameNoSpinBoxValueChanged(self, value):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setOverlayFrameNo(self.frameNoSpinBox.value())
            self.updateInputGraphicsView()

    def dragEnterEvent(self,event):
        event.acceptProposedAction()

    def dropEvent(self,event):
        # event.setDropAction(QtCore.Qt.MoveAction)
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            if len(urls) > 0:
                self.processDropedFile(urls[0].toLocalFile())

        event.acceptProposedAction()

    def processDropedFile(self,filePath):
        root,ext = os.path.splitext(filePath)
        if ext == ".filter":
            # Read Filter
            self.openFilterFile(filePath=filePath)
            return
        elif ext == ".csv":
            self.openCSVFile(filePath=filePath)
        elif ext == ".json":
            self.openJSONFile(filePath=filePath)
        elif ext == ".color":
            self.openColorFile(filePath=filePath)
        elif self.openImageFile(filePath=filePath):
            return
        elif self.openVideoFile(filePath=filePath):
            return

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.hide()
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame, Qt.QueuedConnection)

    def setFrame(self, frame, frameNo):
        if frame is not None:
            self.cv_img = frame
            self.currentFrameNo = frameNo
            self.updateInputGraphicsView()
            self.evaluate()

    def imgInit(self):
        self.cv_img = cv2.imread(os.path.join(sampleDataPath,"color_filter_test.png"))


        self.frameBuffer = Queue()
        self.frameBufferItemGroup = QGraphicsItemGroup()
        self.frameBufferItemGroup.hide()
        self.inputPixmapRenderScene = QGraphicsScene()
        self.inputPixmapRenderScene.addItem(self.frameBufferItemGroup)

        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.graphicsViewResized
        # self.inputScene.addItem(self.frameBufferItemGroup)

        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)
        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputScene.addItem(self.inputPixmapItem)

        self.rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self.inputGraphicsView)
        self.inputGraphicsView.mousePressEvent = self.inputGraphicsViewMousePressEvent
        self.inputGraphicsView.mouseMoveEvent = self.inputGraphicsViewMouseMoveEvent
        self.inputGraphicsView.mouseReleaseEvent = self.inputGraphicsViewMouseReleaseEvent

        self.inputGraphicsView.viewport().installEventFilter(self)

        self.inputGraphicsView.setMouseTracking(True)
        self.overlayScene = QGraphicsScene()
        self.inputGraphicsView.setOverlayScene(self.overlayScene)

        self.zoomedGraphicsView.setScene(self.inputScene)
        self.zoomedGraphicsView.setOverlayScene(self.overlayScene)

    def inputGraphicsViewMousePressEvent(self, event):
        self.origin = QPoint(event.pos())
        self.rubberBand.setGeometry(
            QtCore.QRect(self.origin, QtCore.QSize()))
        self.rubberBand.show()

        # Comment out to permit the view for sending the event to the child scene.
        # QGraphicsView.mousePressEvent(self.inputGraphicsView, event)

    def inputGraphicsViewMouseMoveEvent(self, event):
        if self.rubberBand.isVisible():
            self.rubberBand.setGeometry(
                QtCore.QRect(self.origin, event.pos()).normalized())
        # Comment out to permit the view for sending the event to the child scene.
        # QGraphicsView.mouseMoveEvent(self.inputGraphicsView, event)

    def inputGraphicsViewMouseReleaseEvent(self, event):
        if self.rubberBand.isVisible():
            self.rubberBand.hide()
            rect = self.rubberBand.geometry()
            sceneRect = self.inputGraphicsView.mapToScene(rect).boundingRect()
            self.zoomedGraphicsView.fitInView(QRectF(sceneRect))
            self.zoomedGraphicsView.viewport().update()
        # Comment out to permit the view for sending the event to the child scene.
        self.inputGraphicsView.viewport().update()
        # QGraphicsView.mouseReleaseEvent(self.inputGraphicsView, event)

    def menuInit(self):
        self.actionSaveDataFiles.triggered.connect(self.saveDataFiles)
        self.actionOpenCSVFile.triggered.connect(self.openCSVFile)
        self.actionOpenCSVFile.triggered.connect(self.openJSONFile)
        self.actionOpenCSVFile.triggered.connect(self.openJSONFile)

        self.actionPath.triggered.connect(self.actionPathTriggered)
        self.actionCircle.triggered.connect(self.actionCircleTriggered)
        self.actionIntervalMark.triggered.connect(self.actionIntervalMarkTriggered)
        self.actionShape.triggered.connect(self.actionShapeTriggered)
        self.actionSkeleton.triggered.connect(self.actionSkeletonTriggered)
        self.actionArrow.triggered.connect(self.actionArrowTriggered)

        self.actionChangeOrderOfNum.triggered.connect(self.actionChangeOrderOfNumTriggered)

        self.actionTrackingPathColor.triggered.connect(self.openTrackingPathColorSelectorDialog)

    def actionPathTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawLine(checked)
            if not checked or self.actionIntervalMark.isChecked():
                self.trackingPathGroup.setDrawMarkItem(checked)
            self.updateInputGraphicsView()

    def actionCircleTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawItem(checked)
            self.updateInputGraphicsView()

    def actionIntervalMarkTriggered(self, checked):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setDrawMarkItem(checked)
            self.updateInputGraphicsView()

    def actionShapeTriggered(self, checked):
        if 'shape' in self.line_item_dict.keys():
            line_item = self.line_item_dict['shape']
            if checked:
                line_item.show()
            else:
                line_item.hide()

    def actionSkeletonTriggered(self, checked):
        if 'skeleton' in self.line_item_dict.keys():
            line_item = self.line_item_dict['skeleton']
            if checked:
                line_item.show()
            else:
                line_item.hide()

    def actionArrowTriggered(self, checked):
        if self.movableArrowGroup is not None:
            if checked:
                self.movableArrowGroup.show()
            else:
                self.movableArrowGroup.hide()

    def actionChangeOrderOfNumTriggered(self, checked):
        if len(self.df.keys())!=0 or len(self.line_data_dict.keys())!=0:
            self.videoPlaybackWidget.stop()

            dialog = DataSwapDialog(self)
            dialog.setWindowModality(Qt.WindowModal)
            dialog.setData(self.df, self.line_data_dict)
            dialog.swapAccepted.connect(self.evaluate)

            res = dialog.exec()

    def openTrackingPathColorSelectorDialog(self, activated=False):
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.openColorSelectorDialog(self)

    def openVideoFile(self, activated=False, filePath = None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Video File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False

            self.videoPlaybackWidget.show()
            self.cv_img = self.videoPlaybackWidget.getCurrentFrame()

            self.initialize()

            return True
        else:
            return False

    def openImageFile(self, activated=False, filePath = None):
        if filePath == None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Image File', userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            img = cv2.imread(filePath)
            if img is None:
                return False

            self.cv_img = img
            self.videoPlaybackWidget.hide()
            self.updateInputGraphicsView()

            self.evaluate()

            return True
        else:
            return False

    def openCSVFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open CSV File', userDir, 'CSV files (*.csv)')

        if len(filePath) is not 0:
            df = pd.read_csv(filePath, index_col=0)
            name = df.index.name

            if name is None:
                name = 'position'

            self.df[name] = df
            self.file_name_dict[name] = filePath

            if name is None or name=='position':
                if self.trackingPathGroup is not None:
                    self.inputScene.removeItem(self.trackingPathGroup)

                self.trackingPathGroup = TrackingPathGroup()
                self.trackingPathGroup.setRect(self.inputScene.sceneRect())
                self.inputScene.addItem(self.trackingPathGroup)

                if not self.actionPath.isChecked():
                    self.trackingPathGroup.setDrawLine(False)
                if not self.actionCircle.isChecked():
                    self.trackingPathGroup.setDrawItem(False)
                if not self.actionIntervalMark.isChecked():
                    self.trackingPathGroup.setDrawMarkItem(False)

                self.trackingPathGroup.setDataFrame(self.df['position'])
            elif name=='arrow':
                if self.movableArrowGroup is not None:
                    self.inputScene.removeItem(self.movableArrowGroup)

                self.movableArrowGroup = MovableArrowGroup()
                self.inputScene.addItem(self.movableArrowGroup)
                self.movableArrowGroup.edited.connect(self.arrowEdited)

                if not self.actionArrow.isChecked():
                    self.movableArrowGroup.hide()

            if 'arrow' in self.df.keys() and 'position' in self.df.keys():
                self.movableArrowGroup.setDataFrame(self.df['arrow'], self.df['position'])

            self.initialize()

    def openColorFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Color File', userDir, 'Color files (*.color)')

        if len(filePath) is not 0:
            self.colors = pd.read_csv(filePath, index_col=0).as_matrix().tolist()
            self.colors = [QColor(*rgb) for rgb in self.colors]
            self.setColorsToGraphicsObjects()

    def openJSONFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open JSON File', userDir, 'JSON files (*.json)')

        if len(filePath) is not 0:
            with open(filePath) as f_p:
                data = json.load(f_p)

            name = data['name']
            self.line_data_dict[name] = data
            self.file_name_dict[name] = filePath

            if name in self.line_item_dict.keys():
                self.inputScene.removeItem(self.line_item_dict[name])

            lines = MovableLineGroup()
            lines.setData(data)
            lines.setRect(self.inputScene.sceneRect())

            if name=='shape' and not self.actionShape.isChecked():
                lines.hide()

            if name=='skeleton' and not self.actionSkeleton.isChecked():
                lines.hide()

            self.line_item_dict[name] = lines
            self.inputScene.addItem(lines)

            self.initialize()

    def saveDataFiles(self, activated=False, filePath = None):
        if len(self.df.keys())!=0:
            for k, v in self.df.items():
                f_name, f_ext = os.path.splitext(self.file_name_dict[k])
                candidate_file_path = '{0}-fixed{1}'.format(f_name, f_ext)
                filePath, _ = QFileDialog.getSaveFileName(None, 'Save CSV File', candidate_file_path, "CSV files (*.csv)")

                if len(filePath) is not 0:
                    logger.debug("Saving CSV file: {0}".format(filePath))
                    df = v.copy()
                    col_n = df.as_matrix().shape[1]/2

                    col_names = np.array([('x{0}'.format(i), 'y{0}'.format(i)) for i in range(int(round(col_n)))]).flatten()
                    df.columns = pd.Index(col_names)
                    df.to_csv(filePath)

        for k, v in self.line_data_dict.items():
            f_name, f_ext = os.path.splitext(self.file_name_dict[k])
            candidate_file_path = '{0}-fixed{1}'.format(f_name, f_ext)
            filePath, _ = QFileDialog.getSaveFileName(None, 'Save JSON File', candidate_file_path, "JSON files (*.json)")

            if len(filePath) is not 0:
                logger.debug("Saving JSON file: {0}".format(filePath))
                with open(filePath, 'w') as f_p:
                    json.dump(v, f_p)

    def updateInputGraphicsView(self):
        self.inputScene.removeItem(self.inputPixmapItem)
        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)

        p = QPainter(self.inputPixmap)
        sourceRect = self.inputPixmapRenderScene.sceneRect()
        self.inputPixmapRenderScene.render(p, QRectF(sourceRect), QRectF(sourceRect), QtCore.Qt.IgnoreAspectRatio)

        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        rect = QtCore.QRectF(self.inputPixmap.rect())
        self.inputScene.setSceneRect(rect)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.viewport().update()
        self.graphicsViewResized()

    def eventFilter(self, obj, event):
        if obj is self.inputGraphicsView.viewport() and event.type()==QEvent.Wheel:
            return True

        if event.type() == QEvent.KeyPress:
            if Qt.Key_Home <= event.key() <= Qt.Key_PageDown:
                self.videoPlaybackWidget.playbackSlider.keyPressEvent(event)
                return True

        return False

    def graphicsViewResized(self, event=None):
        self.inputGraphicsView.fitInView(QtCore.QRectF(self.inputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def setColorsToGraphicsObjects(self):
        # FIXME: データセットと色リストのサイズ整合性チェックが必要
        if self.colors is not None:
            if self.trackingPathGroup is not None:
                self.trackingPathGroup.setColors(self.colors)

            for k, v in self.line_item_dict.items():
                v.setColors(self.colors)

    def initialize(self):
        if  not self.videoPlaybackWidget.isOpened():
            return

        if self.trackingPathGroup is not None:
            r = self.trackingPathGroup.autoAdjustRadius(self.cv_img.shape)
            self.radiusSpinBox.setValue(r)
            self.trackingPathGroup.autoAdjustLineWidth(self.cv_img.shape)

            self.trackingPathGroup.setItemsAreMovable(True)

            if self.movableArrowGroup is not None:
                pass

        for k, v in self.line_item_dict.items():
            v.autoAdjustLineWidth(self.cv_img.shape)
            v.autoAdjustMarkSize(self.cv_img.shape)

        self.setColorsToGraphicsObjects()

        self.evaluate()

    def evaluate(self):
        if not self.videoPlaybackWidget.isOpened():
            return

        qimg = misc.cvMatToQImage(self.cv_img)
        pixmapItem = QGraphicsPixmapItem(QPixmap.fromImage(qimg))
        pixmapItem.setOpacity(0.2)

        self.frameBuffer.put(pixmapItem)
        self.frameBufferItemGroup.addToGroup(pixmapItem)
        if self.frameBuffer.qsize() > 10:
            item = self.frameBuffer.get()
            self.frameBufferItemGroup.removeFromGroup(item)

        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setPoints(self.currentFrameNo)

            if self.movableArrowGroup is not None:
                self.movableArrowGroup.setPositions(self.currentFrameNo)

        for k, v in self.line_item_dict.items():
            v.setPolyline(self.currentFrameNo)

    @pyqtSlot(object)
    def arrowEdited(self, name):
        # TODO: 方向の再推定機能の実装
        # quit_msg = "Arrow {} edited.\nRe-estimate the direction in following frames?".format(name)
        # reply = QtWidgets.QMessageBox.question(
        #         self,
        #         'Question',
        #         quit_msg,
        #         QtWidgets.QMessageBox.Yes,
        #         QtWidgets.QMessageBox.No
        #         )
        #
        # if reply == QtWidgets.QMessageBox.Yes:
        #     pass
        # else:
        #     pass
        pass
예제 #32
0
class ExamView(QGraphicsView):
    """Simple extension of QGraphicsView
    - containing an image and click-to-zoom/unzoom
    """
    def __init__(self, fnames):
        QGraphicsView.__init__(self)
        self.initUI(fnames)

    def initUI(self, fnames):
        # set background
        self.setStyleSheet("background: transparent")
        self.setBackgroundBrush(BackGrid())
        self.setRenderHint(QPainter.Antialiasing, True)
        self.setRenderHint(QPainter.SmoothPixmapTransform, True)
        # Make QGraphicsScene
        self.scene = QGraphicsScene()
        # TODO = handle different image sizes.
        self.images = {}
        self.imageGItem = QGraphicsItemGroup()
        self.scene.addItem(self.imageGItem)
        self.updateImage(fnames)

    def updateImage(self, fnames):
        """Update the image with that from filename"""
        for n in self.images:
            self.imageGItem.removeFromGroup(self.images[n])
            self.images[n].setVisible(False)
        if fnames is not None:
            x = 0
            for (n, fn) in enumerate(fnames):
                pix = QPixmap(fn)
                self.images[n] = QGraphicsPixmapItem(pix)
                self.images[n].setTransformationMode(Qt.SmoothTransformation)
                self.images[n].setPos(x, 0)
                self.images[n].setVisible(True)
                sf = float(ScenePixelHeight) / float(pix.height())
                self.images[n].setScale(sf)
                self.scene.addItem(self.images[n])
                # x += self.images[n].boundingRect().width() + 10
                # TODO: why did this have + 10 but the scene did not?
                x += sf * (pix.width() - 1.0)
                # TODO: don't floor here if units of scene are large!
                x = int(x)
                self.imageGItem.addToGroup(self.images[n])

        # Set sensible sizes and put into the view, and fit view to the image.
        br = self.imageGItem.boundingRect()
        self.scene.setSceneRect(
            0,
            0,
            max(1000, br.width()),
            max(1000, br.height()),
        )
        self.setScene(self.scene)
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)

    def mouseReleaseEvent(self, event):
        """Left/right click to zoom in and out"""
        if (event.button() == Qt.RightButton) or (
                QGuiApplication.queryKeyboardModifiers() == Qt.ShiftModifier):
            self.scale(0.8, 0.8)
        else:
            self.scale(1.25, 1.25)
        self.centerOn(event.pos())

    def resetView(self):
        """Reset the view to its reasonable initial state."""
        self.fitInView(self.imageGItem, Qt.KeepAspectRatio)
예제 #33
0
class Ui_MainWindow(QtWidgets.QMainWindow, Ui_MainWindowBase):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.setupUi(self)

        self.videoPlaybackInit()
        self.imgInit()
        self.menuInit()

        self.df = None
        self.trackingPathGroup = None
        self.drawingFlag = False
        self.handInputSystem = None
        self.handInputSystem = HandInputSystem()
        self.handInputSystem.setRect(self.inputScene.sceneRect())
        self.inputScene.addItem(self.handInputSystem)
        self.handInputSystem.addNewDataFrame()
        self.currentFrameNo = 0

        self.colors = []

        self.circleCheckBox.stateChanged.connect(
            self.polyLineCheckBoxStateChanged)
        self.lineCheckBox.stateChanged.connect(
            self.polyLineCheckBoxStateChanged)
        self.overlayCheckBox.stateChanged.connect(
            self.overlayCheckBoxStateChanged)
        self.radiusSpinBox.valueChanged.connect(self.radiusSpinBoxValueChanged)

        self.frameNoSpinBox.valueChanged.connect(
            self.frameNoSpinBoxValueChanged)
        self.groupBox_2.hide()

        self.inputGraphicsView.viewport().setCursor(QtCore.Qt.ArrowCursor)
        #
        self.optionViewButton.pressed.connect(self.optionViewButtonPressed)
        self.zoomedGraphicsView.hide()

        self.dataFrameWidget.dataFrameChanged.connect(self.dataFrameChanged)
        self.dataFrameWidget.hide()
        self.handInputSystem.setColor(self.dataFrameWidget.getColor())

        #self.processDropedFile("/Users/ymnk/temp/Dast/2016/01/hoge.avi")
        #self.processDropedFile("./a.csv")
    def dataFrameChanged(self, addedFrameFlag, editingNo, color):
        if addedFrameFlag:
            self.handInputSystem.addNewDataFrame()
        self.handInputSystem.setEditingNo(editingNo)
        self.handInputSystem.setColor(color)
        print(addedFrameFlag, color, editingNo)

    def optionViewButtonPressed(self):
        if self.groupBox_2.isVisible():
            self.optionViewButton.setText("<")
            self.groupBox_2.hide()
        else:
            self.optionViewButton.setText(">")
            self.groupBox_2.show()

    def overlayCheckBoxStateChanged(self, s):
        if self.overlayCheckBox.isChecked():
            self.frameBufferItemGroup.show()
        else:
            self.frameBufferItemGroup.hide()

        self.updateInputGraphicsView()

    def polyLineCheckBoxStateChanged(self, s):
        overlayFrameNo = self.frameNoSpinBox.value()

        min_value = max(self.currentFrameNo - overlayFrameNo, 0)
        current_pos = self.currentFrameNo - min_value

        if self.handInputSystem is not None:
            self.handInputSystem.setDrawItem(current_pos,
                                             self.circleCheckBox.isChecked())
            self.handInputSystem.setDrawLine(self.lineCheckBox.isChecked())
            self.updateInputGraphicsView()

    def radiusSpinBoxValueChanged(self, value):
        if self.handInputSystem is not None:
            self.handInputSystem.setRadius(self.radiusSpinBox.value())
            self.updateInputGraphicsView()

    def frameNoSpinBoxValueChanged(self, value):
        if self.handInputSystem is not None:
            self.handInputSystem.setOverlayFrameNo(self.frameNoSpinBox.value())
            self.updateInputGraphicsView()

    def dragEnterEvent(self, event):
        event.acceptProposedAction()

    def dropEvent(self, event):
        # event.setDropAction(QtCore.Qt.MoveAction)
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            if len(urls) > 0:
                self.processDropedFile(urls[0].toLocalFile())

        event.acceptProposedAction()

    def processDropedFile(self, filePath):
        root, ext = os.path.splitext(filePath)
        if ext == ".filter":
            # Read Filter
            self.openFilterFile(filePath=filePath)
            return
        elif ext == ".csv":
            self.openCSVFile(filePath=filePath)
        elif self.openImageFile(filePath=filePath):
            return
        elif self.openVideoFile(filePath=filePath):
            return

    def videoPlaybackInit(self):
        self.videoPlaybackWidget.hide()
        self.videoPlaybackWidget.frameChanged.connect(self.setFrame,
                                                      Qt.QueuedConnection)

    def setFrame(self, frame, frameNo):
        if frame is not None:
            self.cv_img = frame
            self.currentFrameNo = frameNo
            self.updateInputGraphicsView()
            if self.videoInitialFlag == True:
                self.graphicsViewResized()
                self.videoInitialFlag = False
            self.evaluate()

    def imgInit(self):
        self.cv_img = cv2.imread(
            os.path.join(sampleDataPath, "color_filter_test.png"))

        self.frameBuffer = Queue()
        self.frameBufferItemGroup = QGraphicsItemGroup()
        self.frameBufferItemGroup.hide()
        self.inputPixmapRenderScene = QGraphicsScene()
        self.inputPixmapRenderScene.addItem(self.frameBufferItemGroup)

        self.inputScene = QGraphicsScene()
        self.inputGraphicsView.setScene(self.inputScene)
        self.inputGraphicsView.resizeEvent = self.graphicsViewResized
        # self.inputScene.addItem(self.frameBufferItemGroup)

        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)
        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.mousePressEvent = self.inputGraphicsViewMousePressEvent
        self.inputGraphicsView.mouseMoveEvent = self.inputGraphicsViewMouseMoveEvent
        self.inputGraphicsView.mouseReleaseEvent = self.inputGraphicsViewMouseReleaseEvent
        self.inputGraphicsView.keyPressEvent = self.inputGraphicsViewKeyPressEvent
        self.inputGraphicsView.keyReleaseEvent = self.inputGraphicsViewKeyReleaseEvent
        self.inputGraphicsView.wheelEvent = self.inputGraphicsViewwheelEvent
        #self.inputGraphicsView.focusInEvent = self.inputGraphicsViewfocusInEvent
        self.inputGraphicsView.viewport().installEventFilter(self)

        self.inputGraphicsView.setMouseTracking(True)
        self.overlayScene = QGraphicsScene()
        self.inputGraphicsView.setOverlayScene(self.overlayScene)

    def inputGraphicsViewfocusInEvent(self, event):
        #
        QGraphicsView.focusInEvent(self.inputGraphicsView, event)

    def inputGraphicsViewMousePressEvent(self, event):
        if event.modifiers() == QtCore.Qt.ShiftModifier:
            # Comment out to permit the view for sending the event to the child scene.
            QGraphicsView.mousePressEvent(self.inputGraphicsView, event)
        else:
            self.drawingFlag = True
            if not self.videoPlaybackWidget.isPlaying():
                self.videoPlaybackWidget.playButtonClicked()

    def inputGraphicsViewMouseMoveEvent(self, event):
        if event.modifiers() == QtCore.Qt.ShiftModifier:
            # Comment out to permit the view for sending the event to the child scene.
            QGraphicsView.mouseMoveEvent(self.inputGraphicsView, event)
        elif self.drawingFlag == True:
            pass
            #self.videoPlaybackWidget.moveNextButtonClicked()
        #self.handInputSystem.inputMouseMoveEvent(mousePosition,self.currentFrameNo)
        #print(self.currentFrameNo)
        #self.positionStack.append(mousePosition)
        #self.handInputSystem.inputMouseMoveEvent(mousePosition)

    def inputGraphicsViewMouseReleaseEvent(self, event):
        if self.drawingFlag == True:
            self.drawingFlag = False
            self.videoPlaybackWidget.playButtonClicked()
        self.handInputSystem.inputMouseReleaseEvent()
        self.handInputSystem.setPoints()
        # Comment out to permit the view for sending the event to the child scene.
        QGraphicsView.mouseReleaseEvent(self.inputGraphicsView, event)
        self.inputGraphicsView.viewport().setCursor(QtCore.Qt.ArrowCursor)

    def inputGraphicsViewKeyPressEvent(self, event):
        mousePosition = QCursor().pos()
        mousePosition = self.inputGraphicsView.mapFromGlobal(mousePosition)
        if event.type() == QtCore.QEvent.KeyPress:
            key = event.key()
            if key == QtCore.Qt.Key_Space:
                self.videoPlaybackWidget.playButtonClicked()
            elif key == QtCore.Qt.Key_A:
                self.videoPlaybackWidget.movePrevButtonClicked()
            elif key == QtCore.Qt.Key_D:
                self.videoPlaybackWidget.moveNextButtonClicked()
            elif key == QtCore.Qt.Key_Down:
                self.inputGraphicsViewScaleDown()
            elif key == QtCore.Qt.Key_Up:
                self.inputGraphicsViewScaleUp()
                pass
            elif key == QtCore.Qt.Key_R:
                self.graphicsViewResized()
            elif key == QtCore.Qt.Key_P:
                pass
                #self.handInputSystem.nextDataFrame()
            elif key == QtCore.Qt.Key_O:
                pass
                #self.handInputSystem.previousDataFrame()
            elif key == QtCore.Qt.Key_J:
                frameNo = self.handInputSystem.getLastInputedFrameIndex()
                self.videoPlaybackWidget.moveToFrame(frameNo)
            elif key == QtCore.Qt.Key_S:
                self.handInputSystem.saveCSV("./a.csv")
        QGraphicsView.keyPressEvent(self.inputGraphicsView, event)

    def inputGraphicsViewKeyReleaseEvent(self, event):

        QGraphicsView.keyReleaseEvent(self.inputGraphicsView, event)

    def inputGraphicsViewwheelEvent(self, event):
        scaleFactor = 1.15
        if event.delta() > 0:
            # Zoom in
            self.inputGraphicsView.scale(scaleFactor, scaleFactor)
        else:
            # Zooming out
            self.inputGraphicsView.scale(1.0 / scaleFactor, 1.0 / scaleFactor)
        QGraphicsView.wheelEvent(self.inputGraphicsView, event)

    def inputGraphicsViewScaleDown(self):
        scaleFactor = 1.15
        self.inputGraphicsView.scale(1.0 / scaleFactor, 1.0 / scaleFactor)

    def inputGraphicsViewScaleUp(self):
        scaleFactor = 1.15
        self.inputGraphicsView.scale(scaleFactor, scaleFactor)

    def menuInit(self):
        self.actionSaveCSVFile.triggered.connect(self.saveCSVFile)
        self.actionOpenCSVFile.triggered.connect(self.openCSVFile)

    def openVideoFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Video File',
                                                      userDir)

        if len(filePath) is not 0:
            self.filePath = filePath

            ret = self.videoPlaybackWidget.openVideo(filePath)
            if ret == False:
                return False
            self.videoInitialFlag = True
            self.videoPlaybackWidget.show()
            self.dataFrameWidget.show()
            # self.evaluate()

            return True
        else:
            return False

    def openImageFile(self, activated=False, filePath=None):
        if filePath == None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open Image File',
                                                      userDir)

        if len(filePath) is not 0:
            self.filePath = filePath
            img = cv2.imread(filePath)
            if img is None:
                return False

            self.cv_img = img
            self.videoPlaybackWidget.hide()
            self.updateInputGraphicsView()

            self.evaluate()

            return True
        else:
            return False

    def openCSVFile(self, activated=False, filePath=None):
        if filePath is None:
            filePath, _ = QFileDialog.getOpenFileName(None, 'Open CSV File',
                                                      userDir,
                                                      'CSV files (*.csv)')

        if len(filePath) is not 0:
            self.df = pd.read_csv(filePath, index_col=0)
            if self.handInputSystem is not None:
                self.inputScene.removeItem(self.handInputSystem)
            self.handInputSystem = HandInputSystem()
            self.handInputSystem.setRect(self.inputScene.sceneRect())
            self.inputScene.addItem(self.handInputSystem)
            self.handInputSystem.setDataFrame(self.df)
            self.handInputSystem.setPoints()

            self.dataFrameWidget.clear()
            self.dataFrameWidget.dataFrameNo = self.handInputSystem.dataFrameNo
            self.dataFrameWidget.editingNo = 0
            for item in range(self.handInputSystem.dataFrameNo + 1):
                color = self.handInputSystem.itemList[item].getColor()
                print(item, color)
                self.dataFrameWidget.colorList.append(color)
            self.dataFrameWidget.setUniqueIDLabel()

            self.evaluate()

    def saveCSVFile(self, activated=False, filePath=None):
        #if self.df is not None:
        if self.handInputSystem.isDataFrame():
            filePath, _ = QFileDialog.getSaveFileName(None, 'Save CSV File',
                                                      userDir,
                                                      "CSV files (*.csv)")

            if len(filePath) is not 0:
                logger.debug("Saving CSV file: {0}".format(filePath))
                self.handInputSystem.saveCSV(filePath)

    def updateInputGraphicsView(self):
        # print("update")
        # self.inputScene.clear()
        self.inputScene.removeItem(self.inputPixmapItem)
        qimg = misc.cvMatToQImage(self.cv_img)
        self.inputPixmap = QPixmap.fromImage(qimg)

        p = QPainter(self.inputPixmap)
        sourceRect = self.inputPixmapRenderScene.sceneRect()
        self.inputPixmapRenderScene.render(p, QRectF(sourceRect),
                                           QRectF(sourceRect),
                                           QtCore.Qt.IgnoreAspectRatio)

        self.inputPixmapItem = QGraphicsPixmapItem(self.inputPixmap)
        rect = QtCore.QRectF(self.inputPixmap.rect())
        self.inputScene.setSceneRect(rect)
        self.inputScene.addItem(self.inputPixmapItem)

        self.inputGraphicsView.viewport().update()
        # self.graphicsViewResized()

    def eventFilter(self, obj, event):
        if obj is self.inputGraphicsView.viewport() and event.type(
        ) == QEvent.Wheel:
            return True
        else:
            return False

    def graphicsViewResized(self, event=None):
        # print("resize")
        # print(self.inputScene)
        self.inputGraphicsView.fitInView(
            QtCore.QRectF(self.inputPixmap.rect()), QtCore.Qt.KeepAspectRatio)

    def evaluate(self):
        if not self.videoPlaybackWidget.isOpened():
            return

        qimg = misc.cvMatToQImage(self.cv_img)
        pixmapItem = QGraphicsPixmapItem(QPixmap.fromImage(qimg))
        pixmapItem.setOpacity(0.2)

        self.frameBuffer.put(pixmapItem)
        self.frameBufferItemGroup.addToGroup(pixmapItem)
        if self.frameBuffer.qsize() > 10:
            item = self.frameBuffer.get()
            self.frameBufferItemGroup.removeFromGroup(item)
        """
        if self.trackingPathGroup is not None:
            self.trackingPathGroup.setPoints(self.currentFrameNo)
        """

        if self.handInputSystem is not None:
            self.handInputSystem.setPoints(self.currentFrameNo)
            if self.drawingFlag is True:
                mousePosition = QCursor().pos()
                mousePosition = self.inputGraphicsView.mapFromGlobal(
                    mousePosition)
                mousePosition = self.inputGraphicsView.mapToScene(
                    mousePosition)
                pos = [mousePosition.x(), mousePosition.y()]
                self.handInputSystem.appendPosition(pos, self.currentFrameNo)
예제 #34
0
파일: mapdata.py 프로젝트: Virtual-/nparse
    def _load(self):
        # Get list of all map files for current zone
        map_file_name = MapData.get_zone_dict()[self.zone.strip().lower()]
        extensions = ['.txt', '_1.txt', '_2.txt', '_3.txt', '_4.txt', '_5.txt']
        maps = [
            os.path.join(MAP_FILES_LOCATION, m)
            for m in [(map_file_name + e) for e in extensions]
            if os.path.exists(os.path.join(MAP_FILES_LOCATION, m))
        ]

        all_x, all_y, all_z = [], [], []

        # TODO: Remove the references to raw
        # Create Lines and Points
        for map_file in maps:
            with open(map_file, 'r') as f:
                for line in f.readlines():
                    line_type = line.lower()[0:1]
                    data = [value.strip() for value in line[1:].split(',')]
                    if line_type == 'l':  # line
                        x1, y1, z1, x2, y2, z2 = list(map(float, data[0:6]))
                        self.raw['lines'].append(
                            MapLine(x1=x1,
                                    y1=y1,
                                    z1=z1,
                                    x2=x2,
                                    y2=y2,
                                    z2=z2,
                                    color=self.color_transform(
                                        QColor(int(data[6]), int(data[7]),
                                               int(data[8])))))
                        all_x.extend((x1, x2))
                        all_y.extend((y1, y2))
                        all_z.append(min(z1, z2))
                        # if abs(z1 - z2) < 2:
                        # if z1 == z2:
                        # all_z.extend((z1, z2))

                    elif line_type == 'p':  # point
                        x, y, z = map(float, data[0:3])
                        self.raw['poi'].append(
                            MapPoint(x=x,
                                     y=y,
                                     z=z,
                                     size=int(data[6]),
                                     text=str(data[7]),
                                     color=self.color_transform(
                                         QColor(int(data[3]), int(data[4]),
                                                int(data[5])))))

        # Create Grid Lines
        lowest_x, highest_x, lowest_y, highest_y, lowest_z, highest_z = min(
            all_x), max(all_x), min(all_y), max(all_y), min(all_z), max(all_z)

        left, right = int(math.floor(lowest_x / 1000) * 1000), int(
            math.ceil(highest_x / 1000) * 1000)
        top, bottom = int(math.floor(lowest_y / 1000) * 1000), int(
            math.ceil(highest_y / 1000) * 1000)

        for number in range(left, right + 1000, 1000):
            self.raw['grid'].append(
                MapLine(x1=number,
                        x2=number,
                        y1=top,
                        y2=bottom,
                        z1=0,
                        z2=0,
                        color=QColor(255, 255, 255, 25)))

        for number in range(top, bottom + 1000, 1000):
            self.raw['grid'].append(
                MapLine(y1=number,
                        y2=number,
                        x1=left,
                        x2=right,
                        z1=0,
                        z2=0,
                        color=QColor(255, 255, 255, 25)))

        self.grid = QGraphicsPathItem()
        line_path = QPainterPath()
        for line in self.raw['grid']:
            line_path.moveTo(line.x1, line.y1)
            line_path.lineTo(line.x2, line.y2)
        self.grid.setPath(line_path)
        self.grid.setPen(
            QPen(line.color, config.data['maps']['grid_line_width']))
        self.grid.setZValue(0)

        # Get z levels
        counter = Counter(all_z)

        # bunch together zgroups based on peaks with floor being low point before rise
        z_groups = []
        last_value = None
        first_run = True
        for z in sorted(counter.items(), key=lambda x: x[0]):
            if last_value is None:
                last_value = z
                continue
            if (abs(last_value[0] - z[0]) < 20) or z[1] < 8:
                last_value = (last_value[0], last_value[1] + z[1])
            else:
                if first_run:
                    first_run = False
                    if last_value[1] < 40 or abs(last_value[0] - z[0]) < 18:
                        last_value = z
                        continue
                z_groups.append(last_value[0])
                last_value = z

        # get last iteration
        if last_value[1] > 50:
            z_groups.append(last_value[0])

        self._z_groups = z_groups

        # Create QGraphicsPathItem for lines seperately to retain colors
        temp_dict = {}
        for l in self.raw['lines']:
            lz = min(l.z1, l.z2)
            lz = self.get_closest_z_group(lz)
            if not temp_dict.get(lz, None):
                temp_dict[lz] = {'paths': {}}
            lc = l.color.getRgb()
            if not temp_dict[lz]['paths'].get(lc, None):
                path_item = QGraphicsPathItem()
                path_item.setPen(
                    QPen(l.color, config.data['maps']['line_width']))
                temp_dict[lz]['paths'][lc] = path_item
            path = temp_dict[lz]['paths'][lc].path()
            path.moveTo(l.x1, l.y1)
            path.lineTo(l.x2, l.y2)
            temp_dict[lz]['paths'][lc].setPath(path)

        # Group QGraphicsPathItems into QGraphicsItemGroups and update self
        for z in temp_dict.keys():
            item_group = QGraphicsItemGroup()
            for (_, path) in temp_dict[z]['paths'].items():
                item_group.addToGroup(path)
            self[z] = {'paths': None, 'poi': []}
            self[z]['paths'] = item_group

        # Create Points of Interest
        for p in self.raw['poi']:
            z = self.get_closest_z_group(p.z)
            self[z]['poi'].append(PointOfInterest(location=p))

        self.geometry = MapGeometry(
            lowest_x=lowest_x,
            highest_x=highest_x,
            lowest_y=lowest_y,
            highest_y=highest_y,
            lowest_z=lowest_z,
            highest_z=highest_z,
            center_x=int(highest_x - (highest_x - lowest_x) / 2),
            center_y=int(highest_y - (highest_y - lowest_y) / 2),
            width=int(highest_x - lowest_x),
            height=int(highest_y - lowest_y),
            z_groups=z_groups)
예제 #35
0
class InitMap():
    def __init__(self, parent):
        super().__init__()

        self.canvas = parent
        self.scene = parent.scene

        self.tagZ = 0
        self.pathTagZ = 0  ## only by paths

        self.mapSet = False
        self.tagSet = False
        self.pathSet = False

        self.mapRect = QRectF()
        self.selections = []

        self.pathGroup = None
        self.tagGroup = None
        self.pathTagGroup = None
        self.paths = []

### --------------------------------------------------------

    def addSelectionsFromCanvas(self):
        if not self.selections:
            self.mapSelections()
        if len(self.selections) > 0:
            self.addMapItem()

    def mapSelections(self):
        self.selections = []
        rect = QRect(self.canvas.rubberBand.geometry())
        for pix in self.scene.items():
            if pix.type == 'pix':
                p = pix.sceneBoundingRect()
                x = int(p.x() + p.width() / 2)
                y = int(p.y() + p.height() / 2)
                if rect.contains(x, y):
                    pix.setSelected(True)
                    self.selections.append(pix.id)
            elif pix.zValue() <= common["pathZ"]:
                break

    def addMapItem(self):
        self.removeMapItem()
        self.mapSet = True
        self.mapRect = self.mapBoundingRects()
        self.canvas.rubberBand.setGeometry(
            QRect(self.canvas.origin, QSize(0, 0)))
        self.map = MapItem(self.mapRect, self)
        self.map.setZValue(self.toFront(50))  ## higher up than tags
        self.scene.addItem(self.map)

    def updateMap(self):
        self.updatePixItemPos()
        self.addMapItem()

    def removeMap(self):
        self.updatePixItemPos()
        self.clearMap()

    def clearMap(self):
        if self.mapSet:
            self.removeMapItem()
            self.mapRect = QRectF()
            self.selections = []
            self.mapSet = False

    def removeMapItem(self):
        for pix in self.scene.items():
            if pix.type == 'map':
                self.scene.removeItem(pix)
                break

    def mapBoundingRects(self):
        tx, ty = common["ViewW"], common["ViewH"]
        bx, by = 0, 0
        for pix in self.scene.items():
            if pix.type == 'pix' and pix.id in self.selections:
                p = pix.sceneBoundingRect()
                x, y, w, h = p.x(), p.y(), p.width(), p.height()
                if x < tx:  ## setting top left
                    tx = x
                if y < ty:
                    ty = y
                if x + w > bx:  ## setting bottom right
                    bx = x + w
                if y + h > by:
                    by = y + h
            elif pix.zValue() <= common["pathZ"]:
                break
        return QRectF(tx, ty, bx - tx, by - ty)
        selections = []

    def updatePixItemPos(self):
        for pix in self.scene.items():
            if pix.type == 'pix':
                p = pix.pos()
                pix.x = p.x()
                pix.y = p.y()
            elif pix.zValue() <= common["pathZ"]:
                break

    def toggleMap(self):
        if self.mapSet == False:
            self.selections = []
            for pix in self.scene.selectedItems():
                self.selections.append(pix.id)
            if self.selections or self.canvas.hasHiddenPix():
                self.addMapItem()
        else:
            self.removeMap()

### --------------------------------------------------------

    def toggleTagItems(self, pid=All):
        if self.canvas.pathMakerOn:
            return
        if self.tagSet:
            self.clearTagGroup()
            self.clearPaths()
            return
        if self.scene.items():
            if self.pathSet:
                QTimer.singleShot(200, self.clearPaths)
            self.addTagGroup()
            k = 0
            self.tagSet = False
            for pix in self.scene.items():
                if pix.type == 'pix':
                    k += 1
                    if pid == All:
                        self.tagIt(pix)
                    elif pid == pix.id:  ## single tag
                        self.tagIt(pix)
                        break
                elif pix.zValue() <= common["pathZ"]:
                    break
            if k > 0:
                self.tagSet = True
            else:
                self.clearTagGroup()

    def addTagGroup(self):
        self.tagZ = self.toFront(20.0)  ## otherwise it can be hidden
        self.tagGroup = QGraphicsItemGroup()
        self.tagGroup.setZValue(self.tagZ)
        self.scene.addItem(self.tagGroup)

    def clearTagGroup(self):
        if self.tagSet:
            self.scene.removeItem(self.tagGroup)
            self.tagSet = False

    def tagIt(self, pix):
        p = pix.sceneBoundingRect()
        x = p.x() + p.width() * .45
        y = p.y() + p.height() * .45
        if 'frame' in pix.fileName:
            x, y = common["ViewW"] * .47, common["ViewH"] - 35
            pix.tag = ""
        tag = TagIt(self.canvas.control, pix.tag, '', pix.zValue())
        tag.setPos(x, y)
        tag.setZValue(self.tagZ)
        self.tagGroup.addToGroup(tag)
        self.tagSet = True

### --------------------------------------------------------

    def togglePaths(self):
        if self.canvas.pathMakerOn:
            return
        if self.pathSet:
            self.clearPaths()
            return
        if self.scene.items():
            k = 0
            self.pathSet = False  ## force clearPaths if fails
            QTimer.singleShot(200, self.clearTagGroup)  ## the other tags
            self.addPathGroup()
            self.addPathTagGroup()
            for pix in self.scene.items():
                if pix.type == 'pix':
                    if pix.tag.endswith('.path'):
                        k += self.displayPath(pix)
                    elif pix.anime and pix.anime.state() == 2:  ## running
                        pix.anime.pause()
                elif pix.zValue() <= common["pathZ"]:
                    break
            if k > 0:
                self.pathSet = True
            else:
                self.clearPaths()

    def addPathGroup(self):
        self.pathGroup = QGraphicsItemGroup()
        self.pathGroup.setZValue(common["pathZ"])
        self.scene.addItem(self.pathGroup)

    def addPathTagGroup(self):
        ## add pathTags group to keep tags separate and visible
        self.pathTagZ = self.toFront(25.0)  ## otherwise it can be hidden
        self.pathTagGroup = QGraphicsItemGroup()
        self.pathTagGroup.setZValue(self.pathTagZ)
        self.scene.addItem(self.pathTagGroup)

    def clearPaths(self):
        if self.pathSet:
            if self.pathGroup:
                self.scene.removeItem(self.pathGroup)
            if self.pathTagGroup:
                self.scene.removeItem(self.pathTagGroup)
            for pix in self.scene.items():
                if pix.type == 'pix' and not pix.tag.endswith('.path'):
                    if pix.anime and pix.anime.state() == 1:  ## paused
                        if self.canvas.control != 'resume':
                            pix.anime.resume()
                elif pix.zValue() <= common["pathZ"]:
                    break
        self.pathSet = False
        self.paths = []

    def displayPath(self, pix):
        tag = pix.tag
        if 'Random' in tag: tag = tag[7:]
        ## don't add duplicates - causes performance issues
        if not tag in self.paths:
            self.paths.append(tag)
            self.addPainterPath(tag)
            return 1
        else:
            return 0

    def addPainterPath(self, tag):
        color = getColorStr()
        path = sidePath.pathLoader(tag)  ## return painter path
        pathPt = path.pointAtPercent(0.0)  ## so its consistent
        ## use painter path
        pathItem = QGraphicsPathItem(path)
        pathItem.setPen(QPen(QColor(color), 3, Qt.DashDotLine))
        pathItem.setFlag(QGraphicsPathItem.ItemIsMovable, False)
        self.pathGroup.addToGroup(pathItem)
        self.addTag(tag, color, pathPt)

    def addTag(self, tag, color, pt):  ## use same offsets and color as path
        tag = TagIt('', tag, color)
        tag.setPos(pt)
        tag.setZValue(self.pathTagZ)  ## use pathTagZ instead of tagZ
        self.pathTagGroup.addToGroup(tag)

    def lastZval(self, str):  ## finds the lowest pix or bkg zValue
        last = 100000.0
        for itm in self.scene.items():
            if itm.type == str and itm.zValue() < last:
                last = itm.zValue()
        return last

    def toFront(self, inc):  ## finds the highest pixitem zValue
        first = 0  ## returns it plus the increment
        for pix in self.scene.items():
            if pix.type == 'pix':
                first = pix.zValue()
                break
            elif pix.zValue() <= common["pathZ"]:
                break
        return inc + first

    def setOriginPt(self, pix):
        self.updateWidthHeight(pix)
        op = QPointF(pix.width / 2, pix.height / 2)
        pix.setTransformOriginPoint(op)

    def updateWidthHeight(self, pix):
        brt = pix.boundingRect()
        pix.width = brt.width()
        pix.height = brt.height()
예제 #36
0
파일: aman.py 프로젝트: andubadea/bluesky
class AMANDisplay(QGraphicsView):
    def __init__(self):
        super().__init__()
        self.setGeometry(0, 0, 500, 600)
        self.setStyleSheet('background-color:#233370')
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene(0, 0, 500, 600)

        # Timeline boundaries
        pen = QPen(QColor('white'))
        brush = QBrush(QColor('#233370'))
        self.scene.addLine(220, 0, 220, 600, pen)
        self.scene.addLine(280, 0, 280, 600, pen)
        self.scene.addLine(0, 30, 500, 30, pen)

        timelinebox = self.scene.addRect(220, 30, 60, 540, pen, brush)
        timelinebox.setFlag(timelinebox.ItemClipsChildrenToShape, True)

        # Timeline scale
        self.timeline  = QGraphicsItemGroup()
        self.timeline.setParentItem(timelinebox)
        self.timeticks = []
        for i in range(40):
            y = 15 * i
            w = 6
            if i % 5 == 0:
                w = 10
                self.timeticks.append(self.scene.addText('%02d' % (40 - i), QFont('Courier', 10)))
                self.timeticks[-1].setPos(240, y - 10)
                self.timeticks[-1].setDefaultTextColor(QColor('white'))
                self.timeline.addToGroup(self.timeticks[-1])
            self.timeline.addToGroup(self.scene.addLine(220, y, 220 + w, y, pen))
            self.timeline.addToGroup(self.scene.addLine(280 - w, y, 280, y, pen))

        self.lrwy = self.scene.addText('18R', QFont('Arial', 20, 50))
        self.lrwy.setPos(1, 1)
        self.lrwy.setDefaultTextColor(QColor('white'))
        # Finalize
        self.setScene(self.scene)
        self.show()

    def update(self, simt, data):
        # data has: ids, iafs, eats, etas, delays, rwys, spdratios

        # First delete old labels
        for key, in self.aircraft.keys:
            if key not in data.ids:
                # del label
                del self.aircraft[key]

        for i in len(data.ids):
            if data.ids[i] not in self.aircraft:
                # self.aircraft[data.ids[i]] = QLabel()
                pass

            # Generate the new label text and position
            newtext = '<font color=Red>bla</font>'  # veranderen
            lbl = self.aircraft[data.ids[i]]
            lbl.setText(newtext)
            lbl.move(posx, posy)  # move in pixels
예제 #37
0
class Imageobj(QGraphicsView):
    leftMouseButtonPressed = pyqtSignal(float, float)
    rightMouseButtonPressed = pyqtSignal(float, float)
    leftMouseButtonReleased = pyqtSignal(float, float)
    rightMouseButtonReleased = pyqtSignal(float, float)
    leftMouseButtonDoubleClicked = pyqtSignal(float, float)
    rightMouseButtonDoubleClicked = pyqtSignal(float, float)

    def __init__(self):
        QGraphicsView.__init__(self)

        # Image is displayed as a QPixmap in a QGraphicsScene attached to this QGraphicsView.
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self.rectgroup = QGraphicsItemGroup()
        self.linegroup = QGraphicsItemGroup()
        self._pixmapHandle = None
        self.canZoom = True
        self.canPan = True
        self.zoomStack = []
        self.aspectRatioMode = Qt.KeepAspectRatio
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.begin = QPoint()
        self.end = QPoint()
        self.helper_bool = False
        self.helper_bool2 = False

        self.rect = QGraphicsRectItem()
        self.line = QGraphicsLineItem()

    def hasImage(self):
        """ Returns whether or not the scene contains an image pixmap.
        """
        return self._pixmapHandle is not None

    def pixmap(self):
        """ Returns the scene's current image pixmap as a QPixmap, or else None if no image exists.
        :rtype: QPixmap | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap()
        return None

    def image(self):
        """ Returns the scene's current image pixmap as a QImage, or else None if no image exists.
        :rtype: QImage | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap().toImage()
        return None

    def setImage(self, image):
        """ Set the scene's current image pixmap to the input QImage or QPixmap.
        Raises a RuntimeError if the input image has type other than QImage or QPixmap.
        :type image: QImage | QPixmap
        """
        if type(image) is QPixmap:
            pixmap = image
        elif type(image) is QImage:
            pixmap = QPixmap.fromImage(image)
        else:
            raise RuntimeError(
                "ImageViewer.setImage: Argument must be a QImage or QPixmap.")
        if self.hasImage():
            self._pixmapHandle.setPixmap(pixmap)
        else:
            self._pixmapHandle = self.scene.addPixmap(pixmap)
        self.setSceneRect(QRectF(
            pixmap.rect()))  # Set scene size to image size.
        self.updateViewer()

    def loadImageFromFile(self, fileName=""):
        """ Load an image from file.
        Without any arguments, loadImageFromFile() will popup a file dialog to choose the image file.
        With a fileName argument, loadImageFromFile(fileName) will attempt to load the specified image file directly.
        """
        fileDir = os.path.dirname(os.path.realpath('__file__'))
        results_dir = os.path.join(fileDir,
                                   'results\\200_frames_of_bloodflow_results')
        if len(fileName) == 0:
            if QT_VERSION_STR[0] == '4':
                fileName = QFileDialog.getOpenFileName(self,
                                                       "Open image file.")
            elif QT_VERSION_STR[0] == '5':
                fileName, dummy = QFileDialog.getOpenFileName(
                    self, "Open image file.")
        if len(fileName) and os.path.isfile(fileName):
            imageName, file_data = self.create_image(fileName, results_dir)
            image = QImage(imageName)
            self.setImage(image)
        print(fileName)

    def Extract_image_and_metadata(self, file_data):
        global file_metadata

        im2show_path = file_data["im2show_path"]
        metadata_path = file_data["metadata_path"]
        # fileName = file_data["fileName"]
        filepath = file_data["path"]
        if os.path.isfile(metadata_path):
            with open(metadata_path, 'r') as fp:
                file_metadata = json.load(fp)
        else:
            with tifffile.TiffFile(filepath) as tif:
                file_metadata = tif.scanimage_metadata
                with open(metadata_path, 'w') as fp:
                    json.dump(file_metadata, fp)

        if not os.path.isfile(im2show_path):
            tif_original = tifffile.imread(filepath)
            # first_five = tif_full_original[1:10:2]#selecting 5 image from tif, only vessels
            tif_original_size = tif_original.shape
            if len(tif_original_size) == 2:
                tif = tif_original.copy()
                arr = tif
            else:
                first_five = tif_original[1:10:2].copy()
                if file_metadata["SI.hScan2D.bidirectional"]:
                    num_im, w, h = first_five.shape
                    tif = np.zeros((num_im, int(h / 2), w))
                for i in range(num_im):
                    tif[i] = first_five[i][::2]
                else:
                    tif = tif_original.copy()
                arr = tif[0]
            tif_size = tif.shape
            print(tif_size)
            # image5 = (tif[0]/5)+(tif[1]/5)+(tif[2]/5)+(tif[3]/5)+(tif[4]/5)
            # arr_avg=np.array(np.round(image5),dtype=np.int16) #round the pixels values
            # arr = tif[0]
            im2show = Image.fromarray(arr)
            try:
                im2show.save(im2show_path)
            except OSError:
                im2show = im2show.convert(mode='I')
                im2show.save(im2show_path)

        return file_metadata

    def updateViewer(self):
        """ Show current zoom (if showing entire image, apply current aspect ratio mode).
        """
        if not self.hasImage():
            return
        if len(self.zoomStack) and self.sceneRect().contains(
                self.zoomStack[-1]):
            self.fitInView(self.zoomStack[-1], Qt.IgnoreAspectRatio
                           )  # Show zoomed rect (ignore aspect ratio).
        else:
            self.zoomStack = [
            ]  # Clear the zoom stack (in case we got here because of an invalid zoom).
            self.fitInView(
                self.sceneRect(), self.aspectRatioMode
            )  # Show entire image (use current aspect ratio mode).

    def resizeEvent(self, event):
        """ Maintain current zoom on resize.
        """
        self.updateViewer()

    def mousePressEvent(self, event):
        """ Start mouse pan or zoom mode.
        """

        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:
            if self.canPan and self.helper_bool:
                self.setDragMode(QGraphicsView.RubberBandDrag)
            elif self.canPan and self.helper_bool2:
                self.setDragMode(QGraphicsView.ScrollHandDrag)
                self.start = scenePos
                #QGraphicsView.mouseMoveEvent(self,event)
                #self.setMouseTracking(True)
            self.leftMouseButtonPressed.emit(scenePos.x(), scenePos.y())
        # self.cursorStartPosition = self.leftMouseButtonPressed.emit(scenePos.x(), scenePos.y())
        # self.start = QPoint(self.cursorStartPosition.x(),self.cursorStartPosition.y())
        elif event.button() == Qt.RightButton:
            if self.canZoom:
                self.setDragMode(QGraphicsView.RubberBandDrag)
            self.rightMouseButtonPressed.emit(scenePos.x(), scenePos.y())
        QGraphicsView.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):
        """ Stop mouse pan or zoom mode (apply zoom if valid).
        """

        QGraphicsView.mouseReleaseEvent(self, event)
        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:
            if self.helper_bool:
                viewBBox = self.zoomStack[-1] if len(
                    self.zoomStack) else self.sceneRect()
                selectionBBox = self.scene.selectionArea().boundingRect(
                ).intersected(viewBBox)
                if selectionBBox.isValid():

                    self.rect.setRect(selectionBBox)
                    self.rect.setPen(QPen(Qt.white))
                    self.scene.addItem(self.rect)

            elif self.helper_bool2:
                viewBBox = self.zoomStack[-1] if len(
                    self.zoomStack) else self.sceneRect()
                self.cursorCurrentPosition = scenePos
                self.current = QPointF(self.cursorCurrentPosition.x(),
                                       self.cursorCurrentPosition.y())
                pen = QPen(Qt.red, 1, Qt.SolidLine)

                self.line.setLine(QLineF(self.start, self.current))
                self.line.setPen(pen)
                self.scene.addItem(self.line)

            self.setDragMode(QGraphicsView.NoDrag)
            self.leftMouseButtonReleased.emit(scenePos.x(), scenePos.y())

        elif event.button() == Qt.RightButton:
            if self.canZoom:
                viewBBox = self.zoomStack[-1] if len(
                    self.zoomStack) else self.sceneRect()
                selectionBBox = self.scene.selectionArea().boundingRect(
                ).intersected(viewBBox)
                self.scene.setSelectionArea(
                    QPainterPath())  # Clear current selection area.
                if selectionBBox.isValid() and (selectionBBox != viewBBox):
                    self.zoomStack.append(selectionBBox)
                    self.updateViewer()
            self.setDragMode(QGraphicsView.NoDrag)
            self.rightMouseButtonReleased.emit(scenePos.x(), scenePos.y())
        # self.scene.addItem(self.group)
        self.updateViewer()

    def mouseDoubleClickEvent(self, event):
        """ Show entire image.
        """

        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:

            self.leftMouseButtonDoubleClicked.emit(scenePos.x(), scenePos.y())
        elif event.button() == Qt.RightButton:
            if self.canZoom:
                self.zoomStack = []  # Clear zoom stack.
                self.updateViewer()
            self.rightMouseButtonDoubleClicked.emit(scenePos.x(), scenePos.y())
        QGraphicsView.mouseDoubleClickEvent(self, event)

    def approve_obj(self):
        self.scene.removeItem(self.rect)
        self.scene.removeItem(self.line)

        viewBBox = self.zoomStack[-1] if len(
            self.zoomStack) else self.sceneRect()
        selectionBBox = self.scene.selectionArea().boundingRect().intersected(
            viewBBox)
        rect = QGraphicsRectItem()
        rect.setRect(selectionBBox)
        rect.setPen(QPen(Qt.green))
        self.rectgroup.addToGroup(rect)
        self.scene.addItem(self.rectgroup)

        line = QGraphicsLineItem()
        line.setLine(QLineF(self.start, self.current))
        line.setPen(QPen(Qt.green))
        self.linegroup.addToGroup(line)
        self.scene.addItem(self.linegroup)

        return (selectionBBox, self.start, self.current)

    def create_fromDB(self, pos_list=[], obj_type=""):
        if obj_type == "rois":
            num_rois = len(pos_list)
            for i in range(num_rois):
                points = pos_list[i]
                rect = QGraphicsRectItem()
                rect.setPen(QPen(Qt.green))
                rect.setRect(points[0], points[1], points[2], points[3])
                self.rectgroup.addToGroup(rect)
            self.scene.addItem(self.rectgroup)
        elif obj_type == "vector":
            num_vec = len(pos_list)
            for i in range(num_vec):
                points = pos_list[i]
                vec = QGraphicsLineItem()
                vec.setPen(QPen(Qt.green))
                vec.setLine(points[0][0], points[0][1], points[1][0],
                            points[1][1])
                self.linegroup.addToGroup(vec)
            self.scene.addItem(self.linegroup)

    def mark_item(self, item_num):
        rect_items = self.rectgroup.childItems()
        line_items = self.linegroup.childItems()
        rect_item = rect_items[item_num]
        line_item = line_items[item_num]
        rect_item.setPen(QPen(Qt.red))
        line_item.setPen(QPen(Qt.red))
        rect_items.remove(rect_item)
        line_items.remove(line_item)
        for i in rect_items:
            i.setPen(QPen(Qt.green))
        for i in line_items:
            i.setPen(QPen(Qt.green))

    def delete_roi(self, num):
        self.scene.removeItem(self.rectgroup)
        self.scene.removeItem(self.linegroup)
        rect_item = self.rectgroup.childItems()[num]
        line_item = self.linegroup.childItems()[num]
        self.rectgroup.removeFromGroup(rect_item)
        self.linegroup.removeFromGroup(line_item)
        self.scene.addItem(self.rectgroup)
        self.scene.addItem(self.linegroup)

    def restart_obj(self):
        self.scene.removeItem(self.rectgroup)
        self.scene.removeItem(self.linegroup)
        rect_items = self.rectgroup.childItems()
        line_items = self.linegroup.childItems()
        for rect_item in rect_items:
            self.rectgroup.removeFromGroup(rect_item)
        for line_item in line_items:
            self.linegroup.removeFromGroup(line_item)