问题描述
我有一个功能正常的绘图应用程序,用于对图像进行一些分割.为此,我有两层,原始图像和我正在绘制的图像层.
I have a functioning drawing application for some segmentation on images. For this I have two layers, the original image and the image layer I am drawing on.
我现在想实现一种擦除方法.我已经实现了撤消功能,但我也希望用户能够选择画笔颜色"以便能够擦除特定部分,例如油漆中的橡皮擦.我认为这可以通过使用不透明的颜色进行绘制来实现,但这只会导致不绘制线条.
I now want to implement a method for erasing. I have implemented undo functionality, but I would also like the user to be able to select a brush "color" as to be able to erase specific parts, like the eraser in paint. I thought this would be possible by drawing with a color with opacity, but that just results in no line being drawn.
因此,我的目标是画一条线,去除图像层中的像素值,以便我可以看到底层图像
The goal for me is therefore to draw a line, that removes the pixel values in the image layer, such that I can see the underlying image
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QMenu, QAction from PyQt5.QtGui import QIcon, QImage, QPainter, QPen from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui import QColor import sys class Window(QMainWindow): def __init__(self): super().__init__() top = 400 left = 400 width = 800 height = 600 self.setWindowTitle("MyPainter") self.setGeometry(top, left, width, height) self.image = QImage(self.size(), QImage.Format_ARGB32) self.image.fill(Qt.white) self.imageDraw = QImage(self.size(), QImage.Format_ARGB32) self.imageDraw.fill(Qt.transparent) self.drawing = False self.brushSize = 2 self.brushColor = Qt.black self.lastPoint = QPoint() self.change = False mainMenu = self.menuBar() changeColour = mainMenu.addMenu("changeColour") changeColourAction = QAction("change",self) changeColour.addAction(changeColourAction) changeColourAction.triggered.connect(self.changeColour) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() def mouseMoveEvent(self, event): if event.buttons() and Qt.LeftButton and self.drawing: painter = QPainter(self.imageDraw) painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button == Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) canvasPainter.drawImage(self.rect(), self.imageDraw, self.imageDraw.rect()) def changeColour(self): if not self.change: # erase self.brushColor = QColor(255,255,255,0) else: self.brushColor = Qt.black self.change = not self.change if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() app.exec()
如何擦除像素子集?
在这个例子中,应该为 changeColour 函数中的 self.brushColor 赋予什么颜色?
How to erase a subset of pixels?
As in this example what color should be given to self.brushColor in the changeColour function?
白色不是解决方案,因为实际上底部的图像是一个复杂的图像,因此我想在擦除时再次使顶层透视".
The colour white is not the solution, because in reality the image at the bottom is a complex image, I therefore want to make the toplayer "see-through" again, when erasing.
推荐答案
你必须改变 compositionMode 到 QPainter::CompositionMode_Clear 并用 eraseRect().
You have to change the compositionMode to QPainter::CompositionMode_Clear and erase with eraseRect().
from PyQt5 import QtCore, QtGui, QtWidgets class Window(QtWidgets.QMainWindow): def __init__(self): super().__init__() top, left, width, height = 400, 400, 800, 600 self.setWindowTitle("MyPainter") self.setGeometry(top, left, width, height) self.image = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32) self.image.fill(QtCore.Qt.white) self.imageDraw = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32) self.imageDraw.fill(QtCore.Qt.transparent) self.drawing = False self.brushSize = 2 self._clear_size = 20 self.brushColor = QtGui.QColor(QtCore.Qt.black) self.lastPoint = QtCore.QPoint() self.change = False mainMenu = self.menuBar() changeColour = mainMenu.addMenu("changeColour") changeColourAction = QtWidgets.QAction("change", self) changeColour.addAction(changeColourAction) changeColourAction.triggered.connect(self.changeColour) def mousePressEvent(self, event): if event.button() == QtCore.Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() def mouseMoveEvent(self, event): if event.buttons() and QtCore.Qt.LeftButton and self.drawing: painter = QtGui.QPainter(self.imageDraw) painter.setPen(QtGui.QPen(self.brushColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)) if self.change: r = QtCore.QRect(QtCore.QPoint(), self._clear_size*QtCore.QSize()) r.moveCenter(event.pos()) painter.save() painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear) painter.eraseRect(r) painter.restore() else: painter.drawLine(self.lastPoint, event.pos()) painter.end() self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button == QtCore.Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QtGui.QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) canvasPainter.drawImage(self.rect(), self.imageDraw, self.imageDraw.rect()) def changeColour(self): self.change = not self.change if self.change: pixmap = QtGui.QPixmap(QtCore.QSize(1, 1)*self._clear_size) pixmap.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(pixmap) painter.setPen(QtGui.QPen(QtCore.Qt.black, 2)) painter.drawRect(pixmap.rect()) painter.end() cursor = QtGui.QCursor(pixmap) QtWidgets.QApplication.setOverrideCursor(cursor) else: QtWidgets.QApplication.restoreOverrideCursor() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())