def show_image(self, pattern, use_grayscale=False, alpha=0, beta=0, gamma=0): # if not self.connected: # self.print_text_signal.emit("Impossible to show image: projector is not connected!") # return loaded_image = QImage(pattern).convertToFormat( QImage.Format.Format_RGB32) values = loaded_image.bits() pixel_values = np.array(values).reshape(loaded_image.height(), loaded_image.width(), 4) if use_grayscale: thickness = DLPColorCalibrator.my_log_function( 1, alpha, beta, gamma) tmp, corrected_values = DLPColorCalibrator.my_color_correction( pixel_values, alpha, beta, gamma, thickness) corrected_values_tr = corrected_values.copy() corrected_image = QImage(corrected_values_tr, corrected_values_tr.shape[1], corrected_values_tr.shape[0], QImage.Format_RGB32) self.img = QPixmap(corrected_image) else: self.img = QPixmap(loaded_image) if self.horizontal_mirror: self.img = self.img.transformed(QTransform().scale(-1, 1)) if self.vertical_mirror: self.img = self.img.transformed(QTransform().scale(1, -1)) self.display_image_signal.emit(self.img) self.setPixmap(self.img)
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
class Viewport(View, QOpenGLWidget): def __init__(self, scene, updateFpsDisplay, renderSettings=Rendersettings(), parent=None): View.__init__(self, scene) QOpenGLWidget.__init__(self, parent) self.renderImage = QImage() self.renderSettings = renderSettings self.updateFpsDisplay = updateFpsDisplay self.shaderProgram = QOpenGLShaderProgram() self.viewPortShaderProgram = QOpenGLShaderProgram() self.lightShaderProgram = QOpenGLShaderProgram() self.eyeLoc = QVector3D(0.0, 0.0, 5.0) self.pressLoc = QVector2D() self.isRendering = False self.viewportPlane = ViewportPlane() self.viewportTexture = None self.timer = QTimer() self.timer.setSingleShot(True) self.timer.timeout.connect(self.checkRender) self.scene.registerView(self, [ UpdateType.MATERIAL_CHANGE, UpdateType.MATERIAL_CREATE, UpdateType.MATERIAL_DELETE, UpdateType.OBJECT_CREATE, UpdateType.OBJECT_DELETE, UpdateType.OBJECT_TRANSFORM, UpdateType.CAMERA_CHANGE, UpdateType.LIGHT_CHANGE, UpdateType.SCENE_LOAD ]) self.timestamps = None self.fpsWindow = 10 self.renderer = None self.renderStartTime = None def initializeGL(self): self.glFunctions = self.context().functions() self.glFunctions.glEnable(GL.GL_DEPTH_TEST) self.glFunctions.glEnable(GL.GL_CULL_FACE) self.glFunctions.glClearColor(0.15, 0.25, 0.3, 1.0) vertSuccess = self.shaderProgram.addShaderFromSourceFile( QOpenGLShader.Vertex, "editor/ui/shaders/vertex.vert") fragSuccess = self.shaderProgram.addShaderFromSourceFile( QOpenGLShader.Fragment, "editor/ui/shaders/fragment.frag") print("Vertex shader compilation {}".format( "successful" if vertSuccess else "failed")) print("Fragment shader compilation {}".format( "successful" if fragSuccess else "failed")) print("Program linking {}".format( "successful" if self.shaderProgram.link() else "failed")) vertSuccess = self.viewPortShaderProgram.addShaderFromSourceFile( QOpenGLShader.Vertex, "editor/ui/shaders/viewportvertex.vert") fragSuccess = self.viewPortShaderProgram.addShaderFromSourceFile( QOpenGLShader.Fragment, "editor/ui/shaders/viewportfragment.frag") print("Viewport vertex shader compilation {}".format( "successful" if vertSuccess else "failed")) print("Viewport fragment shader compilation {}".format( "successful" if fragSuccess else "failed")) print("Viewport program linking {}".format( "successful" if self.viewPortShaderProgram.link() else "failed")) vertSuccess = self.lightShaderProgram.addShaderFromSourceFile( QOpenGLShader.Vertex, "editor/ui/shaders/vertex.vert") fragSuccess = self.lightShaderProgram.addShaderFromSourceFile( QOpenGLShader.Fragment, "editor/ui/shaders/lightfragment.frag") print("Light vertex shader compilation {}".format( "successful" if vertSuccess else "failed")) print("Light fragment shader compilation {}".format( "successful" if fragSuccess else "failed")) print("Light program linking {}".format( "successful" if self.viewPortShaderProgram.link() else "failed")) self.shaderProgram.release() self.viewPortShaderProgram.release() # Call all drawable Objects initGL for c in drawableClasses: if isinstance(c, ViewportPlane): c.initGL(self.viewPortShaderProgram) else: c.initGL(self.shaderProgram) def resizeGL(self, w, h): self.scene.getCamera().setAspect(w, h) if self.viewportTexture and self.context().isValid(): self.viewportTexture.destroy() if self.context().isValid(): self.renderImage = QImage(w, h, QImage.Format_RGB32) self.renderImage.fill(Qt.black) self.viewportTexture = QOpenGLTexture(QOpenGLTexture.Target2D) self.viewportTexture.setSize(w, h) self.viewportTexture.setBorderColor(0, 0, 0, 255) self.viewportTexture.setWrapMode(QOpenGLTexture.ClampToBorder) self.viewportTexture.setMinificationFilter(QOpenGLTexture.Nearest) self.viewportTexture.setMagnificationFilter(QOpenGLTexture.Nearest) self.viewportTexture.setData(self.renderImage, QOpenGLTexture.DontGenerateMipMaps) self.updateRenderResolution(w, h) def paintGL(self): self.glFunctions.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) if not self.isRendering: self.shaderProgram.bind() self.shaderProgram.setUniformValue( "eyePos", self.scene.getCamera().getTranslation()) self.shaderProgram.release() for obj in self.scene.getObjectIterator(): if isinstance(obj, Light): obj.draw(self.lightShaderProgram, self.glFunctions) else: obj.draw(self.shaderProgram, self.glFunctions) else: self.viewportTexture.bind() self.viewportPlane.draw(self.viewPortShaderProgram, self.glFunctions) self.viewportTexture.release() def mousePressEvent(self, e): self.pressLoc = QVector2D(e.localPos()) super().mousePressEvent(e) def mouseMoveEvent(self, e): if e.buttons() == Qt.LeftButton: currPos = QVector2D(e.localPos()) diff = currPos - self.pressLoc diff *= 0.5 self.pressLoc = currPos self.scene.getCamera().rotate(diff.x(), diff.y()) def wheelEvent(self, e): if e.modifiers() == Qt.ShiftModifier: self.scene.getCamera().zoom(-e.angleDelta().y() / 45.0) else: self.scene.getCamera().track(-e.angleDelta().y() / 600.0) def notify(self, updateType): if updateType == UpdateType.SCENE_LOAD: self.scene.getCamera().setAspect(self.width(), self.height()) if self.isRendering: if updateType == UpdateType.CAMERA_CHANGE: self.cameraToRenderer() elif updateType in [ UpdateType.OBJECT_TRANSFORM, UpdateType.OBJECT_CREATE, UpdateType.OBJECT_DELETE, UpdateType.MATERIAL_CREATE, UpdateType.MATERIAL_DELETE, UpdateType.MATERIAL_CHANGE, UpdateType.LIGHT_CHANGE ]: self.renderer.stop() self.renderer.clearMaterials() self.renderer.clearObjects() for mat in self.scene.getMaterialIterator(): self.materialToRenderer(mat) for obj in self.scene.getObjectIterator(): self.sceneObjectToRenderer(obj) self.cameraToRenderer() self.renderer.start() self.timestamps = [[time.time(), 0]] self.renderStartTime = time.time() self.update() def startRender(self): if self.isRendering: return self.isRendering = True self.renderer = PyRenderer(self.width(), self.height()) self.renderer.setRenderSettings(self.renderSettings) self.timestamps = [[time.time(), 0]] self.cameraToRenderer() self.update() for mat in self.scene.getMaterialIterator(): self.materialToRenderer(mat) for obj in self.scene.getObjectIterator(): self.sceneObjectToRenderer(obj) self.renderer.start() self.timer.setInterval(20) self.timer.start() self.renderStartTime = time.time() def stopRender(self): if not self.isRendering: return self.timer.stop() self.isRendering = False self.renderer = None self.resizeGL(self.width(), self.height()) self.update() self.updateFpsDisplay('') def updateRenderResolution(self, width, height): if not self.isRendering: return self.renderer.setResolution(width, height) self.timestamps = [[time.time(), 0]] def checkRender(self): if not self.isRendering: return imageArray, numIterations = self.renderer.getData( self.width(), self.height()) if numIterations < 0 or imageArray.shape != (self.height(), self.width()): self.timer.start() return if self.viewportTexture and self.context().isValid(): self.viewportTexture.destroy() if self.context().isValid(): self.renderImage = QImage(self.width(), self.height(), QImage.Format_RGB32) copyArray = np.ndarray(shape=(self.height(), self.width()), dtype=np.uint32, buffer=self.renderImage.bits()) copyArray[0:, 0:] = imageArray[0:, 0:] self.viewportTexture = QOpenGLTexture(QOpenGLTexture.Target2D) self.viewportTexture.setSize(self.width(), self.height()) self.viewportTexture.setBorderColor(0, 0, 0, 255) self.viewportTexture.setWrapMode(QOpenGLTexture.ClampToBorder) self.viewportTexture.setMinificationFilter(QOpenGLTexture.Nearest) self.viewportTexture.setMagnificationFilter(QOpenGLTexture.Nearest) self.viewportTexture.setData(self.renderImage, QOpenGLTexture.DontGenerateMipMaps) if len(self.timestamps) == self.fpsWindow: self.timestamps.pop() self.timestamps.insert(0, [time.time(), numIterations]) diffs = [(self.timestamps[i][1] - self.timestamps[i + 1][1]) / (self.timestamps[i][0] - self.timestamps[i + 1][0]) for i in range(len(self.timestamps) - 1)] secs = int(time.time() - self.renderStartTime) self.updateFpsDisplay( '{: 4.1f} iterations/sec {:02.0f}:{:02.0f} min {:7d} iterations {:4d} x {:4d} pixel' .format( sum(diffs) / len(diffs), secs // 60, secs % 60, numIterations, self.width(), self.height())) self.update() self.timer.start() def closeViewport(self): self.stopRender() if self.viewportTexture and self.context().isValid(): self.viewportTexture.destroy() def cameraToRenderer(self): cam = self.scene.getCamera() worldPos = cam.getTranslation() targetPos = self.scene.getFocusObject().getTranslation() self.renderer.updateCamera( [worldPos.x(), worldPos.y(), worldPos.z()], [targetPos.x(), targetPos.y(), targetPos.z()], cam.fovY, cam.fStop, cam.focusDistance, cam.stratificationLevel) def sceneObjectToRenderer(self, sceneObject): objType = None materialId = None lightIntensity = 0.0 lightColor = [0.0, 0.0, 0.0] isVisible = True if isinstance(sceneObject, Camera): objType = SceneObjectType.CAMERA materialId = -1 if isinstance(sceneObject, Sphere): objType = SceneObjectType.SPHERE materialId = sceneObject.material.id if isinstance(sceneObject, Cube): objType = SceneObjectType.CUBE materialId = sceneObject.material.id if isinstance(sceneObject, Plane): objType = SceneObjectType.PLANE materialId = sceneObject.material.id if isinstance(sceneObject, Disc): objType = SceneObjectType.DISC materialId = sceneObject.material.id if isinstance(sceneObject, Light): objType = sceneObject.getEmitterShape() materialId = sceneObject.material.id lightIntensity = sceneObject.getIntensity() colVec = sceneObject.getColor() lightColor = [colVec.x(), colVec.y(), colVec.z()] isVisible = sceneObject.getVisibility() matrixArray = sceneObject.calculateModel().transposed().copyDataTo() self.renderer.addObject(sceneObject.id, materialId, objType, matrixArray, lightIntensity, lightColor, sceneObject.area(), isVisible) def materialToRenderer(self, material): if type(material) == DiffuseMaterial: col = material.getEditorColor() self.renderer.addDiffuseMaterial( material.id, [col.x(), col.y(), col.z()]) if type(material) == SpecularMaterial: reflectionColor = material.getReflectionColor() transmissionColor = material.getTransmissionColor() self.renderer.addSpecularMaterial(material.id, [ reflectionColor.x(), reflectionColor.y(), reflectionColor.z() ], [ transmissionColor.x(), transmissionColor.y(), transmissionColor.z() ], material.getIOR()) def setRenderSettings(self, renderSettings): self.renderSettings = renderSettings if self.isRendering: self.renderer.setRenderSettings(self.renderSettings) def getRenderSettings(self): return self.renderSettings def saveImage(self): if not self.isRendering: return saveImage = self.renderImage.mirrored(horizontal=True) fileTuple = QFileDialog.getSaveFileName( self, 'Save destination', dir="./images", filter='Images (*.png *.jpg);;All files (*)') if fileTuple[0]: filename = fileTuple[0] if '.' not in filename: filename += '.png' saveImage.save(filename, quality=100)
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()