def ndarrayToQImage(ndimg, format=QImage.Format_ARGB32): """ Converts a 3D numpy ndarray to a QImage. No sanity check is done regarding the compatibility of the ndarray shape with the QImage format. @param ndimg: The ndarray to be converted @type ndimg: ndarray @param format: The QImage format (default ARGB32) @type format: @return: The converted image @rtype: QImage """ if ndimg.ndim != 3 or ndimg.dtype != 'uint8': raise ValueError( "ndarray2QImage : array must be 3D with dtype=uint8, found ndim=%d, dtype=%s" % (ndimg.ndim, ndimg.dtype)) bytePerLine = ndimg.shape[1] * ndimg.shape[2] if len(np.ravel(ndimg).data) != ndimg.shape[0] * bytePerLine: raise ValueError("ndarrayToQImage : conversion error") # build QImage from buffer qimg = QImage(ndimg.data, ndimg.shape[1], ndimg.shape[0], bytePerLine, format) # keep a ref. to buffer to protect it from garbage collector qimg.buf_ = ndimg.data if qimg.format() == QImage.Format_Invalid: raise ValueError("ndarrayToQImage : wrong conversion") return qimg
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()
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 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
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()