def __init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize): p = QPixmap() p.loadFromData(data, encoding, Qt.AutoColor) w, h = p.width(), p.height() p = p.copy(x0, y0, min(w, x1-x0), min(h, y1-y0)) if p.width() != xsize or p.height() != ysize: p = p.scaled(xsize, ysize, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) QGraphicsPixmapItem.__init__(self, p) self.height, self.width = ysize, xsize self.setTransformationMode(Qt.SmoothTransformation) self.setShapeMode(QGraphicsPixmapItem.BoundingRectShape)
def __init__(self, data, encoding, x0, y0, x1, y1, xsize, ysize): p = QPixmap() p.loadFromData(data, encoding, Qt.ImageConversionFlag.AutoColor) w, h = p.width(), p.height() p = p.copy(x0, y0, min(w, x1-x0), min(h, y1-y0)) if p.width() != xsize or p.height() != ysize: p = p.scaled(xsize, ysize, Qt.AspectRatioMode.IgnoreAspectRatio, Qt.TransformationMode.SmoothTransformation) QGraphicsPixmapItem.__init__(self, p) self.height, self.width = ysize, xsize self.setTransformationMode(Qt.TransformationMode.SmoothTransformation) self.setShapeMode(QGraphicsPixmapItem.ShapeMode.BoundingRectShape)
class PaintBoard(QLabel): signal_right_mouse = pyqtSignal(int) signal_draw = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.__parent = parent self.__board = QPixmap(QSize(440, 440)) self.__board.fill(Qt.transparent) self.__board_old = self.__board.copy() self.__board_old_old = self.__board.copy() self.__board_before_dots = self.__board.copy() self.__thickness = 10 # 默认画笔粗细为10px self.__penColor = QColor(0, 0, 0, 128) self.__painter = QPainter() self.__pen = QPen(self.__penColor, self.__thickness) self.__pen_seg = QPen(QColor(0, 0, 0, 128)) self.__brush = QBrush(QColor(0, 0, 0, 128)) self.__pen.setCapStyle(Qt.RoundCap) #self.__painter.setPen(self.__pen) self.__lastPos = QPoint(0, 0) # 上一次鼠标位置 self.__currentPos = QPoint(0, 0) # 当前的鼠标位置 self.__points = [] # dots模式的点集 self.__mouse_pressed = False self.__can_undo = False self.__has_seg = False self.__mode = 1 self.__ERASE = 0 self.__LINE = 1 self.__RECT = 2 self.__CIRCLE = 3 self.__DOTS = 4 self.__transparent = False self.__trans_board = self.__board.copy() self.__trans_board.fill(Qt.transparent) @staticmethod def dist(p1, p2): return math.hypot(p1.x() - p2.x(), p1.y() - p2.y()) # Each time paintEvent is called it clean the space where it is going to draw. # So it does not save memory of the previous drawings, # A simple solution is to first paint a QPixmap to store what you have painted. # And then paint the widget with that QPixmap. def set_trans(self, trans): self.__transparent = trans self.update() def is_trans(self): return self.__transparent def paintEvent(self, paint_event): # 把board绘制到界面上 self.__painter.begin(self) if not self.__transparent: self.__painter.drawPixmap(0, 0, self.__board) else: self.__painter.drawPixmap(0, 0, self.__trans_board) #结果图关闭mask self.__painter.end() def mousePressEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: self.__mouse_pressed = True self.__board_old_old = self.__board_old.copy() self.__board_old = self.__board.copy() self.__currentPos = mouse_event.pos() self.__lastPos = self.__currentPos if self.__mode == self.__DOTS: if len(self.__points) == 0: self.__board_before_dots = self.__board.copy() self.__parent.childAt(740, 0).setEnabled(False) self.__parent.childAt(840, 0).setEnabled(False) self.__parent.childAt(370, 0).setEnabled(False) self.__parent.childAt(300, 610).setEnabled(False) if len(self.__points) > 0: print( self.dist( self.__points[0], QPoint(self.__currentPos.x(), self.__currentPos.y()))) if len(self.__points) > 2 and \ self.dist(self.__points[0], QPoint(self.__currentPos.x(), self.__currentPos.y())) < 5: self.__board = self.__board_before_dots.copy() self.__painter.begin(self.__board) if self.__ERASE: self.__painter.setCompositionMode( QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) self.__painter.drawPolygon(QPolygon(self.__points)) self.signal_draw.emit() self.__painter.end() self.__points.clear() self.__parent.childAt(740, 0).setEnabled(True) self.__parent.childAt(840, 0).setEnabled(True) self.__parent.childAt(370, 0).setEnabled(True) self.__parent.childAt(300, 610).setEnabled(True) self.update() else: self.__points.append( QPoint(self.__currentPos.x(), self.__currentPos.y())) if not (self.__mode == self.__DOTS and len(self.__points) == 1): self.__can_undo = True self.__parent.childAt(70, 610).setEnabled(True) else: self.__can_undo = False self.__parent.childAt(70, 610).setEnabled(False) def mouseMoveEvent(self, mouse_event): # 把线绘制到board上 self.__currentPos = mouse_event.pos() if self.__mode != self.__LINE: if len(self.__points) > 0: self.__board = self.__board_old.copy() elif not self.__mode == self.__DOTS: if self.__mouse_pressed: self.__board = self.__board_old.copy() self.__painter.begin(self.__board) self.__painter.setPen(self.__pen) if self.__ERASE: self.__painter.setCompositionMode(QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode(QPainter.CompositionMode_Source) if self.__mode == self.__LINE: if self.__mouse_pressed: self.__painter.drawLine(self.__lastPos, self.__currentPos) self.signal_draw.emit() elif self.__mode == self.__RECT: self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) if self.__mouse_pressed: self.__painter.drawRect( self.__lastPos.x(), self.__lastPos.y(), (self.__currentPos.x() - self.__lastPos.x()), (self.__currentPos.y() - self.__lastPos.y())) self.signal_draw.emit() elif self.__mode == self.__CIRCLE: self.__painter.setPen(Qt.NoPen) self.__painter.setBrush(self.__brush) if self.__mouse_pressed: self.__painter.drawEllipse( self.__lastPos.x(), self.__lastPos.y(), (self.__currentPos.x() - self.__lastPos.x()), (self.__currentPos.y() - self.__lastPos.y())) self.signal_draw.emit() elif self.__mode == self.__DOTS: if len(self.__points) > 0: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.setPen(QPen(self.__pen_seg.color(), 1)) self.__painter.drawLine(self.__points[-1], self.__currentPos) self.signal_draw.emit() self.__painter.end() if self.__mode == self.__LINE: self.__lastPos = self.__currentPos self.update() # 触发paintEvent def mouseDoubleClickEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: if not self.__mode == self.__DOTS: if self.__has_seg: x = mouse_event.pos().x() y = mouse_event.pos().y() value = self.segment[y][x] # 注意这里x和y要反过来 self.__painter.begin(self.__board) self.paint_segment(value, x, y) self.__painter.end() self.signal_draw.emit() self.update() # 触发paintEvent def mouseReleaseEvent(self, mouse_event): if mouse_event.button() == Qt.LeftButton: self.__mouse_pressed = False if mouse_event.button() == Qt.RightButton: self.signal_right_mouse.emit(1 - self.__ERASE) return def undo(self): if self.__can_undo: if self.__mode != self.__DOTS: self.__board = self.__board_old.copy() else: if len(self.__points) == 0: self.__board = self.__board_before_dots.copy() else: self.__points.pop() self.__board = self.__board_old_old.copy() self.__board_old = self.__board_old_old.copy() self.signal_draw.emit() self.update() self.__can_undo = False self.__parent.childAt(70, 610).setEnabled(False) def update_segment(self, seg): self.segment = seg self.__parent.childAt(1040, 0).setEnabled(False) self.__has_seg = True def set_board(self, x, y): self.__board = self.__board.scaled(x, y) def update_board(self, board): self.__board = board self.update() def paint_segment(self, value, x, y): has_painted = np.zeros(self.segment.shape, dtype=np.uint8) point_stack = [(x, y)] while len(point_stack) > 0: point = point_stack.pop() x = point[0] y = point[1] self.__painter.setPen(self.__pen_seg) if self.__ERASE: self.__painter.setCompositionMode( QPainter.CompositionMode_Clear) else: self.__painter.setCompositionMode( QPainter.CompositionMode_Source) self.__painter.drawPoint(x, y) has_painted[y][x] = 1 if x + 1 < self.segment.shape[1] and has_painted[y][ x + 1] == 0 and value == self.segment[y][x + 1]: point_stack.append((x + 1, y)) if x - 1 >= 0 and has_painted[y][ x - 1] == 0 and value == self.segment[y][x - 1]: point_stack.append((x - 1, y)) if y + 1 < self.segment.shape[0] and has_painted[ y + 1][x] == 0 and value == self.segment[y + 1][x]: point_stack.append((x, y + 1)) if y - 1 >= 0 and has_painted[ y - 1][x] == 0 and value == self.segment[y - 1][x]: point_stack.append((x, y - 1)) def Thanos(self, label): if len(label) == 0: return False image = self.__board.copy() image.fill(Qt.transparent) pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] for l in label: mask[self.segment == l] = 255 expand_mask(mask, 5) #Image.fromarray(np.uint8(mask)).save('mask_10.jpg') return mask def set_seg(self): self.__has_seg = False def set_pen(self, value): self.__pen.setWidth(value) def pen_black(self): self.__pen.setColor(QColor(0, 0, 0, 128)) def pen_white(self): self.__pen.setColor(QColor(255, 255, 255, 128)) def geo_black(self): self.__pen_seg.setColor(QColor(0, 0, 0, 128)) self.__brush = QBrush(QColor(0, 0, 0, 128)) def geo_white(self): self.__pen_seg.setColor(QColor(255, 255, 255, 128)) self.__brush = QBrush(QColor(255, 255, 255, 128)) def switch_mode(self): self.__ERASE = 1 - self.__ERASE def set_mode(self, mode): self.__ERASE = mode def tool_pen(self): self.__mode = self.__LINE def tool_rect(self): self.__mode = self.__RECT def tool_circle(self): self.__mode = self.__CIRCLE def tool_dots(self): self.__mode = self.__DOTS def clear_board(self): self.__board.fill(Qt.transparent) self.__board_old = self.__board.copy() self.__board_before_dots = self.__board.copy() self.__board_old_old = self.__board.copy() self.__parent.childAt(70, 610).setEnabled(False) self.signal_draw.emit() self.update() def save(self): # save_path = QFileDialog.getSaveFileName(self, 'Save Your Paint', '.\\', '*.jpg') save_path = 'D:/test.png', '*.png' print(save_path) if save_path[0] == "": print("Save cancel") return image = self.__board pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] print(mask) # qimage2numpy(pixels) # Pixels can only be accessed through QPainter functions or by converting the QPixmap to a QImage. image.save(save_path[0]) def get_mask(self): image = self.__board pixels = image.toImage() s = pixels.bits().asstring(pixels.width() * pixels.height() * 4) arr = np.fromstring(s, dtype=np.uint8).reshape( (pixels.height(), pixels.width(), 4)) np.set_printoptions(threshold=sys.maxsize) mask = arr[..., 3] # 取alpha通道,就是不透明度 mask[mask > 0] = 255 return mask def get_board(self): return self.__board.copy() def test(self): # self.pix = QPixmap("road.jpg") self.__painter.begin(self.__board) for i in range(301): for j in range(301): self.__painter.drawPoint(i, j) self.__painter.end() self.update()