def create_image(data: np.ndarray, colormap, data_min=None, data_max=None, normalize=True) -> QImage: """ Create QImage from ARGB array. The ARGB must have shape (width, height, 4) and dtype=ubyte. NOTE: The order of values in the 3rd axis must be (blue, green, red, alpha). :return: """ image_data = Spectrogram.apply_bgra_lookup(data, colormap, data_min, data_max, normalize) if not image_data.flags['C_CONTIGUOUS']: logger.debug("Array was not C_CONTIGUOUS. Converting it.") image_data = np.ascontiguousarray(image_data) try: # QImage constructor needs inverted row/column order image = QImage(image_data.ctypes.data, image_data.shape[1], image_data.shape[0], QImage.Format_ARGB32) except Exception as e: logger.error("could not create image " + str(e)) return QImage() image.data = image_data return image
def readImage(self, lowcut=0.0005, highcut=0.99995): roiLbl = self.roiLbl imNum = self.imageNumber imagePath = pathlib.Path(self.odelayConfig['LocalImageDir']) dataPath = pathlib.Path(self.odelayConfig['LocalDataDir']) # Generate image file Path by combining the region of interest lable with the experiment path roiFolder = pathlib.Path('./' + roiLbl) imageFileName = pathlib.Path('./' + roiLbl + '_' + f'{imNum:00d}' + '.mat') imageFilePath = imagePath / roiFolder / imageFileName # Load Region of Interest Data. This HDF5 file should containt location of image stitch coordinates roiPath = dataPath / 'ODELAY Roi Data' / f'{roiLbl}.hdf5' roiData = fio.loadData(roiPath) background = self.experimentData['backgroundImage'] # This data should be extracted from the Experiment Index file or stage data file. pixSize = self.experimentData['pixSize'] magnification = self.experimentData['magnification'] stInd = f'{imNum-1:03d}' stitchCorners = roiData['stitchMeta'][stInd]['imPix'] anImage = opl.assembleImage(imageFilePath, pixSize, magnification, background, stitchCorners) im = anImage['Bf'] # make a histogram of the image in the bitdept that the image was recorded. imageHist = histogram1d(im.ravel(), 2**16, [0, 2**16], weights=None).astype('float') # Calculate the cumulative probability ignoring zero values cumHist = np.zeros(imageHist.shape, dtype='float') cumHist[1:] = np.cumsum(imageHist[1:]) # if you expect a lot of zero set cumProb = (cumHist - cumHist[0]) / (cumHist[2**16 - 1] - cumHist[0]) # set low and high values ot normalize image contrast. loval = np.argmax(cumProb >= lowcut) hival = np.argmax(cumProb >= highcut) scIm = (im.astype('float') - loval.astype('float')) / ( hival.astype('float') - loval.astype('float')) * 254 lim = np.iinfo('uint8') scIm = np.clip(scIm, lim.min, lim.max) # Set image data type and make sure the array is contiguous in memory. imageData = np.require(scIm, dtype='uint8', requirements='C') # Set data as a QImage. This is a greyscale image Qim = QImage(imageData.data, imageData.shape[1], imageData.shape[0], imageData.shape[1], QImage.Format_Grayscale8) Qim.data = imageData return Qim
def makeQImage(imgData, alpha=None, copy=True, transpose=True): """ Turn an ARGB array into QImage. By default, the data is copied; changes to the array will not be reflected in the image. The image will be given a 'data' attribute pointing to the array which shares its data to prevent python freeing that memory while the image is in use. ============== =================================================================== **Arguments:** imgData Array of data to convert. Must have shape (width, height, 3 or 4) and dtype=ubyte. The order of values in the 3rd axis must be (b, g, r, a). alpha If True, the QImage returned will have format ARGB32. If False, the format will be RGB32. By default, _alpha_ is True if array.shape[2] == 4. copy If True, the data is copied before converting to QImage. If False, the new QImage points directly to the data in the array. Note that the array must be contiguous for this to work (see numpy.ascontiguousarray). transpose If True (the default), the array x/y axes are transposed before creating the image. Note that Qt expects the axes to be in (height, width) order whereas pyqtgraph usually prefers the opposite. ============== =================================================================== """ ## create QImage from buffer ## If we didn't explicitly specify alpha, check the array shape. if alpha is None: alpha = (imgData.shape[2] == 4) copied = False if imgData.shape[ 2] == 3: ## need to make alpha channel (even if alpha==False; QImage requires 32 bpp) if copy is True: d2 = np.empty(imgData.shape[:2] + (4, ), dtype=imgData.dtype) d2[:, :, :3] = imgData d2[:, :, 3] = 255 imgData = d2 copied = True else: raise Exception( 'Array has only 3 channels; cannot make QImage without copying.' ) if alpha: imgFormat = QtGui.QImage.Format_ARGB32 else: imgFormat = QtGui.QImage.Format_RGB32 if transpose: imgData = imgData.transpose( (1, 0, 2)) ## QImage expects the row/column order to be opposite if not imgData.flags['C_CONTIGUOUS']: if copy is False: extra = ' (try setting transpose=False)' if transpose else '' raise Exception( 'Array is not contiguous; cannot make QImage without copying.' + extra) imgData = np.ascontiguousarray(imgData) copied = True if copy is True and copied is False: imgData = imgData.copy() img = QImage(imgData.ctypes.data, imgData.shape[1], imgData.shape[0], imgFormat) img.data = imgData return img