def __init__(self, text, parent): super(DragLabel, self).__init__(parent) metric = QFontMetrics(self.font()) size = metric.size(Qt.TextSingleLine, text) image = QImage(size.width() + 12, size.height() + 12, QImage.Format_ARGB32_Premultiplied) image.fill(qRgba(0, 0, 0, 0)) font = QFont() font.setStyleStrategy(QFont.ForceOutline) painter = QPainter() painter.begin(image) painter.setRenderHint(QPainter.Antialiasing) painter.setBrush(Qt.white) painter.drawRoundedRect(QRectF(0.5, 0.5, image.width() - 1, image.height() - 1), 25, 25, Qt.RelativeSize) painter.setFont(font) painter.setBrush(Qt.black) painter.drawText(QRect(QPoint(6, 6), size), Qt.AlignCenter, text) painter.end() self.setPixmap(QPixmap.fromImage(image)) self.labelText = text
def pixmap(name, size, mode, state): """Returns a (possibly cached) pixmap of the name and size with the default text color. The state argument is ignored for now. """ if mode == QIcon.Selected: color = QApplication.palette().highlightedText().color() else: color = QApplication.palette().text().color() key = (name, size.width(), size.height(), color.rgb(), mode) try: return _pixmaps[key] except KeyError: i = QImage(size, QImage.Format_ARGB32_Premultiplied) i.fill(0) painter = QPainter(i) # render SVG symbol QSvgRenderer(os.path.join(__path__[0], name + ".svg")).render(painter) # recolor to text color painter.setCompositionMode(QPainter.CompositionMode_SourceIn) painter.fillRect(i.rect(), color) painter.end() # let style alter the drawing based on mode, and create QPixmap pixmap = QApplication.style().generatedIconPixmap(mode, QPixmap.fromImage(i), QStyleOption()) _pixmaps[key] = pixmap return pixmap
def createImage(self, transform): scaledRect = transform.mapRect(QRect(0, 0, 25, 25)) image = QImage(scaledRect.width(), scaledRect.height(), QImage.Format_ARGB32_Premultiplied) image.fill(0) painter = QPainter(image) painter.scale(transform.m11(), transform.m22()) painter.setRenderHints(QPainter.TextAntialiasing | QPainter.Antialiasing | QPainter.SmoothPixmapTransform) painter.setPen(Qt.NoPen) if Colors.useEightBitPalette: painter.setBrush(QColor(102, 175, 54)) painter.drawEllipse(0, 0, 25, 25) painter.setFont(Colors.tickerFont()) painter.setPen(QColor(255, 255, 255)) painter.drawText(10, 15, self.letter) else: brush = QLinearGradient(0, 0, 0, 25) brush.setSpread(QLinearGradient.PadSpread) brush.setColorAt(0.0, QColor(102, 175, 54, 200)) brush.setColorAt(1.0, QColor(102, 175, 54, 60)) painter.setBrush(brush) painter.drawEllipse(0, 0, 25, 25) painter.setFont(Colors.tickerFont()) painter.setPen(QColor(255, 255, 255, 255)) painter.drawText(10, 15, self.letter) return image
def _render_qwebpage_full(self, web_rect, render_rect, canvas_size): """Render web page in one step.""" if self._qpainter_needs_tiling(render_rect, canvas_size): # If this condition is true, this function may get stuck. raise ValueError("Rendering region is too large to be drawn" " in one step, use tile-by-tile renderer instead") canvas = QImage(canvas_size, self.qt_image_format) if self.is_jpeg(): # White background for JPEG images, same as we have in all browsers. canvas.fill(Qt.white) else: # Preserve old behaviour for PNG format. canvas.fill(0) painter = QPainter(canvas) try: painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) painter.setWindow(web_rect) painter.setViewport(render_rect) painter.setClipRect(web_rect) self.web_page.mainFrame().render(painter) finally: painter.end() return WrappedQImage(canvas)
def createImage(self, transform): if self.type == DemoTextItem.DYNAMIC_TEXT: return None sx = min(transform.m11(), transform.m22()) sy = max(transform.m22(), sx) textItem = QGraphicsTextItem() textItem.setHtml(self.text) textItem.setTextWidth(self.textWidth) textItem.setFont(self.font) textItem.setDefaultTextColor(self.textColor) textItem.document().setDocumentMargin(2) w = textItem.boundingRect().width() h = textItem.boundingRect().height() image = QImage(int(w * sx), int(h * sy), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(0, 0, 0, 0).rgba()) painter = QPainter(image) painter.scale(sx, sy) style = QStyleOptionGraphicsItem() textItem.paint(painter, style, None) return image
def create_mask(self, control_image, rendered_image, mask_image, overload=1): max_width = min(rendered_image.width(), control_image.width()) max_height = min(rendered_image.height(), control_image.height()) new_mask_image = QImage(control_image.width(), control_image.height(), QImage.Format_ARGB32) new_mask_image.fill(QColor(0, 0, 0)) # loop through pixels in rendered image and compare mismatch_count = 0 linebytes = max_width * 4 for y in range(max_height): control_scanline = control_image.constScanLine(y).asstring(linebytes) rendered_scanline = rendered_image.constScanLine(y).asstring(linebytes) mask_scanline = mask_image.scanLine(y).asstring(linebytes) for x in range(max_width): currentTolerance = qRed(struct.unpack("I", mask_scanline[x * 4 : x * 4 + 4])[0]) if currentTolerance == 255: # ignore pixel new_mask_image.setPixel(x, y, qRgb(currentTolerance, currentTolerance, currentTolerance)) continue expected_rgb = struct.unpack("I", control_scanline[x * 4 : x * 4 + 4])[0] rendered_rgb = struct.unpack("I", rendered_scanline[x * 4 : x * 4 + 4])[0] difference = min(255, colorDiff(expected_rgb, rendered_rgb) * overload) if difference > currentTolerance: # update mask image new_mask_image.setPixel(x, y, qRgb(difference, difference, difference)) mismatch_count += 1 else: new_mask_image.setPixel(x, y, qRgb(currentTolerance, currentTolerance, currentTolerance)) return new_mask_image
def paintQR(self, data): if not data: return qr = qrcode.QRCode() qr.add_data(data) matrix = qr.get_matrix() k = len(matrix) border_color = Qt.white base_img = QImage(k * 5, k * 5, QImage.Format_ARGB32) base_img.fill(border_color) qrpainter = QPainter() qrpainter.begin(base_img) boxsize = 5 size = k * boxsize left = (base_img.width() - size)/2 top = (base_img.height() - size)/2 qrpainter.setBrush(Qt.black) qrpainter.setPen(Qt.black) for r in range(k): for c in range(k): if matrix[r][c]: qrpainter.drawRect(left+c*boxsize, top+r*boxsize, boxsize - 1, boxsize - 1) qrpainter.end() return base_img
def createImage(self, transform): original = QImage(self.image) if original.isNull(): return original size = transform.map(QPoint(self.maxWidth, self.maxHeight)) w = size.x() h = size.y() # Optimization: if image is smaller than maximum allowed size, just # return the loaded image. if original.size().height() <= h and original.size().width() <= w and not self.adjustSize and self.scale == 1: return original # Calculate what the size of the final image will be. w = min(w, float(original.size().width()) * self.scale) h = min(h, float(original.size().height()) * self.scale) adjustx = 1.0 adjusty = 1.0 if self.adjustSize: adjustx = min(transform.m11(), transform.m22()) adjusty = max(transform.m22(), adjustx) w *= adjustx h *= adjusty # Create a new image with correct size, and draw original on it. image = QImage(int(w + 2), int(h + 2), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(0, 0, 0, 0).rgba()) painter = QPainter(image) painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) if self.adjustSize: painter.scale(adjustx, adjusty) if self.scale != 1: painter.scale(self.scale, self.scale) painter.drawImage(0, 0, original) if not self.adjustSize: # Blur out edges. blur = 30 if h < original.height(): brush1 = QLinearGradient(0, h - blur, 0, h) brush1.setSpread(QLinearGradient.PadSpread) brush1.setColorAt(0.0, QColor(0, 0, 0, 0)) brush1.setColorAt(1.0, Colors.sceneBg1) painter.fillRect(0, int(h) - blur, original.width(), int(h), brush1) if w < original.width(): brush2 = QLinearGradient(w - blur, 0, w, 0) brush2.setSpread(QLinearGradient.PadSpread) brush2.setColorAt(0.0, QColor(0, 0, 0, 0)) brush2.setColorAt(1.0, Colors.sceneBg1) painter.fillRect(int(w) - blur, 0, int(w), original.height(), brush2) return image
def overlay_image(img, canvas=None, left=0, top=0): ' Overlay the `img` onto the canvas at the specified position ' if canvas is None: canvas = QImage(img.size(), QImage.Format_RGB32) canvas.fill(Qt.white) left, top = int(left), int(top) imageops.overlay(img, canvas, left, top) return canvas
def add_borders_to_image(img, left=0, top=0, right=0, bottom=0, border_color='#ffffff'): img = image_from_data(img) if not (left > 0 or right > 0 or top > 0 or bottom > 0): return img canvas = QImage(img.width() + left + right, img.height() + top + bottom, QImage.Format_RGB32) canvas.fill(QColor(border_color)) overlay_image(img, canvas, left, top) return canvas
def createRoundButtonBackground(self, transform): scaledRect = transform.mapRect(QRect(0, 0, self.logicalSize.width(), self.logicalSize.height())) image = QImage(scaledRect.width(), scaledRect.height(), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(0, 0, 0, 0).rgba()) painter = QPainter(image) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) painter.setPen(Qt.NoPen) if Colors.useEightBitPalette: painter.setPen(QColor(120, 120, 120)) if self.pressed: painter.setBrush(QColor(60, 60, 60)) elif self.highlighted: painter.setBrush(QColor(100, 100, 100)) else: painter.setBrush(QColor(80, 80, 80)) else: outlinebrush = QLinearGradient(0, 0, 0, scaledRect.height()) brush = QLinearGradient(0, 0, 0, scaledRect.height()) brush.setSpread(QLinearGradient.PadSpread) highlight = QColor(255, 255, 255, 70) shadow = QColor(0, 0, 0, 70) sunken = QColor(220, 220, 220, 30) if self.type == TextButton.PANEL: normal1 = QColor(200, 170, 160, 50) normal2 = QColor(50, 10, 0, 50) else: normal1 = QColor(255, 255, 245, 60) normal2 = QColor(255, 255, 235, 10) if self.pressed: outlinebrush.setColorAt(0, shadow) outlinebrush.setColorAt(1, highlight) brush.setColorAt(0, sunken) painter.setPen(Qt.NoPen) else: outlinebrush.setColorAt(1, shadow) outlinebrush.setColorAt(0, highlight) brush.setColorAt(0, normal1) if not self.highlighted: brush.setColorAt(1, normal2) painter.setPen(QPen(outlinebrush, 1)) painter.setBrush(brush) if self.type == TextButton.PANEL: painter.drawRect(0, 0, scaledRect.width(), scaledRect.height()) else: painter.drawRoundedRect(0, 0, scaledRect.width(), scaledRect.height(), 10, 90, Qt.RelativeSize) return image
class DMXOverview(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setAttribute(Qt.WA_StaticContents) self.parent = parent self.width = 512 self.height = 32 self.pen_width = 1 self.image = QImage(QSize(self.width, self.height), QImage.Format_RGB32) self.setMaximumSize(self.width, self.height) self.setMinimumSize(self.width, self.height) self.last_point = QPoint() self.clear_image() self.white_pen = QPen(Qt.white, 1) self.black_pen = QPen(Qt.black, 1) def draw_frame(self, frame): painter = QPainter(self.image) for line, value in enumerate(frame): self.draw_line(line, value, painter) self.update() def draw_line(self, line, value, painter=None, update=False): if painter == None: painter = QPainter(self.image) painter.setPen(Qt.black) painter.drawLine(QPoint(line, 31 - value // 8), QPoint(line, 31)) painter.setPen(Qt.white) painter.drawLine(QPoint(line, 0), QPoint(line, 31 - value // 8)) if update: self.update() def fill_image(self, color): self.image.fill(color) self.update() def clear_image(self): self.image.fill(Qt.white) self.update() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: line = event.pos().x() self.parent.address_table.verticalScrollBar().setSliderPosition(line) def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image)
def updateMask(control_image_path, rendered_image_path, mask_image_path): control_image = imageFromPath(control_image_path) if not control_image: error("Could not read control image {}".format(control_image_path)) rendered_image = imageFromPath(rendered_image_path) if not rendered_image: error("Could not read rendered image {}".format(rendered_image_path)) if not rendered_image.width() == control_image.width() or not rendered_image.height() == control_image.height(): print( ( "Size mismatch - control image is {}x{}, rendered image is {}x{}".format( control_image.width(), control_image.height(), rendered_image.width(), rendered_image.height() ) ) ) max_width = min(rendered_image.width(), control_image.width()) max_height = min(rendered_image.height(), control_image.height()) # read current mask, if it exist mask_image = imageFromPath(mask_image_path) if mask_image.isNull(): print("Mask image does not exist, creating {}".format(mask_image_path)) mask_image = QImage(control_image.width(), control_image.height(), QImage.Format_ARGB32) mask_image.fill(QColor(0, 0, 0)) # loop through pixels in rendered image and compare mismatch_count = 0 linebytes = max_width * 4 for y in range(max_height): control_scanline = control_image.constScanLine(y).asstring(linebytes) rendered_scanline = rendered_image.constScanLine(y).asstring(linebytes) mask_scanline = mask_image.scanLine(y).asstring(linebytes) for x in range(max_width): currentTolerance = qRed(struct.unpack("I", mask_scanline[x * 4 : x * 4 + 4])[0]) if currentTolerance == 255: # ignore pixel continue expected_rgb = struct.unpack("I", control_scanline[x * 4 : x * 4 + 4])[0] rendered_rgb = struct.unpack("I", rendered_scanline[x * 4 : x * 4 + 4])[0] difference = colorDiff(expected_rgb, rendered_rgb) if difference > currentTolerance: # update mask image mask_image.setPixel(x, y, qRgb(difference, difference, difference)) mismatch_count += 1 if mismatch_count: # update mask mask_image.save(mask_image_path, "png") print("Updated {} pixels in {}".format(mismatch_count, mask_image_path)) else: print("No mismatches in {}".format(mask_image_path))
def resizeImage(self, image, newSize): if image.size() == newSize: return newImage = QImage(newSize, QImage.Format_RGB32) newImage.fill(qRgb(255, 255, 255)) painter = QPainter(newImage) painter.drawImage(QPoint(0, 0), image) self.image = newImage
def addY(bitmap): nbmp = QImage( bitmap.width(), bitmap.height() + 1, bitmap.format() ) nbmp.fill(0) for y in range( bitmap.height() ): for x in range( bitmap.width() ): data = qGray( bitmap.pixel( x, y ) ) if data: nbmp.setPixel( x, y, 1 ) return nbmp
def create_qimage(self): total_width = 0 images = [] while total_width < self._width: w = min(self._width - total_width, 2 ** 15) image = QImage(w, self._height, QImage.Format_ARGB32) image.fill(QColor(235, 235, 235, 255)) total_width += w images.append(image) return images
def blend_on_canvas(img, width, height, bgcolor='#ffffff'): ' Blend the `img` onto a canvas with the specified background color and size ' w, h = img.width(), img.height() scaled, nw, nh = fit_image(w, h, width, height) if scaled: img = img.scaled(nw, nh, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) w, h = nw, nh canvas = QImage(width, height, QImage.Format_RGB32) canvas.fill(QColor(bgcolor)) overlay_image(img, canvas, (width - w)//2, (height - h)//2) return canvas
def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert self.pos == pos self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage( QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied ) # TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height())) target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height())) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int) ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,)) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,)) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4 * 4 downsample_threshold = (7.0 / 16) * 255 labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)
def _blendTile(self, stack_id, tile_nr): """ Blend all of the QImage layers of the patch specified by (stack_id, tile_nr) into a single QImage. """ qimg = None p = None for i, (visible, layerOpacity, layerImageSource) in enumerate(reversed(self._sims)): image_type = layerImageSource.image_type() if issubclass(image_type, QGraphicsItem): with self._cache: patch = self._cache.layer(stack_id, layerImageSource, tile_nr) if patch is not None: assert isinstance( patch, image_type ), "This ImageSource is producing a type of image that is not consistent with it's declared image_type()" # This is a QGraphicsItem, so we don't blend it into the final tile. # (The ImageScene will just draw it on top of everything.) # But this is a convenient place to update the opacity/visible state. if patch.opacity() != layerOpacity or patch.isVisible() != visible: patch.setOpacity(layerOpacity) patch.setVisible(visible) patch.setZValue(i) # The sims ("stacked image sources") are ordered from # top-to-bottom (see imagepump.py), but in Qt, # higher Z-values are shown on top. # Note that the current loop is iterating in reverse order. continue # No need to fetch non-visible image tiles. if not visible or layerOpacity == 0.0: continue with self._cache: patch = self._cache.layer(stack_id, layerImageSource, tile_nr) # patch might be a QGraphicsItem instead of QImage, # in which case it is handled separately, # not composited into the tile. if patch is not None: assert isinstance( patch, QImage ), "Unknown tile layer type: {}. Expected QImage or QGraphicsItem".format(type(patch)) if qimg is None: qimg = QImage(self.tiling.imageRects[tile_nr].size(), QImage.Format_ARGB32_Premultiplied) qimg.fill(0xFFFFFFFF) # Use a hex constant instead. p = QPainter(qimg) p.setOpacity(layerOpacity) p.drawImage(0, 0, patch) if p is not None: p.end() return qimg
def saveImage(self): fileName = QFileDialog.getSaveFileName(self, self.tr("Select save location"), "", self.tr("Images (*.png *.jpg *.bmp *.xpm)")) if "" != fileName[0] and os.path.isdir(os.path.dirname(fileName[0])): imgSize = QSize(self.plot.scene().width() * 4, self.plot.scene().height() * 4) img = QImage(imgSize, QImage.Format_ARGB32) img.fill(Qt.transparent) painter = QPainter(img) self.plot.render(painter) img.save(fileName[0]) del painter QDesktopServices.openUrl(QUrl("file:///" + fileName[0], QUrl.TolerantMode))
def editNew(self): """ Public slot to generate a new, empty image. """ from .IconSizeDialog import IconSizeDialog dlg = IconSizeDialog(self.__image.width(), self.__image.height()) res = dlg.exec_() if res == QDialog.Accepted: width, height = dlg.getData() img = QImage(width, height, QImage.Format_ARGB32) img.fill(qRgba(0, 0, 0, 0)) self.setIconImage(img)
def render(self, page): """Generate an image for this Page.""" i = QImage(page.width, page.height, QImage.Format_ARGB32_Premultiplied) i.fill(self.paperColor) painter = QPainter(i) rect = QRect(0, 0, page.width, page.height) painter.translate(rect.center()) painter.rotate(page.computedRotation * 90) if page.computedRotation & 1: rect.setSize(rect.size().transposed()) painter.translate(-rect.center()) page._svg_r.render(painter, QRectF(rect)) return i
def _rounded_qimage(qimg, radius): r_image = QImage(qimg.width(), qimg.height(), QImage.Format_ARGB32) r_image.fill(Qt.transparent) p = QPainter() pen = QPen(Qt.darkGray) pen.setJoinStyle(Qt.RoundJoin) p.begin(r_image) p.setRenderHint(p.Antialiasing) p.setPen(Qt.NoPen) p.setBrush(QBrush(qimg)) p.drawRoundedRect(0, 0, r_image.width(), r_image.height(), radius, radius) p.end() return r_image
def saveImage(self, frame): element = self.getPostElement(frame.documentElement()) if element is not None: rect = element.geometry() image = QImage(rect.size(), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter(image) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) element.render(painter) painter.end() image.save(self.getName(element))
def render(self, page): """Generate an image for this Page.""" i = QImage(page.width, page.height, self.imageFormat) i.fill(page.paperColor or self.paperColor or QColor(Qt.white)) painter = QPainter(i) rect = QRect(0, 0, page.width, page.height) painter.translate(rect.center()) painter.rotate(page.computedRotation * 90) if page.computedRotation & 1: rect.setSize(rect.size().transposed()) painter.translate(-rect.center()) page._svg_r.render(painter, QRectF(rect)) return i
def wait(self): array_data = self._arrayreq.wait() rectf = self.rectf if array_data.handedness_switched: # array_data should be of type slicingtools.ProjectedArray rectf = QRectF(rectf.height(), rectf.width()) from PyQt5.QtWidgets import QPainter img = QImage(QSize(self.rectf.width(), self.rectf.height()), QImage.Format_ARGB32_Premultiplied) img.fill(0xFFFFFFFF) p = QPainter(img) p.drawImage(0, 0, img) DummyItem(self.rectf).paint(p, None) return img
def fontValuePixmap(font): f = QFont(font) img = QImage(16, 16, QImage.Format_ARGB32_Premultiplied) img.fill(0) p = QPainter(img) p.setRenderHint(QPainter.TextAntialiasing, True) p.setRenderHint(QPainter.Antialiasing, True) f.setPointSize(13) p.setFont(f) t = QTextOption() t.setAlignment(Qt.AlignCenter) p.drawText(QRectF(0, 0, 16, 16), 'A', t) p.end() return QPixmap.fromImage(img)
def font_charBmp(font, char): metric = QFontMetrics( font ).boundingRect( char ) char_rect = QRect( 0, 0, metric.width(), metric.height() ) chr_img = QImage( char_rect.width()+1, char_rect.height(), QImage.Format_Mono ) chr_img.fill(0) # set img painter and draw char to bmp painter = QPainter( chr_img ) painter.setPen( QPen(Qt.white) ) painter.setFont( font ) painter.drawText( char_rect, Qt.AlignJustify, char ) painter.end() del(painter) # crop left / right x0 = 0 x1 = char_rect.width() while x0 < x1 - 1: data_col = 0 for col in range( char_rect.height() ): data_col += chr_img.pixel(x0, col) & 0x00FFFFFF if not data_col: x0 += 1 else: break char_rect.setX(x0) while x1 > x0 + 1: x1 -= 1 data_col = 0 for col in range( char_rect.height() ): data_col += chr_img.pixel(x1, col) & 0x00FFFFFF if not data_col: char_rect.setWidth(x1 - x0) else: break # crop bottom y1 = char_rect.height() while y1 > 1: y1 -= 1 data_row = 0 for row in range( char_rect.width() ): data_row += chr_img.pixel(row, y1) & 0x00FFFFFF if not data_row: char_rect.setHeight(y1) else: break chr_img = chr_img.copy( char_rect ) # chr_img.save( '.\\img\\0%s.bmp' % char, 'bmp' ) return chr_img
def _pasteIcon(self): mime = QApplication.clipboard().mimeData() if mime.hasImage(): image = mime.imageData() # Fill transparent color if present fixedImage = QImage(image.size(), QImage.Format_RGB32) fixedImage.fill(QColor(Qt.white).rgb()) painter = QPainter(fixedImage) painter.drawImage(0, 0, image) painter.end() self._setNewImage(fixedImage) elif mime.hasUrls(): url = mime.urls()[0] self.loadFromFile(url.toLocalFile())
def get_image(self, size): if self.source_setting_changed(): self.update_source() image = QImage(size.width(), size.height(), QImage.Format_ARGB32) painter = QPainter(image) if self.graph is None: if self.settings.contains('protofile'): url = QUrl(self.settings.value('protofile')) self.set_source(url.toDisplayString(QUrl.RemoveScheme)) else: image.fill(QColor(200, 200, 200)) return image self.renderer.load(QByteArray(self.graph)) self.renderer.render(painter) return image
class Map(QWidget): def __init__(self): super().__init__() self.initUI() elHght_72, elWdth_72 = 0, 0 #Mouse click WiFi zone elHght_54, elWdth_54 = 0, 0 elHght_32, elWdth_32 = 0, 0 elHght_11, elWdth_11 = 0, 0 elHght_6, elWdth_6 = 0, 0 elHght_1, elWdth_1 = 0, 0 elCntH, elCntW = 0, 0 #Mouse click WiFi zone center clickNum = 0 #Number of mouse click for device devList = [] #Device list elClr = "#000000" def mousePressEvent(self, event): point = event.pos() painter = QPainter(self._im) painter.setPen(QPen(QColor(Map.elClr), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor(Map.elClr), Qt.SolidPattern)) painter.drawEllipse(point, Map.elCntH, Map.elCntW) painter.setPen(QPen(QColor("#000"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#000"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_72, Map.elWdth_72) painter.setPen(QPen(QColor("#439232"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#439232"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_54, Map.elWdth_54) painter.setPen(QPen(QColor("#923243"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#923243"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_32, Map.elWdth_32) painter.setPen(QPen(QColor("#324392"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#324392"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_11, Map.elWdth_11) painter.setPen(QPen(QColor("#324392"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#324392"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_6, Map.elWdth_6) painter.setPen(QPen(QColor("#324392"), 2, Qt.SolidLine, Qt.RoundCap)) painter.setBrush(QBrush(QColor("#324392"), Qt.CrossPattern)) painter.drawEllipse(point, Map.elHght_1, Map.elWdth_1) if Map.elHght_1 >= 10: painter.setPen(QPen(QColor("#000000"))) painter.setFont(QFont('Arial', 15)) painter.drawText(point, str(Map.clickNum + 1)) print("ClickNum:", Map.clickNum + 1) #Mouse click coordinates pointPressX = point.x() pointPressY = point.y() print("X is", pointPressX) print("Y is", pointPressY) #New device radiusWiFi = [Map.elHght_72, Map.elHght_54, Map.elHght_32, Map.elHght_11, Map.elHght_6, Map.elHght_1] dev = device.Device(Map.clickNum + 1, [pointPressX, pointPressY], radiusWiFi) #Device list Map.devList.append(dev) print("Map.devList", Map.devList) Map.clickNum += 1 #if Map.clickNum >= 1: # device.calcWifiDist(Map.devList) # Перерисуемся self.update() def paintEvent(self, event): super().paintEvent(event) painter = QPainter(self) painter.drawImage(0, 0, self._im) def initUI(self): QToolTip.setFont(QFont('SansSerif', 10)) #Button Router btnRout = QPushButton("Router", self) btnRout.move(30, 50) btnESP = QPushButton("ESP-32", self) btnESP.move(160, 50) btnStp = QPushButton("Stop", self) btnStp.move(290, 50) btnShwInts = QPushButton("Result", self) #btnShwInts = btnStp = QPushButton("Result", self) #when click button, 2 buttons work (stop and Result) btnShwInts.move(420, 50) btnRout.clicked.connect(self.btnRoutnClicked) btnESP.clicked.connect(self.btnESPClicked) btnStp.clicked.connect(self.btnStopClicked) btnShwInts.clicked.connect(self.btnShwIntsClicked) #Size and color for drawing zone self._im = QImage(1700, 960, QImage.Format_ARGB32) self._im.fill(QColor("white")) #Painting of room - rectangle painterRect = QPainter(self._im) painterRect.setPen(QPen(QColor("#000"), 1, Qt.SolidLine, Qt.RoundCap)) painterRect.drawRect(100, 100, 100, 800) ##History # ## Size and color for drawing zone #self._in = QImage(1700, 960, QImage.Format_ARGB32) #self._in.fill(QColor("red")) # ##Color for speed 72Mbps #history = QPainter(self._in) #history.setPen(QPen(QColor("#439232"), 1, Qt.SolidLine, Qt.RoundCap)) ##history_72.setBrush(QBrush(QColor("#439232"), Qt.CrossPattern)) #history.drawRect(400, 100, 100, 800) # ## Color for speed 54Mbps #history_54 = QPainter(self._im) #history_54.setPen(QPen(QColor("#923243"), 1, Qt.SolidLine, Qt.RoundCap)) #history_54.setBrush(QBrush(QColor("#923243"), Qt.CrossPattern)) #history_54.drawRect(50, 150, 50, 50) # ## Color for speed 32Mbps #history_32 = QPainter(self._im) #history_32.setPen(QPen(QColor("#324392"), 1, Qt.SolidLine, Qt.RoundCap)) #history_32.setBrush(QBrush(QColor("#324392"), Qt.CrossPattern)) #history_32.drawRect(50, 200, 50, 50) # ## Color for speed 11Mbps #history_11 = QPainter(self._im) #history_11.setPen(QPen(QColor("#000"), 1, Qt.SolidLine, Qt.RoundCap)) #history_11.setBrush(QBrush(QColor("#000"), Qt.CrossPattern)) #history_11.drawRect(50, 250, 50, 50) # ## Color for speed 6Mbps #history_6 = QPainter(self._im) #history_6.setPen(QPen(QColor("#000"), 1, Qt.SolidLine, Qt.RoundCap)) #history_6.setBrush(QBrush(QColor("#000"), Qt.CrossPattern)) #history_6.drawRect(50, 300, 50, 50) # ## Color for speed 1Mbps #history_1 = QPainter(self._im) #history_1.setPen(QPen(QColor("#000"), 1, Qt.SolidLine, Qt.RoundCap)) #history_1.setBrush(QBrush(QColor("#000"), Qt.CrossPattern)) #history_1.drawRect(50, 350, 50, 50) #Size and Title for program window self.setFixedSize(1700, 960) self.setWindowTitle('Room') self.show() def btnRoutnClicked(self): ''' Function for button Router Changes size and color of router's wifi zone ''' Map.elHght_72, Map.elWdth_72 = rtrWidth #Map.elHght_54, Map.elWdth_54 #Map.elHght_32, Map.elWdth_32 #Map.elHght_11, Map.elWdth_11 #Map.elHght_6, Map.elWdth_6 #Map.elHght_1, Map.elWdth_1 Map.elCntH, Map.elCntW = rtrCnt Map.elClr = "#431292" print("Button Router pressed") def btnESPClicked(self): ''' Function for button ESP-32 Changes size and color of esp's wifi zone ''' Map.elHght_72, Map.elWdth_72 = espWidth_72 Map.elHght_54, Map.elWdth_54 = espWidth_54 Map.elHght_32, Map.elWdth_32 = espWidth_32 Map.elHght_11, Map.elWdth_11 = espWidth_11 Map.elHght_6, Map.elWdth_6 = espWidth_6 Map.elHght_1, Map.elWdth_1 = espWidth_1 Map.elCntH, Map.elCntW = espWidth_Cnt Map.elClr = "#439232" print("Button ESP-32 pressed") def btnStopClicked(self): ''' Function for button Stop Changes size of wifi zone to 0 ''' Map.elHght_72, Map.elWdth_72 = width_stop Map.elHght_54, Map.elWdth_54 = width_stop Map.elHght_32, Map.elWdth_32 = width_stop Map.elHght_11, Map.elWdth_11 = width_stop Map.elHght_6, Map.elWdth_6 = width_stop Map.elHght_1, Map.elWdth_1 = width_stop Map.elCntH, Map.elCntW = width_stop print("Button Stop pressed") def btnShwIntsClicked(self): print("Button Show intersections pressed") if Map.clickNum >= 1: speed = wifi_speed device.calcWifiDist(Map.devList, wifi_speed)
class Viz(QWidget): def __init__(self, prob): super().__init__() self.xLen = self.yLen = 10 * unit w, h = coX + self.xLen + margin * 1, coY + self.yLen + margin * 1 self.canvasSize = (w, h) # self.image = QImage(w, h, QImage.Format_RGB32) # self.image.fill(Qt.white) # self.path = QPainterPath() # self.clearImage() # self.instances = [] self.initInstances(prob) self.initUI(prob['problemName']) QShortcut(QKeySequence("Ctrl+Q"), self, self.close) def initInstances(self, prob): sL, sXY = [], [] for i in range(len(prob['S'])): sL.append('s%d' % i) sx, sy = prob['XY'][prob['S'][i]] sXY.append((coX + sx * self.xLen, coY + (1.0 - sy) * self.yLen)) self.instances.append(RoutineSequence(sL, sXY)) for i in range(len(prob['P'])): wid = 'w%d' % i nid = prob['P'][i] hx, hy = prob['XY'][nid] clr = pallet[nid % len(pallet)] wh = WareHouse(wid, coX + hx * self.xLen, coY + (1.0 - hy) * self.yLen, clr) self.instances.append(wh) partialSeq = prob['S'] al_i, be_i, t_ij, bu = [ prob[k] for k in ['al_i', 'be_i', 't_ij', 'bu'] ] for k in range(len(prob['D'])): nid = 't%d' % k nx, ny = prob['XY'][prob['D'][k]] n0, n1 = prob['h_k'][k], prob['n_k'][k] clr = pallet[n0 % len(pallet)] isValidTask = None min_tt_seq = get_min_tt_seq(partialSeq, n0, n1, al_i, be_i, t_ij) if min_tt_seq is None: isValidTask = False else: tt = get_travelTime(min_tt_seq, al_i, be_i, t_ij) isValidTask = tt < bu self.instances.append( DeliveryPoint(nid, coX + nx * self.xLen, coY + (1.0 - ny) * self.yLen, clr, isValidTask)) # def clearImage(self): # self.path = QPainterPath() # self.image.fill(Qt.white) # self.update() def initUI(self, problemName): w, h = self.canvasSize self.setGeometry(mainFrameOrigin[0], mainFrameOrigin[1], w, h) self.setWindowTitle(problemName) self.setFixedSize(QSize(w, h)) # self.image = QImage(w, h, QImage.Format_RGB32) self.image.fill(Qt.white) pal = self.palette() pal.setColor(QPalette.Background, Qt.white) self.setAutoFillBackground(True) self.setPalette(pal) # self.show() def paintEvent(self, e): qp = QPainter() qp.begin(self) self.drawCanvas(qp) qp.end() # qp = QPainter() qp.begin(self.image) self.drawCanvas(qp) qp.end() def save_img(self, img_fpath): if img_fpath.endswith('.png'): self.image.save(img_fpath, 'png') else: assert img_fpath.endswith('.pdf') w, h = self.canvasSize printer = QPrinter(QPrinter.HighResolution) printer.setPageSizeMM(QSizeF(w / 15, h / 15)) printer.setFullPage(True) printer.setPageMargins(0.0, 0.0, 0.0, 0.0, QPrinter.Millimeter) printer.setColorMode(QPrinter.Color) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(img_fpath) pixmap = self.grab().scaledToHeight( printer.pageRect( QPrinter.DevicePixel).size().toSize().height() * 2) painter = QPainter(printer) painter.drawPixmap(0, 0, pixmap) painter.end() def drawCanvas(self, qp): pen = QPen(Qt.black, 2, Qt.SolidLine) qp.setPen(pen) qp.setBrush(Qt.NoBrush) # Outer lines! qp.drawLine(coX, coY, coX, coY + self.yLen) qp.drawLine(coX, coY + self.yLen, coX + self.xLen, coY + self.yLen) qp.drawLine(coX + self.xLen, coY + self.yLen, coX + self.xLen, coY) qp.drawLine(coX + self.xLen, coY, coX, coY) # pen = QPen(Qt.gray, 1, Qt.DashLine) qp.setPen(pen) for i in range(numGridLines): qp.drawLine(coX + float(i + 1) / (numGridLines + 1) * self.xLen, coY, coX + float(i + 1) / (numGridLines + 1) * self.xLen, coY + self.yLen) qp.drawLine(coX + self.xLen, coY + float(i + 1) / (numGridLines + 1) * self.yLen, coX, coY + float(i + 1) / (numGridLines + 1) * self.yLen) # for ins in self.instances: ins.draw(qp)
class ResultHandler(QDialog): def __init__(self, parent=None): super(ResultHandler, self).__init__() self.setWindowTitle('Dash results') self.control_label = QLabel() self.rendered_label = QLabel() self.diff_label = QLabel() self.mask_label = QLabel() self.new_mask_label = QLabel() grid = QGridLayout() self.test_name_label = QLabel() grid.addWidget(self.test_name_label, 0, 0) grid.addWidget(QLabel('Control'), 1, 0) grid.addWidget(QLabel('Rendered'), 1, 1) grid.addWidget(QLabel('Difference'), 1, 2) grid.addWidget(self.control_label, 2, 0) grid.addWidget(self.rendered_label, 2, 1) grid.addWidget(self.diff_label, 2, 2) grid.addWidget(QLabel('Current Mask'), 3, 0) grid.addWidget(QLabel('New Mask'), 3, 1) grid.addWidget(self.mask_label, 4, 0) grid.addWidget(self.new_mask_label, 4, 1) v_layout = QVBoxLayout() v_layout.addLayout(grid, 1) next_image_button = QPushButton() next_image_button.setText('Skip') next_image_button.pressed.connect(self.load_next) self.overload_spin = QDoubleSpinBox() self.overload_spin.setMinimum(1) self.overload_spin.setMaximum(255) self.overload_spin.setValue(1) preview_mask_button = QPushButton() preview_mask_button.setText('Preview New Mask') preview_mask_button.pressed.connect(self.preview_mask) save_mask_button = QPushButton() save_mask_button.setText('Save New Mask') save_mask_button.pressed.connect(self.save_mask) button_layout = QHBoxLayout() button_layout.addWidget(next_image_button) button_layout.addWidget(QLabel('Mask diff multiplier:')) button_layout.addWidget(self.overload_spin) button_layout.addWidget(preview_mask_button) button_layout.addWidget(save_mask_button) button_layout.addStretch() v_layout.addLayout(button_layout) self.setLayout(v_layout) def closeEvent(self, event): self.reject() def parse_url(self, url): print('Fetching dash results from: {}'.format(url)) page = urllib.request.urlopen(url) soup = BeautifulSoup(page, "lxml") # build up list of rendered images measurement_img = [ img for img in soup.find_all('img') if img.get('alt') and img.get('alt').startswith('Rendered Image') ] images = {} for img in measurement_img: m = re.search('Rendered Image (.*?)\s', img.get('alt')) test_name = m.group(1) rendered_image = img.get('src') images[test_name] = '{}/{}'.format(dash_url, rendered_image) print('found images:\n{}'.format(images)) self.images = images self.load_next() def load_next(self): if not self.images: # all done self.accept() test_name, rendered_image = self.images.popitem() self.test_name_label.setText(test_name) control_image = self.get_control_image_path(test_name) if not control_image: self.load_next() return self.mask_image_path = control_image[:-4] + '_mask.png' self.load_images(control_image, rendered_image, self.mask_image_path) def load_images(self, control_image_path, rendered_image_path, mask_image_path): self.control_image = imageFromPath(control_image_path) if not self.control_image: error('Could not read control image {}'.format(control_image_path)) self.rendered_image = imageFromPath(rendered_image_path) if not self.rendered_image: error( 'Could not read rendered image {}'.format(rendered_image_path)) if not self.rendered_image.width() == self.control_image.width( ) or not self.rendered_image.height() == self.control_image.height(): print( 'Size mismatch - control image is {}x{}, rendered image is {}x{}' .format(self.control_image.width(), self.control_image.height(), self.rendered_image.width(), self.rendered_image.height())) max_width = min(self.rendered_image.width(), self.control_image.width()) max_height = min(self.rendered_image.height(), self.control_image.height()) # read current mask, if it exist self.mask_image = imageFromPath(mask_image_path) if self.mask_image.isNull(): print('Mask image does not exist, creating {}'.format( mask_image_path)) self.mask_image = QImage(self.control_image.width(), self.control_image.height(), QImage.Format_ARGB32) self.mask_image.fill(QColor(0, 0, 0)) self.diff_image = self.create_diff_image(self.control_image, self.rendered_image, self.mask_image) if not self.diff_image: self.load_next() return self.control_label.setPixmap(QPixmap.fromImage(self.control_image)) self.rendered_label.setPixmap(QPixmap.fromImage(self.rendered_image)) self.mask_label.setPixmap(QPixmap.fromImage(self.mask_image)) self.diff_label.setPixmap(QPixmap.fromImage(self.diff_image)) self.preview_mask() def preview_mask(self): self.new_mask_image = self.create_mask(self.control_image, self.rendered_image, self.mask_image, self.overload_spin.value()) self.new_mask_label.setPixmap(QPixmap.fromImage(self.new_mask_image)) def save_mask(self): self.new_mask_image.save(self.mask_image_path, "png") self.load_next() def create_mask(self, control_image, rendered_image, mask_image, overload=1): max_width = min(rendered_image.width(), control_image.width()) max_height = min(rendered_image.height(), control_image.height()) new_mask_image = QImage(control_image.width(), control_image.height(), QImage.Format_ARGB32) new_mask_image.fill(QColor(0, 0, 0)) # loop through pixels in rendered image and compare mismatch_count = 0 linebytes = max_width * 4 for y in range(max_height): control_scanline = control_image.constScanLine(y).asstring( linebytes) rendered_scanline = rendered_image.constScanLine(y).asstring( linebytes) mask_scanline = mask_image.scanLine(y).asstring(linebytes) for x in range(max_width): currentTolerance = qRed( struct.unpack('I', mask_scanline[x * 4:x * 4 + 4])[0]) if currentTolerance == 255: # ignore pixel new_mask_image.setPixel( x, y, qRgb(currentTolerance, currentTolerance, currentTolerance)) continue expected_rgb = struct.unpack( 'I', control_scanline[x * 4:x * 4 + 4])[0] rendered_rgb = struct.unpack( 'I', rendered_scanline[x * 4:x * 4 + 4])[0] difference = min( 255, colorDiff(expected_rgb, rendered_rgb) * overload) if difference > currentTolerance: # update mask image new_mask_image.setPixel( x, y, qRgb(difference, difference, difference)) mismatch_count += 1 else: new_mask_image.setPixel( x, y, qRgb(currentTolerance, currentTolerance, currentTolerance)) return new_mask_image def get_control_image_path(self, test_name): if os.path.isfile(test_name): return path # else try and find matching test image script_folder = os.path.dirname(os.path.realpath(sys.argv[0])) control_images_folder = os.path.join( script_folder, '../tests/testdata/control_images') matching_control_images = [ x[0] for x in os.walk(control_images_folder) if test_name in x[0] ] if len(matching_control_images) > 1: QMessageBox.warning( self, 'Result', 'Found multiple matching control images for {}'.format( test_name)) return None elif len(matching_control_images) == 0: QMessageBox.warning( self, 'Result', 'No matching control images found for {}'.format(test_name)) return None found_control_image_path = matching_control_images[0] # check for a single matching expected image images = glob.glob(os.path.join(found_control_image_path, '*.png')) filtered_images = [i for i in images if not i[-9:] == '_mask.png'] if len(filtered_images) > 1: error('Found multiple matching control images for {}'.format( test_name)) elif len(filtered_images) == 0: error('No matching control images found for {}'.format(test_name)) found_image = filtered_images[0] print('Found matching control image: {}'.format(found_image)) return found_image def create_diff_image(self, control_image, rendered_image, mask_image): # loop through pixels in rendered image and compare mismatch_count = 0 max_width = min(rendered_image.width(), control_image.width()) max_height = min(rendered_image.height(), control_image.height()) linebytes = max_width * 4 diff_image = QImage(control_image.width(), control_image.height(), QImage.Format_ARGB32) diff_image.fill(QColor(152, 219, 249)) for y in range(max_height): control_scanline = control_image.constScanLine(y).asstring( linebytes) rendered_scanline = rendered_image.constScanLine(y).asstring( linebytes) mask_scanline = mask_image.scanLine(y).asstring(linebytes) for x in range(max_width): currentTolerance = qRed( struct.unpack('I', mask_scanline[x * 4:x * 4 + 4])[0]) if currentTolerance == 255: # ignore pixel continue expected_rgb = struct.unpack( 'I', control_scanline[x * 4:x * 4 + 4])[0] rendered_rgb = struct.unpack( 'I', rendered_scanline[x * 4:x * 4 + 4])[0] difference = colorDiff(expected_rgb, rendered_rgb) if difference > currentTolerance: # update mask image diff_image.setPixel(x, y, qRgb(255, 0, 0)) mismatch_count += 1 if mismatch_count: return diff_image else: print('No mismatches') return None
class QImageView(QWidget): '''An experimental class to display images using the QPixmap class. This may be more efficient than using matplotlib for displaying images. ''' image : QImage = None activationMask : QImage = None def __init__(self, parent): super().__init__(parent) #self.setScaledContents(True) # an alternative may be to call # pixmap.scaled(self.size(), Qt.KeepAspectRatio) # in the myplot method. def setImage(self, image : np.ndarray): self.image = image if image is not None: # To construct a 8-bit monochrome QImage, we need a uint8 # numpy array if image.dtype != np.uint8: image = (image*255).astype(np.uint8) self.image = QImage(image, image.shape[1], image.shape[0], QImage.Format_Grayscale8) else: self.image = None self.update() def setActivationMask(self, mask, position = None): '''Set an (activation) mask to be displayed on top of the actual image. The mask should be Arguments --------- mask : numpy.ndarray ''' if mask is None: self.activationMask = None else: self.activationMask = QImage(mask.shape[1], mask.shape[0], QImage.Format_ARGB32) self.activationMask.fill(Qt.red) alpha = QImage(mask, mask.shape[1], mask.shape[0], mask.shape[1], QImage.Format_Alpha8) painter = QPainter(self.activationMask) painter.setCompositionMode(QPainter.CompositionMode_DestinationIn) painter.drawImage(QPoint(),alpha) painter.end() self.update() def paintEvent(self, event): '''Process the paint event by repainting this Widget. Arguments --------- event : QPaintEvent ''' painter = QPainter() painter.begin(self) self._drawImage(painter) self._drawMask(painter) painter.end() def _drawImage(self, painter : QPainter): if self.image is not None: painter.drawImage(self.rect(),self.image) def _drawMask(self, painter : QPainter): '''Display the given image. Image is supposed to be a numpy array. ''' if self.image is not None and self.activationMask is not None: scale_width = self.width() / self.image.width() scale_height = self.height() / self.image.height() delta = (self.image.size() - self.activationMask.size())/2 target = QRect(delta.width()*scale_width, delta.height()*scale_height, self.activationMask.width()*scale_width, self.activationMask.height()*scale_height) #source = QRect(QPoint(),self.activationMask.size()) painter.drawImage(target, self.activationMask)
def exportToMobile(model, params): IMAGE_FORMAT = 'jpg' IMAGE_COMPRESS = 50 USED_FIELDS = ('title', 'unit', 'country', 'year', 'mint', 'mintmark', 'issuedate', 'type', 'series', 'subjectshort', 'material', 'fineness', 'diameter', 'thickness', 'weight', 'mintage', 'rarity', 'obverseimg', 'reverseimg', 'subject', 'price1', 'price2', 'price3', 'price4') if os.path.isfile(params['file']): os.remove(params['file']) db = QSqlDatabase.addDatabase('QSQLITE', 'mobile') db.setDatabaseName(params['file']) if not db.open(): print(db.lastError().text()) QMessageBox.critical(None, "Create mobile collection", "Can't open collection") return sql = """CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US')""" QSqlQuery(sql, db) sql = """INSERT INTO "android_metadata" VALUES ('en_US')""" QSqlQuery(sql, db) mobile_settings = {'Version': 1, 'Type': 'MobilePro', 'Filter': params['filter']} sql = """CREATE TABLE settings ( title CHAR NOT NULL UNIQUE, value CHAR)""" QSqlQuery(sql, db) for key, value in mobile_settings.items(): query = QSqlQuery(db) query.prepare("""INSERT INTO settings (title, value) VALUES (?, ?)""") query.addBindValue(key) query.addBindValue(str(value)) query.exec_() sql = """CREATE TABLE updates ( title CHAR NOT NULL UNIQUE, value CHAR)""" QSqlQuery(sql, db) sql = """INSERT INTO updates (title, value) VALUES ('160203', '2016-02-03T10:19:00')""" QSqlQuery(sql, db) sql = """CREATE TABLE photos ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, image BLOB)""" QSqlQuery(sql, db) sql = """CREATE TABLE coins ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, description_id INTEGER, grade INTEGER, createdat STRING)""" QSqlQuery(sql, db) sql = """CREATE INDEX coins_descriptions ON coins(description_id)""" QSqlQuery(sql, db) sqlFields = [] fields = CollectionFieldsBase() for field in fields: if field.name == 'id': sqlFields.append('id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT') elif field.name == 'image': sqlFields.append('image INTEGER') elif field.name in USED_FIELDS: sqlFields.append("%s %s" % (field.name, Type.toSql(field.type))) sql = "CREATE TABLE descriptions (" + ", ".join(sqlFields) + ")" QSqlQuery(sql, db) while model.canFetchMore(): model.fetchMore() dest_model = QSqlTableModel(None, db) dest_model.setEditStrategy(QSqlTableModel.OnManualSubmit) dest_model.setTable('descriptions') dest_model.select() height = 64 if params['density'] == 'HDPI': height *= 1.5 elif params['density'] == 'XHDPI': height *= 2 elif params['density'] == 'XXHDPI': height *= 3 elif params['density'] == 'XXXHDPI': height *= 4 maxHeight = height * 4 is_obverse_enabled = params['image'] in (ExportDialog.IMAGE_OBVERSE, ExportDialog.IMAGE_BOTH) is_reverse_enabled = params['image'] in (ExportDialog.IMAGE_REVERSE, ExportDialog.IMAGE_BOTH) fields = CollectionFieldsBase() count = model.rowCount() progressDlg = Gui.ProgressDialog("Exporting records", "Cancel", count, None) for i in range(count): progressDlg.step() if progressDlg.wasCanceled(): break coin = model.record(i) if coin.value('status') in ('pass', 'sold'): continue dest_record = dest_model.record() for field in fields: if field.name in ('id', 'image', 'obverseimg', 'reverseimg'): continue if field.name in USED_FIELDS: val = coin.value(field.name) if val is None or val == '': continue dest_record.setValue(field.name, val) # Process images is_obverse_present = not coin.isNull('obverseimg') is_reverse_present = not coin.isNull('reverseimg') if is_obverse_present or is_reverse_present: obverseImage = QImage() reverseImage = QImage() if is_obverse_present: ba = QtCore.QByteArray() buffer = QtCore.QBuffer(ba) buffer.open(QtCore.QIODevice.WriteOnly) obverseImage.loadFromData(coin.value('obverseimg')) if not obverseImage.isNull() and not params['fullimage'] and obverseImage.height() > maxHeight: scaledImage = obverseImage.scaled(maxHeight, maxHeight, Qt.KeepAspectRatio, Qt.SmoothTransformation) scaledImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS) save_data = ba else: if not obverseImage.isNull(): obverseImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS) save_data = ba else: save_data = coin.value('obverseimg') query = QSqlQuery(db) query.prepare("""INSERT INTO photos (image) VALUES (?)""") query.addBindValue(save_data) query.exec_() img_id = query.lastInsertId() dest_record.setValue('obverseimg', img_id) if not obverseImage.isNull(): obverseImage = obverseImage.scaledToHeight(height, Qt.SmoothTransformation) if is_reverse_present: ba = QtCore.QByteArray() buffer = QtCore.QBuffer(ba) buffer.open(QtCore.QIODevice.WriteOnly) reverseImage.loadFromData(coin.value('reverseimg')) if not reverseImage.isNull() and not params['fullimage'] and reverseImage.height() > maxHeight: scaledImage = reverseImage.scaled(maxHeight, maxHeight, Qt.KeepAspectRatio, Qt.SmoothTransformation) scaledImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS) save_data = ba else: if not reverseImage.isNull(): reverseImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS) save_data = ba else: save_data = coin.value('reverseimg') query = QSqlQuery(db) query.prepare("""INSERT INTO photos (image) VALUES (?)""") query.addBindValue(save_data) query.exec_() img_id = query.lastInsertId() dest_record.setValue('reverseimg', img_id) if not reverseImage.isNull(): reverseImage = reverseImage.scaledToHeight(height, Qt.SmoothTransformation) if not is_obverse_enabled: obverseImage = QImage() if not is_reverse_enabled: reverseImage = QImage() image = QImage(obverseImage.width() + reverseImage.width(), height, QImage.Format_RGB32) image.fill(QColor(Qt.white).rgb()) paint = QPainter(image) if is_obverse_present and is_obverse_enabled: paint.drawImage(QtCore.QRectF(0, 0, obverseImage.width(), height), obverseImage, QtCore.QRectF(0, 0, obverseImage.width(), height)) if is_reverse_present and is_reverse_enabled: paint.drawImage(QtCore.QRectF(obverseImage.width(), 0, reverseImage.width(), height), reverseImage, QtCore.QRectF(0, 0, reverseImage.width(), height)) paint.end() ba = QtCore.QByteArray() buffer = QtCore.QBuffer(ba) buffer.open(QtCore.QIODevice.WriteOnly) image.save(buffer, IMAGE_FORMAT, 75) query = QSqlQuery(db) query.prepare("""INSERT INTO photos (image) VALUES (?)""") query.addBindValue(ba) query.exec_() img_id = query.lastInsertId() dest_record.setValue('image', img_id) dest_model.insertRecord(-1, dest_record) progressDlg.setLabelText("Saving...") dest_model.submitAll() progressDlg.setLabelText("Compact...") QSqlQuery("""UPDATE descriptions SET reverseimg = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.reverseimg = t1.id where t1.id <> t2.id and t3.id = descriptions.id) WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.reverseimg = t1.id where t1.id <> t2.id) """, db) QSqlQuery("""UPDATE descriptions SET obverseimg = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.obverseimg = t1.id where t1.id <> t2.id and t3.id = descriptions.id) WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.obverseimg = t1.id where t1.id <> t2.id) """, db) QSqlQuery("""UPDATE descriptions SET image = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.image = t1.id where t1.id <> t2.id and t3.id = descriptions.id) WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.image = t1.id where t1.id <> t2.id) """, db) QSqlQuery("""DELETE FROM photos WHERE id NOT IN (SELECT id FROM photos GROUP BY image)""", db) db.close() progressDlg.setLabelText("Vacuum...") db = QSqlDatabase.addDatabase('QSQLITE', 'mobile') db.setDatabaseName(params['file']) if not db.open(): print(db.lastError().text()) QMessageBox.critical(None, "Create mobile collection", "Can't open collection") return QSqlQuery("VACUUM", db) db.close() progressDlg.reset()
class Window(QMainWindow): def __init__(self): super().__init__() title = "Paint Application" top = 400 left = 400 width = 800 height = 600 self.px_p_meter = 100 icon = "icons/pain.png" self.setWindowTitle(title) self.setGeometry(top, left, width, height) self.setWindowIcon(QIcon(icon)) self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) self.waypoints = [] self.drawing = False self.brushSize = 5 self.brushColor = Qt.black self.lastPoint = QPoint() mainMenu = self.menuBar() fileMenu = mainMenu.addMenu("File") brushSize = mainMenu.addMenu("Brush Size") brushColor = mainMenu.addMenu("Brush Color") ''' saveAction = QAction(QIcon("icons/save.png"), "Save",self) saveAction.setShortcut("Ctrl+S") fileMenu.addAction(saveAction) saveAction.triggered.connect(self.save) ''' exportAction = QAction(QIcon("icons/export.png"), "Export Track", self) exportAction.setShortcut("Ctrl+E") fileMenu.addAction(exportAction) exportAction.triggered.connect(self.exportTrack) clearAction = QAction(QIcon("icons/clear.png"), "Clear", self) clearAction.setShortcut("Ctrl+C") fileMenu.addAction(clearAction) clearAction.triggered.connect(self.clear) threepxAction = QAction(QIcon("icons/threepx.png"), "3px", self) brushSize.addAction(threepxAction) threepxAction.triggered.connect(self.threePixel) fivepxAction = QAction(QIcon("icons/fivepx.png"), "5px", self) brushSize.addAction(fivepxAction) fivepxAction.triggered.connect(self.fivePixel) sevenpxAction = QAction(QIcon("icons/sevenpx.png"), "7px", self) brushSize.addAction(sevenpxAction) sevenpxAction.triggered.connect(self.sevenPixel) ninepxAction = QAction(QIcon("icons/ninepx.png"), "9px", self) brushSize.addAction(ninepxAction) ninepxAction.triggered.connect(self.ninePixel) blackAction = QAction(QIcon("icons/black.png"), "Black", self) blackAction.setShortcut("Ctrl+B") brushColor.addAction(blackAction) blackAction.triggered.connect(self.blackColor) whitekAction = QAction(QIcon("icons/white.png"), "White", self) whitekAction.setShortcut("Ctrl+W") brushColor.addAction(whitekAction) whitekAction.triggered.connect(self.whiteColor) redAction = QAction(QIcon("icons/red.png"), "Red", self) redAction.setShortcut("Ctrl+R") brushColor.addAction(redAction) redAction.triggered.connect(self.redColor) greenAction = QAction(QIcon("icons/green.png"), "Green", self) greenAction.setShortcut("Ctrl+G") brushColor.addAction(greenAction) greenAction.triggered.connect(self.greenColor) yellowAction = QAction(QIcon("icons/yellow.png"), "Yellow", self) yellowAction.setShortcut("Ctrl+Y") brushColor.addAction(yellowAction) yellowAction.triggered.connect(self.yellowColor) painter = QPainter(self.image) painter.setBrush(Qt.black) painter.setPen(QPen(Qt.black, 2, Qt.SolidLine)) painter.drawLine(10, 50, 10 + self.px_p_meter, 50) pen = QPen(Qt.black) pen.setWidth(2) painter.setPen(pen) font = QFont() font.setFamily('Times') font.setBold(True) font.setPointSize(12) painter.setFont(font) painter.drawText(20 + self.px_p_meter, 55, "1 m") def mousePressEvent(self, event): if event.button() == Qt.LeftButton: #self.drawing = True self.lastPoint = event.pos() self.waypoints.append([self.lastPoint.x(), self.lastPoint.y()]) painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawPoint(self.lastPoint) self.update() print([self.lastPoint.x(), self.lastPoint.y()]) #print(self.lastPoint) def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) def save(self): filePath, _ = QFileDialog.getSaveFileName( self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ") fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(10, 10)) points = 1 / 100 * np.array(self.waypoints) ax1.scatter(points[:, 0], points[:, 1]) if filePath == "": return self.image.save(filePath) def exportTrack(self): print("exporting Track") fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(10, 10)) points = 1 / self.px_p_meter * np.array(self.waypoints) points[:, 0] = points[:, 0] - np.mean(points[:, 0]) points[:, 1] = -points[:, 1] + np.mean(points[:, 1]) ax1.scatter(points[:, 0], points[:, 1]) plt.show() name = QFileDialog.getSaveFileName(self, "Save Waypoints", "", "CSV(*.csv)") np.savetxt(name[0], points, delimiter=', ') track_lu_table, smax = InterpolateTrack.generatelookuptable( "tracks/" + name[0][53:-4]) r = 0.2 lencar = 0.06 trk_plt = plotter(track_lu_table, smax, r, lencar) trk_plt.plot_track() plt.show() def clear(self): print("clearing") self.image.fill(Qt.white) self.waypoints = [] self.update() def threePixel(self): self.brushSize = 3 def fivePixel(self): self.brushSize = 5 def sevenPixel(self): self.brushSize = 7 def ninePixel(self): self.brushSize = 9 def blackColor(self): self.brushColor = Qt.black def whiteColor(self): self.brushColor = Qt.white def redColor(self): self.brushColor = Qt.red def greenColor(self): self.brushColor = Qt.green def yellowColor(self): self.brushColor = Qt.yellow
def createImage(self, transform): original = QImage(self.image) if original.isNull(): return original size = transform.map(QPoint(self.maxWidth, self.maxHeight)) w = size.x() h = size.y() # Optimization: if image is smaller than maximum allowed size, just # return the loaded image. if ( original.size().height() <= h and original.size().width() <= w and not self.adjustSize and self.scale == 1 ): return original # Calculate what the size of the final image will be. w = min(w, float(original.size().width()) * self.scale) h = min(h, float(original.size().height()) * self.scale) adjustx = 1.0 adjusty = 1.0 if self.adjustSize: adjustx = min(transform.m11(), transform.m22()) adjusty = max(transform.m22(), adjustx) w *= adjustx h *= adjusty # Create a new image with correct size, and draw original on it. image = QImage(int(w + 2), int(h + 2), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(0, 0, 0, 0).rgba()) painter = QPainter(image) painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) if self.adjustSize: painter.scale(adjustx, adjusty) if self.scale != 1: painter.scale(self.scale, self.scale) painter.drawImage(0, 0, original) if not self.adjustSize: # Blur out edges. blur = 30 if h < original.height(): brush1 = QLinearGradient(0, h - blur, 0, h) brush1.setSpread(QLinearGradient.PadSpread) brush1.setColorAt(0.0, QColor(0, 0, 0, 0)) brush1.setColorAt(1.0, Colors.sceneBg1) painter.fillRect(0, int(h) - blur, original.width(), int(h), brush1) if w < original.width(): brush2 = QLinearGradient(w - blur, 0, w, 0) brush2.setSpread(QLinearGradient.PadSpread) brush2.setColorAt(0.0, QColor(0, 0, 0, 0)) brush2.setColorAt(1.0, Colors.sceneBg1) painter.fillRect(int(w) - blur, 0, int(w), original.height(), brush2) return image
class Window(QMainWindow): def __init__(self): super().__init__() title = "Prajjwal's Paint Application" x = 500 y = 100 width = 1080 height = 720 icon = "icons/Code_Maniac.jpg" self.setWindowTitle(title) self.setGeometry(x, y, width, height) self.setWindowIcon(QIcon(icon)) self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) self.drawing = False self.brushSize = 2 self.brushColor = Qt.black self.lastPoint = QPoint() mainMenu = self.menuBar() fileMenu = mainMenu.addMenu("File") brushSize = mainMenu.addMenu("Brush Size") brushColor = mainMenu.addMenu("Brush Color") shapes = mainMenu.addMenu("Add Shapes") circleAction = QAction(QIcon("icons/save.png"), "Cicle", self) circleAction.setShortcut("Alt+C") shapes.addAction(circleAction) circleAction.triggered.connect(self.circle) rectAction = QAction(QIcon("icons/save.png"), "Rectangle", self) rectAction.setShortcut("Alt+R") shapes.addAction(rectAction) rectAction.triggered.connect(self.rectangle) saveAction = QAction(QIcon("icons/save.png"), "Save", self) saveAction.setShortcut("Ctrl+S") fileMenu.addAction(saveAction) saveAction.triggered.connect(self.save) clearAction = QAction(QIcon("icons/clear.png"), "Clear", self) clearAction.setShortcut("Ctrl+C") fileMenu.addAction(clearAction) clearAction.triggered.connect(self.clear) threepxAction = QAction("3px", self) brushSize.addAction(threepxAction) threepxAction.triggered.connect(self.threePixel) fivepxAction = QAction("5px", self) brushSize.addAction(fivepxAction) fivepxAction.triggered.connect(self.fivePixel) sevenpxAction = QAction("7px", self) brushSize.addAction(sevenpxAction) sevenpxAction.triggered.connect(self.sevenPixel) ninepxAction = QAction("9px", self) brushSize.addAction(ninepxAction) ninepxAction.triggered.connect(self.ninePixel) blackAction = QAction(QIcon("icons/black.png"), "Black", self) blackAction.setShortcut("Ctrl+B") brushColor.addAction(blackAction) blackAction.triggered.connect(self.blackColor) whitekAction = QAction(QIcon("icons/white.png"), "White", self) whitekAction.setShortcut("Ctrl+W") brushColor.addAction(whitekAction) whitekAction.triggered.connect(self.whiteColor) redAction = QAction(QIcon("icons/red.png"), "Red", self) redAction.setShortcut("Ctrl+R") brushColor.addAction(redAction) redAction.triggered.connect(self.redColor) greenAction = QAction(QIcon("icons/green.png"), "Green", self) greenAction.setShortcut("Ctrl+G") brushColor.addAction(greenAction) greenAction.triggered.connect(self.greenColor) yellowAction = QAction(QIcon("icons/yellow.png"), "Yellow", self) yellowAction.setShortcut("Ctrl+Y") brushColor.addAction(yellowAction) yellowAction.triggered.connect(self.yellowColor) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() #print(self.lastPoint) def exit_paint(self, event): if event.type() == KEY_DOWN: if event.key() == Qt.Key_Escape: self.close() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) def save(self): filePath, _ = QFileDialog.getSaveFileName( self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ") if filePath == "": return self.image.save(filePath) def clear(self): self.image.fill(Qt.white) self.update() def threePixel(self): self.brushSize = 3 def fivePixel(self): self.brushSize = 5 def sevenPixel(self): self.brushSize = 7 def ninePixel(self): self.brushSize = 9 def blackColor(self): self.brushColor = Qt.black def whiteColor(self): self.brushColor = Qt.white def redColor(self): self.brushColor = Qt.red def greenColor(self): self.brushColor = Qt.green def yellowColor(self): self.brushColor = Qt.yellow def circle(self): painter = QPainter(self) painter.setPen(QPen(Qt.green, 5, Qt.SolidLine)) painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) painter.drawEllipse(40, 40, 400, 200) pass def rectangle(self): pass
class MaskTransparencyWidget(QWidget): def __init__(self, parent, imgPaths, fov_id_list, mask_dir): super(MaskTransparencyWidget, self).__init__(parent) self.mask_dir = mask_dir self.frameIndex = 0 self.imgPaths = imgPaths self.fov_id_list = fov_id_list self.fovIndex = 0 self.fov_id = self.fov_id_list[self.fovIndex] self.imgIndex = 0 self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1] # TO DO: check if re-annotated mask exists in training_dir, and present that instead of original mask # make indicator appear if we're re-editing the mask again. experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) self.maskStack = io.imread(self.maskImgPath) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.') # add widget to express whether this mask is one you already re-annotated # print(self.frameIndex) self.maskStack[self.frameIndex, :, :] = io.imread(savePath) overwriteSegFile = True else: overwriteSegFile = False img = self.maskStack[self.frameIndex, :, :] img[img > 0] = 255 self.RGBImg = color.gray2rgb(img).astype('uint8') self.RGBImg[:, :, 1:] = 0 # set GB channels to 0 to make the transarency mask red alphaFloat = 0.15 alphaArray = np.zeros(img.shape, dtype='uint8') alphaArray = np.expand_dims(alphaArray, -1) self.alpha = int(255 * alphaFloat) alphaArray[...] = self.alpha self.RGBAImg = np.append(self.RGBImg, alphaArray, axis=-1) self.originalHeight, self.originalWidth, self.originalChannelNumber = self.RGBAImg.shape self.maskQimage = QImage(self.RGBAImg, self.originalWidth, self.originalHeight, self.RGBAImg.strides[0], QImage.Format_RGBA8888).scaled( 1024, 1024, aspectRatioMode=Qt.KeepAspectRatio) self.maskQpixmap = QPixmap(self.maskQimage) self.label = QLabel(self) self.label.setPixmap(self.maskQpixmap) self.drawing = False self.brushSize = 2 self.brushColor = QColor(0, 0, 0, self.alpha) self.lastPoint = QPoint() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: # make the mouse position the center of a circle whose radius is defined as self.brushSize rr, cc = draw.circle(event.y(), event.x(), self.brushSize) for pix in zip(rr, cc): rowIndex = pix[0] colIndex = pix[1] self.maskQimage.setPixelColor(colIndex, rowIndex, self.brushColor) self.maskQpixmap = QPixmap(self.maskQimage) self.label.setPixmap(self.maskQpixmap) self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button == Qt.LeftButton: self.drawing = False def save(self): filePath, _ = QFileDialog.getSaveFileName( self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;TIFF(*.tif *.tiff);;ALL FILES(*.*)" ) if filePath == "": return saveImg = self.maskQimage.convertToFormat( QImage.Format_Grayscale8).scaled(self.originalWidth, self.originalHeight) qimgHeight = saveImg.height() qimgWidth = saveImg.width() for rowIndex in range(qimgHeight): for colIndex in range(qimgWidth): pixVal = qGray(saveImg.pixel(colIndex, rowIndex)) if pixVal > 0: saveImg.setPixelColor(colIndex, rowIndex, QColor(1, 1, 1)) pixVal = qGray(saveImg.pixel(colIndex, rowIndex)) saveImg.save(filePath) def buttonSave(self): experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) # labelSavePath = os.path.join(params['seg_dir'],fileBaseName) print("Saved binary mask image as: ", savePath) if not os.path.isdir(self.mask_dir): os.makedirs(self.mask_dir) # saveImg = self.maskQimage.convertToFormat(QImage.Format_Grayscale8) # This was bugging out and making the image not the same size as it started # saveImg = self.maskQimage.convertToFormat(QImage.Format_Grayscale8).scaled(self.originalWidth,self.originalHeight,aspectRatioMode=Qt.KeepAspectRatio) saveImg = self.maskQimage.convertToFormat( QImage.Format_Grayscale8).scaled(self.originalWidth, self.originalHeight) qimgHeight = saveImg.height() qimgWidth = saveImg.width() print(self.originalHeight, self.originalWidth, qimgHeight, qimgWidth) saveArr = np.zeros((qimgHeight, qimgWidth), dtype='uint8') for rowIndex in range(qimgHeight): for colIndex in range(qimgWidth): pixVal = qGray(saveImg.pixel(colIndex, rowIndex)) if pixVal > 0: saveArr[rowIndex, colIndex] = 1 io.imsave(savePath, saveArr) # labelArr = measure.label(saveArr, connectivity=1) # labelArr = labelArr.astype('uint8') # print(labelSavePath) # io.imsave(labelSavePath,labelArr) def reset(self): self.maskQimage = QImage(self.RGBAImg, self.originalWidth, self.originalHeight, self.RGBAImg.strides[0], QImage.Format_RGBA8888).scaled( 1024, 1024, aspectRatioMode=Qt.KeepAspectRatio) self.maskQpixmap = QPixmap(self.maskQimage) self.label.setPixmap(self.maskQpixmap) self.update() def clear(self): self.imgFill = QColor(0, 0, 0, self.alpha) self.maskQimage = QImage(self.RGBAImg, self.originalWidth, self.originalHeight, self.RGBAImg.strides[0], QImage.Format_RGBA8888).scaled( 1024, 1024, aspectRatioMode=Qt.KeepAspectRatio) self.maskQimage.fill(self.imgFill) self.maskQpixmap = QPixmap(self.maskQimage) self.label.setPixmap(self.maskQpixmap) self.update() def onePx(self): self.brushSize = 1 def threePx(self): self.brushSize = 3 def fivePx(self): self.brushSize = 5 def sevenPx(self): self.brushSize = 7 def ninePx(self): self.brushSize = 9 def blackColor(self): self.brushColor = QColor(0, 0, 0, self.alpha) def redColor(self): self.brushColor = QColor(255, 0, 0, self.alpha) def whiteColor(self): self.brushColor = QColor(255, 255, 255, self.alpha) # def setFOVPeakFrameIndex(self,frame_index,peak_index,fov_id): # self.frameIndex = frame_index # self.fov_id = fov_id # self.imgIndex = peak_id def setImg(self, img): img[img > 0] = 255 self.RGBImg = color.gray2rgb(img).astype('uint8') self.RGBImg[:, :, 1:] = 0 # set green and blue channels to 0 to make the transarency mask red alphaFloat = 0.25 alphaArray = np.zeros(img.shape, dtype='uint8') alphaArray = np.expand_dims(alphaArray, -1) self.alpha = int(255 * alphaFloat) alphaArray[...] = self.alpha self.RGBAImg = np.append(self.RGBImg, alphaArray, axis=-1) self.originalHeight, self.originalWidth, self.originalChannelNumber = self.RGBAImg.shape self.maskQimage = QImage(self.RGBAImg, self.originalWidth, self.originalHeight, self.RGBAImg.strides[0], QImage.Format_RGBA8888).scaled( 1024, 1024, aspectRatioMode=Qt.KeepAspectRatio) self.maskQpixmap = QPixmap(self.maskQimage) self.label.setPixmap(self.maskQpixmap) def next_frame(self): self.frameIndex += 1 try: experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile(r'.+(xy\d{3,4})_(p\d{3,4})_.+' ) # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format( experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.' ) # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] except IndexError: sys.exit( "You've already edited the last frame's mask. Write in functionality to increment to next peak_id now!" ) self.setImg(img) def prior_frame(self): self.frameIndex -= 1 try: experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile(r'.+(xy\d{3,4})_(p\d{3,4})_.+' ) # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format( experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.' ) # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] except IndexError: sys.exit( "You've already edited the last frame's mask. Write in functionality to increment to next peak_id now!" ) self.setImg(img) def next_peak(self): self.imgIndex += 1 self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1] self.maskStack = io.imread(self.maskImgPath) self.frameIndex = 0 experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.') # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] self.setImg(img) def prior_peak(self): self.imgIndex -= 1 self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1] self.maskStack = io.imread(self.maskImgPath) self.frameIndex = 0 experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.') # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] self.setImg(img) def next_fov(self): self.fovIndex += 1 self.fov_id = self.fov_id_list[self.fovIndex] self.imgIndex = 0 self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1] self.maskStack = io.imread(self.maskImgPath) self.frameIndex = 0 experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.') # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] self.setImg(img) def prior_fov(self): self.fovIndex -= 1 self.fov_id = self.fov_id_list[self.fovIndex] self.imgIndex = 0 self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1] self.maskStack = io.imread(self.maskImgPath) self.frameIndex = 0 experiment_name = params['experiment_name'] original_file_name = self.maskImgPath pat = re.compile( r'.+(xy\d{3,4})_(p\d{3,4})_.+') # supports 3- or 4-digit naming mat = pat.match(original_file_name) fovID = mat.groups()[0] peakID = mat.groups()[1] fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID, peakID, self.frameIndex + 1) savePath = os.path.join(self.mask_dir, fileBaseName) if os.path.isfile(savePath): print( 'Re-annotated mask exists in training directory. Loading it.') # add widget to express whether this mask is one you already re-annotated self.maskStack[self.frameIndex, :, :] = io.imread(savePath) img = self.maskStack[self.frameIndex, :, :] self.setImg(img)
def _create_image(self): image = QImage(80, 60, QImage.Format_RGB32) image.fill(Qt.green) return image
class Window(QMainWindow): def __init__(self): super().__init__() self.buildGUI() self.graph = Graph() self.countCity = 0 self.countCom = 0 self.isHandle = False self.countParam = 2 self.selectedTop = [] # list for two connected tops type - Top def buildGUI(self): self.resize(1000, 750) self.image = QImage(2000, 2000, QImage.Format_RGB32) self.image.fill(Qt.white) self.brushSize = 2 self.brushColor = Qt.blue self.initNeed() # инициализируем нужные настройки self.statusBar() self.createWidget() self.center() self.setWindowTitle('Нахождение кратчайшевого пути') self.setWindowIcon(QIcon('iconCat.png')) self.setContextMenuPolicy(Qt.NoContextMenu) self.show() def initNeed(self): painter = QPainter(self.image) painter.drawText(QPointF(10, 50), "Начальная вершина: ") painter.drawText(QPointF(10, 70), "Конечная вершина: ") def mousePressEvent(self, event): selected = False # typ - boolean topCur = Top(event.pos(), self.graph.size() + 1) # type - Top point = event.pos() # type - QPointF painter = QPainter(self.image) for top in self.graph.getSetV(): if top.inside(point): self.brushColor = Qt.red # selected selected = True topCur = top if top in self.selectedTop: self.brushColor = Qt.blue self.selectedTop.remove(top) else: self.selectedTop.append(top) # add in selected list self.pen(painter) painter.drawEllipse(topCur.x() - Constant.rad / 2, topCur.y() - Constant.rad / 2, Constant.rad, Constant.rad) break if event.button() == Qt.LeftButton: # if not selected top, then draw if not selected: # create the top of the graph and installed of the color pen self.brushColor = Qt.blue self.graph.add(topCur) self.countCity = self.countCity + 1 painter.drawText(point, str(topCur.getNumber())) self.pen(painter) painter.drawEllipse(topCur.x() - Constant.rad / 2, topCur.y() - Constant.rad / 2, Constant.rad, Constant.rad) # create the line if len(self.selectedTop) == 2: self.brushColor = Qt.green self.pen(painter) top1 = self.selectedTop.pop(1) # type - Top top2 = self.selectedTop.pop(0) # check for excisting the road #if not top1.exsitRoad(top2): if not self.graph.exsitRoad(top1, top2): painter.drawLine(top1.x(), top1.y(), top2.x(), top2.y()) # target - add first top (top1) connected top (top2) in the list # bilaterial if self.isHandle: self.instalParametDialog() self.brushColor = Qt.black self.pen(painter) param = [] for k in range(self.countParam): param.append(int(self.parametrs[k].text())) painter.drawText( QPointF( (top1.x() + top2.x()) / 2 + 5, (top1.y() + top2.y()) / 2 - 5 + 20 * k), self.parametrs[k].text()) # закомменчено для варианта работы со списокм смежности #top1.add(top2, param) #top2.add(top1, param) self.graph.addConnection(top1, top2, param) else: param = [] for i in range(self.countParam): param.append(random.randint(1, 100)) # добавлено self.graph.addConnection(top1, top2, param) #top1.add(top2, param) #top2.add(top1, param) self.brushColor = Qt.black self.pen(painter) for k in range(self.countParam): painter.drawText( QPointF( (top1.x() + top2.x()) / 2 + 5, (top1.y() + top2.y()) / 2 - 5 + 20 * k), "p=" + str(param[k])) self.brushColor = Qt.blue self.pen(painter) painter.drawEllipse(top1.x() - Constant.rad / 2, top1.y() - Constant.rad / 2, Constant.rad, Constant.rad) painter.drawEllipse(top2.x() - Constant.rad / 2, top2.y() - Constant.rad / 2, Constant.rad, Constant.rad) self.update() def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.image.rect(), self.image, self.image.rect()) def pen(self, painter): painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) # installed the pen def createWidget(self): exitAction = QAction( QIcon('iconCat.png'), '&Выход', self) # create action, install icon, text and parent(where it is) exitAction.setShortcut('Ctrl+Q') # hot keys exitAction.setStatusTip('Выйти из приложения') # tip exitAction.triggered.connect(qApp.quit) self.toolbar = self.addToolBar('Exit') self.toolbar.addAction(exitAction) createBut = QPushButton('Создать') createBut.setShortcut('Ctrl+N') createBut.setToolTip('Настройки для графа') runBut = QPushButton('Запуск') # graph is generated, find the path runBut.setShortcut('Ctrl+R') runBut.setToolTip('Найти путь') clear = QPushButton('Удалить') clear.setShortcut('Delete') clear.setToolTip('Очистить') infoBut = QPushButton("Инфо") infoBut.setShortcut('Ctrl+I') infoBut.setToolTip('Информация о программе') createBut.clicked.connect(self.on_click) runBut.clicked.connect( self.click_run) # start the work of the basic target program clear.clicked.connect(self.click_del) infoBut.clicked.connect(self.click_info) toolbar = self.addToolBar('Exit') # toolbar.addWidget(createBut) потом добавить обратно toolbar.addWidget(runBut) toolbar.addWidget(clear) toolbar.addWidget(infoBut) def drawPath(self, path, painter): #self.brushColor = Qt.red #painter = QPainter(self.image) self.pen(painter) for j in range(len(path) - 1): top1 = self.graph.listV[path[j + 1] - 1] # type - Top top2 = self.graph.listV[path[j] - 1] painter.drawLine(top1.x(), top1.y(), top2.x(), top2.y()) if len(path) != 0: start = path[0] end = path[len(path) - 1] self.brushColor = Qt.black self.pen(painter) top = self.graph.listV[start - 1] painter.drawEllipse(top.x() - Constant.rad / 2, top.y() - Constant.rad / 2, Constant.rad, Constant.rad) top = self.graph.listV[end - 1] painter.drawEllipse(top.x() - Constant.rad / 2, top.y() - Constant.rad / 2, Constant.rad, Constant.rad) self.update() @pyqtSlot() def on_click(self): self.showdialog() @pyqtSlot() def clickSaveSettin(self): self.d.close() def handleInput(self, state): if state == Qt.Checked: self.isHandle = True #self.countParam = 0 @pyqtSlot() def click_info(self): infoDialog = QDialog() aboutMe = QTextEdit(Constant.info) grid = QGridLayout() grid.setSpacing(10) grid.addWidget(aboutMe, 0, 0) infoDialog.setLayout(grid) infoDialog.resize(200, 200) infoDialog.setWindowTitle("Input parametrs") infoDialog.setWindowModality(Qt.ApplicationModal) infoDialog.exec_() @pyqtSlot() def click_run(self): start = 1 end = self.graph.size() if len(self.selectedTop) == 2: top1 = self.selectedTop.pop(1) # type - Top top2 = self.selectedTop.pop(0) start = top1.getNumber() end = top2.getNumber() if start > end: a = start start = end end = a self.graph.initData() self.graph.deystra(start) path = self.graph.printPath(start, end, self.graph.parent) # last top else: self.graph.initData() # закоменченные строки это правка в оригинале были # countCom = self.graph.countComponent() # self.statusBar().showMessage(str(countCom)) #self.graph.initData() # можно убрать в метое есть проверка нужна ли инициализация #for x in self.graph.beginComponent: self.graph.deystra(1) path = self.graph.printPath(start, end, self.graph.parent) # last top if len(path) == 1 or len(path) == 0: print('Not path') self.statusBar().showMessage('Not path') else: self.brushColor = Qt.red painter = QPainter(self.image) painter.drawText(QPointF(160, 50), str(start)) painter.drawText(QPointF(160, 70), str(end)) self.drawPath(path, painter) # type - List<int> self.statusBar().showMessage( str(path) + " = " + str(self.graph.dist[self.graph.size()])) # TODO: найти пересекающиеся ребра и восстановить их @pyqtSlot() def click_del(self): if len(self.selectedTop) != 0: for x in self.selectedTop: self.brushColor = Qt.white painter = QPainter(self.image) self.pen(painter) #clear deleting top painter.drawEllipse(x.x() - Constant.rad / 2, x.y() - Constant.rad / 2, Constant.rad, Constant.rad) # clear conection lines for rib in x.list: painter.drawLine(rib.to.x(), rib.to.y(), x.x(), x.y()) for k in range(self.countParam): painter.eraseRect( QRectF((x.x() + rib.to.x()) / 2 + 5, (x.y() + rib.to.y()) / 2 - 15, 50, 10 * self.countParam)) painter.eraseRect( QRectF(x.x() - 15, x.y() - 15, Constant.rad * 2, Constant.rad * 2)) # restore adjacent circles self.brushColor = Qt.blue self.pen(painter) for rib in x.list: painter.drawEllipse(rib.to.x() - Constant.rad / 2, rib.to.y() - Constant.rad / 2, Constant.rad, Constant.rad) self.brushColor = Qt.black self.pen(painter) painter.drawText(QPointF(rib.to.x(), rib.to.y()), str(rib.to.getNumber())) self.graph.delete(x) self.selectedTop.clear() else: self.graph.deleteAll() self.image.fill(Qt.white) self.countCom = 0 self.countCity = 0 self.initNeed() self.update() @pyqtSlot() def clickOk(self): # at first draw tops self.d.close() if self.countCity == 0: self.countCity = 5 if self.countCom == 0: self.countCom = 5 if self.countParam == 0: self.countParam = 1 if self.countCom > (self.countCity * (self.countCity - 1)) / 2: self.statusBar().showMessage('Too many connections') return painter = QPainter(self.image) width = self.width() height = self.height() flagInside = False i = 0 while i < self.countCity: pos = QPointF( random.randint(Constant.rad * 2, width - Constant.rad * 2), random.randint(Constant.rad * 2, height - Constant.rad * 2)) for top in self.graph.getSetV(): if top.inside(pos): flagInside = True break if not flagInside: top = Top(pos, self.graph.size() + 1) self.graph.add(top) self.brushColor = Qt.black self.pen(painter) painter.drawText(pos, str(top.getNumber())) self.brushColor = Qt.blue self.pen(painter) painter.drawEllipse(top.x() - Constant.rad / 2, top.y() - Constant.rad / 2, Constant.rad, Constant.rad) i = i + 1 flagInside = False # draw connection i = 0 while i < self.countCom: self.brushColor = Qt.green self.pen(painter) a = random.randint(0, self.graph.size() - 1) top1 = self.graph.listV[a] # type - Top b = random.randint(0, self.graph.size() - 1) if a == b: if a + 1 == self.graph.size(): b = b - 1 else: b = b + 1 top2 = self.graph.listV[b] # check for excisting the road if not top1.exsitRoad(top2): painter.drawLine(top1.x(), top1.y(), top2.x(), top2.y()) # count parametres param = [] for j in range(self.countParam): param.append(random.randint(1, 100)) top1.add(top2, param) top2.add(top1, param) self.brushColor = Qt.black self.pen(painter) for k in range(self.countParam): p = str(param[k]) painter.drawText( QPointF((top1.x() + top2.x()) / 2 + 5, (top1.y() + top2.y()) / 2 - 5 + 20 * k), p) i = i + 1 self.update() def autoCheckBox(self, state): if state == Qt.Checked: self.countCity = random.randint(2, 10) a = int((self.countCity * (self.countCity - 1)) / 2) self.countCom = random.randint(1, a) self.countParam = random.randint(0, 3) def editCity(self): if len(self.countCityF.text()) != 0: self.countCity = int(self.countCityF.text()) def editCom(self): self.countCom = int(self.countCommunF.text()) def editParam(self): self.countParam = int(self.countParamF.text()) def center(self): position = self.frameGeometry() #get rectangle our app cnrScreen = QDesktopWidget().availableGeometry().center( ) # get the center point on the screen position.moveCenter(cnrScreen) # rect put on the center self.move(position.topLeft()) # shift app # доделать динамическое обновление параметров @pyqtSlot() def inputToFieldPar(self): line = QLineEdit(self.parDial) self.parametrs.append(line) grid = self.parDial.layout() grid.addWidget(line, len(self.parametrs), 0) line.returnPressed.connect(self.inputToFieldPar) @pyqtSlot() def saveParam(self): self.parDial.close() # диалог, где вручную вводим параметры def instalParametDialog(self): self.parDial = QDialog() self.parametrs = [] grid = QGridLayout() grid.setSpacing(10) countPara = self.countParam for i in range(countPara): line = QLineEdit('0', self.parDial) grid.addWidget(line, i + 1, 0) self.parametrs.append(line) # self.parametrs[0].returnPressed.connect(self.inputToFieldPar) saveParam = QPushButton("Save", self.parDial) grid.addWidget(saveParam, countPara + 1, 1) saveParam.clicked.connect(self.saveParam) self.parDial.setLayout(grid) self.parDial.resize(150, 150) self.parDial.setWindowTitle("Input parametrs") self.parDial.setWindowModality(Qt.ApplicationModal) self.parDial.exec_() def showdialog(self): self.d = QDialog() self.countCityF = QLineEdit(self.d) self.countCommunF = QLineEdit(self.d) self.countParamF = QLineEdit(self.d) isHandleInputF = QCheckBox('') autoGenC = QCheckBox('Авто') ok = QPushButton("ОК", self.d) saveSetting = QPushButton("Сохранить", self.d) saveSetting.setMaximumSize(ok.width(), ok.height()) grid = QGridLayout() grid.setSpacing(10) grid.addWidget(QLabel('Желаемое количество городов:', self.d), 1, 0) grid.addWidget(self.countCityF, 1, 1) grid.addWidget(QLabel('Желаемое количество связей', self.d), 2, 0) grid.addWidget(self.countCommunF, 2, 1) grid.addWidget(QLabel('Желаемое количество параметров', self.d), 3, 0) grid.addWidget(self.countParamF, 3, 1) grid.addWidget(QLabel('Сгенерировать:', self.d), 4, 0) grid.addWidget(autoGenC, 4, 1) grid.addWidget(QLabel('Ручная настройка параметров?', self.d), 5, 0) grid.addWidget(isHandleInputF, 5, 1) grid.addWidget(saveSetting, 6, 0) grid.addWidget(ok, 6, 1) ok.clicked.connect(self.clickOk) saveSetting.clicked.connect(self.clickSaveSettin) autoGenC.stateChanged.connect(self.autoCheckBox) isHandleInputF.stateChanged.connect(self.handleInput) self.countCityF.editingFinished.connect(self.editCity) self.countCommunF.editingFinished.connect(self.editCom) self.countParamF.editingFinished.connect(self.editParam) self.d.setLayout(grid) self.d.resize(150, 150) self.d.setWindowTitle("Настройка графа") self.d.setWindowModality(Qt.ApplicationModal) self.d.exec_()
class Window(QtWidgets.QMainWindow): def __init__(self): QtWidgets.QWidget.__init__(self) uic.loadUi("window.ui", self) self.setMouseTracking(True) self.scene = QtWidgets.QGraphicsScene(0, 0, 520, 520) self.view.setScene(self.scene) self.image = QImage(520, 520, QImage.Format_ARGB32_Premultiplied) self.pen = QPen(black) self.polygon = [] self.cut = [] self.mode = None self.lock = None self.line_2.setEnabled(False) self.click_check = False self.start_point = None self.prev_point = None self.clean.clicked.connect(lambda: self.clean_on_click_button(self)) self._polygon.clicked.connect(lambda: self.add_line_mode(self)) self.line_2.clicked.connect(lambda: self.add_par_line(self)) self._lock.clicked.connect(lambda: self.lock_on_click_button(self)) self.paint.clicked.connect(lambda: self.paint_on_click_button(self)) self.cutter.clicked.connect(lambda: self.add_cutter_mode(self)) self.scene.installEventFilter(self) #----------------- click event ------------------------------------ def eventFilter(self, object, event): if event.type() == QtCore.QEvent.GraphicsSceneMousePress: point = event.scenePos() if (self.mode == "line_mode"): self.add_line(event.scenePos()) if (self.mode == "cutter_mode"): self.add_cutter(event.scenePos()) self.add_point_mouse(point) return False def add_point_mouse(self, point): self.coord.setText("X: " + str(point.x()) + "\nY: " + str(point.y())) #print("coords : ", point.x(), point.y()); def add_line(self, point): #print("line coords : ", point.x(), point.y()); if self.lock: line = [] line.append(self.prev_point) line.append(point) if line not in self.polygon: self.pen.setColor(blue) self.add_row(line, self.table_polygon) self.polygon.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) self.prev_point = point else: self.lock = True self.start_point = point self.prev_point = point def add_cutter(self, point): #print("cutter coords : ", point.x(), point.y()); if self.lock: line = [] line.append(self.prev_point) line.append(point) if line not in self.cut: self.add_row(line, self.table_cut) self.cut.append(line) self.scene.addLine(line[0].x(), line[0].y(), line[1].x(), line[1].y(), self.pen) self.prev_point = point else: self.lock = True self.start_point = point self.prev_point = point #----------------- buttons ------------------------------------ def add_line_mode(self, win): self.mode = None if self.mode != None else "line_mode" self.button_mode_set() self.click_check = False def add_cutter_mode(self, win): self.mode = None if self.mode != None else "cutter_mode" self.button_mode_set() self.click_check = False def lock_on_click_button(self, win): print("locked") if self.prev_point and self.lock: line = [] line.append(self.prev_point) line.append(self.start_point) if self.mode == "cutter_mode": self.add_row(line, self.table_cut) self.cut.append(line) self.scene.addLine(self.prev_point.x(), self.prev_point.y(), self.start_point.x(), self.start_point.y(), self.pen) self.prev_point = None self.start_point = None self.lock = None self.pen.setColor(black) if self.mode == "line_mode": self.add_row(line, self.table_polygon) self.polygon.append(line) self.scene.addLine(self.prev_point.x(), self.prev_point.y(), self.start_point.x(), self.start_point.y(), self.pen) self.prev_point = None self.start_point = None self.lock = None self.pen.setColor(black) def paint_on_click_button(self, win): if not self.cut or not self.polygon: print("Check your input data to continue...") return self.pen.setColor(red) self.make_cut() self.pen.setColor(blue) def clean_on_click_button(self, win): self.line_2.setEnabled(False) self.scene.clear() self.polygon = [] self.cut = [] self.image.fill(white) self.pen.setColor(black) self.table_clean(self.table_cut) self.table_clean(self.table_polygon) def add_par_line(self, win): if not self.cut: return print("parrallel lines") #----------------- methods ------------------------------------ def checkConvexPolygon(self): line_start = self.cut[0] line_end = self.cut[len(self.cut) - 1] rotate = 1 sign = None for i in range(len(self.cut) - 1): line_1 = self.cut[i] line_2 = self.cut[i + 1] v1 = self.vec(line_1[0], line_1[1]) v2 = self.vec(line_2[0], line_2[1]) rotate = v1.x() * v2.y() - v1.y() * v2.x() if sign: if self.sign(sign) != self.sign(rotate): sign = None break else: sign = rotate if sign: v1 = self.vec(line_end[0], line_end[1]) v2 = self.vec(line_start[0], line_start[1]) rotate = v1.x() * v2.y() - v1.y() * v2.x( ) # finding z direction of [a, b] if self.sign(sign) != self.sign(rotate): sign = None if sign: return sign return False def param_line(self, p1, p2, t): return QPointF(p1.x() + (p2.x() - p1.x()) * t, p1.y() + (p2.y() - p1.y()) * t) def sign(self, a): if a <= 0: return False return True def normal(self, vec, norm): if norm > 0: return QPointF(-1 * vec.y(), vec.x()) return QPointF(vec.y(), -1 * vec.x()) def vec(self, p1, p2): return p2 - p1 def vecLen(self, vec): return sqrt(vec.x()**2 + vec.y()**2) def scalar(self, v1, v2): return v1.x() * v2.x() + v1.y() * v2.y() def table_clean(self, table): table.clear() r = table.rowCount() for i in range(r, -1, -1): table.removeRow(i) def button_mode_set(self): if self.mode == None: if self.cut: self.line_2.setEnabled(True) self.clean.setEnabled(True) self.paint.setEnabled(True) self.cutter.setEnabled(True) self._polygon.setEnabled(True) if self.mode == "line_mode": self.clean.setEnabled(False) self.paint.setEnabled(False) self.cutter.setEnabled(False) self.line_2.setEnabled(False) if self.mode == "cutter_mode": self.clean.setEnabled(False) self.paint.setEnabled(False) self._polygon.setEnabled(False) self.line_2.setEnabled(False) def add_row(self, line, table): table.insertRow(table.rowCount()) i = table.rowCount() - 1 item_b = QTableWidgetItem("[{0}, {1}]".format(line[0].x(), line[0].y())) item_e = QTableWidgetItem("[{0}, {1}]".format(line[1].x(), line[1].y())) table.setItem(i, 0, item_b) table.setItem(i, 1, item_e) def make_cut(self): print("pain") norm = self.checkConvexPolygon() if (norm == False): print("The polygon is not convex! Try another one...") return cut, polygon = self.getPoints(self.cut, self.polygon) polygon = self.sutherland_bodgman(cut, polygon, norm) if not polygon: return self.pen.setColor(red) polygon.append(polygon[0]) for i in range(len(polygon)): if i == 0: f = polygon[i] else: self.scene.addLine(f.x(), f.y(), polygon[i].x(), polygon[i].y(), self.pen) f = polygon[i] self.pen.setColor(black) def sutherland_bodgman(self, cut, polygon, norm): for i in range(len(cut) - 1): cutted = [] for j in range(len(polygon)): if j == 0: f = polygon[j] else: t = self.intersection([s, polygon[j]], [cut[i], cut[i + 1]], norm) if t: cutted.append(t) s = polygon[j] if self.visible(s, [cut[i], cut[i + 1]], norm): cutted.append(s) if len(cutted) != 0: t = self.intersection([s, f], [cut[i], cut[i + 1]], norm) if t: cutted.append(t) polygon = copy.deepcopy(cutted) print(polygon) if not len(polygon): return None return polygon def getPoints(self, cut, polygon): newCut = [] for i in cut: newCut.append(i[0]) newCut.append(cut[0][0]) newPol = [] for i in polygon: newPol.append(i[0]) return newCut, newPol def visible(self, s, edge, norm): v1 = self.vec(edge[0], edge[1]) v2 = self.vec(edge[0], s) v = v2.x() * v1.y() - v2.y() * v1.x() if norm * v < 0: return True else: return False def intersection(self, line, edge, norm): vis1 = self.visible(line[0], edge, norm) vis2 = self.visible(line[1], edge, norm) if (vis1 and not vis2) or (not vis1 and vis2): p1 = line[0] p2 = line[1] q1 = edge[0] q2 = edge[1] d = (p2.x() - p1.x()) * (q1.y() - q2.y()) - (q1.x() - q2.x()) * ( p2.y() - p1.y()) w = (q1.x() - p1.x()) * (q1.y() - q2.y()) - (q1.x() - q2.x()) * ( q1.y() - p1.y()) if abs(d) <= 1e-8: return p2 t = w / d return QPointF(p1.x() + (p2.x() - p1.x()) * t, p1.y() + (p2.y() - p1.y()) * t) else: return False
class CanvasClass(QtWidgets.QMainWindow): def __init__(self): global color super(CanvasClass, self).__init__() top = 0 left = 0 width = 800 height = 480 self.setGeometry(top, left, width, height) self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) uic.loadUi('Canvas.ui', self) homeIcon = os.getcwd() + "\\images\\Icons\\" +"home.png" logoutIcon = os.getcwd() + "\\images\\Icons\\" +"logout.png" pencilIcon = os.getcwd() + "\\images\\Icons\\" +"pencil_size.png" BrushIcon = os.getcwd() + "\\images\\Icons\\" +"paint_brush.png" paletteIcon = os.getcwd() + "\\images\\Icons\\" +"color_palette.png" eraserIcon = os.getcwd() + "\\images\\Icons\\" +"eraser.png" self.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.shortcut = QShortcut(QKeySequence("Ctrl+Q"), self) self.shortcut.activated.connect(self.quitApp) self.homeImg = self.findChild(QtWidgets.QLabel, 'homeIcon') self.homeImg.setPixmap(QPixmap(homeIcon)) self.BrushImg = self.findChild(QtWidgets.QLabel, 'BrushImg') self.BrushImg.setPixmap(QPixmap(BrushIcon)) self.paleteButton = self.findChild(QtWidgets.QPushButton,'paleteButton') self.paleteButton.setIcon(QtGui.QIcon(paletteIcon)) self.logoutButton = self.findChild(QtWidgets.QPushButton,'logoutButton') self.logoutButton.setIcon(QtGui.QIcon(logoutIcon)) self.paleteButton.setIconSize(QtCore.QSize(24,24)) self.paleteButton.clicked.connect(self.openColorDialog) self.logoutButton.clicked.connect((self.logout)) self.HomeButton = self.findChild(QtWidgets.QPushButton,'HomeButton') self.HomeButton.clicked.connect(self.openLs) self.NextButton = self.findChild(QtWidgets.QPushButton,'NextButton') self.NextButton.clicked.connect(self.setCanvasImage) self.imgLabel = self.findChild(QtWidgets.QLabel, 'label') self.horizontalSlider = self.findChild(QtWidgets.QSlider,'horizontalSlider') self.horizontalSlider.valueChanged[int].connect(self.getsliderValue) self.horizontalSlider.setMinimum(1) self.horizontalSlider.setMaximum(20) self.horizontalSlider.setValue(20) self.horizontalSlider.setTickPosition(QSlider.NoTicks) self.horizontalSlider.setTickInterval(2) self.drawing = False self.brushSize = 20 self.brushColor = color self.lastpoint = QPoint() self.show() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastpoint = event.pos() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: painter = QPainter(self.image) painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastpoint, event.pos()) self.lastpoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button == Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) def setCanvasImage(self): global LangDir global fileList global imgCount global count global Lang global Cat print(imgCount) if(self.NextButton.text() == 'NEXT'): iname = str(Lang)+"-"+str(Cat)+"-"+str(count) self.saveImage(iname) self.clearCanvas() if count==imgCount-1: msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Success") msg.setInformativeText('You Have Successfully Completed the Task') msg.setWindowTitle("Success") msg.exec_() self.openLs() elif count<imgCount-1: count = count + 1 print(count) else: count = 0 self.imgLabel.setPixmap(QPixmap(LangDir + "\\"+ fileList[count])) if(self.NextButton.text() == 'START'): self.NextButton.setText('NEXT') self.imgLabel.setPixmap(QPixmap(LangDir + "\\"+ fileList[count])) self.clearCanvas() def clearCanvas(self): self.image.fill(Qt.white) def saveImage(self,imgname): global userDir global cwd os.chdir(userDir) filename = str(imgname)+".png" self.image.save(filename,"PNG") os.chdir(cwd) def quitApp(self): sys.exit(0) def openLs(self): loop = QEventLoop() QTimer.singleShot(100, loop.quit) loop.exec_() self.close() self.open = LanguageSelection() @pyqtSlot() def on_click(self): openColorDialog(self) def openColorDialog(self): global color tmpcolor = QColorDialog.getColor() if tmpcolor.isValid(): tmpcolor = (tmpcolor.name()).strip('#') tuple1 = tuple(int(tmpcolor[i:i+2], 16) for i in (0, 2, 4)) color = QColor.fromRgb(tuple1[0],tuple1[1],tuple1[2]) self.brushColor = color def logout(self): loop = QEventLoop() QTimer.singleShot(100, loop.quit) loop.exec_() self.close() self.open = Ui2() def getsliderValue(self,value): self.brushSize= value
from PyQt5.QtGui import QColor, QPen, QBrush, QCursor, QImage, QPainter from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.uic import loadUi from types import MethodType import sys import numpy as np app = QApplication(sys.argv) ##################### importing the file made qt designer ##################### w = loadUi("03-circles.ui") #################### image for saving the picture of circles ################## img = QImage(w.widget.width(), w.widget.height(), QImage.Format_RGB32) img.fill(Qt.white) # image appears white in the beginning (not black) ################################ set painter ################################## imgPainter = QPainter() # first painter painter = QPainter() # second painter ################################## set pen #################################### line_drawer = QPen() line_drawer.setWidth(4) ################################# set switch ################################### switch = 0 start_point_list = [0] end_point_list = [0]
class Menu(QDialog): def __init__(self): super().__init__() self.ui = loadUi("design.ui", self) self.ui.classify.setDisabled(True) self.predictor = Inference() self.image = QImage(self.size(), QImage.Format_Grayscale8) self.image.fill(Qt.white) self.drawing = False self.brush_size = 2 self.color = Qt.black self.last_point = QPoint() self.ui.clear.clicked.connect(self.clear_canvas) self.ui.classify.clicked.connect(self.classify_image) self.ui.select_model.clicked.connect(self.select_model_dialog) self.set_tooltips() self.show() @pyqtSlot() def select_model_dialog(self): gui_utils.set_widgets_to_gray(self) self.update() model_path, _ = QFileDialog.getOpenFileName(self) if model_path: gui_utils.display_model_path(self, model_path) self.predictor.load(model_path) logging.info("Model loaded") gui_utils.set_widgets_clickable(self) @pyqtSlot() def mousePressEvent(self, event): if (event.button() == Qt.LeftButton) & gui_utils.check_boundaries( self, event): self.drawing = True self.last_point = event.pos() @pyqtSlot() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & gui_utils.check_boundaries( self, event): painter = QPainter(self.image) painter.setPen( QPen(self.color, self.brush_size, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.last_point, event.pos()) self.last_point = event.pos() self.update() @pyqtSlot() def mouseReleaseEvent(self, event): if event.button == Qt.LeftButton: self.drawing = False @pyqtSlot() def paintEvent(self, event): canvas_painter = QPainter(self) canvas_painter.drawImage(self.rect(), self.image, self.image.rect()) @pyqtSlot() def clear_canvas(self): logging.debug("Clear canvas procedure executed.") self.image.fill(Qt.white) self.update() @pyqtSlot() def keyPressEvent(self, event): if event.key() == Qt.Key_Shift: self.clear_canvas() if event.key() == Qt.Key_P: self.classify_image() if event.key() == Qt.Key_Escape: logging.debug("Escape button pressed, terminate program.") logging.debug("Classification creation program terminated -- %s" % (datetime.datetime.now())) sys.exit(0) @pyqtSlot() def closeEvent(self, event): logging.debug("Classification program terminated -- %s" % (datetime.datetime.now())) @pyqtSlot() def classify_image(self): img = self.image.copy(QRect(70, 130, 224, 224)) image_path = gui_utils.save_input_image(img) results = self.predictor.predict_top3(image_path) gui_utils.display_results(self, results) logging.info(f'Image classified as {results[0]} with {[results[1]]}') self.update() return @pyqtSlot() def set_tooltips(self): self.ui.label_model_selection.setToolTip( "Select the pretrained model that shall" " be used to classify the input image.") self.ui.label_result_first.setToolTip( "Likelihood for the most probable classification" " result of the input image.") self.ui.label_result_second.setToolTip( "Likelihood for the second most probable classification" " result of the input image.") self.ui.label_result_third.setToolTip( "Likelihood for the third most probable classification result" " of the input image.") self.ui.label_results.setToolTip( "The results of the image classification using the selected model" " in the table on the left.") self.ui.select_model.setToolTip( "Select the pretrained model that shall be used to classify the input image." ) self.ui.clear.setToolTip( "Clear the drawing canvas above. Use SHIFT alternatively.") self.ui.classify.setToolTip( "Click in this button to classify the drawn input image using" " the currently selected model in the table above.") self.ui.frame.setToolTip( "Please draw the greek letter you want to classify.\nBoth," " lower and uppercase letters work.") self.ui.result_first.setToolTip( "The most probable classification result of the input image.") self.ui.result_second.setToolTip( "The second most probable classification result of the input image." ) self.ui.result_third.setToolTip( "The third most probable classification result of the input image." )
def updateMask(control_image_path, rendered_image_path, mask_image_path): control_image = imageFromPath(control_image_path) if not control_image: error('Could not read control image {}'.format(control_image_path)) rendered_image = imageFromPath(rendered_image_path) if not rendered_image: error('Could not read rendered image {}'.format(rendered_image_path)) if not rendered_image.width() == control_image.width( ) or not rendered_image.height() == control_image.height(): print( ('Size mismatch - control image is {}x{}, rendered image is {}x{}'. format(control_image.width(), control_image.height(), rendered_image.width(), rendered_image.height()))) max_width = min(rendered_image.width(), control_image.width()) max_height = min(rendered_image.height(), control_image.height()) # read current mask, if it exist mask_image = imageFromPath(mask_image_path) if mask_image.isNull(): print('Mask image does not exist, creating {}'.format(mask_image_path)) mask_image = QImage(control_image.width(), control_image.height(), QImage.Format_ARGB32) mask_image.fill(QColor(0, 0, 0)) # loop through pixels in rendered image and compare mismatch_count = 0 linebytes = max_width * 4 for y in range(max_height): control_scanline = control_image.constScanLine(y).asstring(linebytes) rendered_scanline = rendered_image.constScanLine(y).asstring(linebytes) mask_scanline = mask_image.scanLine(y).asstring(linebytes) for x in range(max_width): currentTolerance = qRed( struct.unpack('I', mask_scanline[x * 4:x * 4 + 4])[0]) if currentTolerance == 255: # ignore pixel continue expected_rgb = struct.unpack('I', control_scanline[x * 4:x * 4 + 4])[0] rendered_rgb = struct.unpack('I', rendered_scanline[x * 4:x * 4 + 4])[0] difference = colorDiff(expected_rgb, rendered_rgb) if difference > currentTolerance: # update mask image mask_image.setPixel(x, y, qRgb(difference, difference, difference)) mismatch_count += 1 if mismatch_count: # update mask mask_image.save(mask_image_path, "png") print('Updated {} pixels in {}'.format(mismatch_count, mask_image_path)) else: print('No mismatches in {}'.format(mask_image_path))
class QtCrackWidget(QWidget): closeCrackWidget = pyqtSignal() def __init__(self, map, blob, x, y, parent=None): super(QtCrackWidget, self).__init__(parent) self.setStyleSheet("background-color: rgb(60,60,65); color: white") self.qimg_cropped = utils.cropQImage(map, blob.bbox) arr = utils.qimageToNumpyArray(self.qimg_cropped) self.input_arr = rgb2gray(arr) * 255 self.tolerance = 20 self.blob = blob self.xmap = x self.ymap = y self.qimg_crack = QImage(self.qimg_cropped.width(), self.qimg_cropped.height(), QImage.Format_RGB32) self.qimg_crack.fill(qRgb(0, 0, 0)) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setFixedWidth(400) self.setFixedHeight(400) SLIDER_WIDTH = 200 IMAGEVIEWER_SIZE = 300 # SIZE x SIZE self.sliderTolerance = QSlider(Qt.Horizontal) self.sliderTolerance.setFocusPolicy(Qt.StrongFocus) self.sliderTolerance.setMinimumWidth(SLIDER_WIDTH) self.sliderTolerance.setMinimum(1) self.sliderTolerance.setMaximum(100) self.sliderTolerance.setValue(self.tolerance) self.sliderTolerance.setTickInterval(5) self.sliderTolerance.setAutoFillBackground(True) self.sliderTolerance.valueChanged.connect(self.sliderToleranceChanged) self.lblTolerance = QLabel("Tolerance: 20") self.lblTolerance.setAutoFillBackground(True) str = "Tolerance {}".format(self.tolerance) self.lblTolerance.setText(str) layoutTolerance = QHBoxLayout() layoutTolerance.addWidget(self.lblTolerance) layoutTolerance.addWidget(self.sliderTolerance) self.viewerplus = QtImageViewerPlus() self.viewerplus.disableScrollBars() self.viewerplus.setFixedWidth(IMAGEVIEWER_SIZE) self.viewerplus.setFixedHeight(IMAGEVIEWER_SIZE) self.btnCancel = QPushButton("Cancel") self.btnCancel.setAutoFillBackground(True) self.btnApply = QPushButton("Apply") self.btnApply.setAutoFillBackground(True) layoutButtons = QHBoxLayout() layoutButtons.addWidget(self.btnCancel) layoutButtons.addWidget(self.btnApply) layoutV = QVBoxLayout() layoutV.addLayout(layoutTolerance) layoutV.addWidget(self.viewerplus) layoutV.addLayout(layoutButtons) layoutV.setSpacing(10) self.setLayout(layoutV) self.viewerplus.setImage(self.qimg_cropped) self.preview() self.setAutoFillBackground(True) self.setWindowTitle("Crack") def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: # RESET CURRENT OPERATION self.closeCrackWidget.emit() @pyqtSlot() def sliderToleranceChanged(self): # update tolerance value newvalue = self.sliderTolerance.value() str1 = "Tolerance {}".format(newvalue) self.lblTolerance.setText(str1) self.tolerance = newvalue # update the preview of the crack segmentation self.preview() @pyqtSlot() def preview(self): arr = self.input_arr.copy() mask_crack = self.blob.createCrack(arr, self.xmap, self.ymap, self.tolerance, preview=True) self.qimg_crack = utils.maskToQImage(mask_crack) self.viewerplus.setOpacity(0.5) self.viewerplus.setOverlayImage(self.qimg_crack) def apply(self): mask_crack = self.blob.createCrack(self.input_arr, self.xmap, self.ymap, self.tolerance, preview=False)
class miP_MainWindow(QMainWindow): def __init__(self): super().__init__() uic.loadUi('miP_main.ui', self) # Загружаем дизайн (надо не забыть в файл переделать) # Создаем холст self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) self.drawing = False # Сразу же выбираем кисть self.draw_type = brush self.draw_size = 8 self.draw_color1 = Qt.black self.draw_color2 = Qt.white self.lastPoint = QPoint() self.x = 0 self.y = 0 # меню файла self.f_create.triggered.connect(self.create_new_file) self.f_open.triggered.connect(self.open_file) self.f_save.triggered.connect(self.save_file) # инструменты self.i_brush.dtype = brush self.i_brush.triggered.connect(self.choose_draw_type) self.i_eraser.dtype = eraser self.i_eraser.triggered.connect(self.choose_draw_type) self.i_line.dtype = line self.i_line.triggered.connect(self.choose_draw_type) self.i_rect.dtype = rect self.i_rect.triggered.connect(self.choose_draw_type) self.i_oval.dtype = oval self.i_oval.triggered.connect(self.choose_draw_type) # цвет 1 (pen) self.c1_black.color = Qt.black self.c1_black.triggered.connect(self.choose_color1) self.c1_red.color = Qt.red self.c1_red.triggered.connect(self.choose_color1) self.c1_blue.color = Qt.blue self.c1_blue.triggered.connect(self.choose_color1) self.c1_yellow.color = Qt.yellow self.c1_yellow.triggered.connect(self.choose_color1) self.c1_green.color = Qt.green self.c1_green.triggered.connect(self.choose_color1) self.c1_white.color = Qt.white self.c1_white.triggered.connect(self.choose_color1) self.c1_other.triggered.connect(self.choose_color1) # цвет 2 (brush) self.c2_black.color = Qt.black self.c2_black.triggered.connect(self.choose_color2) self.c2_red.color = Qt.red self.c2_red.triggered.connect(self.choose_color2) self.c2_blue.color = Qt.blue self.c2_blue.triggered.connect(self.choose_color2) self.c2_yellow.color = Qt.yellow self.c2_yellow.triggered.connect(self.choose_color2) self.c2_green.color = Qt.green self.c2_green.triggered.connect(self.choose_color2) self.c2_white.color = Qt.white self.c2_white.triggered.connect(self.choose_color2) self.c2_other.triggered.connect(self.choose_color2) # выбор размера (толщины) инструмента self.c_size.triggered.connect(self.choose_size) def create_new_file(self): self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(self.draw_color2) self.update() def save_file(self): fname = QFileDialog.getSaveFileName( self, 'Сохранить картинку', '', 'Картинка (*.jpg);;Картинка (*.png);;Все файлы (*)')[0] self.image.save(fname) def open_file(self): fname = QFileDialog.getOpenFileName( self, 'Выбрать картинку', '', 'Картинка (*.jpg);;Картинка (*.png);;Все файлы (*)')[0] im = Image.open(fname) im = im.resize((800, 600)) im.save('res.png') self.image.load('res.png') def choose_size(self): size, ok_pressed = QInputDialog.getInt( self, "Введите размер кисти", "Размер кисти", self.draw_size, 1, 1000, 1) if ok_pressed: self.draw_size = size def choose_color1(self): # палитра, все обычно if self.sender() != self.c1_other: self.draw_color1 = self.sender().color else: self.draw_color1 = QColorDialog.getColor() def choose_color2(self): # палитра, все обычно if self.sender() != self.c2_other: self.draw_color2 = self.sender().color else: self.draw_color2 = QColorDialog.getColor() def choose_draw_type(self): self.draw_type = self.sender().dtype def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() self.x = event.x() self.y = event.y() self.image.save('res.png') def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: if self.draw_type == brush: painter = QPainter(self.image) painter.setPen(QPen(self.draw_color1, self.draw_size)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() if self.draw_type == eraser: painter = QPainter(self.image) painter.setPen(QPen(self.draw_color2, self.draw_size)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() elif self.draw_type == line: self.image.load('res.png') painter = QPainter(self.image) painter.setPen(QPen(self.draw_color1, self.draw_size)) painter.drawLine(self.lastPoint, event.pos()) elif self.draw_type == rect: self.image.load('res.png') painter = QPainter(self.image) painter.setPen(QPen(self.draw_color1, self.draw_size)) painter.setBrush(QBrush(self.draw_color2)) painter.drawRect(self.x, self.y, event.x() - self.x, event.y() - self.y) elif self.draw_type == oval: self.image.load('res.png') painter = QPainter(self.image) painter.setPen(QPen(self.draw_color1, self.draw_size)) painter.setBrush(QBrush(self.draw_color2)) painter.drawEllipse(self.x, self.y, event.x() - self.x, event.y() - self.y) self.update() def mouseReleaseEvent(self, event): self.drawing = False self.image.save('res.png', 'png') def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect())
class ScribbleArea(QWidget): def __init__(self, parent=None): super(ScribbleArea, self).__init__(parent) self.setAttribute(Qt.WA_StaticContents) self.modified = False self.scribbling = False self.myPenWidth = 1 self.myPenColor = Qt.blue self.image = QImage() self.lastPoint = QPoint() def setPenColor(self, newColor): self.myPenColor = newColor def setPenWidth(self, newWidth): self.myPenWidth = newWidth def clearImage(self): self.image.fill(qRgb(255, 255, 255)) self.modified = True self.update() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastPoint = event.pos() self.scribbling = True def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) and self.scribbling: self.drawLineTo(event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.scribbling: self.drawLineTo(event.pos()) self.scribbling = False def paintEvent(self, event): painter = QPainter(self) dirtyRect = event.rect() painter.drawImage(dirtyRect, self.image, dirtyRect) def resizeEvent(self, event): if self.width() > self.image.width() or self.height( ) > self.image.height(): newWidth = max(self.width(), self.image.width()) newHeight = max(self.height(), self.image.height()) self.resizeImage(self.image, QSize(newWidth, newHeight)) self.update() super(ScribbleArea, self).resizeEvent(event) def drawLineTo(self, endPoint): painter = QPainter(self.image) painter.setPen( QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, endPoint) self.modified = True rad = self.myPenWidth / 2 + 2 self.update( QRect(self.lastPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad)) self.lastPoint = QPoint(endPoint) def resizeImage(self, image, newSize): if image.size() == newSize: return newImage = QImage(newSize, QImage.Format_RGB32) newImage.fill(qRgb(255, 255, 255)) painter = QPainter(newImage) painter.drawImage(QPoint(0, 0), image) self.image = newImage def isModified(self): return self.modified def penColor(self): return self.myPenColor def penWidth(self): return self.myPenWidth
class CheckersPlateWidget(QWidget): MARGIN = 10 MARGIN_CROWN = 25 TIMER_AI_TURN_MS = 150 # Init Method # Init plate size and class variables def __init__(self, size, container): super().__init__() self.container = container self.highlightPossibilities = True self.size = min(size.width(), size.height()) self.setFixedSize(self.size, self.size) self.initSquareDimension() self.initGameVariables(False) # Init Game Variables # Init the game's variables def initGameVariables(self, restart): self.pieceSelected = QPoint(-1, -1) self.squarePossibilities = [] self.plate = [] self.initPlate() self.isAnimationRunning = False self.currentAnimationIndex = 0 self.currentAnimationPossibility = None self.currentAnimationOldPos = QPoint(-1, -1) if restart: self.game.setPlate(self.plate) else: self.game = Game(self.plate, self.container) self.initUI() # Init UI Method # Create the image where the plate is draw and draw it def initUI(self): self.image = QImage(QSize(self.size, self.size), QImage.Format_RGB32) self.image.fill(Qt.white) self.drawPlate() # Restart Game # Init back the variables and restart the game def restartGame(self): self.initGameVariables(True) self.game.restartGame(self.plate) # Toggle AI # Restart the game et toggle AI def toggleAI(self): ai = self.game.Ai self.container.restartGame() self.game.Ai = False if ai else True # Init Square Dimension # Calculate squares' dimension def initSquareDimension(self): self.squareDimension = self.size / Game.NB_PLATE_SQUARES # Init Plate # Init the plate in a double array def initPlate(self): for y in range(0, Game.NB_PLATE_SQUARES): self.plate.append([]) for x in range(0, Game.NB_PLATE_SQUARES): self.plate[y].append({}) compare = 0 if y % 2 == 0 else 1 self.plate[y][x]["queen"] = False if x % 2 == compare: self.plate[y][x]["square"] = Square.WHITE self.plate[y][x]["piece"] = Square.EMPTY self.plate[y][x]["player"] = 0 elif x < Game.NB_LINE_OCCUPED: self.plate[y][x]["square"] = Square.BLACK self.plate[y][x]["piece"] = Square.WHITE self.plate[y][x]["player"] = 2 elif x > Game.NB_PLATE_SQUARES - 1 - Game.NB_LINE_OCCUPED: self.plate[y][x]["square"] = Square.BLACK self.plate[y][x]["piece"] = Square.BLACK self.plate[y][x]["player"] = 1 else: self.plate[y][x]["square"] = Square.BLACK self.plate[y][x]["piece"] = Square.EMPTY self.plate[y][x]["player"] = 0 # Toggle Highlight Possibilities # Enable or disable show of possibilities def toggleHighlightPossibilities(self): self.highlightPossibilities = False if self.highlightPossibilities else True # Draw Plate # Draw the plate on the image from the double array def drawPlate(self): for y in range(0, Game.NB_PLATE_SQUARES): for x in range(0, Game.NB_PLATE_SQUARES): pieceSelected = True if x == self.pieceSelected.x( ) and y == self.pieceSelected.y() else False squarePossibility = True if self.game.getPointInPossibilities( self.squarePossibilities, QPoint(x, y)) else False if self.plate[y][x]["square"] == Square.BLACK: self.drawSquare(x, y, Qt.gray, squarePossibility) else: self.drawSquare(x, y, Qt.lightGray, squarePossibility) if self.plate[y][x]["piece"] == Square.BLACK: self.drawPiece(x, y, Qt.black, pieceSelected) elif self.plate[y][x]["piece"] == Square.WHITE: self.drawPiece(x, y, Qt.white, pieceSelected) if self.plate[y][x]["queen"] == True: posX = x * self.squareDimension + self.MARGIN_CROWN posY = y * self.squareDimension + self.MARGIN_CROWN width = self.squareDimension - 2 * self.MARGIN_CROWN self.drawPieceFromFile(posX, posY, width, "./icons/crown") self.update() # Draw Square # Draw a square on the image def drawSquare(self, x, y, color, possibility): painter = QPainter(self.image) color = Qt.darkGray if possibility and self.highlightPossibilities else QColor( color) painter.setBrush(color) painter.setPen(color) painter.drawRect(x * self.squareDimension, y * self.squareDimension, self.squareDimension - 1, self.squareDimension - 1) # Draw Piece # Draw a piece on the image def drawPiece(self, x, y, color, selected): painter = QPainter(self.image) color = QColor(color) if selected: color.setAlpha(120) painter.setBrush(color) painter.setPen(color) posX = x * self.squareDimension + self.MARGIN posY = y * self.squareDimension + self.MARGIN width = self.squareDimension - 2 * self.MARGIN painter.drawEllipse(posX, posY, width, width) # Draw Piece From File # Draw a piece from a file on the image def drawPieceFromFile(self, posX, posY, width, path): piece = QPixmap(path) painter = QPainter(self.image) painter.drawPixmap(posX, posY, width, width, piece) # Paint Event (override method) # Called on window focus or resize # Draw the image on widget def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) # Mouse Press Event (override method) # Called when user press a button on mouse # Move a piece or select one def mousePressEvent(self, event): if event.button() == Qt.LeftButton and not self.game.hasWon(): if not self.isAnimationRunning and not self.game.isTurnAI(): x, y = self.getSelectedSquare(event) pos = QPoint(x, y) # Case cliquée + Clique sur une possibilité if self.pieceSelected.x() != -1 and self.pieceSelected.y() != -1\ and self.game.getPointInPossibilities(self.squarePossibilities, pos) is not None: possibility = self.game.getPointInPossibilities( self.squarePossibilities, pos) self.startAnimation(possibility, self.pieceSelected) self.pieceSelected = QPoint(-1, -1) self.squarePossibilities = [] # Clique sur une case du plateau else: self.pieceSelected = QPoint(-1, -1) self.squarePossibilities = [] player = 1 if self.game.isTurnJ1() else 2 if self.plate[y][x]["piece"] != Square.EMPTY and self.plate[ y][x]["player"] == player: if not self.game.isGameRunning(): self.game.launchGame() self.pieceSelected = pos self.squarePossibilities = self.game.getPossibility( pos) self.game.setPlate(self.plate) self.drawPlate() self.update() # Start Animation # Start a piece's move (and/or eat) def startAnimation(self, possibility, fromPiece): self.isAnimationRunning = True self.currentAnimationIndex = 0 self.currentAnimationPossibility = possibility self.currentAnimationOldPos = fromPiece QTimer.singleShot( self.TIMER_AI_TURN_MS if self.game.isTurnAI() else 10, self.doAnimation) # Do Animation # Move and/or eat a piece def doAnimation(self): possibility = self.currentAnimationPossibility i = self.currentAnimationIndex if i < len(possibility.getPieceMoves()): self.game.movePiece(self.currentAnimationOldPos, possibility.getPieceMoves()[i], self.plate, True) self.currentAnimationOldPos = possibility.getPieceMoves()[i] if i < possibility.getNbPiecesEat(): self.game.eatPiece(possibility.getPosPiecesEat()[i], self.plate) self.currentAnimationIndex += 1 self.game.setPlate(self.plate) self.drawPlate() self.update() if self.currentAnimationIndex >= len(possibility.getPieceMoves()): self.game.removePieces(possibility.getNbPiecesEat()) self.isAnimationRunning = False self.currentAnimationPossibility = None self.currentAnimationIndex = 0 if not self.checkWin(): self.game.toggleTurn() else: QTimer.singleShot(500, self.doAnimation) # Get Selected Square # Convert mouse coordinates to a specific cell def getSelectedSquare(self, event): for y in range(0, Game.NB_PLATE_SQUARES): posYMin = y * self.squareDimension posYMax = y * self.squareDimension + self.squareDimension if posYMin <= event.pos().y() <= posYMax: for x in range(0, Game.NB_PLATE_SQUARES): posXMin = x * self.squareDimension posXMax = x * self.squareDimension + self.squareDimension if posXMin <= event.pos().x() <= posXMax: return x, y return -1, -1 # Check Win # Display a message if someone won def checkWin(self): if self.checkLoose(): self.game.stopGame(True) player = "Black" if self.game.isTurnJ1() else "White" if not self.game.isAi(): QMessageBox.about(self, "Win !", "Player " + player + " won !") elif not self.game.isTurnJ1(): QMessageBox.about(self, "Loose !", "You loose ... AI won !") else: QMessageBox.about(self, "Win !", "You win against the AI !") return True return False # Check Loose # Check if a player loose def checkLoose(self): player = 2 if self.game.isTurnJ1() else 1 for y in range(0, self.game.NB_PLATE_SQUARES): for x in range(0, self.game.NB_PLATE_SQUARES): if self.plate[y][x]["player"] == player: return False return True # Get Game # Return the Game class def getGame(self): return self.game
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def fill_invert(self): color_fill = self.colormain color_background = QColor(255,255,255).rgb() for rebr in edges: old = -1 old_sy = -1 flag = False for j in range(len(rebr)-1): x1 = rebr[j][0] y1 = rebr[j][1] x2 = rebr[j+1][0] y2 = rebr[j+1][1] dx = int(x2 - x1) dy = int(y2 - y1) sx = sign(dx) sy = sign(dy) dx = abs(dx) dy = abs(dy) if (j == 0): first_sy = sy elif (j == len(rebr)-2): if (sy < 0 and first_sy < 0 or sy > 0 and first_sy > 0): flag = True if (sy == 0): continue if (sy < 0 and old_sy > 0 or sy > 0 and old_sy < 0): old = -1 old_sy = sy swap = False if (dy <= dx): swap = False else: swap = True dx,dy = dy,dx e = int(2*dy-dx) x = int(x1) y = int(y1) color = QColor(0,0,0) for i in range(dx+1): slave_x = x if (old != y): if flag and y == rebr[0][1]: continue while slave_x < WIDTH: current_color = self.image.pixelColor(slave_x,y) if current_color.rgb() == color_background: self.image.setPixel(int(slave_x),int(y),color_fill) else: self.image.setPixel(int(slave_x),int(y),color_background) slave_x += 1 old = y QApplication.processEvents() if (e>=0): if (swap): x += sx else: y +=sy e = e-2*dx if (e < 0): if (swap): y +=sy else: x += sx e = e+2*dy self.repaint() main_old =y2 def Bresenham(self,x1,y1,x2,y2,color = QColor(0,0,0).rgb()): dx = int(x2 - x1) dy = int(y2 - y1) sx = sign(dx) sy = sign(dy) dx = abs(dx) dy = abs(dy) swap = False if (dy <= dx): swap = False else: swap = True dx,dy = dy,dx e = int(2*dy-dx) x = int(x1) y = int(y1) for i in range(dx+1): self.image.setPixel(x,y,color) if (e>=0): if (swap): x += sx else: y +=sy e = e-2*dx if (e < 0): if (swap): y +=sy else: x += sx e = e+2*dy def initUI(self): self.setGeometry(100,100, 800, 500) self.setWindowTitle('Points') self.Group = QHBoxLayout(self) self.v = QVBoxLayout() self.GraphView = QGraphicsView(self) self.scene = QGraphicsScene(self) self.image = QImage(WIDTH,HIGHT - 20,QImage.Format_RGB32) self.Group.addWidget(self.GraphView) self.Group.addLayout(self.v) self.image.fill(Qt.white) self.GraphView.setGeometry(10,10,WIDTH,HIGHT ) self.GraphView.setStyleSheet("background-color: white") self.scene.addPixmap(QPixmap.fromImage(self.image)) self.GraphView.setScene(self.scene) self.fill_butt = QPushButton('Fill', self) self.fill_butt.resize(self.fill_butt.sizeHint()) self.table = QTableWidget(self) self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(["x","y"]) self.v.addWidget(self.table) v1 = QHBoxLayout() self.clear = QPushButton('Clear', self) self.clear.resize(self.fill_butt.sizeHint()) v1.addWidget(self.clear) self.Add = QPushButton('Add', self) self.Add.resize(self.fill_butt.sizeHint()) v1.addWidget(self.Add) self.v.addLayout(v1) self.v.addWidget(self.fill_butt) self.color_button = QPushButton(self) self.color_button.setGeometry(800,100,40,20) self.v.addWidget(self.color_button) self.colormain = QColor(0,255,0).rgb() self.color_button.setStyleSheet('QPushButton{background-color:'+QColor(0,255,0).name()+'}') self.capslock = False self.color_button.clicked.connect(lambda: self.GetColor()) self.Add.clicked.connect(lambda: self.ShowDialog()) self.fill_butt.clicked.connect(lambda: self.Fill()) self.clear.clicked.connect(lambda: self.Clear()) self.show() def keyPressEvent(self, QKeyEvent): if QKeyEvent.key() == 16777252: self.capslock = not self.capslock def GetColor(self): color = QColorDialog.getColor() self.colormain = color.rgb() hexcolor = color.name() self.color_button.setStyleSheet('QPushButton{background-color:'+hexcolor+'}') def Fill(self): self.fill_invert() self.draw_borders() def ShowDialog(self): text, ok = QInputDialog.getText(self, 'Input Dialog', 'Enter X Y:') if ok: text = text.split() x = int(text[0]) y = int(text[1]) i = len(edges_slave) if i: self.Bresenham(edges_slave[i-1][0],edges_slave[i-1][1],x,y) edges_slave.append([x,y]) self.table_appender([x,y]) def Clear(self): edges.clear() edges_slave.clear() self.table.setRowCount(0) self.image.fill(Qt.white) def draw_borders(self): for j in range(len(edges)): for i in range(len(edges[j])-1): self.Bresenham(edges[j][i][0],edges[j][i][1],edges[j][i+1][0],edges[j][i+1][1]) self.repaint() def mousePressEvent(self, QMouseEvent): if (QMouseEvent.button() == Qt.LeftButton): cord = QMouseEvent.pos() y = cord.y() x = cord.x() if (x >= 10 and y>=10 and y<=HIGHT and x<=WIDTH): x -= 10 y -= 10 i = len(edges_slave) if self.capslock and i: if y != edges_slave[i-1][1]: der = (x - edges_slave[i-1][0])/(y - edges_slave[i-1][1]) else: der = 2 if abs(der) <= 1: x = edges_slave[i-1][0] else: y = edges_slave[i-1][1] if i: self.Bresenham(edges_slave[i-1][0],edges_slave[i-1][1],x,y) edges_slave.append([x,y]) self.table_appender([x,y]) elif (QMouseEvent.button() == Qt.RightButton): i = len(edges_slave) if i: x = edges_slave[0][0] y = edges_slave[0][1] self.Bresenham(edges_slave[i-1][0],edges_slave[i-1][1],x,y) edges_slave.append([x,y]) edges.append(copy.deepcopy(edges_slave)) edges_slave.clear() self.table_appender(['end','end']) def table_appender(self,coord): N = self.table.rowCount() self.table.setRowCount(N+1) self.table.setItem(N,0,QTableWidgetItem(str(coord[0]))) self.table.setItem(N,1,QTableWidgetItem(str(coord[1]))) def paintEvent(self, e): self.scene.clear() self.scene.addPixmap(QPixmap.fromImage(self.image))
def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): border_color = Qt.white base_img = QImage(self.f_size.width(),self.f_size.height(), QImage.Format_ARGB32) base_img.fill(border_color) img = QImage(img) painter = QPainter() painter.begin(base_img) total_distance_h = round(base_img.width() / self.abstand_v) dist_v = round(total_distance_h) / 2 dist_h = round(total_distance_h) / 2 img = img.scaledToWidth(base_img.width() - (2 * (total_distance_h))) painter.drawImage(total_distance_h, total_distance_h, img) #frame around image pen = QPen(Qt.black, 2) painter.setPen(pen) #horz painter.drawLine(0, total_distance_h, base_img.width(), total_distance_h) painter.drawLine(0, base_img.height()-(total_distance_h), base_img.width(), base_img.height()-(total_distance_h)) #vert painter.drawLine(total_distance_h, 0, total_distance_h, base_img.height()) painter.drawLine(base_img.width()-(total_distance_h), 0, base_img.width()-(total_distance_h), base_img.height()) #border around img border_thick = 6 Rpath = QPainterPath() Rpath.addRect(QRectF((total_distance_h)+(border_thick/2), (total_distance_h)+(border_thick/2), base_img.width()-((total_distance_h)*2)-((border_thick)-1), (base_img.height()-((total_distance_h))*2)-((border_thick)-1))) pen = QPen(Qt.black, border_thick) pen.setJoinStyle (Qt.MiterJoin) painter.setPen(pen) painter.drawPath(Rpath) Bpath = QPainterPath() Bpath.addRect(QRectF((total_distance_h), (total_distance_h), base_img.width()-((total_distance_h)*2), (base_img.height()-((total_distance_h))*2))) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawPath(Bpath) pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawLine(0, base_img.height()/2, total_distance_h, base_img.height()/2) painter.drawLine(base_img.width()/2, 0, base_img.width()/2, total_distance_h) painter.drawLine(base_img.width()-total_distance_h, base_img.height()/2, base_img.width(), base_img.height()/2) painter.drawLine(base_img.width()/2, base_img.height(), base_img.width()/2, base_img.height() - total_distance_h) #print code f_size = 37 QFontDatabase.addApplicationFont(os.path.join(os.path.dirname(__file__), 'DejaVuSansMono-Bold.ttf')) font = QFont("DejaVu Sans Mono", f_size-11, QFont.Bold) font.setPixelSize(35) painter.setFont(font) if not calibration_sheet: if is_cseed: #its a secret painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) painter.drawImage(((total_distance_h))+11, ((total_distance_h))+11, QImage(icon_path('electrumb.png')).scaledToWidth(2.1*(total_distance_h), Qt.SmoothTransformation)) painter.setPen(QPen(Qt.white, border_thick*8)) painter.drawLine(base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2, (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2, base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2 - 77, (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2) painter.setPen(QColor(0,0,0,255)) painter.drawText(QRect(0, base_img.height()-107, base_img.width()-total_distance_h - border_thick - 11, base_img.height()-total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.version + '_'+self.versioned_seed.checksum) painter.end() else: # revealer painter.setPen(QPen(border_color, 17)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) painter.setPen(QPen(Qt.black, 2)) painter.drawLine(0, dist_v, base_img.width(), dist_v) painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) logo = QImage(icon_path('revealer_c.png')).scaledToWidth(1.3*(total_distance_h)) painter.drawImage((total_distance_h)+ (border_thick), ((total_distance_h))+ (border_thick), logo, Qt.SmoothTransformation) #frame around logo painter.setPen(QPen(Qt.black, border_thick)) painter.drawLine(total_distance_h+border_thick, total_distance_h+logo.height()+3*(border_thick/2), total_distance_h+logo.width()+border_thick, total_distance_h+logo.height()+3*(border_thick/2)) painter.drawLine(logo.width()+total_distance_h+3*(border_thick/2), total_distance_h+(border_thick), total_distance_h+logo.width()+3*(border_thick/2), total_distance_h+logo.height()+(border_thick)) #frame around code/qr qr_size = 179 painter.drawLine((base_img.width()-((total_distance_h))-(border_thick/2)-2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2, (base_img.width()/2+(total_distance_h/2)-border_thick-(border_thick*8)/2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2) painter.drawLine((base_img.width()/2+(total_distance_h/2)-border_thick-(border_thick*8)/2)-qr_size, (base_img.height()-((total_distance_h)))-((border_thick*8))-(border_thick/2)-2, base_img.width()/2 + (total_distance_h/2)-border_thick-(border_thick*8)/2-qr_size, ((base_img.height()-((total_distance_h)))-(border_thick/2)-2)) painter.setPen(QPen(Qt.white, border_thick * 8)) painter.drawLine( base_img.width() - ((total_distance_h)) - (border_thick * 8) / 2 - (border_thick / 2) - 2, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2, base_img.width() / 2 + (total_distance_h / 2) - border_thick - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8) / 2) - (border_thick / 2) - 2) painter.setPen(QColor(0,0,0,255)) painter.drawText(QRect(((base_img.width()/2) +21)-qr_size, base_img.height()-107, base_img.width()-total_distance_h - border_thick -93, base_img.height()-total_distance_h - border_thick), Qt.AlignLeft, self.versioned_seed.get_ui_string_version_plus_seed()) painter.drawText(QRect(0, base_img.height()-107, base_img.width()-total_distance_h - border_thick -3 -qr_size, base_img.height()-total_distance_h - border_thick), Qt.AlignRight, self.versioned_seed.checksum) # draw qr code qr_qt = self.paintQR(self.versioned_seed.get_ui_string_version_plus_seed() + self.versioned_seed.checksum) target = QRectF(base_img.width()-65-qr_size, base_img.height()-65-qr_size, qr_size, qr_size ) painter.drawImage(target, qr_qt) painter.setPen(QPen(Qt.black, 4)) painter.drawLine(base_img.width()-65-qr_size, base_img.height()-65-qr_size, base_img.width() - 65 - qr_size, (base_img.height() - ((total_distance_h))) - ((border_thick * 8)) - (border_thick / 2) - 4 ) painter.drawLine(base_img.width()-65-qr_size, base_img.height()-65-qr_size, base_img.width() - 65, base_img.height()-65-qr_size ) painter.end() else: # calibration only painter.end() cal_img = QImage(self.f_size.width() + 100, self.f_size.height() + 100, QImage.Format_ARGB32) cal_img.fill(Qt.white) cal_painter = QPainter() cal_painter.begin(cal_img) cal_painter.drawImage(0,0, base_img) #black lines in the middle of border top left only cal_painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) cal_painter.drawLine(0, dist_v, base_img.width(), dist_v) cal_painter.drawLine(dist_h, 0, dist_h, base_img.height()) pen = QPen(Qt.black, 2, Qt.DashDotDotLine) cal_painter.setPen(pen) n=15 cal_painter.setFont(QFont("DejaVu Sans Mono", 21, QFont.Bold)) for x in range(-n,n): #lines on bottom (vertical calibration) cal_painter.drawLine((((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)-13, x+2+base_img.height()-(dist_v), (((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)+13, x+2+base_img.height()-(dist_v)) num_pos = 9 if x > 9 : num_pos = 17 if x < 0 : num_pos = 20 if x < -9: num_pos = 27 cal_painter.drawText((((base_img.width())/(n*2)) *(x))+ (base_img.width()/2)-num_pos, 50+base_img.height()-(dist_v), str(x)) #lines on the right (horizontal calibrations) cal_painter.drawLine(x+2+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/n)+(base_img.height()/2)-13, x+2+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/n)+(base_img.height()/2)+13) cal_painter.drawText(30+(base_img.width()-(dist_h)), ((base_img.height()/(2*n)) *(x))+ (base_img.height()/2)+13, str(x)) cal_painter.end() base_img = cal_img return base_img
class Window(QMainWindow): def __init__(self): super().__init__() title = "Podaj liczbe do odczytania" top = 400 left = 200 width = 1000 height = 800 self.setWindowTitle(title) self.setGeometry(top, left, width, height) self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.black) self.drawing = False self.brushSize = 80 self.brushColor = Qt.white self.lastPoint = QPoint() mainMenu = self.menuBar() fileMenu = mainMenu.addMenu("Plik") saveAction = QAction(QIcon(), "Zbadaj[E]", self) saveAction.setShortcut("E") fileMenu.addAction(saveAction) saveAction.triggered.connect(self.save) clearAction = QAction(QIcon(), "wyczysc[W]", self) clearAction.setShortcut("W") fileMenu.addAction(clearAction) clearAction.triggered.connect(self.clear) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.lastPoint = event.pos() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) & self.drawing: painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, event.pos()) self.lastPoint = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = False def paintEvent(self, event): canvasPainter = QPainter(self) canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) def save(self): self.image.save( str(pathlib.Path(__file__).parent.absolute()) + "/" + "epaint_obraz.png") image = cv2.imread("epaint_obraz.png") image = resize_image(image, 28, 28) cv2.imwrite("epaint_obraz.png", image) json_file = open('model.json', 'r') loaded_model_json = json_file.read() json_file.close() loaded_model = model_from_json(loaded_model_json) loaded_model.load_weights("model.h5") img = imread('epaint_obraz.png') def rgb2gray(rgb): return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) gray = rgb2gray(img) gray = gray.reshape((1, 28, 28, 1)) prediction = loaded_model.predict(gray) QMessageBox.about(self, "Liczba to:", str(np.argmax(prediction))) def clear(self): self.image.fill(Qt.black) self.update()
class MaskItem(pg.GraphicsObject): """Mask item used for drawing mask on an ImageItem.""" _TRANSPARENT = QColor(0, 0, 0, 0) _COLOR_FORMAT = QImage.Format_ARGB32 def __init__(self, item, parent=None): """Initialization. :param ImageItem item: a reference to the masked image item. """ super().__init__(parent=parent) if not isinstance(item, ImageItem): raise TypeError("Input item must be an ImageItem instance.") self._image_item = weakref.ref(item) item.draw_started_sgn.connect(self.onDrawStarted) item.draw_region_changed_sgn.connect(self.onDrawRegionChanged) item.draw_finished_sgn.connect(self.onDrawFinished) # pen for drawing the bounding box self._boundary_color = FColor.mkPen( config['GUI_MASK_BOUNDING_BOX_COLOR']) self._fill_color = FColor.mkColor( config['GUI_MASK_FILL_COLOR'], alpha=180) self.state = MaskState.UNMASK self._mask = None # QImage self._mask_rect = QRectF(0, 0, 0, 0) self._mask_pub = ImageMaskPub() self._p1 = None self._p2 = None def maybeInitializeMask(self, shape): h, w = shape if self._mask is None: self._mask = QImage(w, h, self._COLOR_FORMAT) self._mask.fill(self._TRANSPARENT) self._mask_rect = QRectF(0, 0, w, h) def boundingRect(self): """Override.""" return self._mask_rect @pyqtSlot(int, int) def onDrawStarted(self, x, y): self._p1 = (x, y) @pyqtSlot(int, int) def onDrawRegionChanged(self, x, y): self.prepareGeometryChange() self._p2 = (x, y) def _selectedRect(self): if self._p1 is None or self._p2 is None: return QRectF(0, 0, 0, 0) rect = QRectF(QPoint(*self._p1), QPoint(*self._p2)) return rect.intersected(self._mask_rect) @pyqtSlot() def onDrawFinished(self): rect = self._selectedRect() x = int(rect.x()) y = int(rect.y()) w = int(rect.width()) h = int(rect.height()) if self.state == MaskState.MASK: self._mask_pub.draw((x, y, w, h)) elif self.state == MaskState.UNMASK: self._mask_pub.erase((x, y, w, h)) self._p1 = None self._p2 = None for i in range(x, x+w): for j in range(y, y+h): if self.state == MaskState.MASK: self._mask.setPixelColor(i, j, self._fill_color) elif self.state == MaskState.UNMASK: self._mask.setPixelColor(i, j, self._TRANSPARENT) self._updateImageItem() def removeMask(self): """Completely remove the current mask.""" # The following sequence ensures that it can be used to rescue if # there is discrepancy between ImageTool and the ImageProcessor. self._mask_pub.remove() if self._mask is None: return self._mask.fill(self._TRANSPARENT) self._updateImageItem() def paint(self, p, *args): """Override.""" if self._mask is None: return p.setRenderHint(QPainter.Antialiasing) p.setPen(self._boundary_color) p.drawImage(self.boundingRect(), self._mask) p.drawRect(self._selectedRect()) def mask(self): w = self._mask.width() h = self._mask.height() mask_array = np.zeros((h, w), dtype=bool) for i in range(w): for j in range(h): mask_array[j, i] = \ self._mask.pixelColor(i, j) == self._fill_color return mask_array def setMask(self, mask): """Set a given image mask. :param np.ndarray mask: mask in ndarray. shape = (h, w) """ self._mask_pub.set(mask) h, w = mask.shape self._mask = QImage(w, h, self._COLOR_FORMAT) for i in range(w): for j in range(h): if mask[j, i]: self._mask.setPixelColor(i, j, self._fill_color) else: self._mask.setPixelColor(i, j, self._TRANSPARENT) self._mask_rect = QRectF(0, 0, w, h) self._updateImageItem() def _updateImageItem(self): image_item = self._image_item() if image_item is not None: image_item.update()
class Blob(object): """ Blob data. A blob is a group of pixels. A blob can be tagged with the class and other information. Both the set of pixels and the corresponding vectorized version are stored. """ def __init__(self, region, offset_x, offset_y, id): if region == None: # AN EMPTY BLOB IS CREATED.. self.area = 0.0 self.perimeter = 0.0 self.centroid = np.zeros((2)) self.bbox = np.zeros((4)) # placeholder; empty contour self.contour = np.zeros((2, 2)) self.inner_contours = [] self.qpath = None self.qpath_gitem = None self.instance_name = "noname" self.blob_name = "noname" self.id = 0 else: # extract properties self.centroid = np.array(region.centroid) cy = self.centroid[0] cx = self.centroid[1] self.centroid[0] = cx + offset_x self.centroid[1] = cy + offset_y # Bounding box (min_row, min_col, max_row, max_col). # Pixels belonging to the bounding box are in the half-open # interval [min_row, max_row) and [min_col, max_col). self.bbox = np.array(region.bbox) width = self.bbox[3] - self.bbox[1] height = self.bbox[2] - self.bbox[0] # BBOX -> TOP, LEFT, WIDTH, HEIGHT self.bbox[0] = self.bbox[0] + offset_y self.bbox[1] = self.bbox[1] + offset_x self.bbox[2] = width self.bbox[3] = height # QPainterPath associated with the contours self.qpath = None # QGraphicsItem associated with the QPainterPath self.qpath_gitem = None # to extract the contour we use the mask cropped according to the bbox input_mask = region.image.astype(int) self.contour = np.zeros((2, 2)) self.inner_contours = [] self.createContourFromMask(input_mask) self.setupForDrawing() self.calculatePerimeter() self.calculateArea(input_mask) # a string with a progressive number to identify the instance self.instance_name = "coral" + str(id) # a string with a number to identify the blob plus its centroid xc = int(self.centroid[0]) yc = int(self.centroid[1]) self.blob_name = "blob" + str(id) + "-" + str(xc) + "-" + str(yc) self.id = id # deep extreme points (for fine-tuning) self.deep_extreme_points = np.zeros((4, 2)) # name of the class self.class_name = "Empty" # color of the class self.class_color = [128, 128, 128] # note about the coral, i.e. damage type self.note = "" # QImage corresponding to the current mask self.qimg_mask = None # QPixmap associated with the mask (for pixel-level editing operations) self.pxmap_mask = None # QGraphicsItem associated with the pixmap mask self.pxmap_mask_gitem = None # membership group (if any) self.group = None def copy(self): blob = Blob() blob.centroid = self.centroid.copy() blob.bbox = self.bbox.copy() blob.classname = self.classname blob.classcolor = self.classcolor blob.instance_name = self.instance_name blob.id = self.id blob.note = self.note return blob def setId(self, id): # a string with a number to identify the blob plus its centroid xc = int(self.centroid[0]) yc = int(self.centroid[1]) self.blob_name = "blob" + str(id) + "-" + str(xc) + "-" + str(yc) self.id = id def getMask(self): """ It creates the mask from the contour and returns it. """ r = self.bbox[3] c = self.bbox[2] mask = np.zeros((r, c)) # main polygon [rr, cc] = polygon(self.contour[:, 1], self.contour[:, 0]) rr = rr - int(self.bbox[0]) cc = cc - int(self.bbox[1]) mask[rr, cc] = 1 # holes for inner_contour in self.inner_contours: [rr, cc] = polygon(inner_contour[:, 1], inner_contour[:, 0]) rr = rr - int(self.bbox[0]) cc = cc - int(self.bbox[1]) mask[rr, cc] = 0 return mask def updateUsingMask(self, new_bbox, new_mask): self.bbox = new_bbox self.createContourFromMask(new_mask) self.setupForDrawing() self.calculatePerimeter() self.calculateArea(new_mask) self.calculateCentroid(new_mask) def snapToBorder(self, points): """ Given a curve specified as a set of points, snap the curve on the blob mask: 1) the initial segments of the curve are removed until they snap 2) the end segments of the curve are removed until they snap """ contour = self.contour.copy() test = points_in_poly(points, contour) jump = np.gradient(test.astype(int)) ind = np.nonzero(jump) ind = np.asarray(ind) snappoints = None if ind.shape[1] > 2: first_el = ind[0, 0] + 1 last_el = ind[0, -1] snappoints = points[first_el:last_el, :].copy() return snappoints def createFromClosedCurve(self, points): """ It creates a blob starting from a closed curve. If the curve is not closed False is returned. If the curve intersect itself many times the first segmented region is created. """ pt_min = np.amin(points, axis=0) xmin = pt_min[0] ymin = pt_min[1] pt_max = np.amax(points, axis=0) xmax = pt_max[0] ymax = pt_max[1] x_left = int(xmin) - 8 y_top = int(ymin) - 8 x_right = int(xmax) + 8 y_bottom = int(ymax) + 8 bbox = np.array([y_top, x_left, x_right - x_left, y_bottom - y_top]) mask = np.zeros((bbox[3], bbox[2])) mask_area = bbox[3] * bbox[2] for i in range(points.shape[0]): x = points[i, 0] y = points[i, 1] yy = int(y) - bbox[0] xx = int(x) - bbox[1] for offsetx in range(-1, 2): for offsety in range(-1, 2): mask[yy + offsety, xx + offsetx] = 1 mask_flood = flood(mask, (4, 4), tolerance=0).astype(int) for i in range(points.shape[0]): x = points[i, 0] y = points[i, 1] yy = int(y) - bbox[0] xx = int(x) - bbox[1] for offsetx in range(-1, 2): for offsety in range(-1, 2): mask_flood[yy + offsety, xx + offsetx] = 1 for y in range(mask_flood.shape[0]): for x in range(mask_flood.shape[1]): if mask_flood[y, x] == 1: mask[y, x] = 0 else: mask[y, x] = 1 mask = ndi.binary_fill_holes(mask).astype(int) # check regions = measure.regionprops(mask) if len(regions) != 1: return False else: region = regions[0] check = region.area / mask_area if check > 0.95: return False else: self.updateUsingMask(bbox, mask) return True def createCrack(self, input_arr, x, y, tolerance, preview=True): """ Given a inner blob point (x,y), the function use it as a seed for a paint butcket tool and create a correspondent blob hole """ x_crop = x - self.bbox[1] y_crop = y - self.bbox[0] input_arr = gaussian(input_arr, 2) # input_arr = segmentation.inverse_gaussian_gradient(input_arr, alpha=1, sigma=1) blob_mask = self.getMask() crack_mask = flood(input_arr, (int(y_crop), int(x_crop)), tolerance=tolerance).astype(int) cracked_blob = np.logical_and((blob_mask > 0), (crack_mask < 1)) cracked_blob = cracked_blob.astype(int) if preview: return cracked_blob else: self.updateUsingMask(self.bbox, cracked_blob) return cracked_blob def addToMask(self, points): """ Given a curve specified as a set of points, the pixels OUTSIDE the blob but inside the handle created by the curve are added to the blob. """ # store the original inner contours (i.e. the holes) original_inner_contours = [] for inner_contour in self.inner_contours: duplicate_inner_contour = inner_contour.copy() original_inner_contours.append(duplicate_inner_contour) # enlarge the mask y1A = self.bbox[0] x1A = self.bbox[1] x2A = x1A + self.bbox[2] y2A = y1A + self.bbox[3] pt_min = np.amin(points, axis=0) xmin = pt_min[0] ymin = pt_min[1] pt_max = np.amax(points, axis=0) xmax = pt_max[0] ymax = pt_max[1] x1B = int(xmin) y1B = int(ymin) x2B = int(xmax) y2B = int(ymax) x_left = min(x1A, x1B) - 2 y_top = min(y1A, y1B) - 2 x_right = max(x2A, x2B) + 2 y_bottom = max(y2A, y2B) + 2 bbox_union = np.array( [y_top, x_left, x_right - x_left, y_bottom - y_top]) mask_union = np.zeros((bbox_union[3], bbox_union[2])) blob_mask = self.getMask() for y in range(blob_mask.shape[0]): for x in range(blob_mask.shape[1]): yy = y + (self.bbox[0] - bbox_union[0]) xx = x + (self.bbox[1] - bbox_union[1]) mask_union[yy, xx] = blob_mask[y, x] for i in range(points.shape[0]): x = points[i, 0] y = points[i, 1] yy = int(y) - bbox_union[0] xx = int(x) - bbox_union[1] for offsetx in range(-1, 2): for offsety in range(-1, 2): mask_union[yy + offsety, xx + offsetx] = 1 mask_union = ndi.binary_fill_holes(mask_union).astype(int) self.updateUsingMask(bbox_union, mask_union) # RE-ADD THE ORIGINAL INNER CONTOURS (I.E. THE HOLES) if original_inner_contours: self.inner_contours.clear() for inner_contour in original_inner_contours: # recover inner contour list self.inner_contours.append(inner_contour) # update qpainterpath self.setupForDrawing() def cutFromMask(self, points): """ Given a curve specified as a set of points, the pixels INSIDE the blob but "cutted" by the curve are removed from the blob. """ # enlarge the mask y1A = self.bbox[0] x1A = self.bbox[1] x2A = x1A + self.bbox[2] y2A = y1A + self.bbox[3] pt_min = np.amin(points, axis=0) xmin = pt_min[0] ymin = pt_min[1] pt_max = np.amax(points, axis=0) xmax = pt_max[0] ymax = pt_max[1] x1B = int(xmin) y1B = int(ymin) x2B = int(xmax) y2B = int(ymax) x_left = min(x1A, x1B) - 2 y_top = min(y1A, y1B) - 2 x_right = max(x2A, x2B) + 2 y_bottom = max(y2A, y2B) + 2 bbox_union = np.array( [y_top, x_left, x_right - x_left, y_bottom - y_top]) mask_union = np.zeros((bbox_union[3], bbox_union[2])) blob_mask = self.getMask() for y in range(blob_mask.shape[0]): for x in range(blob_mask.shape[1]): yy = y + (self.bbox[0] - bbox_union[0]) xx = x + (self.bbox[1] - bbox_union[1]) mask_union[yy, xx] = blob_mask[y, x] for i in range(points.shape[0]): x = points[i, 0] y = points[i, 1] yy = int(y) - bbox_union[0] xx = int(x) - bbox_union[1] for offsetx in range(-1, 2): for offsety in range(-1, 2): mask_union[yy + offsety, xx + offsetx] = 0 label_image = measure.label(mask_union) regions = measure.regionprops(label_image) if len(regions) > 1: # TENERE SOLO QUELLA CON AREA MASSIMA ?? area_max = 0 region_to_remove = None for region in regions: if region.area > area_max: area_max = region.area for region in regions: if region.area < area_max: for coords in region.coords: mask_union[coords[0], coords[1]] = 0 self.updateUsingMask(bbox_union, mask_union) def createContourFromMask(self, mask): """ It creates the contour (and the corrisponding polygon) from the blob mask. """ # NOTE: The mask is expected to be cropped around its bbox (!!) (see the __init__) self.inner_contours.clear() # we need to pad the mask to avoid to break the contour that touchs the borders PADDED_SIZE = 2 img_padded = pad(mask, (PADDED_SIZE, PADDED_SIZE), mode="constant", constant_values=(0, 0)) contours = measure.find_contours(img_padded, 0.5) number_of_contours = len(contours) if number_of_contours > 1: # search the longest contour npoints_max = 0 index = 0 for i, contour in enumerate(contours): npoints = contour.shape[0] if npoints > npoints_max: npoints_max = npoints index = i # divide the contours in OUTER contour and INNER contours for i, contour in enumerate(contours): if i == index: self.contour = np.array(contour) else: coordinates = np.array(contour) self.inner_contours.append(coordinates) # adjust the coordinates of the outer contour # (NOTE THAT THE COORDINATES OF THE BBOX ARE IN THE GLOBAL MAP COORDINATES SYSTEM) for i in range(self.contour.shape[0]): ycoor = self.contour[i, 0] xcoor = self.contour[i, 1] self.contour[i, 0] = xcoor - PADDED_SIZE + self.bbox[1] self.contour[i, 1] = ycoor - PADDED_SIZE + self.bbox[0] # adjust coordinates of the INNER contours for j, contour in enumerate(self.inner_contours): for i in range(contour.shape[0]): ycoor = contour[i, 0] xcoor = contour[i, 1] self.inner_contours[j][ i, 0] = xcoor - PADDED_SIZE + self.bbox[1] self.inner_contours[j][ i, 1] = ycoor - PADDED_SIZE + self.bbox[0] elif number_of_contours == 1: coords = measure.approximate_polygon(contours[0], tolerance=1.2) self.contour = np.array(coords) # adjust the coordinates of the outer contour # (NOTE THAT THE COORDINATES OF THE BBOX ARE IN THE GLOBAL MAP COORDINATES SYSTEM) for i in range(self.contour.shape[0]): ycoor = self.contour[i, 0] xcoor = self.contour[i, 1] self.contour[i, 0] = xcoor - PADDED_SIZE + self.bbox[1] self.contour[i, 1] = ycoor - PADDED_SIZE + self.bbox[0] else: print("ZERO CONTOURS -> THERE ARE SOME PROBLEMS HERE !!!!!!)") def setupForDrawing(self): """ Create the QPolygon and the QPainterPath according to the blob's contours. """ # QPolygon to draw the blob qpolygon = QPolygonF() for i in range(self.contour.shape[0]): qpolygon << QPointF(self.contour[i, 0], self.contour[i, 1]) self.qpath = QPainterPath() self.qpath.addPolygon(qpolygon) for inner_contour in self.inner_contours: qpoly_inner = QPolygonF() for i in range(inner_contour.shape[0]): qpoly_inner << QPointF(inner_contour[i, 0], inner_contour[i, 1]) path_inner = QPainterPath() path_inner.addPolygon(qpoly_inner) self.qpath = self.qpath.subtracted(path_inner) def createQPixmapFromMask(self): w = self.bbox[2] h = self.bbox[3] self.qimg_mask = QImage(w, h, QImage.Format_ARGB32) self.qimg_mask.fill(qRgba(0, 0, 0, 0)) if self.class_name == "Empty": rgba = qRgba(255, 255, 255, 255) else: rgba = qRgba(self.class_color[0], self.class_color[1], self.class_color[2], 100) blob_mask = self.getMask() for x in range(w): for y in range(h): if mask[y, x] == 1: self.qimg_mask.setPixel(x, y, rgba) self.pxmap_mask = QPixmap.fromImage(self.qimg_mask) def calculateCentroid(self, mask): sumx = 0.0 sumy = 0.0 n = 0 for y in range(mask.shape[0]): for x in range(mask.shape[1]): if mask[y, x] == 1: sumx += float(x) sumy += float(y) n += 1 # NOTE: centroid is (x,y), bbox is [width height] self.centroid[0] = int(sumx / n) + self.bbox[1] self.centroid[1] = int(sumy / n) + self.bbox[0] xc = int(self.centroid[0]) yc = int(self.centroid[1]) self.instance_name = "coral-" + str(xc) + "-" + str(yc) def calculateContourPerimeter(self, contour): # perimeter of the outer contour px1 = contour[0, 0] py1 = contour[0, 1] N = contour.shape[0] pxlast = contour[N - 1, 0] pylast = contour[N - 1, 1] perim = math.sqrt((px1 - pxlast) * (px1 - pxlast) + (py1 - pylast) * (py1 - pylast)) for i in range(1, contour.shape[0]): px2 = contour[i, 0] py2 = contour[i, 1] d = math.sqrt((px1 - px2) * (px1 - px2) + (py1 - py2) * (py1 - py2)) perim += d px1 = px2 py1 = py2 return perim def calculatePerimeter(self): self.perimeter = self.calculateContourPerimeter(self.contour) for contour in self.inner_contours: self.perimeter += self.calculateContourPerimeter(self.contour) def calculateArea(self, mask): self.area = 0.0 for y in range(mask.shape[0]): for x in range(mask.shape[1]): if mask[y, x] == 1: self.area += 1.0 def fromDict(self, dict): """ Set the blob information given it represented as a dictionary. """ self.bbox = np.asarray(dict["bbox"]) self.centroid = np.asarray(dict["centroid"]) self.area = dict["area"] self.perimeter = dict["perimeter"] self.contour = np.asarray(dict["contour"]) inner_contours = dict["inner contours"] self.inner_contours = [] for c in inner_contours: self.inner_contours.append(np.asarray(c)) self.deep_extreme_points = np.asarray(dict["deep_extreme_points"]) self.class_name = dict["class name"] self.class_color = dict["class color"] self.instance_name = dict["instance name"] self.blob_name = dict["blob name"] self.id = dict["id"] self.note = dict["note"] # finalize blob self.setupForDrawing() def toDict(self): """ Get the blob information as a dictionary. """ dict = {} dict["bbox"] = self.bbox.tolist() dict["centroid"] = self.centroid.tolist() dict["area"] = self.area dict["perimeter"] = self.perimeter dict["contour"] = self.contour.tolist() dict["inner contours"] = [] for c in self.inner_contours: dict["inner contours"].append(c.tolist()) dict["deep_extreme_points"] = self.deep_extreme_points.tolist() dict["class name"] = self.class_name dict["class color"] = self.class_color dict["instance name"] = self.instance_name dict["blob name"] = self.blob_name dict["id"] = self.id dict["note"] = self.note return dict
class Paint(QMainWindow): # Создание окна def __init__(self): # Инициализация super().__init__() try: # Попытка прочитать файл f = open('size.txt', 'r') width = int(f.readline()) # Ширина окна height = int(f.readline()) # Высота окна f.close() except Exception: # Если ошибка f = open('size.txt', 'w') # Создать файл f.write('1200' + '\n' + '900') # Перезапись файла f.close() # Закрытие файла width = 1200 height = 900 self.coords = QLabel(self) # Координаты мыши self.coords.setText("Координаты:None, None") # Изначальные координаты self.coords.resize(150, 15) # Изменение размера self.coords.move(width - 150, height - 20) # Перемещение self.last = 0 # Количество изображений self.setMouseTracking(True) # Отслеживание мыши без нажатия self.copyA = False # Переменная для области копирования icon = 'icons/main.png' # Ссылка на основную иконку os.makedirs('last') # Создание путой папки self.setWindowTitle('MyDrawing') # Назвние окна self.setGeometry(0, 35, width, height) # Размеры окна self.setWindowIcon(QIcon(icon)) # Иконка окна # Создание изображения self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) # Заливка изображения белым цветом # Добавление картинки self.image.save('last/' + str(self.last) + '.png') self.last += 1 # Добавление к количеству картинок self.drawing = False # Переменная для рисования self.brushSize = 2 # Размер кисти self.brushColor = Qt.black # Цвет кисти self.lastPoint = QPoint() # Координаты последней точки mainMenu = self.menuBar() # Создание меню fileMenu = mainMenu.addMenu('Файл') # Добавление в меню вкладки "Файл" # Добавление в меню кнопки "Размер кисти" brushMenu = mainMenu.addMenu('Размер кисти') # Добавление в меню кнопки "Цвет кисти" brushColor = mainMenu.addMenu('Цвет кисти') # Добавление в меню кнопки "Геометричсекие фигуры" shapes = mainMenu.addMenu('Геометрические фигуры') # Создание кнопки сохранения и добавление иконки saveAction = QAction(QIcon('icons/save.jpg'), 'Сохранить', self) saveAction.setShortcut('Ctrl+S') # Добавление комбинации клавиш fileMenu.addAction(saveAction) # Добавление в меню # Вызов функции save() при нажатии saveAction.triggered.connect(self.save) # Создание кнопки очистки и добавление иконки clearAction = QAction(QIcon('icons/clear.jpeg'), 'Очистить', self) clearAction.setShortcut('Ctrl+A') # Добавление комбинации клавиш fileMenu.addAction(clearAction) # Добавление в меню clearAction.triggered.connect(self.clear) # Вызов функции при нажатии # Создание кнопки для изменения размера окна sizeAction = QAction(QIcon('icons/size.png'), 'Изменить размер', self) sizeAction.setShortcut('Ctrl+T') # Добавление комбинации клавиш fileMenu.addAction(sizeAction) # Добавление в меню sizeAction.triggered.connect(self.sizeAdd) # Вызов функции при нажатии # Создание кнопки для добавления изображения addAction = QAction(QIcon('icons/picture.jpg'), 'Добавить изображение', self) addAction.setShortcut('Ctrl+N') # Добавление комбинации клавиш fileMenu.addAction(addAction) # Добавление в меню # При нажатии вызов функции addAction.triggered.connect(self.addPicture) # Создание кнопки для копирования области copyAction = QAction(QIcon('icons/copy.png'), 'Копировать', self) copyAction.setShortcut('Ctrl+C') # Добавление комбинации клавиш fileMenu.addAction(copyAction) # Добавление в меню # При нажатии вызов функции copyAction.triggered.connect(self.copyArea) # Создание кнопки вырезать cutAction = QAction(QIcon('icons/cut.jpg'), 'Вырезать', self) cutAction.setShortcut('Ctrl+X') # Добавление комбинации клавиш fileMenu.addAction(cutAction) # Добавление в меню # Вызов функции при нажатии cutAction.triggered.connect(self.cutArea) # Создание кнопки для вставки области pasteAction = QAction(QIcon('icons/paste.jpg'), 'Вставить', self) pasteAction.setShortcut('Ctrl+V') # Добавление комбинации клавиш fileMenu.addAction(pasteAction) # Добавление в меню # При нажатии вызов функции pasteAction.triggered.connect(self.pasteArea) # Создание кнопки для заливки pourAction = QAction(QIcon('icons/pour.jpg'), 'Залить', self) pourAction.setShortcut('Ctrl+H') # Добавление комбинации клавиш fileMenu.addAction(pourAction) # Добавление в меню # Вызов функции при нажатии pourAction.triggered.connect(self.fillAll) # Создание кнопки отмена cancelAction = QAction(QIcon('icons/back.png'), 'Отмена', self) cancelAction.setShortcut('Ctrl+Z') # Добавление комбинации клавиш fileMenu.addAction(cancelAction) # Добавление в меню # Вызов функции при нажатии cancelAction.triggered.connect(self.returnLast) undoAction = QAction(QIcon('icons/undo.png'), 'Вернуть', self) undoAction.setShortcut('Ctrl+Shift+Z') # Добавление комбинации клавиш fileMenu.addAction(undoAction) # Добавление в меню # Вызов функции при нажатии undoAction.triggered.connect(self.returnUp) # Создание кнопки 3 px и добавление иконки px3Action = QAction(QIcon('icons/3.jpg'), '3 px', self) px3Action.setShortcut('Ctrl+3') # Добавление комбинации клавиш brushMenu.addAction(px3Action) # Добавление в меню px3Action.triggered.connect(self.px3) # Вызов функции при нажатии # Создание кнопки 5 px и добавление иконки px5Action = QAction(QIcon('icons/5.jpg'), '5 px', self) px5Action.setShortcut('Ctrl+5') # Добавление комбинации клавиш brushMenu.addAction(px5Action) # Добавление в меню px5Action.triggered.connect(self.px5) # Вызов функции при нажатии # Создание кнопки 7 px и добавление иконки px7Action = QAction(QIcon('icons/7.jpg'), '7 px', self) px7Action.setShortcut('Ctrl+7') # Добавление комбинации клавиш brushMenu.addAction(px7Action) # Добавление в меню px7Action.triggered.connect(self.px7) # Вызов функции при нажатии # Создание кнопки 9 px и добавление иконки px9Action = QAction(QIcon('icons/9.jpg'), '9 px', self) px9Action.setShortcut('Ctrl+9') # Добавление комбинации клавиш brushMenu.addAction(px9Action) # Добавление в меню px9Action.triggered.connect(self.px9) # Вызов функции при нажатии # Создание кнопки для всех размеров pxOtherAction = QAction(QIcon('icons/pxO.jpg'), 'Все размеры', self) pxOtherAction.setShortcut('Ctrl+P') # Добавление комбинации клавиш brushMenu.addAction(pxOtherAction) # Добавление в меню # Вызов функции при нажатии pxOtherAction.triggered.connect(self.pxOther) # Создание кнопки для выбора черного цвета blackAction = QAction(QIcon('icons/black.jpg'), 'Черный цвет', self) blackAction.setShortcut('Ctrl+B') # Добавление комбинации клавиш brushColor.addAction(blackAction) # Добавление в меню # Вызов функции при нажатии blackAction.triggered.connect(self.blackColor) # Создание кнопки для выбора белого цвета whiteAction = QAction(QIcon('icons/clean.jpg'), 'Ластик', self) whiteAction.setShortcut('Ctrl+W') # Добавление комбинации клавиш brushColor.addAction(whiteAction) # Добавление в меню # Вызов функции при нажатии whiteAction.triggered.connect(self.whiteColor) # Создание кнопки для выбора красного цвета redAction = QAction(QIcon('icons/red.png'), 'Красный цвет', self) redAction.setShortcut('Ctrl+R') # Добавление комбинации клавиш brushColor.addAction(redAction) # Добавление в меню redAction.triggered.connect(self.redColor) # Вызов функции при нажатии # Создание кнопки для выбора зеленого цвета greenAction = QAction(QIcon('icons/green.png'), 'Зеленый цвет', self) greenAction.setShortcut('Ctrl+G') # Добавление комбинации клавиш brushColor.addAction(greenAction) # Добавление в меню # Вызов функции при нажатии greenAction.triggered.connect(self.greenColor) # Создание кнопки для выбора желтого цвета yellowAction = QAction(QIcon('icons/yellow.png'), 'Желтый цвет', self) yellowAction.setShortcut('Ctrl+Y') # Добавление комбинации клавиш brushColor.addAction(yellowAction) # Добавление в меню # Вызов функции при нажатии yellowAction.triggered.connect(self.yellowColor) # Создание кнопки для выбора всех цветов otherAction = QAction(QIcon('icons/other.jpg'), 'Другие цвета', self) otherAction.setShortcut('Ctrl+O') # Добавление комбинации клавиш brushColor.addAction(otherAction) # Добавление в меню # Вызов функции при нажатии otherAction.triggered.connect(self.otherColor) # Создание кнопки для прямоугольника rectangleAction = QAction(QIcon('icons/rectangle.jpg'), 'Прямоугольник', self) shapes.addAction(rectangleAction) # Добавление прямоугольника в меню # Вызов функции при нажатии rectangleAction.triggered.connect(self.rectangle) # Создание кнопки эллипса ellipsAction = QAction(QIcon('icons/ellipse.png'), 'Эллипс', self) shapes.addAction(ellipsAction) # Добавление эллипса в меню # Вызов функции при нажатии ellipsAction.triggered.connect(self.ellips) # Создание кнопки для линии lineAction = QAction(QIcon('icons/line.jpg'), 'Линия', self) shapes.addAction(lineAction) # Добавление линии в меню # Вызов функции при нажатии lineAction.triggered.connect(self.line) # Создание кнопки для звезды starAction = QAction(QIcon('icons/star.png'), 'Звезда', self) shapes.addAction(starAction) # Добавление звезды в меню # Вызов функции при нажатии starAction.triggered.connect(self.star) # Создание кнопки для текста textAction = QAction(QIcon('icons/text.png'), 'Текст', self) shapes.addAction(textAction) # # Добавление текста в меню # Вызов функции при нажатии textAction.triggered.connect(self.writeText) # Создание кнопки для треугольник triangleAction = QAction(QIcon('icons/triangle.png'), 'Треугольник', self) shapes.addAction(triangleAction) # Вызов функции при нажатии triangleAction.triggered.connect(self.triangle) # Функция нажатия кнопки мыши def mousePressEvent(self, event, cord=False): if event.button() == Qt.LeftButton: # Если нажата левая кнопка self.drawing = True # То переменная рисования True self.lastPoint = event.pos() # Координаты послдней точки def mouseMoveEvent(self, event): # Функция перемещения мышки # Изменение координаты в QLabel self.coords.setText("Координаты:{}, {}".format(event.x(), event.y())) # Если нажата левая кнопка и переменная рисования if event.buttons() and Qt.LeftButton and self.drawing: painter = QPainter(self.image) # Создание объекта QPainter # Цвет и свойства painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPoint, event.pos()) # Рисование линии self.lastPoint = event.pos() # Изменение последней координаты self.update() # Обновление окна def mouseReleaseEvent(self, event): # Функция отжатия кнопки self.lastImage() self.drawing = False # переменна рисования False def paintEvent(self, event): # Функция рисовая canvasPainter = QPainter(self) # Создание объекта # Рисование линии canvasPainter.drawImage(self.rect(), self.image, self.image.rect()) def save(self): # Функция сохранения # Сохранение пути files = 'PNG(*.png);;JPEG(*.jpg *jpeg);; ALL Files(*.*)' filePath, _ = QFileDialog.getSaveFileName(self, 'Сохранить изображение', '', files) if not filePath: # Проверка на пустоту пути return self.image.save(filePath) # Сохранение def clear(self): # Функция очистки self.image.fill(Qt.white) # Заливка изображения белым self.update() # Обновление изображения def px3(self): # Функция изменения размера self.brushSize = 3 def px5(self): # Функция изменения размера self.brushSize = 5 def px7(self): # Функция изменения размера self.brushSize = 7 def px9(self): # Функция изменения размера self.brushSize = 9 def pxOther(self): # Функция изменения размера i, okBtnPressed = QInputDialog.getInt(self, "Толщина", "Толщина линии", 2, 1, 80, 1) self.brushSize = i def blackColor(self): # Функция изменения цвета self.brushColor = Qt.black def whiteColor(self): # Функция изменения цвета self.brushColor = Qt.white def redColor(self): # Функция изменения цвета self.brushColor = Qt.red def greenColor(self): # Функция изменения цвета self.brushColor = Qt.green def yellowColor(self): # Функция изменения цвета self.brushColor = Qt.yellow def otherColor(self): # Функция изменения цвета self.brushColor = QColorDialog.getColor() # Функция получения координат от пользователя def get_cord(self, title, qustion, _min, _max): cord, okBtnPressed = QInputDialog.getInt(self, title, qustion, 0, _min, _max, 1) return cord # Функция для создания прямоугольника def rectangle(self): # Координата левого верхнего угла по x leftX = self.get_cord("Координата x", "Координата левого верхнего угла по x", 0, 1200) # Координата левого верхнего угла по y leftY = self.get_cord("Координата y", "Координата левого верхнего угла по y", 0, 2000) width = self.get_cord("Длина", "Длина", 0, 2000) # Длина height = self.get_cord("Высота", "Высота", 0, 2000) # высота cP = QPainter(self.image) # Создание объекта класса QPainter cP.setPen(self.brushColor) # Цвет границ cP.setBrush(self.brushColor) # Цвет фигуры cP.drawRect(leftX, leftY, width, height) # Нанесение прямоугольника self.lastImage() self.update() # Обновление рисунка def ellips(self): # Функция создания эллипса x = self.get_cord('Координата x', 'Координата центра по x', 0, 2000) # Координата центра по x y = self.get_cord('Координата по y', 'Координата центра по y', 0, 2000) # Координата центра по y w = self.get_cord("Ширина", "Ширина", 0, 2000) # ширина h = self.get_cord("Высота", "Высота", 0, 2000) # высота cP = QPainter(self.image) # Создание объекта класса QPainter cP.setPen(self.brushColor) # Цвет границ cP.setBrush(self.brushColor) # Цвет фигуры cP.drawEllipse(x, y, w, h) # Рисование эллипса self.lastImage() # Добавление изображения self.update() # обновление рисунка def addPicture(self): # Выбор разрешений files = 'PNG(*.png);;JPEG(*.jpg *jpeg);; ALL Files(*.*)' # Выбор файла filePath, _ = QFileDialog.getOpenFileName(self, 'Выбрать', '', files) img = QImage(filePath) # Открытие изображения painter = QPainter(self.image) # Создание объекта x = self.get_cord('Координата x', 'Координата левого верхнего угла по x', 0, 2000) # Координата левого верхнего угла по x y = self.get_cord('Координата по y', 'Координата левого верхнего угла по y', 0, 2000) # Координата левого верхнего угла по y painter.drawImage(x, y, img) # Вывод изображения self.lastImage() # Добавление изображения self.update() # Обновление окна def line(self): x1 = self.get_cord('Координата x', 'Координата первой точки по x', 0, 2000) # Координата первой точки по x y1 = self.get_cord('Координата по y', 'Координата первой точки по y', 0, 2000) # Координата первой точки по y x2 = self.get_cord('Координата x', 'Координата второй точки по x', 0, 2000) # Координата второй точки по x y2 = self.get_cord('Координата по y', 'Координата второй точки по y', 0, 2000) # Координата второй точки по y cP = QPainter(self.image) cP.setPen(QPen(self.brushColor, self.brushSize)) # Цвет границ cP.setBrush(self.brushColor) # Цвет фигуры cP.drawLine(x1, y1, x2, y2) # Рисование линии self.lastImage() # Добавление изображения self.update() # Обновление окна def star(self): x1 = self.get_cord('Координата x', 'Координата верхней точки по x', 0, 2000) # Координата верхней точки по x y1 = self.get_cord('Координата по y', 'Координата верхней точки по y', 0, 2000) # Координата верхней точки по y x2 = self.get_cord('Координата x', 'Координата левой точки по x', 0, 2000) # Координата левой точки по x y2 = self.get_cord('Координата по y', 'Координата левой точки по y', 0, 2000) # Координата левой точки по y x3 = self.get_cord('Координата x', 'Координата левой нижней точки по x', 0, 2000) # Координата левой нижней точки по x y3 = self.get_cord('Координата по y', 'Координата левой нижней точки по y', 0, 2000) # Координата левой нижней точки по y cP = QPainter(self.image) cP.setPen(self.brushColor) # Цвет границ cP.setBrush(self.brushColor) # Цвет фигуры points = QPolygon([ QPoint(x2, y2), QPoint(x1 + x1 - x2, y2), QPoint(x3, y3), QPoint(x1, y1), QPoint(x1 + x1 - x3, y3) ]) self.lastImage() # Добавление изображения cP.drawPolygon(points) # Нарисовать полигон def triangle(self): # Функция для рисования треугольника x1 = self.get_cord('Координата x', 'Координата первой точки по x', 0, 2000) # Координата первой точки по x y1 = self.get_cord('Координата по y', 'Координата первой точки по y', 0, 2000) # Координата первой точки по y x2 = self.get_cord('Координата x', 'Координата второй точки по x', 0, 2000) # Координата второй точки по x y2 = self.get_cord('Координата по y', 'Координата второй точки по y', 0, 2000) # Координата второй точки по y x3 = self.get_cord('Координата x', 'Координата третьей точки по x', 0, 2000) # Координата третьей нижней точки по x y3 = self.get_cord('Координата по y', 'Координата третьей точки по y', 0, 2000) # Координата третьей нижней точки по y cP = QPainter(self.image) cP.setPen(self.brushColor) # Цвет границ cP.setBrush(self.brushColor) # Цвет фигуры points = QPolygon([QPoint(x1, y1), QPoint(x2, y2), QPoint(x3, y3)]) self.lastImage() # Добавление изображения cP.drawPolygon(points) # Нарисовать полигон def copyArea(self): # Функция копирования области x = self.get_cord('Координата x', 'Координата левого верхнего угла по x', 0, 2000) # Координата левого верхнего угла по x y = self.get_cord('Координата по y', 'Координата левого верхнего угла по y', 0, 2000) # Координата левого верхнего угла по y w = self.get_cord("Ширина", "Ширина", 0, 2000) # ширина h = self.get_cord("Высота", "Высота", 0, 2000) # высота self.copyA = QImage.copy(self.image, x, y, w, h) def writeText(self): # Функция для вывода текста i, okBtnPressed = QInputDialog.getText( self, "Текст", "Введите текст") # Диалоговое окно для ввода текста cP = QPainter(self.image) cP.setPen(self.brushColor) cP.setFont(QFont('Decorative', self.get_cord('Шрифт', 'Шрифт', 1, 150))) # Шрифт cP.drawText( self.get_cord('Координата x', 'Координата левого нижнего угла по x', 0, 2000), self.get_cord('Координата y', 'Координата левого нижнего угла по y', 0, 2000), i) # Координата self.lastImage() # Добавление изображения self.update() # Обновление страницы def fillAll(self): # Функция для заливки окна self.image.fill(self.brushColor) # Заливка цветом self.lastImage() # Добавление изображения self.update() # Обновление картины def cutArea(self): # Функция для вырезания области x = self.get_cord('Координата x', 'Координата левого верхнего угла по x', 0, 2000) # Координата левого верхнего угла по x y = self.get_cord('Координата по y', 'Координата левого верхнего угла по y', 0, 2000) # Координата левого верхнего угла по y w = self.get_cord("Ширина", "Ширина", 0, 2000) # ширина h = self.get_cord("Высота", "Высота", 0, 2000) # высота self.copyA = QImage.copy(self.image, x, y, w, h) cP = QPainter(self.image) # Создание объекта класса QPainter cP.setPen(Qt.white) cP.setBrush(Qt.white) cP.drawRect(x, y, w, h) # Закраска области в белый self.update() # Обновление рисунка def pasteArea(self): # Функция вставки области if not self.copyA: # Если область пустая return x = self.get_cord('Координата x', 'Координата левого верхнего угла по x', 0, 2000) # Координата левого верхнего угла по x y = self.get_cord('Координата по y', 'Координата левого верхнего угла по y', 0, 2000) # Координата левого верхнего угла по y painter = QPainter(self.image) # Создание объекта painter.drawImage(x, y, self.copyA) # Вывод изображения self.lastImage() # Добавление изображения self.update() # Обновление окна def sizeAdd(self): # Функция изменения размера окна w = self.get_cord('Ширина окна', 'Ширина окна', 0, 2000) # Ширина окна h = self.get_cord('Высота окна', 'Высота окна', 0, 2000) # Высота окна f = open('size.txt', 'w') # Открытие файла с размерами f.write(str(w) + '\n' + str(h)) # Перезапись файла f.close() # Закрытие файла QMessageBox.about(self, "Перезапустите программу", "Перезапустите программу") # Сообщение def closeEvent(self, event): # Функция для закрытия # Сообщение при закрытии приложения reply = QMessageBox.question(self, 'Сообщение', "Вы уверены, что хотите выйти?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: # Если Да try: shutil.rmtree('last') except Exception: pass event.accept() # То выход else: event.ignore() # Иначе игнорировать def lastImage(self): # Функция добавления картинки в папку self.image.save('last/' + str(self.last) + '.png') # Сохранение self.last += 1 i = 0 while len(os.listdir('last/')) > self.last: # Если картинок больше os.remove('last/' + str(self.last + i) + '.png') i += 1 def returnLast(self): # Функция возвращения последней картинки if self.last - 1 >= 0: self.image.fill(Qt.white) # Заливки пустым self.last -= 2 painter = QPainter(self.image) # Возвращение последней картинки painter.drawImage(0, 0, QImage('last/' + str(self.last) + '.png')) self.last += 1 self.update() # Обновление картинки def returnUp(self): # Функция возвращения передней картинки if self.last != len(os.listdir('last/')): self.image.fill(Qt.white) painter = QPainter(self.image) # Возвращение передней картинки painter.drawImage(0, 0, QImage('last/' + str(self.last) + '.png')) self.last += 1 self.update() # Обновление картинки
def newImage(self, width, height): image = QImage(width, height, QImage.Format_RGB32) image.fill(Qt.white) self.setImage(image)
class QtMapViewer(QGraphicsView): """ PyQt map viewer widget. """ # Mouse button signals emit image scene (x, y) coordinates. leftMouseButtonPressed = pyqtSignal(float, float) mouseMoveLeftPressed = pyqtSignal(float, float) # custom signal viewUpdated = pyqtSignal() def __init__(self, preferred_size): QGraphicsView.__init__(self) self.setStyleSheet("color: rgb(49,51,53)") MIN_SIZE = 300 MAX_SIZE = 500 self.THUMB_SIZE = preferred_size if self.THUMB_SIZE > MAX_SIZE: self.THUMB_SIZE = MAX_SIZE if self.THUMB_SIZE < MIN_SIZE: self.THUMB_SIZE = MIN_SIZE self.BORDER_SIZE = 2 # Image is displayed as a QPixmap in a QGraphicsScene attached to this QGraphicsView. self.scene = QGraphicsScene() self.setScene(self.scene) # Store a local handle to the scene's current image pixmap. self._pxmapitem = None # Image aspect ratio mode. self.aspectRatioMode = Qt.KeepAspectRatio # Set scrollbar self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Panning is enabled if and only if the image is greater than the viewport. self.panEnabled = False # zoom is always active self.zoom_factor = 1.0 # transparency self.opacity = 1.0 self.HIGHLIGHT_RECT_WIDTH = 10 self.HIGHLIGHT_RECT_HEIGHT = 10 self.HIGHLIGHT_COLOR = QColor(200, 200, 200) self.overlay_image = QImage(self.HIGHLIGHT_RECT_WIDTH, self.HIGHLIGHT_RECT_HEIGHT, QImage.Format_ARGB32) self.overlay_image.fill(self.HIGHLIGHT_COLOR) self.setFixedWidth(self.THUMB_SIZE) self.setFixedHeight(self.THUMB_SIZE) self.pixmap = QPixmap(self.THUMB_SIZE, self.THUMB_SIZE) self.imgwidth = 0 self.imgheight = 0 def image(self): """ Returns the scene's current image as a QImage. """ if self.hasImage(): return self._pxmapitem.pixmap().toImage() return None def hasImage(self): """ Returns whether or not the scene contains an image pixmap. """ return self._pxmapitem is not None def setImage(self, image): """ Set the scene's current image (input image must be a QImage) """ if image is None: qimg = QImage(self.THUMB_SIZE, self.THUMB_SIZE, QImage.Format_ARGB32) qimg.fill(qRgba(40, 40, 40, 255)) self.pixmap = QPixmap.fromImage(qimg) self.imgwidth = self.THUMB_SIZE self.imgheight = self.THUMB_SIZE elif type(image) is QImage: imageARGB32 = image.convertToFormat(QImage.Format_ARGB32) self.pixmap = QPixmap.fromImage(imageARGB32) self.imgwidth = image.width() self.imgheight = image.height() else: raise RuntimeError("Argument must be a QImage.") if self.hasImage(): self._pxmapitem.setPixmap(self.pixmap) else: self._pxmapitem = self.scene.addPixmap(self.pixmap) # Set scene size to image size (!) self.setSceneRect(QRectF(self.pixmap.rect())) if self.imgwidth > self.imgheight: aspectratio = self.imgheight / self.imgwidth h = (int)(aspectratio * self.width()) self.setFixedHeight(h) # calculate zoom factor pixels_of_border = 10 zf1 = (self.geometry().width() - pixels_of_border) / self.imgwidth zf2 = (self.geometry().height() - pixels_of_border) / self.imgheight zf = min(zf1, zf2) if zf > 1.0: zf = 1.0 self.zoom_factor = zf self.updateViewer() def setOpacity(self, opacity): self.opacity = opacity def loadImageFromFile(self, fileName=""): """ Load an image from file. """ image = QImage(fileName) self.setImage(image) def drawOverlayImage(self, top, left, bottom, right): W = self.pixmap.width() H = self.pixmap.height() self.HIGHLIGHT_RECT_WIDTH = (right - left) * W self.HIGHLIGHT_RECT_HEIGHT = (bottom - top) * H self.HIGHLIGHT_RECT_POSX = left * W self.HIGHLIGHT_RECT_POSY = top * H self.overlay_image = QImage(self.HIGHLIGHT_RECT_WIDTH, self.HIGHLIGHT_RECT_HEIGHT, QImage.Format_ARGB32) self.overlay_image.fill(self.HIGHLIGHT_COLOR) if self.overlay_image.width() > 1: pxmap = self.pixmap.copy() p = QPainter() p.begin(pxmap) p.setOpacity(self.opacity) p.drawImage(self.HIGHLIGHT_RECT_POSX, self.HIGHLIGHT_RECT_POSY, self.overlay_image) p.end() self._pxmapitem.setPixmap(pxmap) def updateViewer(self): """ Show current zoom (if showing entire image, apply current aspect ratio mode). """ if not self.hasImage(): return self.resetTransform() self.setTransformationAnchor(self.AnchorViewCenter) self.scale(self.zoom_factor, self.zoom_factor) #self.fitInView(self.sceneRect(), self.aspectRatioMode) def clipScenePos(self, scenePosition): posx = scenePosition.x() posy = scenePosition.y() if posx < 0: posx = 0 if posy < 0: posy = 0 if posx > self.imgwidth: posx = self.imgwidth if posy > self.imgheight: posy = self.imgheight return [posx, posy] def resizeEvent(self, event): """ Maintain current zoom on resize. """ if self.imgwidth > 0 and self.imgheight > 0: pixels_of_border = 10 zf1 = (self.geometry().width() - pixels_of_border) / self.imgwidth zf2 = (self.geometry().height() - pixels_of_border) / self.imgheight zf = min(zf1, zf2) if zf > 1.0: zf = 1.0 self.zoom_factor = zf self.updateViewer() def mousePressEvent(self, event): scenePos = self.mapToScene(event.pos()) if event.button() == Qt.LeftButton: if self.panEnabled: self.setDragMode(QGraphicsView.ScrollHandDrag) clippedCoords = self.clipScenePos(scenePos) clippedCoords[0] = clippedCoords[0] / self.imgwidth clippedCoords[1] = clippedCoords[1] / self.imgheight self.leftMouseButtonPressed.emit(clippedCoords[0], clippedCoords[1]) def mouseMoveEvent(self, event): QGraphicsView.mouseMoveEvent(self, event) scenePos = self.mapToScene(event.pos()) if event.buttons() == Qt.LeftButton: clippedCoords = self.clipScenePos(scenePos) clippedCoords[0] = clippedCoords[0] / self.imgwidth clippedCoords[1] = clippedCoords[1] / self.imgheight self.mouseMoveLeftPressed.emit(clippedCoords[0], clippedCoords[1]) def mouseDoubleClickEvent(self, event): QGraphicsView.mouseDoubleClickEvent(self, event)
class Canvas(QWidget): def __init__(self, parent=None): super(Canvas, self).__init__(parent) self.myPenWidth = 2 self.myPenColor = Qt.black self.image = QImage() self.check = False self.back = deque(maxlen=10) self.next = deque(maxlen=10) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.back.append(self.resizeImage(self.image, self.image.size())) self.lastPos = event.pos() self.check = True def mouseMoveEvent(self, event): if event.buttons() and Qt.LeftButton and self.check: self.drawLine(event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.check: self.drawLine(event.pos()) self.check = False def drawLine(self, endPos): painter = QPainter(self.image) painter.setPen( QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(self.lastPos, endPos) self.update() self.lastPos = QPoint(endPos) def paintEvent(self, event): painter = QPainter(self) rect = event.rect() painter.drawImage(rect, self.image, rect) def resizeEvent(self, event): if self.image.width() < self.width() or self.image.height( ) < self.height(): changeWidth = max(self.width(), self.image.width()) changeHeight = max(self.height(), self.image.height()) self.image = self.resizeImage(self.image, QSize(changeWidth, changeHeight)) self.update() def resizeImage(self, image, newSize): changeImage = QImage(newSize, QImage.Format_RGB32) changeImage.fill(qRgb(255, 255, 255)) painter = QPainter(changeImage) painter.drawImage(QPoint(0, 0), image) return changeImage def saveImage(self, filename): if self.image.save(filename): return True else: return False def openImage(self, filename): image = QImage() if not image.load(filename): return False self.image = image self.update() return True def penColor(self): return self.myPenColor def penWidth(self): return self.myPenWidth def setPenColor(self, newColor): self.myPenColor = newColor def setPenWidth(self, newWidth): self.myPenWidth = newWidth def resetImage(self): self.image.fill(qRgb(255, 255, 255)) self.update() def backImage(self): if self.back: back_ = self.back.pop() self.next.append(back_) self.image = QImage(back_) self.update() def nextImage(self): if self.next: next_ = self.next.pop() self.back.append(next_) self.image = QImage(next_) self.update()
class DrawWindow(MainDesign): contextToolbar = None def __init__(self, pix: QPixmap = None): super().__init__() # set image from desktop screen shot self.defaultPix = pix self.saveManager = SaveManager(self) # create image self.image = QImage(350, 380, QImage.Format_RGB32) self.image.fill(Qt.white) # settings of GUI self.setupUI() self.addHandlers() # current state of programm self.state: IState = LineState(self) # history of changes and objects self.history = History.getInstance() self.objects: List[IObject] = [] self.setWindowIcon(QIcon('./Images/Logo.ico')) self.setWindowTitle('Joxi paint') def addHandlers(self): self.saveAction.triggered.connect(lambda *args: self.saveManager.save(self.image)) self.saveBufferAction.triggered.connect(lambda *args: self.saveManager.saveBuffer(self.image)) self.saveServerAction.triggered.connect(lambda *args: self.saveManager.saveServer(self.image)) self.clearAction.triggered.connect(self.clear) self.unExecuteAction.triggered.connect(self.back) self.quitAction.triggered.connect(self.quit) self.LineAction.triggered.connect(lambda x: self.setState(LineState(self))) self.RectAction.triggered.connect(lambda x: self.setState(RectState(self))) self.CircleAction.triggered.connect(lambda x: self.setState(EllipseState(self))) self.ArrowAction.triggered.connect(lambda x: self.setState(ArrowState(self))) self.PenAction.triggered.connect(lambda x: self.setState(PenState(self))) self.PencilAction.triggered.connect(lambda x: self.setState(PencilState(self))) self.ImageAction.triggered.connect(lambda x: , self.addImage()) self.TextAction.triggered.connect(lambda x: self.setState(TextState(self))) self.EditAction.triggered.connect(lambda x: self.setState(MoveState(self))) self.pasteAction.triggered.connect(self.paste) def clear(self): # clear window command = ClearCommand(self) command.execute() self.history.addCommand(command) self.repaint() def setToolbar(self, toolbar): if self.contextToolbar: #delete old toolbar self.contextToolbar.destroy() self.contextToolbar.hide() # set new toolbar self.contextToolbar = toolbar self.addToolBar(Qt.TopToolBarArea, self.contextToolbar) def back(self): self.history.removeCommand() self.repaint() def setState(self, state: IState): if not hasattr(state, 'editField'): self.setFocus(Qt.NoFocusReason) self.state = state def select(self, obj: IObject): # set edit mode self.setState(obj.getEditMode(self)) # enable actions self.deleteAction.triggered.connect(lambda *args: self.delete(obj)) self.deleteAction.setDisabled(False) self.copyAction.triggered.connect(lambda *args: self.copy(obj)) self.copyAction.setDisabled(False) def unSelect(self): # set move mode self.setState(MoveState(self)) self.repaint() # disable actions self.deleteAction.triggered.connect(lambda *args: None) self.deleteAction.setDisabled(True) self.copyAction.triggered.connect(lambda *args: None) self.copyAction.setDisabled(True) def delete(self, obj: IObject): if obj in self.objects: deleteCommand = DeleteCommand(self, obj) deleteCommand.execute() self.history.addCommand(deleteCommand) self.repaint() def copy(self, obj: IObject): cb: QClipboard = QApplication.clipboard() data: str = binascii.hexlify(dumps(obj)).decode('utf-8') cb.setText(data, mode=cb.Clipboard) def paste(self): try: data = binascii.unhexlify(QApplication.clipboard().text()) obj = loads(data) command = PasteCommand(self, obj) command.execute() self.history.addCommand(command) self.repaint() except binascii.Error: pass def addImage(self): path, f = QFileDialog.getOpenFileName() if path: imageComm = CreateImage(self, path) imageComm.execute() self.history.addCommand(imageComm) def quit(self): app.exit() def paintEvent(self, *args, **kwargs): # repaint app self.image.fill(Qt.white) if self.defaultPix: qp = QPainter(self.image) qp.drawPixmap(self.defaultPix.rect(), self.defaultPix) del qp for obj in self.objects: obj.draw(self.image) self.state.paint(self.image)