def paintEvent(self, evt): """ Protected method handling a paint event. @param evt reference to the paint event (QPaintEvent) """ if self.__privateMode: backgroundColor = QColor(220, 220, 220) # light gray foregroundColor = Qt.black else: backgroundColor = QApplication.palette().color(QPalette.Base) foregroundColor = QApplication.palette().color(QPalette.Text) if self.__browser is not None: p = self.palette() progress = self.__browser.progress() if progress == 0 or progress == 100: if self.__browser.url().scheme() == "https": if QSslCertificate is not None: if self.__browser.page().hasValidSslInfo(): backgroundColor = Preferences.getHelp( "SaveUrlColor") else: backgroundColor = Preferences.getHelp("SaveUrlColor") p.setBrush(QPalette.Base, backgroundColor) p.setBrush(QPalette.Text, foregroundColor) else: if self.__browser.url().scheme() == "https": if QSslCertificate is not None: if self.__browser.page().hasValidSslInfo(): backgroundColor = Preferences.getHelp( "SaveUrlColor") else: backgroundColor = Preferences.getHelp("SaveUrlColor") highlight = QApplication.palette().color(QPalette.Highlight) r = (highlight.red() + 2 * backgroundColor.red()) // 3 g = (highlight.green() + 2 * backgroundColor.green()) // 3 b = (highlight.blue() + 2 * backgroundColor.blue()) // 3 loadingColor = QColor(r, g, b) if abs(loadingColor.lightness() - backgroundColor.lightness()) < 20: # special handling for special color schemes (e.g Gaia) r = (2 * highlight.red() + backgroundColor.red()) // 3 g = (2 * highlight.green() + backgroundColor.green()) // 3 b = (2 * highlight.blue() + backgroundColor.blue()) // 3 loadingColor = QColor(r, g, b) gradient = QLinearGradient( QPointF(0, 0), QPointF(self.width(), 0)) gradient.setColorAt(0, loadingColor) gradient.setColorAt(progress / 100.0 - 0.000001, loadingColor) gradient.setColorAt(progress / 100.0, backgroundColor) p.setBrush(QPalette.Base, gradient) self.setPalette(p) E5LineEdit.paintEvent(self, evt)
def mixColors(col1, col2, f=.5): fromString = False if type(col1) == str: fromString = True col1 = QColor(col1) if type(col2) == str: col2 = QColor(col2) f2 = 1-f r = col1.red() * f + col2.red() * f2 g = col1.green() * f + col2.green() * f2 b = col1.blue() * f + col2.blue() * f2 return QColor(r, g, b) if not fromString else QColor(r, g, b).name()
class ColorSwatchWidget(QLabel): def __init__(self, color=QColor(255, 255, 255, 255)): if isinstance(color, QColor): self.current_color = color else: # otherwise, it should be an rgb or rgba tuple if len(color) == 3: self.current_color = QColor(color[0], color[1], color[2], 255) else: self.current_color = QColor(color[0], color[1], color[2], color[3]) super(QLabel, self).__init__("") self.setMinimumSize(30, 30) self.reset_style_sheet() def reset_style_sheet(self): color_string = "rgb(" + str(self.current_color.red()) + ", " + \ str(self.current_color.green()) + ", " + \ str(self.current_color.blue()) + ")" self.setStyleSheet("QLabel { background-color : "+ color_string + "; " "border-style: outset;" "border-width: 2px;" "border-color: beige;}") def set_color(self, color): self.current_color = color def mousePressEvent(self, e): color_dialog = QColorDialog() color_dialog.exec_() self.current_color = color_dialog.selectedColor() self.reset_style_sheet() def value(self): return self.current_color
def _get_flight_bgcolor(fl: XNFlight) -> QColor: ret = QColor(255, 255, 255) mis = fl.mission if mis == 'ownharvest': ret = QColor(255, 255, 200) elif mis == 'owndeploy': ret = QColor(200, 200, 255) elif mis == 'ownattack': ret = QColor(255, 200, 230) elif mis == 'owntransport': ret = QColor(200, 255, 200) elif mis == 'ownespionage': ret = QColor(255, 220, 150) elif mis == 'owncolony': ret = QColor(190, 210, 255) elif mis == 'ownmissile': ret = QColor(165, 255, 255) elif mis == 'ownbase': ret = QColor(153, 200, 255) elif mis == 'attack': ret = QColor(255, 230, 230) if fl.direction == 'return': # darken -20% ret.setRed(ret.red() * 0.8) ret.setGreen(ret.green() * 0.8) ret.setBlue(ret.blue() * 0.8) return ret
def _update_colors(self): op = self.topLevelOperatorView ctable = self._doneSegmentationLayer.colorTable for name, label in self._shownObjects3D.items(): color = QColor(ctable[op.MST.value.object_names[name]]) color = (old_div(color.red(), 255.0), old_div(color.green(), 255.0), old_div(color.blue(), 255.0)) self._renderMgr.setColor(label, color) if self._showSegmentationIn3D and self._segmentation_3d_label is not None: self._renderMgr.setColor(self._segmentation_3d_label, (0.0, 1.0, 0.0)) # Green
def render_color_scribble(self): r = [] g = [] b = [] for i in range(8): for j in range(8): color = QColor(self.scribble_widget.image().pixel(j, i)) r.append(color.red()) g.append(color.green()) b.append(color.blue()) self.set_rgb(r, g, b)
def qcolor2rgbmpl(qcolor: QColor) -> Tuple[float, float, float]: """ Calculates the red, green and blue components of the given QColor instance. :param qcolor: the input QColor instance :type qcolor: QColor :return: the triplet of the three RGB color values :type: a tuple of three floats """ red = qcolor.red() / 255.0 green = qcolor.green() / 255.0 blue = qcolor.blue() / 255.0 return red, green, blue
def hsl_changed(self, *_args): if self.changing: return h, s, l = self.spin_h.value(), self.spin_s.value(), self.spin_l.value() hsl = QColor() hsl.setHsl(h, s, l) r, g, b = hsl.red(), hsl.green(), hsl.blue() self.changing = True self.spin_r.setValue(r) self.spin_g.setValue(g) self.spin_b.setValue(b) self.changing = False self.rgb_led.set_rgb_value(r, g, b) self.label_color.setStyleSheet('QLabel {{ background: #{:02x}{:02x}{:02x} }}'.format(r, g, b))
def updateGUI(self): img = self.camera.getOrigImage() if img is not None: self.image = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) self.sourceImg.setPixmap(QPixmap.fromImage(self.image)) filt = self.getFilterName() img = self.camera.getFilteredImage(filt) if img is not None: self.imageF = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) self.filterImg.setPixmap(QPixmap.fromImage(self.imageF)) #print "update" pos = self.sourceImg.getMousePos() if pos != None: #print pos x_ini = (self.sourceImg.width()*self.ZOOM_X*pos.x())/self.sourceImg.width() y_ini = (self.sourceImg.height()*self.ZOOM_X*pos.y())/self.sourceImg.height() rect = QRect(x_ini-100,y_ini-100,200,200) #print 'orig', pos.x(), ",", pos.y(), ",", self.sourceImg.size() #print 'scale', x_ini, ",", y_ini #self.crop.setPixmap(QPixmap.fromImage(self.image.copy(rect).scaled(1000,1000))) #print self.sourceImg.pixmap().size() im2 = self.image.copy().scaled(self.sourceImg.width()*self.ZOOM_X,self.sourceImg.height()*self.ZOOM_X) self.crop.setPixmap(QPixmap.fromImage(im2.copy(rect))) #print self.crop.pixmap().size() pos = self.sourceImg.getMousePos() #print pos rgb = QColor(self.image.pixel(pos)) self.tootippixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + "); border: 1px solid;") self.tootippixel.setGeometry(pos.x(), pos.y()+52, 20,20) self.pixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ");border: 1px solid;") text = "XY ["+str(pos.x())+","+str(pos.y())+"]\nrgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ")" self.rgbVal.setText(text)
class QAVButton(QPushButton): def __init__(self, label): """ builds a custom button and displays it""" # calls super constuctor super(QAVButton, self).__init__(label) self.sound = QSoundEffect() self.volume = 1. self.color = QColor(Qt.gray) self.count = 0 self.duration = 1000 self.rate = 20 self.timer = QTimer() self.timer.timeout.connect(self.update_anim) self.mode = "sin" self.pressed.connect(self.start) self.released.connect(self.stop) self.is_accelerating = False self.update_color_with_alha(1) def setSound(self, sound_file): self.sound.setSource(QUrl.fromLocalFile(sound_file)) self.sound.setLoopCount(QSoundEffect.Infinite) def start(self): self.count = 0 self.sound.play() self.timer.start(self.rate) def stop(self): self.timer.stop() self.sound.stop() def set_color(self, col): self.color = col self.update_color_with_alha(1) def update_color_with_alha(self, alpha): red = self.color.red() green = self.color.green() blue = self.color.blue() bg_style = f"background-color:rgba({red},{green},{blue}, {alpha})" self.setStyleSheet(bg_style) def update_anim(self): #logarithmic (check with perception of luminosity/brighness) #val = math.log(count + 1) #linear if self.mode == "sin": val = math.sin(self.count * 2 * math.pi) / 2 + 0.5 elif self.mode == "lin": val = 1 - self.count else: val = math.log(self.count + 1) alpha = round(val * 100) + 155 self.update_color_with_alha(alpha) amplitude = val * 0.8 + 0.2 self.sound.setVolume(amplitude) self.count = self.count + self.rate / self.duration # print(count) if self.count >= 1 - self.rate / self.duration: self.count = 0 if self.is_accelerating: self.duration = max(200, self.duration * 0.95)
def _deserialize_color(color: QColor) -> AssColor: return AssColor( color.red(), color.green(), color.blue(), 255 - color.alpha() )
def updateGUI(self): defined_img=None if self.file_path is not None: defined_img=QImage(self.file_path).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) img = self.camera.getOrigImage() if defined_img is not None: img=defined_img self.image=img elif defined_img is None: if img is not None: self.image = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) if img is not None: self.sourceImg.setPixmap(QPixmap.fromImage(self.image)) #Filter Image filt = self.getFilterName() if (filt is not "Orig"): disc2 = self.camera.getFilter(filt).apply(self.colorSpace) imgDisc = QImage(disc2.data, disc2.shape[1], disc2.shape[0], disc2.shape[1] * disc2.shape[2], QImage.Format_RGB888).scaled(200, 200) self.colorSpaceLabel.setPixmap(QPixmap.fromImage(imgDisc)) img = self.camera.getOrigImage() if defined_img is not None: img2=cv2.imread(self.file_path) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) if (filt is not "Orig"): self.imageF=self.camera.getFilter(filt).apply(img2) self.imageF= QImage(self.imageF.data, self.imageF.shape[1], self.imageF.shape[0], self.imageF.shape[1] * self.imageF.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) else: self.imageF=QImage(img2.data, img2.shape[1], img2.shape[0], img2.shape[1] * img2.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) elif defined_img is None: if img is not None: img = self.camera.getFilteredImage(filt) self.imageF = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) #img = self.camera.getFilteredImage(filt) self.filterImg.setPixmap(QPixmap.fromImage(self.imageF)) #print "update" pos = self.sourceImg.getMousePos() if pos != None: #print pos x_ini = (self.sourceImg.width()*self.ZOOM_X*pos.x())/self.sourceImg.width() y_ini = (self.sourceImg.height()*self.ZOOM_X*pos.y())/self.sourceImg.height() rect = QRect(x_ini-100,y_ini-100,200,200) #print 'orig', pos.x(), ",", pos.y(), ",", self.sourceImg.size() #print 'scale', x_ini, ",", y_ini #self.crop.setPixmap(QPixmap.fromImage(self.image.copy(rect).scaled(1000,1000))) #print self.sourceImg.pixmap().size() im2 = self.image.copy().scaled(self.sourceImg.width()*self.ZOOM_X,self.sourceImg.height()*self.ZOOM_X) self.crop.setPixmap(QPixmap.fromImage(im2.copy(rect))) #print self.crop.pixmap().size() pos = self.sourceImg.getMousePos() #print pos rgb = QColor(self.image.pixel(pos)) self.tootippixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + "); border: 1px solid;") self.tootippixel.setGeometry(pos.x(), pos.y()+52, 20,20) self.pixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ");border: 1px solid;") text = "XY ["+str(pos.x())+","+str(pos.y())+"]\nrgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ")" self.rgbVal.setText(text)
class Canvas(widgets.QWidget): def __init__(self, parent=None): super().__init__(parent) self.background_color = QColor('#000000') self.rubberMode = False self.rubberModeStrokeWidthFctr = 20 self.stroke_width = 1 self.pen_color = QColor('#00FF00') self.col_prev_rct = QRect(0, 0, 20, 20) self.initImage() self.points = list() self.curDragPoints = list() self._initPointsAverager() self.reg = list() # self.setMouseTracking(True) def setPointsData(self, data): self.points = data.points self.img = data.img self.validateImage() self.update() def setPoints(self, points): self.points = points def validateImage(self): if self.img.isNull(): self.initImage() def getPointsData(self): return PointsData(self.points, self.img) @pyqtSlot() def retrieveUpdatedData(self): try: data = self.dataRetriever() self.setPointsData(data) except: pass @pyqtSlot() def updateData(self): try: self.dataUpdater(self.getPointsData()) except: pass def getPoints(self): return self.points def initImage(self): self.img = initImage(self.size(), self.background_color) def drawColorPreview(self): self.painter.setBrush(QBrush(self.pen_color)) self.painter.drawRect(self.col_prev_rct) def rgba(self): return (self.pen_color.red(), self.pen_color.green(), self.pen_color.blue(), self.pen_color.alpha()) @pyqtSlot(int, int, int, int) def rgba_changed(self, r, g, b, a): self.pen_color = QColor(r, g, b, a) self.update() @pyqtSlot('QString') def setPenColor(self, col_hex): self.pen_color = QColor(col_hex) self.update() @pyqtSlot() def saveImage(self): if self.img.isNull(): return img_path = saveFileDialog(self) if img_path: pixmp = QPixmap.fromImage(self.img) pixmp.save(img_path, quality=100) @pyqtSlot(int) def setStrokeWidth(self, sw): self.stroke_width = max(sw, 0.25) def strokeWidth(self): return self.stroke_width def resizeEvent(self, e): if not self.img.isNull(): self.img = resizeImage(self.img, self.size(), self.background_color) def paintEvent(self, event): painter = QPainter(self) self.painter = painter self.paintBackground() if not self.img.isNull(): pixmp = QPixmap.fromImage(self.img) painter.drawPixmap(pixmp.rect(), pixmp, pixmp.rect()) # for p in self.curDragPoints: # col = self.background_color if self.rubberMode else self.pen_color # self.drawDispersePoint(p, self.stroke_width, col=col) self.drawColorPreview() painter.end() del painter def createImagePainter(self): if self.img.isNull(): return painter = QPainter(self.img) self.painter = painter def deletePainter(self): self.painter.end() del self.painter def drawLinesOnImage(self, points): if self.img.isNull(): return self.createImagePainter() self.drawLines(points) self.deletePainter() def drawLatestAveragedPontsOnImage(self, averager=None): if averager is None: averager = self.pntsAvrgr # self.pntsAvrgr.getLatestAveragedPoints() - if no new points are available, None is returned! latestAvrgdPoints = averager.getLatestAveragedPoints() if latestAvrgdPoints is not None: self.drawLinesOnImage(latestAvrgdPoints) self.update() @pyqtSlot() def clearCanvas(self): self._clearPoints() self._clearImg() self.updateData() self.update() def _clearImg(self): if self.img.isNull(): return painter = QPainter(self.img) painter.setBrush(QBrush(self.background_color)) painter.drawRect(self.img.rect()) painter.end() del painter def _clearPoints(self): self.points.clear() self.curDragPoints.clear() def paintBackground(self): self.painter.setBrush(QBrush(self.background_color)) self.painter.drawRect(0, 0, 10000, 10000) def mouseMoveEvent(self, e): self.mouseMovePressed(e) def mousePressEvent(self, e): btns = e.buttons() if btns == Qt.LeftButton or btns == Qt.RightButton: self.rubberMode = btns == Qt.RightButton self._initPointsAverager() self.curDragPoints = list() self.addPoint((e.x(), e.y())) def _onAvrgrFinalized(self, averager): self.points.append(averager.getPoints()) self.updateData() self.update() def mouseReleaseEvent(self, e): #pnts_cnt = len(self.curDragPoints) self.pntsAvrgr.finalize() #self.points.append( self.pntsAvrgr.getPoints() ) #self.drawLatestAveragedPontsOnImage() self.curDragPoints = list() self.rubberMode = False self.update() def _initPointsAverager(self): pntsAvrgr = PointsAverager() pntsAvrgr.rubberMode = self.rubberMode def newAvrgPntsAvlbl(): rmBckup = self.rubberMode self.rubberMode = pntsAvrgr.rubberMode self._newAveragedPointsAvailable(pntsAvrgr) self.rubberMode = rmBckup def onFnlzd(): self._onAvrgrFinalized(pntsAvrgr) pntsAvrgr.onNewAvergedPointsAvailable.connect(newAvrgPntsAvlbl) pntsAvrgr.onFinalized.connect(onFnlzd) self.pntsAvrgr = pntsAvrgr def _newAveragedPointsAvailable(self, averager): self.drawLatestAveragedPontsOnImage(averager) def mouseMovePressed(self, e): curPnt = (e.x(), e.y()) self.addPoint(curPnt) def addPoint(self, p): self.curDragPoints.append(p) self.pntsAvrgr.addPoint(p) #self.drawLatestAveragedPontsOnImage() self.update() def drawLines(self, pnts): pen = QPen() pen.setWidth(1) pen_width = self.stroke_width if self.rubberMode: pen_width *= self.rubberModeStrokeWidthFctr col = self.background_color if self.rubberMode else self.pen_color ld = LineDrawer() ld.addPoints(pnts) ld.drawLines(self.painter, col, pen_width)
class MovablePolyLine(QGraphicsObject): def __init__(self, parent=None): super(MovablePolyLine, self).__init__(parent) self.setZValue(1000) self.polygon = QPolygonF() self.radius = 5.0 self.itemList = [] self.rect = QRectF() self.color = QColor(255,0,0) self.setOpacity(0.5) # self.setHandlesChildEvents(False) # self.setFlags(QGraphicsItem.ItemIsMovable) self.isDrawLine = True self.drawItemFlags = None self.points = None self.itemType = QGraphicsEllipseItem def setDrawLine(self, flag): self.isDrawLine = flag def setDrawItems(self, flags): self.drawItemFlags = flags for item, flag in zip(self.itemList, flags): if flag: item.show() else: item.hide() def setRadius(self, r): self.radius = r radii = 2*self.radius rectList = [QRectF(-self.radius, -self.radius, radii, radii) for p in self.points] for item, rect in zip(self.itemList, rectList): item.setRect(rect) def setLineWidth(self, w): self.lineWidth = w self.update() def getLineWidth(self): return self.lineWidth def setColor(self, rgb): self.color = QColor(*rgb) for item in self.itemList: item.setBrush(self.color) def getColor(self): return [self.color.red(),self.color.green(),self.color.blue()] def getRadius(self): return self.radius def setPoints(self, ps=None, flags=None): if ps is not None and self.points is not None: if len(ps)==len(self.points): self.points = ps for item, point in zip(self.itemList, self.points): item.setPos(*point) item.mouseMoveEvent = self.generateItemMouseMoveEvent(item, point) item.mousePressEvent = self.generateItemMousePressEvent(item, point) self.update() return scene = self.scene() if scene is not None: for item in self.itemList: scene.removeItem(item) del item self.itemList.clear() if ps is not None: self.points = ps if flags is not None: self.drawItemFlags = flags if self.points is not None: radii = 2*self.radius rectList = [QRectF(-self.radius, -self.radius, radii, radii) for p in self.points] self.itemList = [self.itemType(self) for rect in rectList] for item, point, rect, flag in zip(self.itemList, self.points, rectList, self.drawItemFlags): item.setBrush(self.color) item.setRect(rect) item.setPos(*point) if not flag: item.hide() item.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemSendsScenePositionChanges) item.setAcceptHoverEvents(True) item.mouseMoveEvent = self.generateItemMouseMoveEvent(item, point) item.mousePressEvent = self.generateItemMousePressEvent(item, point) def setRect(self, rect): self.rect = rect def generateItemMouseMoveEvent(self, item, point): def itemMouseMoveEvent(event): self.itemType.mouseMoveEvent(item, event) centerPos = item.scenePos() point[0] = centerPos.x() point[1] = centerPos.y() self.update() return itemMouseMoveEvent def generateItemMousePressEvent(self, item, point): def itemMousePressEvent(event): self.itemType.mousePressEvent(item, event) pass return itemMousePressEvent def boundingRect(self): return self.rect def paint(self, painter, option, widget): if self.points is not None and self.isDrawLine: painter.save() pen = QPen(self.color) pen.setWidth(self.getLineWidth()) painter.setPen(pen) qPoints = [QPointF(*p.tolist()) for p in self.points] polygon = QPolygonF(qPoints) painter.drawPolyline(polygon) painter.restore()
def mouseMoveEvent(self, event): if not self.cross: mouse_x = event.pos().x() mouse_y = event.pos().y() self.mouse_pos = event.pos() if self.img != None: rgb = QColor(self.img.pixel(self.mouse_pos)) text = "XY[" + str(mouse_x) + "," + str(mouse_y)+ "] RGB(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ")" QToolTip.showText(QPoint(QCursor.pos()), text) self.repaint()
def color_values(color: QColor) -> t.Tuple[int, int, int, int]: return color.red(), color.green(), color.blue(), color.alpha()
def blend_colors(color1: QColor, color2: QColor, ratio: float) -> int: return qRgb( int(color1.red() * (1 - ratio) + color2.red() * ratio), int(color1.green() * (1 - ratio) + color2.green() * ratio), int(color1.blue() * (1 - ratio) + color2.blue() * ratio), )
class GuiProjectEditStatus(QWidget): COL_LABEL = 0 COL_USAGE = 1 KEY_ROLE = Qt.UserRole COL_ROLE = Qt.UserRole + 1 NUM_ROLE = Qt.UserRole + 2 def __init__(self, mainGui, theProject, isStatus): QWidget.__init__(self, mainGui) self.mainConf = novelwriter.CONFIG self.mainGui = mainGui self.theProject = theProject self.mainTheme = mainGui.mainTheme if isStatus: self.theStatus = self.theProject.statusItems pageLabel = self.tr("Novel File Status Levels") colSetting = "statusColW" else: self.theStatus = self.theProject.importItems pageLabel = self.tr("Note File Importance Levels") colSetting = "importColW" wCol0 = self.mainConf.pxInt( self.theProject.options.getInt("GuiProjectSettings", colSetting, 130) ) self.colDeleted = [] self.colChanged = False self.selColour = QColor(100, 100, 100) self.iPx = self.mainTheme.baseIconSize # The List # ======== self.listBox = QTreeWidget() self.listBox.setHeaderLabels([ self.tr("Label"), self.tr("Usage"), ]) self.listBox.itemSelectionChanged.connect(self._selectedItem) self.listBox.setColumnWidth(self.COL_LABEL, wCol0) self.listBox.setIndentation(0) for key, entry in self.theStatus.items(): self._addItem(key, entry["name"], entry["cols"], entry["count"]) # List Controls # ============= self.addButton = QPushButton(self.mainTheme.getIcon("add"), "") self.addButton.clicked.connect(self._newItem) self.delButton = QPushButton(self.mainTheme.getIcon("remove"), "") self.delButton.clicked.connect(self._delItem) self.upButton = QPushButton(self.mainTheme.getIcon("up"), "") self.upButton.clicked.connect(lambda: self._moveItem(-1)) self.dnButton = QPushButton(self.mainTheme.getIcon("down"), "") self.dnButton.clicked.connect(lambda: self._moveItem(1)) # Edit Form # ========= self.editName = QLineEdit() self.editName.setMaxLength(40) self.editName.setEnabled(False) self.editName.setPlaceholderText(self.tr("Select item to edit")) self.colPixmap = QPixmap(self.iPx, self.iPx) self.colPixmap.fill(QColor(100, 100, 100)) self.colButton = QPushButton(QIcon(self.colPixmap), self.tr("Colour")) self.colButton.setIconSize(self.colPixmap.rect().size()) self.colButton.clicked.connect(self._selectColour) self.saveButton = QPushButton(self.tr("Save")) self.saveButton.clicked.connect(self._saveItem) # Assemble # ======== self.listControls = QVBoxLayout() self.listControls.addWidget(self.addButton) self.listControls.addWidget(self.delButton) self.listControls.addWidget(self.upButton) self.listControls.addWidget(self.dnButton) self.listControls.addStretch(1) self.editBox = QHBoxLayout() self.editBox.addWidget(self.editName) self.editBox.addWidget(self.colButton) self.editBox.addWidget(self.saveButton) self.mainBox = QVBoxLayout() self.mainBox.addWidget(self.listBox) self.mainBox.addLayout(self.editBox) self.innerBox = QHBoxLayout() self.innerBox.addLayout(self.mainBox) self.innerBox.addLayout(self.listControls) self.outerBox = QVBoxLayout() self.outerBox.addWidget(QLabel("<b>%s</b>" % pageLabel)) self.outerBox.addLayout(self.innerBox) self.setLayout(self.outerBox) return def getNewList(self): """Return list of entries. """ if self.colChanged: newList = [] for n in range(self.listBox.topLevelItemCount()): item = self.listBox.topLevelItem(n) newList.append({ "key": item.data(self.COL_LABEL, self.KEY_ROLE), "name": item.text(self.COL_LABEL), "cols": item.data(self.COL_LABEL, self.COL_ROLE), }) return newList, self.colDeleted return [], [] ## # User Actions ## def _selectColour(self): """Open a dialog to select the status icon colour. """ if self.selColour is not None: newCol = QColorDialog.getColor( self.selColour, self, self.tr("Select Colour") ) if newCol.isValid(): self.selColour = newCol pixmap = QPixmap(self.iPx, self.iPx) pixmap.fill(newCol) self.colButton.setIcon(QIcon(pixmap)) self.colButton.setIconSize(pixmap.rect().size()) return def _newItem(self): """Create a new status item. """ newItem = self._addItem(None, self.tr("New Item"), (100, 100, 100), 0) newItem.setBackground(self.COL_LABEL, QBrush(QColor(0, 255, 0, 70))) newItem.setBackground(self.COL_USAGE, QBrush(QColor(0, 255, 0, 70))) self.colChanged = True return def _delItem(self): """Delete a status item. """ selItem = self._getSelectedItem() if selItem is not None: iRow = self.listBox.indexOfTopLevelItem(selItem) if selItem.data(self.COL_LABEL, self.NUM_ROLE) > 0: self.mainGui.makeAlert(self.tr( "Cannot delete a status item that is in use." ), nwAlert.ERROR) else: self.listBox.takeTopLevelItem(iRow) self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE)) self.colChanged = True return def _saveItem(self): """Save changes made to a status item. """ selItem = self._getSelectedItem() if selItem is not None: selItem.setText(self.COL_LABEL, simplified(self.editName.text())) selItem.setIcon(self.COL_LABEL, self.colButton.icon()) selItem.setData(self.COL_LABEL, self.COL_ROLE, ( self.selColour.red(), self.selColour.green(), self.selColour.blue() )) self.editName.setEnabled(False) self.colChanged = True return def _addItem(self, key, name, cols, count): """Add a status item to the list. """ pixmap = QPixmap(self.iPx, self.iPx) pixmap.fill(QColor(*cols)) item = QTreeWidgetItem() item.setText(self.COL_LABEL, name) item.setIcon(self.COL_LABEL, QIcon(pixmap)) item.setData(self.COL_LABEL, self.KEY_ROLE, key) item.setData(self.COL_LABEL, self.COL_ROLE, cols) item.setData(self.COL_LABEL, self.NUM_ROLE, count) item.setText(self.COL_USAGE, self._usageString(count)) self.listBox.addTopLevelItem(item) return item def _moveItem(self, step): """Move and item up or down step. """ selItem = self._getSelectedItem() if selItem is None: return tIndex = self.listBox.indexOfTopLevelItem(selItem) nChild = self.listBox.topLevelItemCount() nIndex = tIndex + step if nIndex < 0 or nIndex >= nChild: return cItem = self.listBox.takeTopLevelItem(tIndex) self.listBox.insertTopLevelItem(nIndex, cItem) self.listBox.clearSelection() cItem.setSelected(True) self.colChanged = True return def _selectedItem(self): """Extract the info of a selected item and populate the settings boxes and button. """ selItem = self._getSelectedItem() if selItem is None: return cols = selItem.data(self.COL_LABEL, self.COL_ROLE) name = selItem.text(self.COL_LABEL) pixmap = QPixmap(self.iPx, self.iPx) pixmap.fill(QColor(*cols)) self.selColour = QColor(*cols) self.editName.setText(name) self.colButton.setIcon(QIcon(pixmap)) self.editName.setEnabled(True) self.editName.selectAll() self.editName.setFocus() return ## # Internal Functions ## def _getSelectedItem(self): """Get the currently selected item. """ selItem = self.listBox.selectedItems() if len(selItem) > 0: return selItem[0] return None def _usageString(self, nUse): """Generate usage string. """ if nUse == 0: return self.tr("Not in use") elif nUse == 1: return self.tr("Used once") else: return self.tr("Used by {0} items").format(nUse)
class AppWindow(QMainWindow): def __init__(self): super(AppWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.img_area.setScaledContents(False) self.ui.img_area.setStyleSheet('border: 1px solid red') self.add_tool_bar() self.bind_actions() self.init_vars() def init_vars(self): self.open_mode = OPEN_MODE.OPEN_FILE self.opened_files = [] self.cur_img = None self.panel_pic = None # 用来在上面绘制矩阵等形状 self.origin_img = None # 保留原始大小的图片 self.labelimg = None self.scale = 1 self.cur_rect_list = [] self.cur_label_list = [] self.histroty = [] self.fill_color = QColor('green') self.pixel_range = [-5, 5] self.state = STATE.NORMAL self.start_point = None self.end_point = None self.polygon_points = None self.ellipse_points = None self.modified = False self.saved = False self.logger = logging.getLogger(__name__) self.logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(levelname)s %(funcName)s %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) def refresh_vars(self): self.cur_img = None self.panel_pic = None # 用来在上面绘制矩阵等形状 self.origin_img = None # 保留原始大小的图片 self.labelimg = None self.scale = 1 self.cur_rect_list = [] self.cur_label_list = [] self.histroty = [] self.state = STATE.NORMAL self.ui.actionRectangle.setChecked(False) self.ui.actionPolygon.setChecked(False) self.ui.actionEllipse.setChecked(False) self.start_point = None self.end_point = None self.polygon_points = None self.ellipse_points = None self.modified = False self.saved = False def bind_actions(self): self.ui.actionOpen_File.triggered.connect(self.open_file) self.ui.actionOpen_Dir.triggered.connect(self.open_dir) self.ui.file_list.itemClicked.connect(self.file_list_item_changed) self.ui.actionZoom_In.triggered.connect(self.zoom_in_pic) self.ui.actionZoom_Out.triggered.connect(self.zoom_out_pic) self.ui.img_area.mouse_pressed.connect(self.mouse_pressed) self.ui.img_area.mouse_move.connect(self.mouse_move) self.ui.img_area.mouse_release.connect(self.mouse_release) self.ui.actionfill_color.triggered.connect(self.set_fill_color) self.ui.actionSet_Pixel_Range.triggered.connect(self.set_pixel_range) self.ui.actionUndo.triggered.connect(self.undo) self.ui.actionSave.triggered.connect(self.save) self.ui.actionPolygon.triggered.connect(self.create_polygon) self.ui.actionRectangle.triggered.connect(self.create_rectangle) self.ui.actionEllipse.triggered.connect(self.create_ellipse) def save(self): name = str(self.selected_filename.absolute()) items = name.split('.') output_filename = '.'.join(items[:-1]) + '.npy' np.save(output_filename, self.labelimg) self.saved = True self.modified = False def undo(self, checked): if self.state == STATE.DRAW_POLYGON and self.polygon_points is not None and self.polygon_points[ 'finish'] is False: if len(self.polygon_points['points']) == 1: self.polygon_points = None elif len(self.polygon_points['points']) > 1: self.polygon_points['points'].pop(-1) self.draw_lines(self.polygon_points['points'], False) if self.labelimg is not None: pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) else: if len(self.histroty) == 0: return x, y = self.histroty.pop(-1) self.labelimg[x, y] = 0 pic = self.draw_points() self.show_pic(file_name=None, content=pic) self.modified = True def set_fill_color(self, checked): color = QColorDialog.getColor() if color.isValid(): self.fill_color = color def set_pixel_range(self, checked): dialog = PixelRangeDialog() if dialog.exec_(): v1, v2 = dialog.get_result() self.pixel_range = [v1, v2] self.logger.debug(self.pixel_range) def create_polygon(self, checked): if checked: self.state = STATE.DRAW_POLYGON self.ui.actionEllipse.setChecked(False) self.ui.actionRectangle.setChecked(False) else: self.state = STATE.NORMAL def create_rectangle(self, checked): if checked: self.state = STATE.DRAW_RECTANGLE self.ui.actionEllipse.setChecked(False) self.ui.actionPolygon.setChecked(False) else: self.state = STATE.NORMAL def create_ellipse(self, checked): if checked: self.state = STATE.DRAW_ELLIPSE self.ui.actionPolygon.setChecked(False) self.ui.actionRectangle.setChecked(False) else: self.state = STATE.NORMAL def pos_in_img_area(self, pos: PyQt5.QtCore.QPoint): if self.cur_img is None: return False, None width = self.ui.img_area.width() height = self.ui.img_area.height() img_height, img_width, _ = self.cur_img.shape w = (width - img_width) // 2 h = (height - img_height) // 2 x_valid = w <= pos.x() <= w + img_width y_valid = h <= pos.y() <= h + img_height valid = x_valid and y_valid if valid: return True, (pos.x() - w, pos.y() - h) else: return False, None def mouse_pressed(self, ev: QMouseEvent): if self.state == STATE.NORMAL: return if ev.button() == Qt.LeftButton: pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) self.logger.debug(valid) if valid: self.logger.debug(relative_pos) point = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) if self.state == STATE.DRAW_RECTANGLE: self.start_point = point self.end_point = None self.logger.debug(self.start_point) elif self.state == STATE.DRAW_POLYGON: if self.polygon_points is None or self.polygon_points[ 'finish'] is True: self.polygon_points = { 'finish': False, 'points': [point] } else: p1 = np.array([ self.polygon_points['points'][0][0] * self.scale, self.polygon_points['points'][0][1] * self.scale ]) p2 = np.array( [point[0] * self.scale, point[1] * self.scale]) dis = np.linalg.norm(p1 - p2, 2) if dis < 10: self.polygon_points['finish'] = True self.draw_lines(self.polygon_points['points'], True) else: self.polygon_points['points'].append(point) self.draw_lines(self.polygon_points['points'], False) if self.labelimg is not None: pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif self.state == STATE.DRAW_ELLIPSE: if self.ellipse_points is None: self.ellipse_points = {'points': [point], 'info': None} elif len(self.ellipse_points['points']) == 1: self.ellipse_points['points'].append(point) self.draw_lines(self.ellipse_points['points'], False) if self.labelimg is not None: pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif len(self.ellipse_points['points']) == 2: self.ellipse_points['points'].append(point) self.ellipse_points['info'] = self.draw_ellipse( self.ellipse_points['points']) if self.labelimg is not None: pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) else: self.ellipse_points = {'points': [point], 'info': None} else: raise NotImplementedError() elif ev.button() == Qt.RightButton: pass def mouse_move(self, ev: QMouseEvent): if self.state == STATE.NORMAL: return pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) if valid: relative_pos = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) if self.state == STATE.DRAW_RECTANGLE: self.draw_rect(self.start_point, relative_pos) if self.labelimg is not None: pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif self.state == STATE.DRAW_POLYGON: pass elif self.state == STATE.DRAW_ELLIPSE: pass else: raise NotImplementedError() def draw_ellipse(self, points): color_r, color_g, color_b = self.fill_color.red( ), self.fill_color.green(), self.fill_color.blue() points = list( map( lambda item: (int(item[0] * self.scale), int(item[1] * self.scale)), points)) p1 = np.array(points[0]) p2 = np.array(points[1]) if p1[0] > p2[0]: p1, p2 = p2, p1 p3 = np.array(points[2]) center = tuple((p1 + p2) // 2) r1 = int(np.linalg.norm(p1 - p2, 2) / 2) a = p2[1] - p1[1] b = p1[0] - p2[0] c = p2[0] * p1[1] - p1[0] * p2[1] r2 = int(np.abs(a * p3[0] + b * p3[1] + c) / np.sqrt(a**2 + b**2)) if r1 > r2: theta = -1 * (np.arctan(a / b) * 180) / np.pi self.panel_pic = cv.ellipse(self.cur_img.copy(), center, (r1, r2), theta, 0, 360, (color_r, color_g, color_b), 1) return ((int(center[0] / self.scale), int(center[1] / self.scale)), (int(r1 / self.scale), int(r2 / self.scale)), theta) else: theta = (np.arctan(a / b) * 180) / np.pi if theta > 0: theta = 90 - theta else: theta = -90 - theta self.panel_pic = cv.ellipse(self.cur_img.copy(), center, (r2, r1), theta, 0, 360, (color_r, color_g, color_b), 1) return ((int(center[0] / self.scale), int(center[1] / self.scale)), (int(r2 / self.scale), int(r1 / self.scale)), theta) def draw_lines(self, points, end=False): b, g, r = self.fill_color.blue(), self.fill_color.green( ), self.fill_color.red() temp_img = self.cur_img.copy() points = list( map( lambda item: (int(item[0] * self.scale), int(item[1] * self.scale)), points)) for i in range(len(points) - 1): temp_img = cv.line(temp_img, points[i], points[i + 1], (r, g, b), 1) if end: temp_img = cv.line(temp_img, points[-1], points[0], (r, g, b), 1) self.panel_pic = temp_img def draw_rect(self, start_point, end_point): b, g, r = self.fill_color.blue(), self.fill_color.green( ), self.fill_color.red() self.fill_color.rgb() start_point = (int(start_point[0] * self.scale), int(start_point[1] * self.scale)) end_point = (int(end_point[0] * self.scale), int(end_point[1] * self.scale)) self.panel_pic = cv.rectangle(self.cur_img.copy(), start_point, end_point, (r, g, b), 1) def draw_points(self): if self.labelimg is None: return b, g, r = self.fill_color.blue(), self.fill_color.green( ), self.fill_color.red() x, y = np.where(self.labelimg == 1) temp = self.panel_pic.copy() for i in range(x.shape[0]): cv.circle(temp, (int(y[i] * self.scale), int(x[i] * self.scale)), 1, (r, g, b), 1) return temp def mouse_release(self, ev: QMouseEvent): if self.state == STATE.NORMAL: return if ev.button() == Qt.LeftButton: if self.state == STATE.DRAW_RECTANGLE: pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) self.logger.debug(valid) if valid: self.logger.debug(relative_pos) self.end_point = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) elif ev.button() == Qt.RightButton: if self.state == STATE.NORMAL: return if self.state == STATE.DRAW_RECTANGLE: if self.start_point is None or self.end_point is None: return pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) if valid: click_pos = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) min_x, max_x = min(self.start_point[0], self.end_point[0]), max( self.start_point[0], self.end_point[0]) min_y, max_y = min(self.start_point[1], self.end_point[1]), max( self.start_point[1], self.end_point[1]) self.logger.debug(click_pos) if min_x <= click_pos[0] <= max_x and min_y <= click_pos[ 1] <= max_y: pixel_value = self.origin_img[click_pos[1], click_pos[0], 0] low, high = pixel_value + \ self.pixel_range[0], pixel_value + \ self.pixel_range[1] selected_area = self.origin_img[min_y:max_y + 1, min_x:max_x + 1, 0] x, y = np.where( (selected_area >= low) * (selected_area <= high)) x = x + min_y y = y + min_x self.labelimg[x, y] = 1 pic = self.draw_points() self.show_pic(file_name=None, content=pic) self.histroty.append((x, y)) self.modified = True elif self.state == STATE.DRAW_POLYGON: if self.polygon_points is None or self.polygon_points[ 'finish'] is False: return pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) if valid: click_pos = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) self.logger.debug(click_pos) x_pos = np.array( [item[0] for item in self.polygon_points['points']]) y_pos = np.array( [item[1] for item in self.polygon_points['points']]) min_x, max_x = x_pos.min(), x_pos.max() min_y, max_y = y_pos.min(), y_pos.max() p = np.array(self.polygon_points['points']).reshape( [1, len(self.polygon_points['points']), 2]) p[0, :, 0] -= min_x p[0, :, 1] -= min_y mask = np.zeros([max_y - min_y + 1, max_x - min_x + 1], np.uint8) mask = cv.fillPoly(mask, p, 1) pixel_value = self.origin_img[click_pos[1], click_pos[0], 0] low, high = pixel_value + \ self.pixel_range[0], pixel_value + self.pixel_range[1] selected_img = self.origin_img[min_y:max_y + 1, min_x:max_x + 1, 0] x, y = np.where( (selected_img >= low) * (selected_img <= high) * mask) x = x + min_y y = y + min_x self.labelimg[x, y] = 1 pic = self.draw_points() self.show_pic(file_name=None, content=pic) self.histroty.append((x, y)) self.modified = True elif self.state == STATE.DRAW_ELLIPSE: if self.ellipse_points is None or len( self.ellipse_points['points'] ) < 3 or self.ellipse_points['info'] is None: return pos = ev.pos() valid, relative_pos = self.pos_in_img_area(pos) if valid: click_pos = (int(relative_pos[0] / self.scale), int(relative_pos[1] / self.scale)) self.logger.debug(click_pos) center, r, theta = self.ellipse_points['info'] theta = int(np.around(theta)) p = cv.ellipse2Poly(center, r, theta, 0, 360, 1) num_p = p.shape[0] p = p.reshape((1, num_p, 2)) min_x, max_x = np.min(p[0, :, 0]), np.max(p[0, :, 0]) min_y, max_y = np.min(p[0, :, 1]), np.max(p[0, :, 1]) p[0, :, 0] -= min_x p[0, :, 1] -= min_y mask = np.zeros((max_y - min_y + 1, max_x - min_x + 1), np.uint8) mask = cv.fillPoly(mask, p, 1) pixel_value = self.origin_img[click_pos[1], click_pos[0], 0] low, high = pixel_value + \ self.pixel_range[0], pixel_value + self.pixel_range[1] selected_img = self.origin_img[min_y:max_y + 1, min_x:max_x + 1, 0] x, y = np.where( (selected_img >= low) * (selected_img <= high) * mask) x = x + min_y y = y + min_x self.labelimg[x, y] = 1 pic = self.draw_points() self.show_pic(file_name=None, content=pic) self.histroty.append((x, y)) self.modified = True self.saved = False def zoom_in_pic(self, checked): self.zoom_pic(True) def zoom_out_pic(self, checked): self.zoom_pic(False) def zoom_pic(self, zoom_in): if self.cur_img is None: return if zoom_in: if self.scale >= 5: pass elif self.scale < 1: self.scale += 0.1 else: self.scale += 1 else: if self.scale == 0: pass elif self.scale <= 1: self.scale -= 0.1 else: self.scale -= 1 self.logger.debug(self.scale) height, width, _ = self.origin_img.shape self.cur_img = cv.resize( self.origin_img, (int(height * self.scale), int(width * self.scale)), cv.INTER_LINEAR) if self.state == STATE.DRAW_RECTANGLE: if self.start_point is not None and self.end_point is not None: self.draw_rect(self.start_point, self.end_point) if self.labelimg is not None: pic = self.draw_points() self.show_pic(content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif self.state == STATE.DRAW_POLYGON: if self.polygon_points is not None and self.polygon_points[ 'finish'] is True: self.draw_lines(self.polygon_points['points'], True) if self.labelimg is not None: pic = self.draw_points() self.show_pic(content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif self.state == STATE.DRAW_ELLIPSE: if self.ellipse_points is not None and len( self.ellipse_points['points']) == 3: self.draw_ellipse(self.ellipse_points['points']) if self.labelimg is not None: pic = self.draw_points() self.show_pic(content=pic) else: self.show_pic(file_name=None, content=self.panel_pic) elif self.labelimg is not None: self.panel_pic = self.cur_img.copy() pic = self.draw_points() self.show_pic(file_name=None, content=pic) else: self.show_pic(file_name=None) def file_list_item_changed(self, item): if self.modified and not self.saved: res = QMessageBox.warning( self, 'warning', 'Changes not saved, do you want to save?', QMessageBox.Ok | QMessageBox.No, QMessageBox.Ok) if res == QMessageBox.Ok: self.save() base_pic_name = item.text() for index, filename in enumerate(self.opened_files): if filename.name == base_pic_name: selected_filename = filename break self.selected_filename = selected_filename self.refresh_vars() self.open(self.selected_filename) def add_tool_bar(self): self.toolbar = QToolBar() self.addToolBar(Qt.TopToolBarArea, self.toolbar) self.toolbar.addAction(self.ui.actionOpen_File) self.toolbar.addAction(self.ui.actionOpen_Dir) self.toolbar.addAction(self.ui.actionSave) self.toolbar.addAction(self.ui.actionZoom_In) self.toolbar.addAction(self.ui.actionZoom_Out) self.toolbar.addAction(self.ui.actionfill_color) self.toolbar.addAction(self.ui.actionSet_Pixel_Range) self.toolbar.addAction(self.ui.actionRectangle) self.toolbar.addAction(self.ui.actionEllipse) self.toolbar.addAction(self.ui.actionPolygon) self.toolbar.addAction(self.ui.actionUndo) def show_pic(self, file_name=None, content=None): if file_name is not None: file_name = str(file_name.absolute()) img = cv.imdecode(np.fromfile(file_name, dtype=np.uint8), -1) assert img is not None if len(img.shape) == 2: img = cv.cvtColor(img, cv.COLOR_GRAY2BGR) height, width, channel = img.shape self.cur_img = cv.cvtColor(img, cv.COLOR_BGR2RGB) self.origin_img = self.cur_img self.labelimg = np.zeros(self.origin_img.shape[:2], dtype=np.int) qimg = QImage(self.cur_img.data, width, height, width * channel, QImage.Format_RGB888) self.ui.img_area.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.ui.img_area.setPixmap(QPixmap.fromImage(qimg)) self.ui.img_area.adjustSize() elif content is not None: height, width, channel = content.shape qimg = QImage(content.data, width, height, width * channel, QImage.Format_RGB888) self.ui.img_area.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.ui.img_area.setPixmap(QPixmap.fromImage(qimg)) self.ui.img_area.adjustSize() else: height, width, channel = self.cur_img.shape qimg = QImage(self.cur_img.data, width, height, width * channel, QImage.Format_RGB888) self.ui.img_area.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.ui.img_area.setPixmap(QPixmap.fromImage(qimg)) self.ui.img_area.adjustSize() def open_file(self, checked): if self.modified and not self.saved: res = QMessageBox.warning( self, 'warning', 'Changes not saved, do you want to save?', QMessageBox.Ok | QMessageBox.No, QMessageBox.Ok) if res == QMessageBox.Ok: self.save() filename, filetype = QFileDialog.getOpenFileName( self, '选取文件', '.', 'PNG Files(*.png);;JPG Files(*.jpg)') if filename == '': return filename = Path(filename) self.open_mode = OPEN_MODE.OPEN_FILE self.opened_files = [filename] self.selected_filename = filename self.open(self.selected_filename) self.refresh_list() def open_dir(self, checked): if self.modified and not self.saved: res = QMessageBox.warning( self, 'warning', 'Changes not saved, do you want to save?', QMessageBox.Ok | QMessageBox.No, QMessageBox.Ok) if res == QMessageBox.Ok: self.save() opened_dir = QFileDialog.getExistingDirectory(self, '打开文件夹', '.') if opened_dir == '': return opened_dir = Path(opened_dir) self.open_mode = OPEN_MODE.OPEN_DIR self.opened_files = list(opened_dir.iterdir()) self.opened_files = [ item for item in self.opened_files if util.is_pic(item) ] if len(self.opened_files) == 0: QMessageBox.warning(self, 'warning', 'No image found') else: self.selected_filename = self.opened_files[0] self.open(self.selected_filename) self.refresh_list() def refresh_list(self): self.ui.file_list.clear() for file_name in self.opened_files: base_name = file_name.name self.ui.file_list.addItem(base_name) def open(self, filename: Path): self.setWindowTitle(filename.name) self.show_pic(file_name=filename) temp = str(filename).split('.') npy_filename = '.'.join(temp[:-1]) + '.npy' if os.path.exists(npy_filename): self.labelimg = np.load(npy_filename) self.panel_pic = self.cur_img.copy() pic = self.draw_points() self.show_pic(file_name=None, content=pic)
class TimelineDelta(object): """ """ def __init__(self, begin, end=30, title=None, height=30, top=0, parent=None): """ :param begin: :param end: :param title: :param height: :param top: :param parent: """ self._top = top self._height = height self._parent = parent self._title = title self._lock = False self._begin = begin self._end = end self.checkNumberOfTracks() self._defautcolor = parent._tracks[self.track].color ########################################################################## #### HELPERS/FUNCTIONS ################################################### ########################################################################## def checkNumberOfTracks(self): """ :return: """ if self.track >= (self._parent.numberoftracks - 1): for i in range(self._parent.numberoftracks - 1, self.track + 1): self._parent.addTrack() def collide(self, x, y): """ :param x: :param y: :return: """ return self.begin <= x <= self.end and self._top <= y <= (self._top + self._height) def in_range(self, start, end): """ :param start: :param end: :return: """ return start <= self.begin and end >= self.end or \ self.begin <= start <= self.end or \ self.begin <= end <= self.end def canSlideBegin(self, x, y): """ :param x: :param y: :return: """ return not self._lock and x == int(round(self.begin)) and self._top <= y <= (self._top + self._height) def canSlideEnd(self, x, y): """ :param x: :param y: :return: """ return not self._lock and int(round(self.end)) == x and self._top <= y <= (self._top + self._height) def moveEnd(self, x): """ Move the right edge of the event rectangle. :param x: """ # Do nothing if locked if self._lock: return # Do nothing if trying to go over the pther edge if self._end <= self._begin - x and x < 0: return # Increment accordingly self._end += x / self._parent._scale # Minimum begin position is at 0 if self._end > (self._parent.width() / self._parent._scale): self._end = (self._parent.width() / self._parent._scale) def moveBegin(self, x): """ Move the left edge of the event rectangle. :param x: """ # Do nothing if locked if self._lock: return # Do nothing if trying to go over the other edge if self._begin >= self._end - x and x > 0: return # Increment accordingly self._begin += x / self._parent._scale # Minimum begin position is at 0 if self._begin < 0: self._begin = 0 def move(self, x, y): """ :param x: :param y: :return: """ if self._lock: return if (self.begin + x) >= 0 and (self.end + x) <= self._parent.width(): self._begin += x / self._parent._scale self._end += x / self._parent._scale current_track = self.track new_track = Track.whichTrack(y) if current_track != new_track and new_track >= 0 and new_track <= self._parent.numberoftracks: self.track = new_track self.checkNumberOfTracks() def showEditWindow(self): """ :return: """ text, ok = QInputDialog.getText( self._parent, 'Edit event', 'Comment:', text=self._title) if ok: self._title = str(text) self._parent.repaint() def draw(self, painter, showvalues=False): """ :param painter: :param showvalues: :return: """ start, end = self.begin, self.end if self._lock: transparency = 0.1 else: transparency = 0.5 painter.setPen(QColor(0, 0, 0)) painter.setOpacity(transparency) painter.drawRoundedRect( start, self._top, end - start, self._height, 3, 3) painter.setOpacity(1.0) painter.drawText(start + 3, self._top + 19, self._title) if showvalues: painter.drawText( start, self._top + 44, "[%d;%d] delta:%d" % (self._begin, self._end, self._end - self._begin)) def remove(self): """ :return: """ try: self._parent._tracks[self.track].periods.remove(self) except: pass ########################################################################## #### PROPERTIES ########################################################## ########################################################################## @property def title(self): return self._title @property def lock(self): return self._lock @lock.setter def lock(self, value): self._lock = value @property def begin(self): return self._begin * self._parent._scale @begin.setter def begin(self, value): if self._lock: return self._begin = value / self._parent._scale if self._begin < 0: self._begin = 0 @property def end(self): return self._end * self._parent._scale @end.setter def end(self, value): if self._lock: return self._end = value / self._parent._scale if self._end > (self._parent.width() / self._parent._scale): self._end = (self._parent.width() / self._parent._scale) @property def track(self): return Track.whichTrack(self._top) @track.setter def track(self, value): # if the object exists in other track remove it if self.track < len(self._parent._tracks) and self in self._parent._tracks[self.track].periods: self.remove() # Verify if the new track exists. In case not create it self._top = Track.whichTop(value) if self.track >= len(self._parent._tracks): self._parent.addTrack() # if do not exists in the track add it if self not in self._parent._tracks[self.track].periods: self._parent._tracks[self.track].periods.append(self) @property def color(self): return self._defautcolor @color.setter def color(self, value): self._defautcolor = QColor(value) if (type(value) == str) else value @property def bgrcolor(self): return self._defautcolor.blue(), self._defautcolor.green(), self._defautcolor.red() @property def properties(self): return ['P', self._lock, int(round(self._begin)), int(round(self._end)), self._title, self._defautcolor.name(), self.track] @properties.setter def properties(self, value): self._lock = value[1] == 'True' self._begin = int(value[2]) self._end = int(value[3]) self._title = value[4] self._defautcolor = QColor(value[5]) self.track = int(value[6]) self.checkNumberOfTracks()
def to_css_format(color: QColor, alpha=255): return "rgba({r}, {g}, {b}, {a})".format(r=color.red(), g=color.green(), b=color.blue(), a=alpha)
def QtColorToSting(clr: QtGui.QColor): return "rgb({0}, {1}, {2})".format(clr.red(), clr.green(), clr.blue())
def onchange_text(): color = QColor(qrand() % 256, qrand() % 256, qrand() % 256) w.setStyleSheet('background: rgb({}, {}, {});'.format(color.red(), color.green(), color.blue()))
def updateGUI(self): defined_img = None if self.file_path is not None: defined_img = QImage(self.file_path).scaled( self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) img = self.camera.getOrigImage() if defined_img is not None: img = defined_img self.image = img elif defined_img is None: if img is not None: self.image = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled( self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) if img is not None: self.sourceImg.setPixmap(QPixmap.fromImage(self.image)) #Filter Image filt = self.getFilterName() if (filt is not "Orig"): disc2 = self.camera.getFilter(filt).apply(self.colorSpace) imgDisc = QImage(disc2.data, disc2.shape[1], disc2.shape[0], disc2.shape[1] * disc2.shape[2], QImage.Format_RGB888).scaled(200, 200) self.colorSpaceLabel.setPixmap(QPixmap.fromImage(imgDisc)) img = self.camera.getOrigImage() if defined_img is not None: img2 = cv2.imread(self.file_path) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) if (filt is not "Orig"): self.imageF = self.camera.getFilter(filt).apply(img2) self.imageF = QImage( self.imageF.data, self.imageF.shape[1], self.imageF.shape[0], self.imageF.shape[1] * self.imageF.shape[2], QImage.Format_RGB888).scaled(self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) else: self.imageF = QImage(img2.data, img2.shape[1], img2.shape[0], img2.shape[1] * img2.shape[2], QImage.Format_RGB888).scaled( self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) elif defined_img is None: if img is not None: img = self.camera.getFilteredImage(filt) self.imageF = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * img.shape[2], QImage.Format_RGB888).scaled( self.IMAGE_COLS_MAX, self.IMAGE_ROWS_MAX) #img = self.camera.getFilteredImage(filt) self.filterImg.setPixmap(QPixmap.fromImage(self.imageF)) #print "update" pos = self.sourceImg.getMousePos() if pos != None: #print pos x_ini = (self.sourceImg.width() * self.ZOOM_X * pos.x()) / self.sourceImg.width() y_ini = (self.sourceImg.height() * self.ZOOM_X * pos.y()) / self.sourceImg.height() rect = QRect(x_ini - 100, y_ini - 100, 200, 200) #print 'orig', pos.x(), ",", pos.y(), ",", self.sourceImg.size() #print 'scale', x_ini, ",", y_ini #self.crop.setPixmap(QPixmap.fromImage(self.image.copy(rect).scaled(1000,1000))) #print self.sourceImg.pixmap().size() im2 = self.image.copy().scaled( self.sourceImg.width() * self.ZOOM_X, self.sourceImg.height() * self.ZOOM_X) self.crop.setPixmap(QPixmap.fromImage(im2.copy(rect))) #print self.crop.pixmap().size() pos = self.sourceImg.getMousePos() #print pos rgb = QColor(self.image.pixel(pos)) self.tootippixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + "); border: 1px solid;") self.tootippixel.setGeometry(pos.x(), pos.y() + 52, 20, 20) self.pixel.setStyleSheet("background: rgb(" + str(rgb.red()) + "," + str(rgb.green()) + "," + str(rgb.blue()) + ");border: 1px solid;") text = "XY [" + str(pos.x()) + "," + str( pos.y()) + "]\nrgb(" + str(rgb.red()) + "," + str( rgb.green()) + "," + str(rgb.blue()) + ")" self.rgbVal.setText(text)
def _setColor(self, color: QColor): self.color = color self.setStyleSheet("background-color: rgb({},{},{});".format( color.red(), color.green(), color.blue()))
class ColorItem(QGraphicsItem): n = 0 def __init__(self): super(ColorItem, self).__init__() self.color = QColor(qrand() % 256, qrand() % 256, qrand() % 256) self.setToolTip( "QColor(%d, %d, %d)\nClick and drag this color onto the robot!" % (self.color.red(), self.color.green(), self.color.blue())) self.setCursor(Qt.OpenHandCursor) def boundingRect(self): return QRectF(-15.5, -15.5, 34, 34) def paint(self, painter, option, widget): painter.setPen(Qt.NoPen) painter.setBrush(Qt.darkGray) painter.drawEllipse(-12, -12, 30, 30) painter.setPen(QPen(Qt.black, 1)) painter.setBrush(QBrush(self.color)) painter.drawEllipse(-15, -15, 30, 30) def mousePressEvent(self, event): if event.button() != Qt.LeftButton: event.ignore() return self.setCursor(Qt.ClosedHandCursor) def mouseMoveEvent(self, event): if QLineF(QPointF(event.screenPos()), QPointF(event.buttonDownScreenPos(Qt.LeftButton))).length( ) < QApplication.startDragDistance(): return drag = QDrag(event.widget()) mime = QMimeData() drag.setMimeData(mime) ColorItem.n += 1 if ColorItem.n > 2 and qrand() % 3 == 0: image = QImage(':/images/head.png') mime.setImageData(image) drag.setPixmap(QPixmap.fromImage(image).scaled(30, 40)) drag.setHotSpot(QPoint(15, 30)) else: mime.setColorData(self.color) mime.setText( "#%02x%02x%02x" % (self.color.red(), self.color.green(), self.color.blue())) pixmap = QPixmap(34, 34) pixmap.fill(Qt.white) painter = QPainter(pixmap) painter.translate(15, 15) painter.setRenderHint(QPainter.Antialiasing) self.paint(painter, None, None) painter.end() pixmap.setMask(pixmap.createHeuristicMask()) drag.setPixmap(pixmap) drag.setHotSpot(QPoint(15, 20)) drag.exec_() self.setCursor(Qt.OpenHandCursor) def mouseReleaseEvent(self, event): self.setCursor(Qt.OpenHandCursor)
def qcolor_to_qsscolor(c: QColor) -> str: """Convert a QColor to a string that can be used in a QStyleSheet.""" ensure_valid(c) return "rgba({}, {}, {}, {})".format(c.red(), c.green(), c.blue(), c.alpha())
class CircleBarGraphWidget(QLabel): def __init__(self, parentWidget: QWidget = None, title="Title", minValue=0, maxValue=100, size=200, barColor=None): super().__init__(parentWidget) self.size = size self.value = 0 self.title = title self.minValue = minValue self.maxValue = maxValue if barColor is not None: [red, green, blue] = [ int(float(i)) for i in barColor.split("(")[1].split(")")[0].split(",") ] self.barColor = QColor(red, green, blue) else: self.barColor = QColor(50, 50, 255) self.textColor = QColor(255, 255, 255) self.setAlignment(Qt.AlignCenter) def setSize(self, size): # TODO: Use the QWidget size functions instead of this sketchy one self.size = size self.setGeometry(0, 0, size, size) self.setMinimumWidth(size) self.setMinimumHeight(size) def paintEvent(self, e): painter = QPainter(self) # Grey background fontSize = int(self.width() * 0.1) padding = 4 painter.setPen(QPen(self.textColor, 1, Qt.SolidLine)) painter.setFont(QFont("Monospace", fontSize)) fontHeight = int(fontSize * 1.5) valueText = str(self.value)[0:6] painter.drawText(QRect(0, 0, self.width(), self.height() * 0.9), Qt.AlignCenter, valueText) painter.setFont(QFont("Monospace", fontSize / 2)) painter.drawText( QRect(0, (self.height() * 0.9 / 2) + fontHeight / 2 + padding, self.width(), fontHeight / 2), Qt.AlignCenter, self.title) theta = clamp( interpolate(self.value, self.minValue, self.maxValue, 0, 360 * 16), 0, 360 * 16) barPadding = 20 painter.setPen(QPen(self.barColor, 30, Qt.SolidLine)) painter.translate(0, self.height()) painter.rotate(-90) painter.drawArc(barPadding, barPadding, self.width() - 2 * barPadding, self.height() - 2 * barPadding, 0, -theta) def setValue(self, value): self.value = value def setTextColor(self, textColor: str): if "rgb" in textColor: [red, green, blue] = [ int(float(i)) for i in textColor.split("(")[1].split(")")[0].split(",") ] self.textColor = QColor(red, green, blue) else: self.textColor = QColor(textColor) @staticmethod def getType(): return "CircleBarGraph" def getLimits(self): return [self.minValue, self.maxValue] def getMin(self): return str(self.minValue) def getMax(self): return str(self.maxValue) def getColor(self): colorString = "rgb({0},{1},{2})".format(self.barColor.red(), self.barColor.green(), self.barColor.blue()) return colorString
class MainWindow(QMainWindow, Ui_MainWindow): ''' Main ui ''' def __init__(self, *args, obj=None, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setupUi(self) self.cwd = getcwd() self.raw.fig.canvas.mpl_connect('button_press_event', self.readFile) self.apply_1.clicked.connect(self.converting_planes) self.apply_2.clicked.connect(self.pseudo) self.apply_3.clicked.connect(self.kmeans_planes) self.color_widget_1.mouseReleaseEvent = self.color1 self.color_widget_2.mouseReleaseEvent = self.color2 self.color_1 = QColor(255, 255, 255) self.color_2 = QColor(0, 0, 0) def readFile(self, e): ''' Read a picture ''' imgChoose, _ = QFileDialog.getOpenFileName(self, "Open image", self.cwd, "Image Files (*.png *.jpg *.jpeg *.bmp)") if imgChoose == "": return self.raw_img = imread(imgChoose) self.b,self.g,self.r = split(self.raw_img) self.raw_img = merge([self.r, self.g, self.b]) # self.gray_img = sum(self.raw_img, axis=2) / 3.0 self.processed_img = self.raw_img.copy() self.raw.axes.cla() self.raw.axes.imshow(self.raw_img) self.raw.axes.set_axis_off() self.raw.draw() # self.filtered_img = zeros(shape=self.raw_img.shape) def saveImage(self, e): ''' Save an image ''' imageName, _ = QFileDialog.getSaveFileName(self, "Save Image As", "", "Image Files (*.png *.jpg)") if imageName == "": return if imageName: e.canvas.figure.savefig(imageName) def draw_on(self, p, img, cmap = None, vmin = None, vmax = None): p.axes.cla() p.axes.imshow(img, cmap = cmap, vmin = vmin, vmax = vmax) p.axes.set_axis_off() p.draw() def color1(self, e): self.color_1 = QColorDialog.getColor() r, g, b = str(self.color_1.red()), str(self.color_1.green()), str(self.color_1.blue()) self.color_widget_1.setStyleSheet(f"background-color: rgb({r}, {g}, {b});") def color2(self, e): self.color_2 = QColorDialog.getColor() r, g, b = str(self.color_2.red()), str(self.color_2.green()), str(self.color_2.blue()) self.color_widget_2.setStyleSheet(f"background-color: rgb({r}, {g}, {b});") def reset(self): self.filtered_img = zeros(shape = self.raw_img.shape) self.filter.axes.cla() self.filter.axes.imshow(self.filtered_img, cmap='gray', vmin=0, vmax=255) self.filter.axes.set_axis_off() self.filter.draw() def pseudo(self): btnId = self.pseudo_group.checkedId() #-2 ~ -7 if btnId == -2: im_gray = self.processed_img im_color = cv.applyColorMap(im_gray, cv.COLORMAP_AUTUMN) r, g, b = im_gray[:,:, 0], im_gray[:,:, 1], im_gray[:,:, 2] self.draw_on(self.pseudo1, r, 'gray') self.draw_on(self.pseudo2, g, 'gray') self.draw_on(self.pseudo3, b, 'gray') self.draw_on(self.mixed_pseudo, im_color) elif btnId == -3: im_gray = self.processed_img im_color = cv.applyColorMap(im_gray, cv.COLORMAP_JET) r, g, b = im_gray[:,:, 0], im_gray[:,:, 1], im_gray[:,:, 2] self.draw_on(self.pseudo1, r, 'gray') self.draw_on(self.pseudo2, g, 'gray') self.draw_on(self.pseudo3, b, 'gray') self.draw_on(self.mixed_pseudo, im_color) elif btnId == -4: im_gray = self.processed_img im_color = cv.applyColorMap(im_gray, cv.COLORMAP_RAINBOW) r, g, b = im_gray[:,:, 0], im_gray[:,:, 1], im_gray[:,:, 2] self.draw_on(self.pseudo1, r, 'gray') self.draw_on(self.pseudo2, g, 'gray') self.draw_on(self.pseudo3, b, 'gray') self.draw_on(self.mixed_pseudo, im_color) elif btnId == -5: gray = 0.299 * self.r + 0.587 * self.g + 0.114 * self.b level = self.c_level.value() - 1 r1, g1, b1 = self.color_1.red(), self.color_1.green(), self.color_1.blue() r2, g2, b2 = self.color_2.red(), self.color_2.green(), self.color_2.blue() r_step = (r2 - r1) / level g_step = (g2 - g1) / level b_step = (b2 - b1) / level new_r = zeros(self.r.shape) new_g = zeros(self.r.shape) new_b = zeros(self.r.shape) for x in range(self.r.shape[0]): for y in range(self.r.shape[1]): new_r[x][y] = around(r1 + np.round(gray[x][y] * level / 255) * r_step) new_g[x][y] = around(g1 + np.round(gray[x][y] * level / 255) * g_step) new_b[x][y] = around(b1 + np.round(gray[x][y] * level / 255) * b_step) new_r, new_g, new_b = new_r.astype(np.int), new_g.astype(np.int), new_b.astype(np.int) mix = dstack([new_r, new_g, new_b]) mix[mix > 255] = 255 self.draw_on(self.pseudo1, self.r, 'gray') self.draw_on(self.pseudo2, self.g, 'gray') self.draw_on(self.pseudo3, self.b, 'gray') self.draw_on(self.mixed_pseudo, mix) def converting_planes(self): btnId = self.plane_btns.checkedId() #-2 ~ -7 if btnId == -2: self.rgb(self.plane1, self.plane2, self.plane3, self.mixed_plane) elif btnId == -3: self.cmy(self.plane1, self.plane2, self.plane3, self.mixed_plane) elif btnId == -4: self.hsi(self.plane1, self.plane2, self.plane3, self.mixed_plane) elif btnId == -5: self.xyz(self.plane1, self.plane2, self.plane3, self.mixed_plane) elif btnId == -6: self.lab(self.plane1, self.plane2, self.plane3, self.mixed_plane) elif btnId == -7: self.yuv(self.plane1, self.plane2, self.plane3, self.mixed_plane) def kmeans_planes(self): btnId = self.btns_2.checkedId() if btnId == -2: self.kmeans(self.rgb(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value()) elif btnId == -3: self.kmeans(self.cmy(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value() ) elif btnId == -4: self.kmeans(self.hsi(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value()) elif btnId == -5: self.kmeans(self.xyz(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value()) elif btnId == -6: self.kmeans(self.lab(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value()) elif btnId == -7: self.kmeans(self.yuv(self.kplane1, self.kplane2, self.kplane3, self.kmeans_processed), self.k_level.value()) def rgb(self, p1, p2, p3, p4): self.draw_on(p1, self.r, 'gray', 0, 255) self.draw_on(p2, self.g, 'gray', 0, 255) self.draw_on(p3, self.b, 'gray', 0, 255) mix = dstack([self.r, self.g, self.b]) self.draw_on(p4, mix, None, 0, 255) return mix def cmy(self, p1, p2, p3, p4): self.draw_on(p1, 255-self.r, 'gray', 0, 255) self.draw_on(p2, 255-self.g, 'gray', 0, 255) self.draw_on(p3, 255-self.b, 'gray', 0, 255) mix = dstack([255-self.r, 255-self.g, 255-self.b]) self.draw_on(p4, mix, None, 0, 255) return mix def hsi(self, p1, p2, p3, p4): r, g, b = self.r / 255, self.g / 255, self.b / 255 h, s, i = zeros(r.shape), zeros(r.shape), zeros(r.shape) for x in range(r.shape[0]): for y in range(r.shape[1]): min_ = min(r[x][y], g[x][y], b[x][y]) s[x][y] = 1 - (3 / (r[x][y] + g[x][y] + b[x][y])) * min_ i[x][y] = (r[x][y] + g[x][y] + b[x][y]) / 3 up = ((r[x][y] - g[x][y]) + (r[x][y] - b[x][y])) * .5 down = ((r[x][y] - g[x][y])** 2 + (r[x][y] - b[x][y]) * (g[x][y] - b[x][y]))** .5 degree = arccos(up / down) if b[x][y] > g[x][y]: h[x][y] = 360 - np.degrees(degree) else: h[x][y] = np.degrees(degree) h = h * 255 / 360 h[np.isnan(h)] = 0 s = s * 255 s[np.isnan(s)] = 0 i = i * 255 i[np.isnan(i)] = 0 h, s, i = h.astype(np.int), s.astype(np.int), i.astype(np.int) self.draw_on(p1, h, 'gray') self.draw_on(p2, s, 'gray') self.draw_on(p3, i, 'gray') mix = dstack([h, s, i]) self.draw_on(p4, mix) return mix def xyz(self, p1, p2, p3, p4): x_, y_, z = zeros(self.r.shape), zeros(self.r.shape), zeros(self.r.shape) for x in range(self.r.shape[0]): for y in range(self.r.shape[1]): x_[x][y] = 0.412453 * self.r[x][y] + 0.35758 * self.g[x][y] + 0.180423 * self.b[x][y] y_[x][y] = 0.212671 * self.r[x][y] + 0.71516 * self.g[x][y] + 0.072169 * self.b[x][y] z[x][y] = 0.019334 * self.r[x][y] + 0.119193 * self.g[x][y] + 0.950227 * self.b[x][y] x_, y_, z = x_.astype(np.int), y_.astype(np.int), z.astype(np.int) self.draw_on(p1, x_, 'gray') self.draw_on(p2, y_, 'gray') self.draw_on(p3, z, 'gray') mix = dstack([x_, y_, z]) mix[mix > 255] = 255 self.draw_on(p4, mix) return mix def lab(self, p1, p2, p3, p4): x_, y_, z = zeros(self.r.shape), zeros(self.r.shape), zeros(self.r.shape) for x in range(self.r.shape[0]): for y in range(self.r.shape[1]): x_[x][y] = 0.412453 * self.r[x][y] + 0.35758 * self.g[x][y] + 0.180423 * self.b[x][y] y_[x][y] = 0.212671 * self.r[x][y] + 0.71516 * self.g[x][y] + 0.072169 * self.b[x][y] z[x][y] = 0.019334 * self.r[x][y] + 0.119193 * self.g[x][y] + 0.950227 * self.b[x][y] x_, y_, z = x_ / 255, y_ / 255, z / 255 xn = 0.950456 yn = 1.0 zn = 1.088754 l, a, b = zeros(self.r.shape), zeros(self.r.shape), zeros(self.r.shape) for x in range(self.r.shape[0]): for y in range(self.r.shape[1]): if y_[x][y] / yn > .008856: l[x][y] = 116 * (y_[x][y]/yn)**(1/3) - 16 else: 903.3 * y_[x][y]/yn a[x][y] = 500 * (dum(x_[x][y], xn) - dum(y_[x][y], yn)) b[x][y] = 200 * (dum(y_[x][y], yn) - dum(z[x][y], zn)) l = l * 255 a = a * 255 b = b * 255 l, a, b = l.astype(np.int), a.astype(np.int), b.astype(np.int) mix = dstack([l, a, b]) mix[mix > 255] = 255 self.draw_on(p1, l, 'gray') self.draw_on(p2, a, 'gray') self.draw_on(p3, b, 'gray') self.draw_on(p4, mix) return mix def yuv(self, p1, p2, p3, p4): y_, u, v = zeros(self.r.shape), zeros(self.r.shape), zeros(self.r.shape) for x in range(self.r.shape[0]): for y in range(self.r.shape[1]): y_[x][y] = 0.299 * self.r[x][y] + 0.587 * self.g[x][y] + 0.114 * self.b[x][y] u[x][y] = -0.169 * self.r[x][y] + -0.331 * self.g[x][y] + 0.5 * self.b[x][y] + 128 v[x][y] = 0.5 * self.r[x][y] + -0.419 * self.g[x][y] + 0.081 * self.b[x][y] + 128 y_, u, v = y_.astype(np.int), u.astype(np.int), v.astype(np.int) mix = dstack([y_, u, v]) mix[mix > 255] = 255 self.draw_on(p1, y_, 'gray') self.draw_on(p2, u, 'gray') self.draw_on(p3, v, 'gray') self.draw_on(p4, mix) return mix def kmeans(self, img, k): Z = img.reshape((-1, 3)) Z = float32(Z) criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0) ret, label, center = cv.kmeans(Z, k, None, criteria, 10, cv.KMEANS_RANDOM_CENTERS) center = uint8(center) res = center[label.flatten()] res2 = res.reshape((img.shape)) self.mixed_kplane.axes.cla() self.mixed_kplane.axes.imshow(res2) self.mixed_kplane.axes.set_axis_off() self.mixed_kplane.draw()
def paintEvent(self, event): super(WaterFloatButton, self).paintEvent(event) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) # 鼠标悬浮进度 edge_color = QColor(self.hover_bg) pro = 0 if self.hover_progress > 0 or self.press_progress or len( self.waters) > 0: if self.water_animation: ''' 不用判断 water 是出现还是消失状态 如果一直悬浮的话,颜色不会变 而如果是点一下立马移开,文字会出现一种“渐隐渐现”的效果 ''' if len(self.waters) > 0: pro = max(self.hover_progress, self.waters[-1].progress) else: pro = self.hover_progress else: math.max(self.hover_progress, self.press_progress) edge_color.setAlpha(255 * (100 - pro) / 100) # 画边框 path = QPainterPath() if self.show_foreground: path = self.getBgPainterPath() # 整体背景 # 出现动画 if self.show_ani_appearing and self.show_ani_progress != 100 and self.border_bg.alpha( ) != 0: pw = self.size().width() * self.show_ani_progress / 100 rect = QRect(0, 0, pw, self.size().height()) rect_path = QPainterPath() rect_path.addRect(rect) path &= rect_path x = self.show_ani_point.x() y = self.show_ani_point.y() gen = self.quick_sqrt(x * x + y * y) x = -self.water_self.radius * x / gen # 动画起始中心点横坐标 反向 y = -self.water_self.radius * y / gen # 动画起始中心点纵坐标 反向 if self.border_bg.alpha() != 0: # 如果有背景,则不进行画背景线条 painter.setPen(self.border_bg) painter.drawPath(path) # 画文字 if (self.self_enabled or self.fore_enabled) and self.text != '': rect = QRect(QPoint(0, 0), self.size()) color: QColor if pro: if self.auto_text_color: aim_color = QColor(0, 0, 0) if self.isLightColor( self.hover_bg) else QColor(255, 255, 255) color = QColor( self.text_color.red() + (aim_color.red() - self.text_color.red()) * pro / 100, self.text_color.green() + (aim_color.green() - self.text_color.green()) * pro / 100, self.text_color.blue() + (aim_color.blue() - self.text_color.blue()) * pro / 100, 255) painter.setPen(color) else: color = self.text_color color.setAlpha(255) painter.setPen(color) if self.font_size > 0: font = painter.font() font.setPixelSize(self.font_size) painter.setFont(font) painter.drawText(rect, Qt.AlignCenter, self.text)
class DrawMask(QWidget): PREVIEW_CLIP_WIDTH = 450 PREVIEW_MASK_WIDTH = 450 def __init__(self, parent=None): super(DrawMask, self).__init__(parent=parent) self.parent = parent self.image_clip_data = None self.show_image_size = (0, 0) self.image_mask_data = None self.image_draw_data = None self.item_name_to_clip_image_info = { } # (clip image, clip_pos_size, left_up_pos, size) self.item_name_to_mask_image_info = {} # (mask image) self.current_item_name = 'image 1' self.color_pen = QColor(50, 200, 50) self.brush_size = 6 # pick color ft2 = QFont() ft2.setBold(True) self.btn_color = QPushButton('Color', self) self.btn_color.clicked.connect(self.on_clicked_color) self.btn_color.setFont(ft2) pla = self.btn_color.palette() pla.setColor(QPalette.ButtonText, self.color_pen) self.btn_color.setPalette(pla) # brush setting self.label_brush_size = QLabel('Brush Size') self.spin_brush_size = QSpinBox(self) self.spin_brush_size.setRange(2, 50) self.spin_brush_size.setSingleStep(1) self.spin_brush_size.setValue(self.brush_size) self.spin_brush_size.valueChanged.connect(self.on_change_brush_size) self.btn_clear = QPushButton('Clear Mask', self) self.btn_clear.clicked.connect(self.on_clicked_clear) self.btn_finish = QPushButton('Finish', self) self.btn_finish.clicked.connect(self.on_clicked_finish) # image self.image_draw_mask = DrawLabel('image draw', self) self.image_draw_mask.setAlignment(Qt.AlignTop) self.image_draw_mask.setCursor(Qt.CrossCursor) self.image_mask_preview = QLabel('mask preview') self.image_mask_preview.setAlignment(Qt.AlignHCenter) # listview self.label_listview = QLabel('Select Image') self.model_image_clip = QStringListModel(self) self.model_image_clip.setStringList( self.item_name_to_clip_image_info.keys()) self.listview_image_clip = QListView(self) self.listview_image_clip.setModel(self.model_image_clip) self.listview_image_clip.setEditTriggers( QAbstractItemView.NoEditTriggers) self.listview_image_clip.doubleClicked.connect( lambda: self.on_clicked_listview_item(self.listview_image_clip)) self.grid_layout = QGridLayout() self.grid_layout.addWidget(self.label_brush_size, 0, 0, 1, 1) self.grid_layout.addWidget(self.spin_brush_size, 0, 1, 1, 1) self.grid_layout.addWidget(self.btn_color, 0, 2, 1, 1) self.grid_layout.addWidget(self.btn_clear, 0, 6, 1, 2) self.grid_layout.addWidget(self.btn_finish, 0, 8, 1, 2) self.grid_layout.addWidget(self.image_draw_mask, 1, 0, 5, 5) self.grid_layout.addWidget(self.image_mask_preview, 1, 5, 5, 5, Qt.AlignTop) self.grid_layout.addWidget(self.label_listview, 6, 5, 1, 2) self.grid_layout.addWidget(self.listview_image_clip, 7, 5, 1, 4) self.setLayout(self.grid_layout) def set_image(self, item_name_to_clip_image_info): self.item_name_to_clip_image_info = item_name_to_clip_image_info self.model_image_clip.setStringList( self.item_name_to_clip_image_info.keys()) for item_name, clip_image_info in self.item_name_to_clip_image_info.items( ): self.item_name_to_mask_image_info[item_name] = (np.copy( clip_image_info[0]), ) self.item_name_to_mask_image_info[item_name][0][:, :] = 0 self.parent.setTabEnabled(2, True) self.set_current_draw('image 1') def set_current_draw(self, item_name): from image_inpainting_demo import set_label_image self.current_item_name = item_name # show preview self.image_clip_data = self.item_name_to_clip_image_info[ self.current_item_name][0] # create mask self.image_mask_data = self.item_name_to_mask_image_info[ self.current_item_name][0] set_label_image(self.image_mask_preview, self.PREVIEW_MASK_WIDTH, self.image_mask_data) # draw image color = (self.color_pen.red(), self.color_pen.green(), self.color_pen.blue()) self.image_draw_data = np.copy((self.image_mask_data / 255 * color) + ( (1 - self.image_mask_data / 255) * self.image_clip_data)) self.image_draw_data = np.array(self.image_draw_data, np.uint8) self.show_image_size = set_label_image(self.image_draw_mask, self.PREVIEW_CLIP_WIDTH, self.image_draw_data) def draw_mask(self, pos): from image_inpainting_demo import set_label_image show_width, show_height = self.show_image_size height, width, bytesPerComponent = self.image_clip_data.shape # calculate row coordinate to_row_width, to_row_height = width / float( show_width), height / float(show_height) actual_x, actual_y = int(pos[0] * to_row_width), int(pos[1] * to_row_height) half_size = int(math.ceil(self.brush_size / 2.0)) x1, y1 = min(actual_x + half_size, width), min(actual_y + half_size, width) x0, y0 = max(actual_x - (self.brush_size - half_size), 0), max(actual_y - (self.brush_size - half_size), 0) self.image_mask_data[y0:y1 + 1, x0:x1 + 1] = 255 set_label_image(self.image_mask_preview, self.PREVIEW_MASK_WIDTH, self.image_mask_data) self.refresh_mask_image((x0, y0, x1, y1)) def refresh_mask_image(self, x0y0_x1y1=None): from image_inpainting_demo import set_label_image color = (self.color_pen.red(), self.color_pen.green(), self.color_pen.blue()) if x0y0_x1y1: x1, y1 = x0y0_x1y1[2], x0y0_x1y1[3] x0, y0 = x0y0_x1y1[0], x0y0_x1y1[1] self.image_draw_data[y0:y1 + 1, x0:x1 + 1] = color else: self.image_draw_data = np.copy( (self.image_mask_data / 255 * color) + ((1 - self.image_mask_data / 255) * self.image_clip_data)) self.image_draw_data = np.array(self.image_draw_data, np.uint8) set_label_image(self.image_draw_mask, self.PREVIEW_CLIP_WIDTH, self.image_draw_data) def on_clicked_color(self): new_color = QColorDialog.getColor() if new_color.isValid(): pla = self.btn_color.palette() pla.setColor(QPalette.ButtonText, new_color) self.btn_color.setPalette(pla) self.color_pen = new_color self.refresh_mask_image() def on_change_brush_size(self): self.brush_size = int(self.spin_brush_size.value()) def on_clicked_clear(self): from image_inpainting_demo import set_label_image self.image_mask_data[:, :] = 0 set_label_image(self.image_mask_preview, self.PREVIEW_MASK_WIDTH, self.image_mask_data) self.refresh_mask_image() def on_clicked_finish(self): self.parent.image_inpainting.set_image( self.item_name_to_clip_image_info, self.item_name_to_mask_image_info) def on_clicked_listview_item(self, listview): data = listview.currentIndex().data() self.set_current_draw(data)
class RGBSlider(QWidget): def __init__(self, _image=None, *args, **kwargs): super().__init__(*args, **kwargs) self._image = _image self.initializeUI() def initializeUI(self): """ Initialize the window and display its contents to the screen. """ self.setMinimumSize(225, 300) self.setWindowTitle('9.3 - RGB Slider') # Store the current pixel value self.current_val = QColor() self.setupWidgets() self.show() def setupWidgets(self): """ Create instances of widgets and arrange them in layouts. """ # Image that will display the current color set by # slider/spin_box values self.color_display = QImage(100, 100, QImage.Format_RGBX64) self.color_display.fill(Qt.black) self.cd_label = QLabel() self.cd_label.setPixmap(QPixmap.fromImage(self.color_display)) self.cd_label.setScaledContents(True) # Create RGB sliders and spinboxes red_label = QLabel("Red") red_label.setFont(QFont('Helvetica', 14)) self.red_slider = QSlider(Qt.Horizontal) self.red_slider.setObjectName("Red") self.red_slider.setMaximum(255) self.red_spinbox = QSpinBox() self.red_spinbox.setMaximum(255) green_label = QLabel("Green") green_label.setFont(QFont('Helvetica', 14)) self.green_slider = QSlider(Qt.Horizontal) self.green_slider.setObjectName("Green") self.green_slider.setMaximum(255) self.green_spinbox = QSpinBox() self.green_spinbox.setMaximum(255) blue_label = QLabel("Blue") blue_label.setFont(QFont('Helvetica', 14)) self.blue_slider = QSlider(Qt.Horizontal) self.blue_slider.setObjectName("Blue") self.blue_slider.setMaximum(255) self.blue_spinbox = QSpinBox() self.blue_spinbox.setMaximum(255) # Use the hex labels to display color values in hex format hex_label = QLabel("Hex Color ") self.hex_values_label = QLabel() hex_h_box = QHBoxLayout() hex_h_box.addWidget(hex_label, Qt.AlignRight) hex_h_box.addWidget(self.hex_values_label, Qt.AlignRight) hex_container = QWidget() hex_container.setLayout(hex_h_box) # Create grid layout for sliders and spinboxes grid = QGridLayout() grid.addWidget(red_label, 0, 0, Qt.AlignLeft) grid.addWidget(self.red_slider, 1, 0) grid.addWidget(self.red_spinbox, 1, 1) grid.addWidget(green_label, 2, 0, Qt.AlignLeft) grid.addWidget(self.green_slider, 3, 0) grid.addWidget(self.green_spinbox, 3, 1) grid.addWidget(blue_label, 4, 0, Qt.AlignLeft) grid.addWidget(self.blue_slider, 5, 0) grid.addWidget(self.blue_spinbox, 5, 1) grid.addWidget(hex_container, 6, 0, 1, 0) # Use [] to pass arguments to the valueChanged signal # The sliders and spinboxes for each color should display the # same values and be updated at the same time. self.red_slider.valueChanged['int'].connect(self.updateRedSpinBox) self.red_spinbox.valueChanged['int'].connect(self.updateRedSlider) self.green_slider.valueChanged['int'].connect(self.updateGreenSpinBox) self.green_spinbox.valueChanged['int'].connect(self.updateGreenSlider) self.blue_slider.valueChanged['int'].connect(self.updateBlueSpinBox) self.blue_spinbox.valueChanged['int'].connect(self.updateBlueSlider) # Create container for rgb widgets rgb_widgets = QWidget() rgb_widgets.setLayout(grid) v_box = QVBoxLayout() v_box.addWidget(self.cd_label) v_box.addWidget(rgb_widgets) self.setLayout(v_box) # The following methods update the red, green and blue # sliders and spinboxes. def updateRedSpinBox(self, value): self.red_spinbox.setValue(value) self.redValue(value) def updateRedSlider(self, value): self.red_slider.setValue(value) self.redValue(value) def updateGreenSpinBox(self, value): self.green_spinbox.setValue(value) self.greenValue(value) def updateGreenSlider(self, value): self.green_slider.setValue(value) self.greenValue(value) def updateBlueSpinBox(self, value): self.blue_spinbox.setValue(value) self.blueValue(value) def updateBlueSlider(self, value): self.blue_slider.setValue(value) self.blueValue(value) # Create new colors based upon the changes to the RGB values def redValue(self, value): new_color = qRgb(value, self.current_val.green(), self.current_val.blue()) self.updateColorInfo(new_color) def greenValue(self, value): new_color = qRgb(self.current_val.red(), value, self.current_val.blue()) self.updateColorInfo(new_color) def blueValue(self, value): new_color = qRgb(self.current_val.red(), self.current_val.green(), value) self.updateColorInfo(new_color) def updateColorInfo(self, color): """ Update color displayed in image and set the hex values accordingly. """ self.current_val = QColor(color) self.color_display.fill(color) self.cd_label.setPixmap(QPixmap.fromImage(self.color_display)) self.hex_values_label.setText("{}".format(self.current_val.name())) def getPixelValues(self, event): """ The method reimplements the mousePressEvent method. To use, set an widget's mousePressEvent equal to getPixelValues, like so: image_label.mousePressEvent = rgb_slider.getPixelValues If an _image != None, then the user can select pixels in the images, and update the sliders to get view the color, and get the rgb and hex values. """ x = event.x() y = event.y() # valid() returns true if the point selected is a valid # coordinate pair within the image if self._image.valid(x, y): self.current_val = QColor(self._image.pixel(x, y)) red_val = self.current_val.red() green_val = self.current_val.green() blue_val = self.current_val.blue() self.updateRedSpinBox(red_val) self.updateRedSlider(red_val) self.updateGreenSpinBox(green_val) self.updateGreenSlider(green_val) self.updateBlueSpinBox(blue_val) self.updateBlueSlider(blue_val)
class MovablePolyLine(QGraphicsObject): def __init__(self, parent=None): super(MovablePolyLine, self).__init__(parent) self.setZValue(1000) self.polygon = QPolygonF() self.radius = 5.0 self.itemList = [] self.rect = QRectF() self.color = QColor(255,0,0) self.lineWidth = 5 self.brightness = 0 self.setOpacity(0.5) # self.setHandlesChildEvents(False) # self.setFlags(QGraphicsItem.ItemIsMovable) self.isDrawLine = True self.drawItemFlags = None self.points = None self.itemType = QGraphicsEllipseItem def setDrawLine(self, flag): self.isDrawLine = flag def setDrawItems(self, flags): self.drawItemFlags = flags for item, flag in zip(self.itemList, flags): if flag: item.show() else: item.hide() def setRadius(self, r): self.radius = r if self.points is None: return radii = 2*self.radius rectList = [QRectF(-self.radius, -self.radius, radii, radii) for p in self.points] for item, rect in zip(self.itemList, rectList): item.setRect(rect) def setLineWidth(self, w): self.lineWidth = w self.update() def getLineWidth(self): return self.lineWidth def setColor(self, rgb): rgb = [min(val+self.brightness, 255) for val in rgb] self.color = QColor(*rgb) for item in self.itemList: item.setBrush(self.color) def setBrightness(self, val): delta = val - self.brightness self.brightness = val rgb = [min(val+delta, 255) for val in [self.color.red(), self.color.green(), self.color.blue()]] self.color = QColor(*rgb) for item in self.itemList: item.setBrush(self.color) def getRadius(self): return self.radius # TODO:NaNが入ってると劇的に重くなるので,無理矢理NaNをはじいてはいる. #もう少しきれいに書き直すこと. #フレームが前に進むたびに値を詰め直しているためおそいので,その対策も同時に. def setPoints(self, ps=None, flags=None): if ps is not None and self.points is not None: points = [p for p in ps if not np.any(pd.isnull(p))] if len(points)==len(self.points): self.points = points for item, point in zip(self.itemList, self.points): item.setPos(*point) item.mouseMoveEvent = self.generateItemMouseMoveEvent(item, point) item.mousePressEvent = self.generateItemMousePressEvent(item, point) self.update() return scene = self.scene() if scene is not None: for item in self.itemList: scene.removeItem(item) del item self.itemList.clear() if flags is not None: self.drawItemFlags = flags drawItemFlags = self.drawItemFlags if ps is not None: self.points = [p for p in ps if not np.any(pd.isnull(p))] drawItemFlags = [f for f, p in zip(self.drawItemFlags, ps) if not np.any(pd.isnull(p))] if self.points is not None: radii = 2*self.radius rectList = [QRectF(-self.radius, -self.radius, radii, radii) for p in self.points] self.itemList = [self.itemType(self) for rect in rectList] for item, point, rect, flag in zip(self.itemList, self.points, rectList, drawItemFlags): item.setBrush(self.color) item.setRect(rect) item.setPos(*point) if not flag: item.hide() item.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemSendsScenePositionChanges) item.setAcceptHoverEvents(True) item.mouseMoveEvent = self.generateItemMouseMoveEvent(item, point) item.mousePressEvent = self.generateItemMousePressEvent(item, point) def setRect(self, rect): self.rect = rect def generateItemMouseMoveEvent(self, item, point): def itemMouseMoveEvent(event): self.itemType.mouseMoveEvent(item, event) centerPos = item.scenePos() point[0] = centerPos.x() point[1] = centerPos.y() self.update() return itemMouseMoveEvent def generateItemMousePressEvent(self, item, point): def itemMousePressEvent(event): self.itemType.mousePressEvent(item, event) pass return itemMousePressEvent def boundingRect(self): return self.rect def paint(self, painter, option, widget): if self.points is not None and self.isDrawLine: painter.save() pen = QPen(self.color) pen.setWidth(self.getLineWidth()) painter.setPen(pen) qPoints = [QPointF(*p.tolist()) for p in self.points] polygon = QPolygonF(qPoints) painter.drawPolyline(polygon) painter.restore()
def convertColor(color: QColor): return [color.red() / 255, color.green() / 255, color.blue() / 255]
class ColorItem(QGraphicsItem): n = 0 def __init__(self): super(ColorItem, self).__init__() self.color = QColor(qrand() % 256, qrand() % 256, qrand() % 256) self.setToolTip( "QColor(%d, %d, %d)\nClick and drag this color onto the robot!" % (self.color.red(), self.color.green(), self.color.blue()) ) self.setCursor(Qt.OpenHandCursor) self.setAcceptedMouseButtons(Qt.LeftButton) def boundingRect(self): return QRectF(-15.5, -15.5, 34, 34) def paint(self, painter, option, widget): painter.setPen(Qt.NoPen) painter.setBrush(Qt.darkGray) painter.drawEllipse(-12, -12, 30, 30) painter.setPen(QPen(Qt.black, 1)) painter.setBrush(QBrush(self.color)) painter.drawEllipse(-15, -15, 30, 30) def mousePressEvent(self, event): self.setCursor(Qt.ClosedHandCursor) def mouseMoveEvent(self, event): if ( QLineF(QPointF(event.screenPos()), QPointF(event.buttonDownScreenPos(Qt.LeftButton))).length() < QApplication.startDragDistance() ): return drag = QDrag(event.widget()) mime = QMimeData() drag.setMimeData(mime) ColorItem.n += 1 if ColorItem.n > 2 and qrand() % 3 == 0: root = QFileInfo(__file__).absolutePath() image = QImage(root + "/images/head.png") mime.setImageData(image) drag.setPixmap(QPixmap.fromImage(image).scaled(30, 40)) drag.setHotSpot(QPoint(15, 30)) else: mime.setColorData(self.color) mime.setText("#%02x%02x%02x" % (self.color.red(), self.color.green(), self.color.blue())) pixmap = QPixmap(34, 34) pixmap.fill(Qt.white) painter = QPainter(pixmap) painter.translate(15, 15) painter.setRenderHint(QPainter.Antialiasing) self.paint(painter, None, None) painter.end() pixmap.setMask(pixmap.createHeuristicMask()) drag.setPixmap(pixmap) drag.setHotSpot(QPoint(15, 20)) drag.exec_() self.setCursor(Qt.OpenHandCursor) def mouseReleaseEvent(self, event): self.setCursor(Qt.OpenHandCursor)
def createStyle(kpi, custom=False, sqlIdx=None): style = {} #try: # mandatory stuff if 'subtype' in kpi: style['subtype'] = kpi['subtype'] else: style['subtype'] = None if 'name' in kpi: if custom: style['name'] = 'cs-' + kpi['name'] else: style['name'] = kpi['name'] else: return None if 'type' in kpi: if kpi['type'] == 'service': style['type'] = 's' else: style['type'] = 'h' else: return None if custom: if 'nofilter' in kpi: style['nofilter'] = True else: style['nofilter'] = False if 'sqlname' in kpi: style['sqlname'] = kpi['sqlname'] else: if 'subtype' in kpi and kpi['subtype'] == 'gantt': style['sqlname'] = 'None' else: return None # optional stuff if 'group' in kpi: style['group'] = kpi['group'] else: style['group'] = '' if 'description' in kpi: style['desc'] = kpi['description'] else: style['desc'] = '' if 'label' in kpi: style['label'] = kpi['label'] else: style['label'] = '' if 'sUnit' in kpi and 'dUnit' in kpi: sUnit = kpi['sUnit'].split('/') dUnit = kpi['dUnit'].split('/') if len(sUnit) > 1 and len( dUnit) > 1 and sUnit[1] == 'sample' and dUnit[1] == 'sec': style['sUnit'] = sUnit[0] style['dUnit'] = dUnit[0] style['perSample'] = True else: style['sUnit'] = kpi['sUnit'] style['dUnit'] = kpi['dUnit'] else: style['sUnit'] = '-' #create pen if 'color' in kpi: color = QColor(kpi['color']) else: color = QColor('#DDD') if 'style' in kpi and kpi['style'] != '': if kpi['style'] == 'solid': penStyle = Qt.SolidLine elif kpi['style'] == 'dotted': penStyle = Qt.DotLine elif kpi['style'] == 'dashed': penStyle = Qt.DashLine elif kpi['style'] == 'dotline': penStyle = Qt.DotLine elif kpi['style'] == 'bar' or kpi['style'] == 'candle': penStyle = Qt.SolidLine else: log('[W] pen style unknown: %s - [%s]' % (kpi['name'], (kpi['style']))) penStyle = Qt.DashDotDotLine else: if style['type'] == 'h': penStyle = Qt.DashLine else: penStyle = Qt.SolidLine if kpi['name'][:7] == '---#---': style['pen'] = '-' else: if 'subtype' in kpi and kpi['subtype'] == 'gantt': # gantt stuff if 'width' in kpi: style['width'] = int(kpi['width']) else: style['width'] = 8 if 'font' in kpi: style['font'] = int(kpi['font']) else: style['font'] = 8 if 'shift' in kpi: style['shift'] = int(kpi['shift']) else: style['shift'] = 2 if 'style' in kpi and (kpi['style'] == 'bar' or kpi['style'] == 'candle'): style['style'] = kpi['style'] else: style['style'] = 'bar' clr = QColor(color) style['brush'] = clr penColor = QColor(clr.red() * 0.75, clr.green() * 0.75, clr.blue() * 0.75) style['pen'] = QPen(penColor, 1, penStyle) if 'y_range' in kpi and kpi['y_range'] != '': yr = kpi['y_range'] style['y_range'] = [None] * 2 style['y_range'][0] = 100 - max(0, yr[0]) style['y_range'][1] = 100 - min(100, yr[1]) else: style['y_range'] = [0, 100] else: # regular kpis style['pen'] = QPen(color, 1, penStyle) style['sql'] = sqlIdx ''' except Exception as e: log(str(kpi)) log(style) log('Error creating a style: %s' % str(e)) return None ''' return style
class ClockBack(QColorThemedGraphicsObject): """ Draw a nice back face of the clock. This is just the white circle for now. """ def get_alpha(self): return self._alpha def set_alpha(self,c): self._alpha = c self.update() alpha = pyqtProperty(float, get_alpha, set_alpha) def get_line_width(self): return self._line_width def set_line_width(self,c): self._line_width = c self.update() line_width = pyqtProperty(float, get_line_width, set_line_width) def set_outline_color(self, outline_color): self._outline_color = outline_color def __init__(self, size, *args, **kw): super(ClockBack,self).__init__(*args, **kw) self.size = size self.bbox = QRectF(0, 0, self.size, self.size) self._color = QColor(255,0,0,255) self._outline_color = QColor(255,0,0,255) self._alpha = 255 self._line_width = 3 def paint(self, painter, option, widget): # Draw background painter.setPen(QPen(QColor(self._outline_color.red(), self._outline_color.green(), self._outline_color.blue(), 0.5*255 + 0.5*self._alpha ), self._line_width)) # How much white to mix in? # At low alpha, I want the background to be super close to # pure white. A=(1 - 0.07*(self._alpha/255.)) B=1-A painter.setBrush(QColor(255*A+B*self._color.red(), 255*A+B*self._color.green(), 255*A+B*self._color.blue(), self._alpha )) center = self.size/2 painter.drawEllipse(self.bbox) ## Draw four ticks along the sides #pen = QPen(QColor(self._color.red(), # self._color.green(), # self._color.blue(), # 128), 2) #painter.setPen(pen) #START, END = 0.40, 0.43 #painter.drawLine(QPointF(center, center + START*self.size), # QPointF(center, center + END*self.size)) #painter.drawLine(QPointF(center, center - START*self.size), # QPointF(center, center - END*self.size)) #painter.drawLine(QPointF(center + START*self.size, center), # QPointF(center + END*self.size, center)) #painter.drawLine(QPointF(center - START*self.size, center), # QPointF(center - END*self.size, center)) def boundingRect(self): return QRectF(-self._line_width, -self._line_width, self.size + 2*self.line_width, self.size + 2*self.line_width)
class MainWindow(QMainWindow): def __init__(self, app): super().__init__() self.app = app self.showMaximized() self.image_service = ImageService() self.storage_service = StorageService() self.stacked_widget = QStackedWidget() self.stacked_widget.showMaximized() self.main_widget = MainWidget(self) self.settings_widget = SettingsWidget(self, Settings()) self.pattern_widget = PatternWidget(self, Pattern()) self.stacked_widget.addWidget(self.main_widget) self.stacked_widget.addWidget(self.pattern_widget) self.stacked_widget.addWidget(self.settings_widget) self.setCentralWidget(self.stacked_widget) self.selected_pattern_name = None self.selected_settings_name = None self.pattern = None self.settings = None self._create_actions() self._set_menu_bar() self._set_tool_bar() self.errors_color = QColor(255, 0, 0) def _create_actions(self): self.new_pattern_action = QAction( QIcon(os.path.join(ICONS_DIR, 'add.png')), "New pattern", self) self.new_pattern_action.triggered.connect( self._new_pattern_action_handler) self.new_settings_action = QAction( QIcon(os.path.join(ICONS_DIR, 'settings.png')), "New settings", self) self.new_settings_action.triggered.connect( self._new_settings_action_handler) self.next_image_action = QAction( QIcon(os.path.join(ICONS_DIR, 'next')), "Next image", self) self.next_image_action.triggered.connect( self._next_image_action_handler) self.next_image_action.setEnabled(False) self.errors_color_action = QAction( QIcon(os.path.join(ICONS_DIR, 'color.png')), "Errors marker", self) self.errors_color_action.triggered.connect( self._errors_color_action_handler) self.exit_action = QAction('Exit', self) self.exit_action.triggered.connect(self.app.quit) def _create_pattern_combo(self): self.pattern_combo = QComboBox(self) avaliable_pcbs = self.storage_service.get_avaliable_pattern_names() for name in avaliable_pcbs: self.pattern_combo.addItem(name) self.pattern_combo.activated[str].connect( self._selected_pattern_action_handler) def _create_settings_combo(self): self.settings_combo = QComboBox(self) avaliable_settings_names = self.storage_service.get_avaliable_settings_names( ) for name in avaliable_settings_names: self.settings_combo.addItem(name) self.settings_combo.activated[str].connect( self._selected_settings_action_handler) def _set_menu_bar(self): menu_bar = self.menuBar() menu_file = menu_bar.addMenu('File') menu_file.addAction(self.new_pattern_action) menu_file.addAction(self.exit_action) def _set_tool_bar(self): self._create_pattern_combo() self._create_settings_combo() self.tool_bar = self.addToolBar('Tools') self.tool_bar.addWidget(self.pattern_combo) self.tool_bar.addAction(self.new_pattern_action) self.tool_bar.addSeparator() self.tool_bar.addWidget(self.settings_combo) self.tool_bar.addAction(self.new_settings_action) self.tool_bar.addAction(self.errors_color_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.next_image_action) def _new_pattern_action_handler(self): file_dialog = QFileDialog(self) file_dialog.setNameFilters(["All Files (*)", "Images (*.png *.jpg)"]) file_dialog.selectNameFilter("Images (*.png *.jpg)") if file_dialog.exec_(): filename = file_dialog.selectedFiles()[0] with wait_cursor(): image_orig = cv2.imread(filename, cv2.IMREAD_COLOR) self.stacked_widget.removeWidget(self.pattern_widget) self.settings_widget = PatternWidget(self, Pattern()) self.stacked_widget.addWidget(self.pattern_widget) self.stacked_widget.setCurrentWidget(self.pattern_widget) self.pattern_widget.setImage(image_orig) self.pattern_widget.update() def _new_settings_action_handler(self): file_dialog = QFileDialog(self) file_dialog.setNameFilters(["All Files (*)", "Images (*.png *.jpg)"]) file_dialog.selectNameFilter("Images (*.png *.jpg)") if file_dialog.exec_(): filename = file_dialog.selectedFiles()[0] with wait_cursor(): image_orig = cv2.imread(filename, cv2.IMREAD_COLOR) self.stacked_widget.removeWidget(self.settings_widget) self.settings_widget = SettingsWidget(self, Settings()) self.stacked_widget.addWidget(self.settings_widget) self.stacked_widget.setCurrentWidget(self.settings_widget) self.settings_widget.setImage(image_orig) self.settings_widget.update() def _next_image_action_handler(self): #all requirements met, don't check again image_orig = self.storage_service.next_image() if image_orig != None: with wait_cursor(): images = self.image_service.transform_image( image_orig, self.settings) images = self.image_service.compare(self.pattern, images, self.settings) bgr = [ self.errors_color.blue(), self.errors_color.green(), self.errors_color.red() ] images = self.image_service.mark_errors(images, bgr) self.stacked_widget.removeWidget(self.main_widget) self.main_widget = MainWidget(self) self.stacked_widget.addWidget(self.main_widget) self.stacked_widget.setCurrentWidget(self.main_widget) self.main_widget.setImage(images) def _errors_color_action_handler(self): color = QColorDialog.getColor() if color.isValid(): self.errors_color = color def _selected_pattern_action_handler(self, name): self.selected_pattern_name = name self.pattern = self.storage_service.load_pattern( self.selected_pattern_name) self._toggle_next_image_action() def _selected_settings_action_handler(self, name): self.selected_settings_name = name self.settings = self.storage_service.load_settings( self.selected_settings_name) self._toggle_next_image_action() def _toggle_next_image_action(self): if self.selected_pattern_name and self.selected_pattern_name != PATTERN_COMBO_NAME and self.selected_settings_name and self.selected_settings_name != SETTINGS_COMBO_NAME: self.next_image_action.setEnabled(True) else: self.next_image_action.setEnabled(False) ### PUBLIC METHODS ### def pattern_finished(self, pattern_name): if pattern_name: self.pattern_combo.clear() avaliable_pattern_names = self.storage_service.get_avaliable_pattern_names( ) for name in avaliable_pattern_names: self.pattern_combo.addItem(name) index = self.pattern_combo.findText(pattern_name) self.pattern_combo.setCurrentIndex(index) self.selected_pattern_name = pattern_name self._toggle_next_image_action() self.stacked_widget.setCurrentWidget(self.main_widget) def settings_finished(self, settings_name): if settings_name: self.settings_combo.clear() avaliable_settings_names = self.storage_service.get_avaliable_settings_names( ) for name in avaliable_settings_names: self.settings_combo.addItem(name) index = self.settings_combo.findText(settings_name) self.settings_combo.setCurrentIndex(index) self.selected_settings_name = name self._toggle_next_image_action() self.stacked_widget.setCurrentWidget(self.main_widget)