def handleDrawing(self, pos): if self.current and self.current.reachMaxPoints() is False: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() if minX == maxX: maxX = maxX + 1 if minY == maxY: maxY = maxY + 1 self.current.addPoint(QPointF( maxX, minY)) # Adding canvas points is done here self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def handleDrawing(self, pos): if self.current and self.current.reachMaxPoints() is False: if self.fourpoint: targetPos = self.line[self.pointnum] self.current.addPoint(targetPos) print('current points in handleDrawing is ', self.line[self.pointnum]) self.update() if self.pointnum == 3: self.finalise() else: initPos = self.current[0] print('initPos', self.current[0]) minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise() elif not self.outOfPixmap(pos): print('release') self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def mousePressEvent(self, ev): if PYQT5: pos = self.transformPos(ev.pos()) else: pos = self.transformPos(ev.posF()) if ev.button() == QtCore.Qt.LeftButton: if self.drawing(): if self.current: try: self.current.addPoint(self.line[1]) except Exception as e: print(e, file=sys.stderr) return self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update() else: self.selectShapePoint(pos) self.prevPoint = pos self.repaint() elif ev.button() == QtCore.Qt.RightButton and self.editing(): self.selectShapePoint(pos) self.prevPoint = pos self.repaint()
def handleDrawing(self, pos): """ Handles the drawing of a box. :param pos: The position of the box. """ if self.current and self.current.reachMaxPoints() is False: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.current.addPoint(initPos) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalize() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def handleDrawing(self, pos): # if self.current and self.current.reachMaxPoints() is False: # initPos = self.current[0] # # minX = initPos.x() # # minY = initPos.y() # # targetPos = self.line[1] # # maxX = targetPos.x() # # maxY = targetPos.y() # # maxX = pos.x() # # maxY = pos.y() # # self.current.addPoint(QPointF(maxX, minY)) # # self.current.addPoint(QPointF(minX, maxY)) # # print(minX,maxX,minY,maxY) # if(self.closeEnough(pos, initPos)): # self.finalise() # else: # print(self.current) # self.current.addPoint(pos) if self.current and self.current.reachMaxPoints() is False: self.current.addPoint(pos) if self.current.isLastPoint(): self.minimumBoundingRectangle() self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT # 默认为EDIT模式 self.shapes = [] # 用于存储当前图像上的bbox,内容为current(libs.shape.py中Shape()类型的数据结构) self.current = None # 用于存储当前绘制的bbox的四个角的坐标的数据 self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.drawingLineColor = QColor(0, 0, 255) self.drawingRectColor = QColor(0, 0, 255) self.line = Shape(line_color=self.drawingLineColor) self.prevPoint = QPointF() # 这个是存储上一次的按键位置吗 self.offsets = QPointF(), QPointF() self.scale = 1.0 # 图像缩放的比例 self.pixmap = QPixmap() # 显示图像的控件 self.visible = {} # TODO 这是啥 self._hideBackround = False # TODO 这两个是啥? self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # 鼠标指针形状,默认就是正常的指针 # Menus: self.menus = (QMenu(), QMenu()) # 不知道这是啥 # Set widget options. self.setMouseTracking(True) # 鼠标追踪,要想实现mouseMoveEvent,则需要开启鼠标追踪 self.setFocusPolicy(Qt.WheelFocus) # 与焦点设置有关,tab+鼠标滚轮选择焦点 self.verified = False # TODO 这个是啥 self.drawSquare = False # TODO 盲猜点Create RectBox设为True,画完BBox后变为False #initialisation for panning self.pan_initial_pos = QPoint() # QPoint代表一个坐标点
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None self.selectedShapes = [] # save the selected shape here self.lineColor = QColor(255, 0, 0) self.line = Shape() self.lineWidth = 1 self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.pixmap = QPixmap() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Menus: self.menu = QMenu() # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) self.verified = False self.currentLabel = "" self.currentDType = self.POLYGON self.undoStack = QUndoStack(self) self.image_editing_status = self.LABEL self.eraser_strength = 5 self.image_np = None self.erasing_points = []
def handleDrawing(self, pos): if self.current: #and self.current.reachMaxPoints() is False: if self.ploygon(): self.current.addPoint(self.line[1]) else: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.current.addPoint(initPos) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT self.shapes = [] self.current = None self.selected_shape = None # save the selected shape here self.selected_shape_copy = None self.drawing_line_color = QColor(0, 0, 255) self.drawing_rect_color = QColor(0, 0, 255) self.line = Shape(line_color=self.drawing_line_color) self.prev_point = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.label_font_size = 8 self.pixmap = QPixmap() self.visible = {} self._hide_background = False self.hide_background = False self.h_shape = None self.h_vertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) self.verified = False self.draw_square = False # initialisation for panning self.pan_initial_pos = QPoint()
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.drawingLineColor = QColor(0, 0, 255) self.drawingRectColor = QColor(0, 0, 255) self.line = Shape(line_color=self.drawingLineColor) self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.pixmap = QPixmap() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) self.verified = False self.drawSquare = False
def cutImageRect(self): self.reImage = Shape() minX = 0 minY = 0 maxX = 1280 maxY = 720 if self.W > self.H: if maxX > self.W: maxX = self.W if maxY > self.H: maxY = self.H maxX = maxY * 16 / 9 else: if maxY > self.H: maxY = self.H if maxX > self.W: maxX = self.W maxY = maxX * 9 / 16 self.line.points = [QPointF(minX, minY), QPointF(maxX, maxY)] targetPos = self.line[1] self.reImage.addPoint(QPointF(minX, minY)) self.reImage.addPoint(QPointF(maxX, minY)) self.reImage.addPoint(targetPos) self.reImage.addPoint(QPointF(minX, maxY)) self.refinalise()
def mouseMoveEvent(self, ev): pos = self.transformPos(ev.pos()) self.hilightVertex(None) index = self.findShapeNearest(pos) self.hilightVertex(index, visible=True) for i in range(len(self.shapes)): corner = self.findCorner(pos, self.shapes[i]) self.idRecreate = None if corner is not None: self.hilightVertex(i, corner=corner) self.idRecreate = i break if self.recreate and not self.drawing: self.br = pos self.shapes[self.idRecreate] = Shape(self.tl, self.br, self.idRecreate) if self.pixmap is None: return super(Canvas, self).mouseMoveEvent(ev) if self.edit: p1 = QPointF(0, pos.y()) p2 = QPointF(self.pixmap.width(), pos.y()) self.line_x = [p1, p2] p1 = QPointF(pos.x(), 0) p2 = QPointF(pos.x(), self.pixmap.height()) self.line_y = [p1, p2] elif self.drawing: self.br = pos self.current = Shape(self.tl, self.br, len(self.shapes))
def rotateBackPoints(self, xmin, ymin, xmax, ymax, angle): center=QPointF((xmin+xmax)/2,(ymin+ymax)/2) k0=Shape.rotatePoint(self,center,QPointF(xmin,ymin),-angle) k2=Shape.rotatePoint(self,center,QPointF(xmax,ymax),-angle) rotatedPoints=[k0,k2] points= [(int(point.x()),int(point.y())) for point in rotatedPoints] return points
def startCreatingBBox(self, pos): if not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line = Shape() self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def handleDrawing(self, pos): if not self.outOfPixmap(pos): if (self.current == None): self.current = Shape() self.current.addPoint(pos) if (len(self.current.points) == 22): self.finalise() self.line.points = [pos, pos] self.update()
def detectShapes(self, image_QT): image_QT = image_QT.convertToFormat(4) width = image_QT.width() height = image_QT.height() ptr = image_QT.bits() ptr = image_QT.bits() ptr.setsize(image_QT.byteCount()) arr = np.array(ptr).reshape(height, width, 4) # cv2.imwrite("test.png",arr) arr = cv2.cvtColor(arr, cv2.COLOR_RGBA2RGB) arr = cv2.cvtColor(arr, cv2.COLOR_BGR2RGB) cnt_germ, cnt_nongerm = classifySeeds(arr) # print(cnt_germ) # print(cnt_nongerm) for germ in cnt_germ: minX = germ[0] minY = germ[1] maxX = germ[0] + germ[2] maxY = germ[1] + germ[3] self.current = Shape() self.current.addPoint(QPointF(minX, minY)) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(QPointF(maxX, maxY)) self.current.addPoint(QPointF(minX, maxY)) self.current.label = "germinated" self.current.close() self.shapes.append(self.current) self.current = None self.newShape.emit() self.update() self.repaint() for germ in cnt_nongerm: minX = germ[0] minY = germ[1] maxX = germ[0] + germ[2] maxY = germ[1] + germ[3] self.current = Shape() self.current.addPoint(QPointF(minX, minY)) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(QPointF(maxX, maxY)) self.current.addPoint(QPointF(minX, maxY)) self.current.label = "non-germinated" self.current.close() self.shapes.append(self.current) self.current = None self.newShape.emit() self.update() self.repaint()
def autoDrawing(self, pos): self.current = Shape() minX = pos[0] minY = pos[1] maxX = pos[2] maxY = pos[3] self.current.addPoint(QPointF(maxX, maxY)) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(QPointF(minX, minY)) self.current.addPoint(QPointF(minX, maxY)) self.autoFinalise()
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs)#*args将输入的参数存放为元组,**kwargs将输入的参数存放为字典 # Initialise local state. self.shape_type = self.POLYGON_SHAPE self.brush_point = None self.task_mode = 3 self.erase_mode = False self.current_brush_path = None self.mask_Image = None self.brush_color =QColor(255,0,0,255) self.brush_size = 10 self.brush = QPainter(); self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.lineColor = QColor(0, 0, 255) self.line = Shape(line_color=self.lineColor) self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.bg_image = QImage() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter(self) self.font_size = 50 self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) ##point self.point_point=None self.point_point_list=[] self.point_dex=None self.point_color=[QColor(r ,g ,b ) for r in [0,255,120,30] for g in [0,255,120,30] for b in [0,255,120,30]] self.point_move=None self.point_path= None self.point_selecteditem=None self.point_delete=False self.point_modified=False self.point_shape={} self.point_link=[[1, 2], [1, 3], [2, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6, 7], [6, 8], [6, 12], [7, 9], [7, 13], [8, 10], [9, 11], [12, 13], [12, 14], [13, 15], [14, 16], [15, 17]] self.point_num =max(np.array(self.point_link)[:,1]) self.point_visible = {i:True for i in range(len(self.point_link))} self.point_deletedid=[] self.point_ids=[] self.point_all_deleted=False
def createImageRect(self): self.current = Shape() minX = 0 minY = 0 maxX = 160 maxY = 160 self.line.points = [QPointF(minX, minY), QPointF(maxX, maxY)] targetPos = self.line[1] self.current.addPoint(QPointF(minX, minY)) self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise()
def handleDrawing(self, pos): if self.current: self.undoStack.push(AddPointCommand(self, pos)) self.line.points = [pos, pos] elif not self.outOfPixmap(pos): self.current = Shape() self.current.label = self.currentLabel self.current.d_type = self.currentDType self.undoStack.push(AddPointCommand(self, pos)) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def makeBackRotatedShape(self, points, angle): canvas=Canvas() shape=Shape() xmax=points[2][0] xmin=points[0][0] ymax=points[2][1] ymin=points[0][1] shape.centerPoint=QPointF(( xmin+xmax)/2,(ymin+ymax)/2) shape.points= [QPointF(point[0],point[1]) for point in points] rotatedShapePoints=canvas.getRotatedShape(shape,angle) points= [(round(point.x(),0),round(point.y(),0)) for point in rotatedShapePoints] return points
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) #*args将输入的参数存放为元组,**kwargs将输入的参数存放为字典 # Initialise local state. self.shape_type = self.POLYGON_SHAPE self.brush_point = None self.task_mode = 3 self.erase_mode = False self.current_brush_path = None self.mask_Image = None self.brush_color = QColor(255, 0, 0, 255) self.brush_size = 10 self.brush = QPainter() self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.lineColor = QColor(0, 0, 255) self.line = Shape(line_color=self.lineColor) self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.bg_image = QImage() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter(self) self.font_size = 50 self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) ##point self.point_point = None self.point_point_list = [] self.point_dex = None self.point_color = [ QColor(r, g, b) for r in [0, 255, 120, 30] for g in [0, 255, 120, 30] for b in [0, 255, 120, 30] ] self.point_move = None self.point_path = None self.point_selecteditem = None self.point_delete = False
def Segment_Roi(self): # self.seg_count = self.seg_count +1 if self.flag_enter_polygon: bgdmodel = np.zeros((1, 65), np.float64) fgdmodel = np.zeros((1, 65), np.float64) cv2.grabCut(self.img2_for_grab, self.mask_for_grab, self.rect_for_grab, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_RECT) cv2.grabCut(self.img2_for_grab, self.mask_for_grab, self.rect_for_grab, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_MASK) mask2 = np.where( (self.mask_for_grab == 1) + (self.mask_for_grab == 3), 255, 0).astype('uint8') self.output = cv2.bitwise_and(self.img2_for_grab, self.img2_for_grab, mask=mask2) gray = cv2.cvtColor(self.output, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY) contours = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #,hierarchy contours_big_area = [] max_contours = 0 max_contours_i = 0 for i in range(len(contours[1])): if len(contours[1][i]) > max_contours: max_contours = len(contours[1][i]) max_contours_i = i # for i in range(len(contours[1][max_contours_i])): contours_tmp = np.array(contours[1][max_contours_i]) contours_big_area.append(contours_tmp) # if self.seg_count == 1: self.shapes.remove(self.shapes[len(self.shapes) - 1]) # self.update() self.contours_t = Shape() for i in range(len(contours_big_area[0])): self.contours_t.addPoint( QPointF(contours_big_area[0][i][0][0], contours_big_area[0][i][0][1])) self.contours_t.addPoint( QPointF(contours_big_area[0][0][0][0], contours_big_area[0][0][0][1])) self.shapes.append(self.contours_t) self.setHiding(False) self.newShape.emit() self.update() else: print('Please paint polygon first')
def handleDrawing(self, pos): if self.current: self.current.addPoint(pos, self.transformToLatLon(pos, True)) if len(self.current) == 3: self.current.close() self.finalise() elif not self.outOfPixmap(pos): self.current = Shape(parent_canvas=self) self.current.addPoint(pos, self.transformToLatLon(pos, True)) self.recalculateMovedLatlonPointsSelectedShape() self.update()
def add_shape(self, bbox, label, bbox_source, id_number): is_gate = label == "gate" shape = Shape(label, bbox_source=bbox_source, id_number=id_number, is_gate=is_gate) xmin, ymin, xmax, ymax = bbox if is_gate: shape.addPoint(QPointF(xmin, ymin)) shape.addPoint(QPointF(xmax, ymax)) else: shape.addPoint(QPointF(xmin, ymin)) shape.addPoint(QPointF(xmax, ymin)) shape.addPoint(QPointF(xmax, ymax)) shape.addPoint(QPointF(xmin, ymax)) shape.close() self.main_window.addLabel(shape) self.shapes.append(shape)
def handleDrawing(self, pos): # left button up to end drawing if self.current: # Add point to existing shape if self.shapeFactory.isType(shapeTypes.polygon): self.current.addPoint(self.line[1]) self.line[0] = self.current[-1] if self.current.isClosed(): self.finalise() elif self.shapeFactory.isType(shapeTypes.line): assert len(self.current.points) == 1 self.current.points = self.line.points self.finalise() elif self.shapeFactory.isType(shapeTypes.box): initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise() elif self.shapeFactory.isType(shapeTypes.ellipse): if self.current.tooClose(pos): self.escapeCurrent() return elif len(self.current.points) == 1: self.current.addPoint(self.line[1]) self.line = Shape(line_color=self.drawingLineColor) elif len(self.current.points) == 2: self.line.points = [pos, pos] self.current.addPoint(self.line[0]) elif len(self.current.points) == 3: self.current.addPoint(self.line[1]) if self.current.isClosed(): self.finalise() # left button down to create new shape. elif not self.outOfPixmap(pos): self.current = self.shapeFactory.getShape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__pixmap = QPixmap() self.__mode = PMode.IDLE self.__prevmode = PMode.IDLE self.__current = None self.__hShape = None self.__hVertex = None self.__shapes = [] self.__drawingLineColor = QColor(45, 168, 179) self.__drawingRectColor = QColor(45, 168, 179) self.__line = Shape(line_color=self.drawingLineColor) self.__prevPoint = QPointF() self.__selectedShape = None self.__verified = False self.__hideBackground = False self.__toggleBackground = False self.__visible = {} self.scale = 1.0 self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Load string bundle for i18n self.__stringBundle = StringBundle.getBundle() self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus)
def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.lineColor = QColor(0, 0, 255) self.line = Shape(line_color=self.lineColor) self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.pixmap = QPixmap() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) self.verified = False
def handleMasking(self, pos): if not self.outOfPixmap(pos): if self.pVertex is None: self.pVertex = Shape(line_color=self.drawingLineColor) if self.maskType == self.BOX_MASK: self.drawingPolygon.emit(True) self.pVertex.penWidth = 2 self.pVertex.close() else: self.pVertex.penWidth = self.penWidth self.pVertex.addPoint(pos) self.pVertex.maskType = self.maskType self.pVertex.highlightVertex( len(self.pVertex) - 1, self.pVertex.MOVE_VERTEX) self.update()
def load_record(self): if not self.may_continue(): return self.set_clean() self.clear_labels() item = self.recordList.selectedItems()[0] if not item: return self.current_record = item.text() if self.stream_enabled: self._stop_video() component = self.componentList.selectedItems()[0].text() filename = item.text().replace('№', '') f = filename.split(' ') filename = '{}{:04d}'.format(f[0], int(f[1])) path = os.path.join(self.path, component, 'records', filename) img_path = path + '.jpg' txt_path = path + '.txt' self.frame = cv2.imread(img_path) if self.frame is None: return self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB) self.canvas.loadPixmap( QPixmap.fromImage(qimage2ndarray.array2qimage(self.frame))) self.canvas.adjustSize() with open(txt_path, 'r') as bndboxes_file: for box in bndboxes_file: index, xcen, ycen, w, h = box.strip().split(' ') label = self.database_handler.classes[int(index)] xmin, ymin, xmax, ymax = yolo2points(xcen, ycen, w, h, self.frame.shape[1], self.frame.shape[0]) points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)] shape = Shape(label=label) for x, y in points: x, y, snapped = self.canvas.snapPointToCanvas(x, y) if snapped: self.set_dirty() shape.addPoint(QPointF(x, y)) shape.difficult = False shape.fill_color = generate_color_by_text(label) shape.line_color = generate_color_by_text(label) shape.close() self.shapes.append(shape) self.add_label(shape) self.canvas.loadShapes(self.shapes)
def boundedMoveVertex(self, pos): index, shape = self.hVertex, self.hShape if self.shapeOutOfPixmap(shape.points): #this is pre fix. For bug when shape reach Picmap edge. return if shape.shape3D: # 3D editing OFF return rotatedAxis = False if shape.deg > 0 and not shape.tetragon: rotatedAxis = True shape.points = self.getRotatedShape(shape, -shape.deg) pos = Shape.rotatePoint(self, shape.centerPoint, pos, -shape.deg) point = shape[index] if self.outOfPixmap(pos): if self.shapeOutOfPixmap(shape.points) == False: pos = self.intersectionPoint(point, pos) shiftPos = pos - point shape.moveVertexBy(index, shiftPos) lindex = (index + 1) % 4 rindex = (index + 3) % 4 lshift = None rshift = None if index % 2 == 0: #lyginiai index if shape.tetragon == True: rshift = QPointF(0, 0) lshift = QPointF(0, 0) elif shape.tetragon == False: rshift = QPointF(shiftPos.x(), 0) lshift = QPointF(0, shiftPos.y()) else: #nelyginiai index if shape.tetragon == True: lshift = QPointF(0, 0) rshift = QPointF(0, 0) elif shape.tetragon == False: lshift = QPointF(shiftPos.x(), 0) rshift = QPointF(0, shiftPos.y()) shape.moveVertexBy(rindex, rshift) shape.moveVertexBy(lindex, lshift) if rotatedAxis: shape.points = self.getRotatedShape(shape, shape.deg) pos = Shape.rotatePoint(self, shape.centerPoint, pos, shape.deg)
def handleDrawing(self, pos): if self.current and self.current.reachMaxPoints() is False: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update()
class Canvas(QWidget): zoomRequest = pyqtSignal(int) scrollRequest = pyqtSignal(int, int) newShape = pyqtSignal() selectionChanged = pyqtSignal(bool) shapeMoved = pyqtSignal() drawingPolygon = pyqtSignal(bool) CREATE, EDIT = list(range(2)) epsilon = 11.0 def __init__(self, *args, **kwargs): super(Canvas, self).__init__(*args, **kwargs) # Initialise local state. self.mode = self.EDIT self.shapes = [] self.current = None self.selectedShape = None # save the selected shape here self.selectedShapeCopy = None self.lineColor = QColor(0, 0, 255) self.line = Shape(line_color=self.lineColor) self.prevPoint = QPointF() self.offsets = QPointF(), QPointF() self.scale = 1.0 self.pixmap = QPixmap() self.visible = {} self._hideBackround = False self.hideBackround = False self.hShape = None self.hVertex = None self._painter = QPainter() self._cursor = CURSOR_DEFAULT # Menus: self.menus = (QMenu(), QMenu()) # Set widget options. self.setMouseTracking(True) self.setFocusPolicy(Qt.WheelFocus) self.verified = False def enterEvent(self, ev): self.overrideCursor(self._cursor) def leaveEvent(self, ev): self.restoreCursor() def focusOutEvent(self, ev): self.restoreCursor() def isVisible(self, shape): return self.visible.get(shape, True) def drawing(self): return self.mode == self.CREATE def editing(self): return self.mode == self.EDIT def setEditing(self, value=True): self.mode = self.EDIT if value else self.CREATE if not value: # Create self.unHighlight() self.deSelectShape() self.prevPoint = QPointF() self.repaint() def unHighlight(self): if self.hShape: self.hShape.highlightClear() self.hVertex = self.hShape = None def selectedVertex(self): return self.hVertex is not None def mouseMoveEvent(self, ev): """Update line with last point and current coordinates.""" pos = self.transformPos(ev.pos()) # Polygon drawing. if self.drawing(): self.overrideCursor(CURSOR_DRAW) if self.current: color = self.lineColor if self.outOfPixmap(pos): # Don't allow the user to draw outside the pixmap. # Project the point to the pixmap's edges. pos = self.intersectionPoint(self.current[-1], pos) elif len(self.current) > 1 and self.closeEnough(pos, self.current[0]): # Attract line to starting point and colorise to alert the # user: pos = self.current[0] color = self.current.line_color self.overrideCursor(CURSOR_POINT) self.current.highlightVertex(0, Shape.NEAR_VERTEX) self.line[1] = pos self.line.line_color = color self.prevPoint = QPointF() self.current.highlightClear() else: self.prevPoint = pos self.repaint() return # Polygon copy moving. if Qt.RightButton & ev.buttons(): if self.selectedShapeCopy and self.prevPoint: self.overrideCursor(CURSOR_MOVE) self.boundedMoveShape(self.selectedShapeCopy, pos) self.repaint() elif self.selectedShape: self.selectedShapeCopy = self.selectedShape.copy() self.repaint() return # Polygon/Vertex moving. if Qt.LeftButton & ev.buttons(): if self.selectedVertex(): self.boundedMoveVertex(pos) self.shapeMoved.emit() self.repaint() elif self.selectedShape and self.prevPoint: self.overrideCursor(CURSOR_MOVE) self.boundedMoveShape(self.selectedShape, pos) self.shapeMoved.emit() self.repaint() return # Just hovering over the canvas, 2 posibilities: # - Highlight shapes # - Highlight vertex # Update shape/vertex fill and tooltip value accordingly. self.setToolTip("Image") for shape in reversed([s for s in self.shapes if self.isVisible(s)]): # Look for a nearby vertex to highlight. If that fails, # check if we happen to be inside a shape. index = shape.nearestVertex(pos, self.epsilon) if index is not None: if self.selectedVertex(): self.hShape.highlightClear() self.hVertex, self.hShape = index, shape shape.highlightVertex(index, shape.MOVE_VERTEX) self.overrideCursor(CURSOR_POINT) self.setToolTip("Click & drag to move point") self.setStatusTip(self.toolTip()) self.update() break elif shape.containsPoint(pos): if self.selectedVertex(): self.hShape.highlightClear() self.hVertex, self.hShape = None, shape self.setToolTip( "Click & drag to move shape '%s'" % shape.label) self.setStatusTip(self.toolTip()) self.overrideCursor(CURSOR_GRAB) self.update() break else: # Nothing found, clear highlights, reset state. if self.hShape: self.hShape.highlightClear() self.update() self.hVertex, self.hShape = None, None self.overrideCursor(CURSOR_DEFAULT) def mousePressEvent(self, ev): pos = self.transformPos(ev.pos()) if ev.button() == Qt.LeftButton: if self.drawing(): self.handleDrawing(pos) else: self.selectShapePoint(pos) self.prevPoint = pos self.repaint() elif ev.button() == Qt.RightButton and self.editing(): self.selectShapePoint(pos) self.prevPoint = pos self.repaint() def mouseReleaseEvent(self, ev): if ev.button() == Qt.RightButton: menu = self.menus[bool(self.selectedShapeCopy)] self.restoreCursor() if not menu.exec_(self.mapToGlobal(ev.pos()))\ and self.selectedShapeCopy: # Cancel the move by deleting the shadow copy. self.selectedShapeCopy = None self.repaint() elif ev.button() == Qt.LeftButton and self.selectedShape: if self.selectedVertex(): self.overrideCursor(CURSOR_POINT) else: self.overrideCursor(CURSOR_GRAB) elif ev.button() == Qt.LeftButton: pos = self.transformPos(ev.pos()) if self.drawing(): self.handleDrawing(pos) def endMove(self, copy=False): assert self.selectedShape and self.selectedShapeCopy shape = self.selectedShapeCopy #del shape.fill_color #del shape.line_color if copy: self.shapes.append(shape) self.selectedShape.selected = False self.selectedShape = shape self.repaint() else: self.selectedShape.points = [p for p in shape.points] self.selectedShapeCopy = None def hideBackroundShapes(self, value): self.hideBackround = value if self.selectedShape: # Only hide other shapes if there is a current selection. # Otherwise the user will not be able to select a shape. self.setHiding(True) self.repaint() def handleDrawing(self, pos): if self.current and self.current.reachMaxPoints() is False: initPos = self.current[0] minX = initPos.x() minY = initPos.y() targetPos = self.line[1] maxX = targetPos.x() maxY = targetPos.y() self.current.addPoint(QPointF(maxX, minY)) self.current.addPoint(targetPos) self.current.addPoint(QPointF(minX, maxY)) self.finalise() elif not self.outOfPixmap(pos): self.current = Shape() self.current.addPoint(pos) self.line.points = [pos, pos] self.setHiding() self.drawingPolygon.emit(True) self.update() def setHiding(self, enable=True): self._hideBackround = self.hideBackround if enable else False def canCloseShape(self): return self.drawing() and self.current and len(self.current) > 2 def mouseDoubleClickEvent(self, ev): # We need at least 4 points here, since the mousePress handler # adds an extra one before this handler is called. if self.canCloseShape() and len(self.current) > 3: self.current.popPoint() self.finalise() def selectShape(self, shape): self.deSelectShape() shape.selected = True self.selectedShape = shape self.setHiding() self.selectionChanged.emit(True) self.update() def selectShapePoint(self, point): """Select the first shape created which contains this point.""" self.deSelectShape() if self.selectedVertex(): # A vertex is marked for selection. index, shape = self.hVertex, self.hShape shape.highlightVertex(index, shape.MOVE_VERTEX) self.selectShape(shape) return for shape in reversed(self.shapes): if self.isVisible(shape) and shape.containsPoint(point): self.selectShape(shape) self.calculateOffsets(shape, point) return def calculateOffsets(self, shape, point): rect = shape.boundingRect() x1 = rect.x() - point.x() y1 = rect.y() - point.y() x2 = (rect.x() + rect.width()) - point.x() y2 = (rect.y() + rect.height()) - point.y() self.offsets = QPointF(x1, y1), QPointF(x2, y2) def boundedMoveVertex(self, pos): index, shape = self.hVertex, self.hShape point = shape[index] if self.outOfPixmap(pos): pos = self.intersectionPoint(point, pos) shiftPos = pos - point shape.moveVertexBy(index, shiftPos) lindex = (index + 1) % 4 rindex = (index + 3) % 4 lshift = None rshift = None if index % 2 == 0: rshift = QPointF(shiftPos.x(), 0) lshift = QPointF(0, shiftPos.y()) else: lshift = QPointF(shiftPos.x(), 0) rshift = QPointF(0, shiftPos.y()) shape.moveVertexBy(rindex, rshift) shape.moveVertexBy(lindex, lshift) def boundedMoveShape(self, shape, pos): if self.outOfPixmap(pos): return False # No need to move o1 = pos + self.offsets[0] if self.outOfPixmap(o1): pos -= QPointF(min(0, o1.x()), min(0, o1.y())) o2 = pos + self.offsets[1] if self.outOfPixmap(o2): pos += QPointF(min(0, self.pixmap.width() - o2.x()), min(0, self.pixmap.height() - o2.y())) # The next line tracks the new position of the cursor # relative to the shape, but also results in making it # a bit "shaky" when nearing the border and allows it to # go outside of the shape's area for some reason. XXX #self.calculateOffsets(self.selectedShape, pos) dp = pos - self.prevPoint if dp: shape.moveBy(dp) self.prevPoint = pos return True return False def deSelectShape(self): if self.selectedShape: self.selectedShape.selected = False self.selectedShape = None self.setHiding(False) self.selectionChanged.emit(False) self.update() def deleteSelected(self): if self.selectedShape: shape = self.selectedShape self.shapes.remove(self.selectedShape) self.selectedShape = None self.update() return shape def copySelectedShape(self): if self.selectedShape: shape = self.selectedShape.copy() self.deSelectShape() self.shapes.append(shape) shape.selected = True self.selectedShape = shape self.boundedShiftShape(shape) return shape def boundedShiftShape(self, shape): # Try to move in one direction, and if it fails in another. # Give up if both fail. point = shape[0] offset = QPointF(2.0, 2.0) self.calculateOffsets(shape, point) self.prevPoint = point if not self.boundedMoveShape(shape, point - offset): self.boundedMoveShape(shape, point + offset) def paintEvent(self, event): if not self.pixmap: return super(Canvas, self).paintEvent(event) p = self._painter p.begin(self) p.setRenderHint(QPainter.Antialiasing) p.setRenderHint(QPainter.HighQualityAntialiasing) p.setRenderHint(QPainter.SmoothPixmapTransform) p.scale(self.scale, self.scale) p.translate(self.offsetToCenter()) p.drawPixmap(0, 0, self.pixmap) Shape.scale = self.scale for shape in self.shapes: if (shape.selected or not self._hideBackround) and self.isVisible(shape): shape.fill = shape.selected or shape == self.hShape shape.paint(p) if self.current: self.current.paint(p) self.line.paint(p) if self.selectedShapeCopy: self.selectedShapeCopy.paint(p) # Paint rect if self.current is not None and len(self.line) == 2: leftTop = self.line[0] rightBottom = self.line[1] rectWidth = rightBottom.x() - leftTop.x() rectHeight = rightBottom.y() - leftTop.y() color = QColor(0, 220, 0) p.setPen(color) brush = QBrush(Qt.BDiagPattern) p.setBrush(brush) p.drawRect(leftTop.x(), leftTop.y(), rectWidth, rectHeight) if self.drawing() and not self.prevPoint.isNull() and not self.outOfPixmap(self.prevPoint): p.setPen(QColor(0, 0, 0)) p.drawLine(self.prevPoint.x(), 0, self.prevPoint.x(), self.pixmap.height()) p.drawLine(0, self.prevPoint.y(), self.pixmap.width(), self.prevPoint.y()) self.setAutoFillBackground(True) if self.verified: pal = self.palette() pal.setColor(self.backgroundRole(), QColor(184, 239, 38, 128)) self.setPalette(pal) else: pal = self.palette() pal.setColor(self.backgroundRole(), QColor(232, 232, 232, 255)) self.setPalette(pal) p.end() def transformPos(self, point): """Convert from widget-logical coordinates to painter-logical coordinates.""" return point / self.scale - self.offsetToCenter() def offsetToCenter(self): s = self.scale area = super(Canvas, self).size() w, h = self.pixmap.width() * s, self.pixmap.height() * s aw, ah = area.width(), area.height() x = (aw - w) / (2 * s) if aw > w else 0 y = (ah - h) / (2 * s) if ah > h else 0 return QPointF(x, y) def outOfPixmap(self, p): w, h = self.pixmap.width(), self.pixmap.height() return not (0 <= p.x() <= w and 0 <= p.y() <= h) def finalise(self): assert self.current if self.current.points[0] == self.current.points[-1]: self.current = None self.drawingPolygon.emit(False) self.update() return self.current.close() self.shapes.append(self.current) self.current = None self.setHiding(False) self.newShape.emit() self.update() def closeEnough(self, p1, p2): #d = distance(p1 - p2) #m = (p1-p2).manhattanLength() # print "d %.2f, m %d, %.2f" % (d, m, d - m) return distance(p1 - p2) < self.epsilon def intersectionPoint(self, p1, p2): # Cycle through each image edge in clockwise fashion, # and find the one intersecting the current line segment. # http://paulbourke.net/geometry/lineline2d/ size = self.pixmap.size() points = [(0, 0), (size.width(), 0), (size.width(), size.height()), (0, size.height())] x1, y1 = p1.x(), p1.y() x2, y2 = p2.x(), p2.y() d, i, (x, y) = min(self.intersectingEdges((x1, y1), (x2, y2), points)) x3, y3 = points[i] x4, y4 = points[(i + 1) % 4] if (x, y) == (x1, y1): # Handle cases where previous point is on one of the edges. if x3 == x4: return QPointF(x3, min(max(0, y2), max(y3, y4))) else: # y3 == y4 return QPointF(min(max(0, x2), max(x3, x4)), y3) return QPointF(x, y) def intersectingEdges(self, x1y1, x2y2, points): """For each edge formed by `points', yield the intersection with the line segment `(x1,y1) - (x2,y2)`, if it exists. Also return the distance of `(x2,y2)' to the middle of the edge along with its index, so that the one closest can be chosen.""" x1, y1 = x1y1 x2, y2 = x2y2 for i in range(4): x3, y3 = points[i] x4, y4 = points[(i + 1) % 4] denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1) nua = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3) nub = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3) if denom == 0: # This covers two cases: # nua == nub == 0: Coincident # otherwise: Parallel continue ua, ub = nua / denom, nub / denom if 0 <= ua <= 1 and 0 <= ub <= 1: x = x1 + ua * (x2 - x1) y = y1 + ua * (y2 - y1) m = QPointF((x3 + x4) / 2, (y3 + y4) / 2) d = distance(m - QPointF(x2, y2)) yield d, i, (x, y) # These two, along with a call to adjustSize are required for the # scroll area. def sizeHint(self): return self.minimumSizeHint() def minimumSizeHint(self): if self.pixmap: return self.scale * self.pixmap.size() return super(Canvas, self).minimumSizeHint() def wheelEvent(self, ev): qt_version = 4 if hasattr(ev, "delta") else 5 if qt_version == 4: if ev.orientation() == Qt.Vertical: v_delta = ev.delta() h_delta = 0 else: h_delta = ev.delta() v_delta = 0 else: delta = ev.angleDelta() h_delta = delta.x() v_delta = delta.y() mods = ev.modifiers() if Qt.ControlModifier == int(mods) and v_delta: self.zoomRequest.emit(v_delta) else: v_delta and self.scrollRequest.emit(v_delta, Qt.Vertical) h_delta and self.scrollRequest.emit(h_delta, Qt.Horizontal) ev.accept() def keyPressEvent(self, ev): key = ev.key() if key == Qt.Key_Escape and self.current: print('ESC press') self.current = None self.drawingPolygon.emit(False) self.update() elif key == Qt.Key_Return and self.canCloseShape(): self.finalise() elif key == Qt.Key_Left and self.selectedShape: self.moveOnePixel('Left') elif key == Qt.Key_Right and self.selectedShape: self.moveOnePixel('Right') elif key == Qt.Key_Up and self.selectedShape: self.moveOnePixel('Up') elif key == Qt.Key_Down and self.selectedShape: self.moveOnePixel('Down') def moveOnePixel(self, direction): # print(self.selectedShape.points) if direction == 'Left' and not self.moveOutOfBound(QPointF(-1.0, 0)): # print("move Left one pixel") self.selectedShape.points[0] += QPointF(-1.0, 0) self.selectedShape.points[1] += QPointF(-1.0, 0) self.selectedShape.points[2] += QPointF(-1.0, 0) self.selectedShape.points[3] += QPointF(-1.0, 0) elif direction == 'Right' and not self.moveOutOfBound(QPointF(1.0, 0)): # print("move Right one pixel") self.selectedShape.points[0] += QPointF(1.0, 0) self.selectedShape.points[1] += QPointF(1.0, 0) self.selectedShape.points[2] += QPointF(1.0, 0) self.selectedShape.points[3] += QPointF(1.0, 0) elif direction == 'Up' and not self.moveOutOfBound(QPointF(0, -1.0)): # print("move Up one pixel") self.selectedShape.points[0] += QPointF(0, -1.0) self.selectedShape.points[1] += QPointF(0, -1.0) self.selectedShape.points[2] += QPointF(0, -1.0) self.selectedShape.points[3] += QPointF(0, -1.0) elif direction == 'Down' and not self.moveOutOfBound(QPointF(0, 1.0)): # print("move Down one pixel") self.selectedShape.points[0] += QPointF(0, 1.0) self.selectedShape.points[1] += QPointF(0, 1.0) self.selectedShape.points[2] += QPointF(0, 1.0) self.selectedShape.points[3] += QPointF(0, 1.0) self.shapeMoved.emit() self.repaint() def moveOutOfBound(self, step): points = [p1+p2 for p1, p2 in zip(self.selectedShape.points, [step]*4)] return True in map(self.outOfPixmap, points) def setLastLabel(self, text): assert text self.shapes[-1].label = text return self.shapes[-1] def undoLastLine(self): assert self.shapes self.current = self.shapes.pop() self.current.setOpen() self.line.points = [self.current[-1], self.current[0]] self.drawingPolygon.emit(True) def resetAllLines(self): assert self.shapes self.current = self.shapes.pop() self.current.setOpen() self.line.points = [self.current[-1], self.current[0]] self.drawingPolygon.emit(True) self.current = None self.drawingPolygon.emit(False) self.update() def loadPixmap(self, pixmap): self.pixmap = pixmap self.shapes = [] self.repaint() def loadShapes(self, shapes): self.shapes = list(shapes) self.current = None self.repaint() def setShapeVisible(self, shape, value): self.visible[shape] = value self.repaint() def currentCursor(self): cursor = QApplication.overrideCursor() if cursor is not None: cursor = cursor.shape() return cursor def overrideCursor(self, cursor): self._cursor = cursor if self.currentCursor() is None: QApplication.setOverrideCursor(cursor) else: QApplication.changeOverrideCursor(cursor) def restoreCursor(self): QApplication.restoreOverrideCursor() def resetState(self): self.restoreCursor() self.pixmap = None self.update()