def qimage_to_numpy(self, image: QImage) -> Image: image = image.convertToFormat(QImage.Format.Format_RGB32) width = image.width() height = image.height() ptr = image.constBits() arr = np.array(ptr).reshape((height, width, 4))[:, :, :3] return arr
def to_qimage(array): """Convert NumPy array to QImage object Args: arr: A numpy array Returns: An QImage object. """ if array is None: raise ValueError("The argument 'arr' can not be 'None'.") if len(array.shape) not in (2, 3): raise TypeError("Unsupported image format.") shape = array.shape[:2][::-1] stride = array.strides[0] cdim = 0 if len(array.shape) != 3 else array.shape[2] formats = { 0: QImage.Format_Grayscale8, 3: QImage.Format_RGB888, 4: QImage.Format_RGBA8888 } if cdim not in formats: raise TypeError("Unsupported image format.") qimage = QImage(array.data, *shape, stride, formats[cdim]) return qimage.convertToFormat(QImage.Format_RGBA8888)
def readImage(self, filename, sbimage): image = QImage() if (image.load(filename.getString())): # Keep in 8-bits mode if that was what we read if (image.depth() == 8 and image.isGrayscale()): c = 1 else: # FIXME: consider if we should detect allGrayscale() and alpha (c = 2) c = 3 if image.hasAlphaChannel(): c = 4 image.convertToFormat(QImage.Format_ARGB32) else: image.convertToFormat(QImage.Format_RGB32) # FIXME 20080508 jkg: implement when pivy is ready #sbimage.setValue(SbVec2s(image.width(), image.height()), c, None) return True return False
def QImageToCV(image: QImage) -> ndarray: if image.format() != QImage.Format_RGB888: image = image.convertToFormat(QImage.Format_RGB888) width = image.width() height = image.height() ptr = image.bits() arr = array(ptr).reshape(height, width, 3) return arr
def __init__(self, name, baseSize, contourPath, presetFilename=None, image=None): """ @param name: @type name: str @param baseSize: @type baseSize: int @param contourPath: base shape of the brush family @type contourPath: QPainterPath @param presetFilename: preset file @type presetFilename: str """ self.name = name self.baseSize = baseSize # init the brush pixmap self.basePixmap = QPixmap(self.baseSize, self.baseSize) # to get an alpha channel, we must fill the pixmap a first time with an opacity < 255 self.basePixmap.fill(QColor(0, 0, 0, 0)) if self.name == 'eraser': self.basePixmap.fill(QColor(0, 0, 0, 255)) self.contourPath = contourPath # init brush cursor self.baseCursor = QPixmap(self.baseSize, self.baseSize) self.baseCursor.fill(QColor(0, 0, 0, 0)) qp = QPainter(self.baseCursor) pen = qp.pen() pen.setWidth(self.baseSize / 20) qp.setPen(pen) # needed!! qp.drawPath(contourPath) qp.end() self.__pxmp = None self.bOpacity = 1.0 self.bFlow = 1.0 self.bHardness = 1.0 self.preset = None if presetFilename is not None: img = QImage(presetFilename) elif image is not None: img = image else: return img = img.convertToFormat(QImage.Format_ARGB32) buf = QImageBuffer(img) b = np.sum(buf[..., :3], axis=-1, dtype=np.float) b /= 3 buf[..., 3] = b self.preset = QPixmap.fromImage(img)
def qimg_to_rgb_arr(qimg: QImage) -> RGBArrayF: """Convert a :class:`QtGui.QImage` to an :data:`RGBArrayF` """ fmt = QImage.Format_RGB32 if qimg.format() != fmt: qimg = qimg.convertToFormat(fmt) width, height = qimg.width(), qimg.height() num_pixels = width * height bfr = qimg.constBits() int_arr = np.frombuffer(bfr, dtype=np.uint8, count=num_pixels * 4) bgra_arr = int_arr.reshape((height, width, 4)) / 255 # Format_RGB32 stored as 0xffRRGGBB # so take only the first 3 items but in reverse rgb_arr = bgra_arr[..., 2::-1] return rgb_arr
class Scribble(QWidget): def __init__(self, parent=None, scribbleImagePath=""): QWidget.__init__(self, parent) self.show() self.raise_() # Available space to display on self.imageAreaWidth = 0 self.imageAreaHeight = 0 # Real number of pixels (unscaled) self.scribbleWidth = 1 self.scribbleHeight = 1 # Scaling factor between the real image size and the size after scaling to fit the imageArea self.scaleFactor = 1.0 self.scribbling = False # if scribbling at this time and moment self.penMoved = False # if the pen already moved while scribbling self.myPenWidth = 1 self.myPenColor = QColor(0, 0, 255, 255) self.lastPoint = None self.scribbleImagePath = scribbleImagePath self.image = None def refreshScribble(self, width, height): self.imageAreaWidth = width self.imageAreaHeight = height self.setGeometry(0, 0, self.imageAreaWidth, self.imageAreaHeight) def setColor(self, color): # QColor object self.myPenColor = color def setPenSize(self, size): self.myPenWidth = size def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastPoint = event.pos() self.scribbling = True self.penMoved = False def mouseMoveEvent(self, event): if self.scribbling: self.drawLineTo(event.pos()) self.penMoved = True def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.scribbling: self.drawLineTo(event.pos()) if self.myPenColor == QColor(255, 0, 0, 255): self.drawCircle(event.pos()) self.scribbling = False self.penMoved = False def setupScribble(self, width, height): self.scribbleWidth = width self.scribbleHeight = height if self.scribbleImagePath == "": self.image = QImage(self.scribbleWidth, self.scribbleHeight, QImage.Format_ARGB32) # print(self.image.depth()) # prints 32 self.image.fill(qRgba(0, 0, 0, 0)) else: self.image = QImage(self.scribbleImagePath) self.image = self.image.convertToFormat(QImage.Format_ARGB32) self.update() def drawCircle(self, point): painter = QPainter(self.image) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.setRenderHint(QPainter.Antialiasing) brush = QBrush(QColor(0, 0, 255, 255), Qt.SolidPattern) pen = QPen(brush, 0.2 * self.myPenWidth / self.scaleFactor, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) painter.setPen(pen) radius = 1.5 * self.myPenWidth / self.scaleFactor rectangle = QRectF((point.x() / self.scaleFactor) - (radius / 2), (point.y() / self.scaleFactor) - (radius / 2), radius, radius) painter.drawEllipse(rectangle) self.update() def drawLineTo(self, endPoint): if not self.penMoved: endPoint.setX( endPoint.x() + 1 ) # ensures a dot is being drawn if there was just a click and no mouse move painter = QPainter(self.image) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.setRenderHint(QPainter.Antialiasing) brush = QBrush(self.myPenColor, Qt.SolidPattern) pen = QPen(brush, self.myPenWidth / self.scaleFactor, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) # pen = QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) painter.setPen(pen) painter.drawLine(self.lastPoint / self.scaleFactor, endPoint / self.scaleFactor) self.update() self.lastPoint = endPoint def paintEvent(self, event): painter = QPainter(self) dirtyRect = event.rect() scaledImage = self.image.scaled(self.imageAreaWidth, self.imageAreaHeight, Qt.KeepAspectRatio, Qt.FastTransformation) self.scaleFactor = float(scaledImage.width()) / float( self.scribbleWidth) painter.drawImage(dirtyRect, scaledImage, dirtyRect)
def redoIt(self): maya_cmds.undoInfo(stateWithoutFlush=False) try: image = QImage(self.image) if image.format() != QImage.Format_RGBA8888: image = image.convertToFormat(QImage.Format_RGBA8888) imageBits = image.bits() imageWidth = image.width() imageHeight = image.height() imageWidthM = imageWidth - 1 imageHeightM = imageHeight - 1 mFnMesh = OpenMaya.MFnMesh( OpenMaya.MGlobal.getSelectionListByName( self.shape).getDagPath(0)) mPoints = mFnMesh.getPoints(OpenMaya.MSpace.kWorld) self.mPoints = OpenMaya.MPointArray(mPoints) tmp1, uvIdsFace = mFnMesh.getAssignedUVs(self.uvName) tmp2, vertexIdsFace = mFnMesh.getVertices() u, v = mFnMesh.getUVs(self.uvName) uvs = [0] * len(u) for i in xrange(len(uvIdsFace)): uvIdFace = uvIdsFace[i] uvs[vertexIdsFace[i]] = [u[uvIdFace], v[uvIdFace]] if self.matrixIs.X: diffX = self.matrixMax.X - self.matrixMin.X for i in xrange(len(mPoints)): u = int((uvs[i][0] % 1.0) * imageWidthM) v = int((uvs[i][1] % 1.0) * imageHeightM) mPoints[i].x += ((ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.X]) * diffX) / 255.0) + self.matrixMin.X if self.matrixIs.Y: diffY = self.matrixMax.Y - self.matrixMin.Y for i in xrange(len(mPoints)): u = int((uvs[i][0] % 1.0) * imageWidthM) v = int((uvs[i][1] % 1.0) * imageHeightM) mPoints[i].y += ((ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.Y]) * diffY) / 255.0) + self.matrixMin.Y if self.matrixIs.Z: diffZ = self.matrixMax.Z - self.matrixMin.Z for i in xrange(len(mPoints)): u = int((uvs[i][0] % 1.0) * imageWidthM) v = int((uvs[i][1] % 1.0) * imageHeightM) mPoints[i].z += ((ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.Z]) * diffZ) / 255.0) + self.matrixMin.Z if self.matrixIs.N: diffN = self.matrixMax.N - self.matrixMin.N mNormals = mFnMesh.getVertexNormals(True, OpenMaya.MSpace.kWorld) for i in xrange(len(mPoints)): u = int((uvs[i][0] % 1.0) * imageWidthM) v = int((uvs[i][1] % 1.0) * imageHeightM) mPoints[i].x += mNormals[i].x * (( (ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.N]) * diffN) / 255.0) + self.matrixMin.N) mPoints[i].y += mNormals[i].y * (( (ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.N]) * diffN) / 255.0) + self.matrixMin.N) mPoints[i].z += mNormals[i].z * (( (ord(imageBits[ (u + v * imageWidth) * 4 + self.matrixCha.N]) * diffN) / 255.0) + self.matrixMin.N) mFnMesh.setPoints(mPoints, OpenMaya.MSpace.kWorld) mFnMesh.updateSurface() except Exception as e: print >> stderr, str(e) maya_cmds.undoInfo(stateWithoutFlush=True)
class Map(QQuickPaintedItem): def __init__(self, parent = None): super(Map, self).__init__(parent) self.viewport = None self.setAcceptedMouseButtons(Qt.AllButtons) self.generate() clicked = Signal(QPoint) @Slot() def generate(self): # QImage does not work with bits, only with bytes self.image = QImage(300, 300, QImage.Format_Grayscale8) self.oldImage = None self.generateMap() self._percentage = 0 self._pressClick = QPoint() def pixel(self, x: int, y: int, image = None) -> bool: if not image: image = self.image # This solves: # QImage::pixelIndex: Not applicable for 8-bpp images (no palette) return image.bits()[int(x) + int(y) * image.bytesPerLine()] & 0xff def setPixel(self, x: int, y: int, value: int, image = None): if not image: image = self.image # This solves: # QImage::pixelIndex: Not applicable for 8-bpp images (no palette) image.bits()[int(x) + int(y) * image.bytesPerLine()] = value def createRandomMap(self): for i in range(self.image.byteCount()): if random.random() < 0.35: self.image.bits()[i] = 255 else: self.image.bits()[i] = 0 def countNeighbors(self, x: int, y: int, image = None, n = 1) -> int: if not image: image = self.image count = 0 for i in range(-n , n + 1): for u in range(-n , n + 1): if not i and not u: continue #TODO: pixel function is poor # need to use bits() if x + i < 0 or y + u < 0 or \ x + i >= image.width() or y + u >= image.height(): count += 1 continue if not self.pixel(x + i, y + u, image): count += 1 return count @Slot(int) def doStep(self, n = 1): if self.image.format() != QImage.Format_Grayscale8: print("Wrong file format, generate map again.") return deathLimit = 14 self._percentage = 0 for _ in range(n): _image = self.image.copy() for x in range(self.image.width()): self._percentage += 1.0/(self.image.width()*n) if x%10 == 0: # Update percentage self.percentageChanged.emit() # processEvent is necessary QEventLoop().processEvents() # Update map self.update() for y in range(self.image.height()): if self.countNeighbors(x, y, _image, 2) > deathLimit or \ x == 0 or y == 0 or x == _image.width() - 1 or y == _image.height() - 1: self.setPixel(x, y, 0) else: self.setPixel(x, y, 255) # Update percentage self.update() self.oldImage = self.image.copy() self.percentageChanged.emit() QEventLoop().processEvents() def generateMap(self): self.createRandomMap() self.update() self.oldImage = self.image.copy() def paint(self, painter): painter.drawImage(QRect(0, 0, self.width(), self.height()), self.image) self.viewport = painter.viewport() def keyPressEvent(self, event): if event.key() == Qt.Key_Space: print('Update..') start = time.time() self.doStep() print('Took: %.2fs' % (time.time() - start)) event.accept() def mousePressEvent(self, event): a, b = event.pos().x()*self.image.width()/self.width(), event.pos().y()*self.image.height()/self.height() self.clicked.emit(QPoint(a, b)) def mouseMoveEvent(self, event): a, b = event.pos().x()*self.image.width()/self.width(), event.pos().y()*self.image.height()/self.height() self.clicked.emit(QPoint(a, b)) def percentage(self): return self._percentage percentageChanged = Signal() percentage = Property(float, percentage, notify=percentageChanged) @Slot() def addVehicle(self): self.image = self.image.convertToFormat(QImage.Format_RGBA8888) painter = QPainter(self.image) painter.drawImage(QRect(50, 50, 13, 15), QImage("imgs/turtle.png")) painter.end() self.update() @Slot(str) def saveMap(self, path: str): # Check image encoder if(self.image.format() != QImage.Format_Grayscale8): print('Wrong map pixel format, create map without vehicle added.') return ok = self.image.save(path) if(not ok): print('It was not possible to save Map in:', path) @Slot(str) def loadMap(self, path: str): # Check image encoder image = QImage(path) if(image.format() != QImage.Format_Grayscale8): print('Wrong map pixel format, map should be Grayscale8.') return self.image = image self.oldImage = self.image.copy() self.update()