def convertRGBArrayToFloatArray(rgbArray, scalarRange=[0.0, 1.0]): linearSize = rgbArray.GetNumberOfTuples() outputArray = vtkFloatArray() outputArray.SetNumberOfComponents(1) outputArray.SetNumberOfTuples(linearSize) for idx in range(linearSize): outputArray.SetTuple1( idx, getScalarFromRGB(rgbArray.GetTuple(idx), scalarRange)) return outputArray
def convertImageToFloat(srcPngImage, destFile, scalarRange=[0.0, 1.0]): reader = vtkPNGReader() reader.SetFileName(srcPngImage) reader.Update() rgbArray = reader.GetOutput().GetPointData().GetArray(0) stackSize = rgbArray.GetNumberOfTuples() size = reader.GetOutput().GetDimensions() outputArray = vtkFloatArray() outputArray.SetNumberOfComponents(1) outputArray.SetNumberOfTuples(stackSize) for idx in range(stackSize): outputArray.SetTuple1( idx, getScalarFromRGB(rgbArray.GetTuple(idx), scalarRange)) # Write float file with open(destFile, 'wb') as f: f.write(buffer(outputArray)) return size
# Test to test #17793. # Ensures that field data arrays are correctly marked as partial when dealing # with composite datasets. from paraview.modules.vtkPVClientServerCoreCore import vtkPVDataInformation from paraview.vtk.vtkCommonDataModel import vtkMultiBlockDataSet, vtkPolyData from paraview.vtk.vtkCommonCore import vtkFloatArray mb = vtkMultiBlockDataSet() mb.SetBlock(0, vtkPolyData()) mb.SetBlock(1, vtkPolyData()) arr = vtkFloatArray() arr.SetNumberOfTuples(1) arr.SetName("Field1"); mb.GetFieldData().AddArray(arr) di = vtkPVDataInformation() di.CopyFromObject(mb) assert di.GetFieldDataInformation().GetArrayInformation("Field1").GetIsPartial() == 0 mb2 = vtkMultiBlockDataSet() mb2.SetBlock(0, mb) mb2.SetBlock(1, vtkPolyData()) arr = vtkFloatArray() arr.SetNumberOfTuples(1) arr.SetName("Field2"); mb2.GetFieldData().AddArray(arr) di = vtkPVDataInformation()
def processDirectory(self, directory): # Load depth depthStack = [] imageSize = self.config['size'] linearSize = imageSize[0] * imageSize[1] nbLayers = len(self.layers) stackSize = nbLayers * linearSize layerList = range(nbLayers) for layerIdx in layerList: with open(os.path.join(directory, 'depth_%d.float32' % layerIdx), "rb") as f: a = array.array('f') a.fromfile(f, linearSize) depthStack.append(a) orderArray = vtkUnsignedCharArray() orderArray.SetName('layerIdx') orderArray.SetNumberOfComponents(1) orderArray.SetNumberOfTuples(stackSize) pixelSorter = [(i, i) for i in layerList] for pixelId in range(linearSize): # Fill pixelSorter for layerIdx in layerList: if depthStack[layerIdx][pixelId] < 1.0: pixelSorter[layerIdx] = (layerIdx, depthStack[layerIdx][pixelId]) else: pixelSorter[layerIdx] = (255, 1.0) # Sort pixel layers pixelSorter.sort(key=lambda tup: tup[1]) # Fill sortedOrder array for layerIdx in layerList: orderArray.SetValue(layerIdx * linearSize + pixelId, pixelSorter[layerIdx][0]) # Write order (sorted order way) with open(os.path.join(directory, 'order.uint8'), 'wb') as f: f.write(buffer(orderArray)) self.data.append({ 'name': 'order', 'type': 'array', 'fileName': '/order.uint8' }) # Remove depth files for layerIdx in layerList: os.remove(os.path.join(directory, 'depth_%d.float32' % layerIdx)) # Encode Normals (sorted order way) if 'normal' in self.config['light']: sortedNormal = vtkUnsignedCharArray() sortedNormal.SetNumberOfComponents(3) # x,y,z sortedNormal.SetNumberOfTuples(stackSize) # Get Camera orientation and rotation information camDir = [0, 0, 0] worldUp = [0, 0, 0] with open(os.path.join(directory, "camera.json"), "r") as f: camera = json.load(f) camDir = normalize([ camera['position'][i] - camera['focalPoint'][i] for i in range(3) ]) worldUp = normalize(camera['viewUp']) # [ camRight, camUp, camDir ] will be our new orthonormal basis for normals camRight = vectProduct(camDir, worldUp) camUp = vectProduct(camRight, camDir) # Tmp structure to capture (x,y,z) normal normalByLayer = vtkFloatArray() normalByLayer.SetNumberOfComponents(3) normalByLayer.SetNumberOfTuples(stackSize) # Capture all layer normals zPosCount = 0 zNegCount = 0 for layerIdx in layerList: # Load normal(x,y,z) from current layer normalLayer = [] for comp in [0, 1, 2]: with open( os.path.join( directory, 'normal_%d_%d.float32' % (layerIdx, comp)), "rb") as f: a = array.array('f') a.fromfile(f, linearSize) normalLayer.append(a) # Store normal inside vtkArray offset = layerIdx * linearSize for idx in range(linearSize): normalByLayer.SetTuple3(idx + offset, normalLayer[0][idx], normalLayer[1][idx], normalLayer[2][idx]) # Re-orient normal to be view based vect = normalByLayer.GetTuple3(layerIdx * linearSize + idx) if not math.isnan(vect[0]): # Express normal in new basis we computed above rVect = normalize([ -dotProduct(vect, camRight), dotProduct(vect, camUp), dotProduct(vect, camDir) ]) # Need to reverse vector ? if rVect[2] < 0: normalByLayer.SetTuple3( layerIdx * linearSize + idx, -rVect[0], -rVect[1], -rVect[2]) else: normalByLayer.SetTuple3( layerIdx * linearSize + idx, rVect[0], rVect[1], rVect[2]) # Sort normals and encode them as 3 bytes ( -1 < xy < 1 | 0 < z < 1) for idx in range(stackSize): layerIdx = int(orderArray.GetValue(idx)) if layerIdx == 255: # No normal => same as view direction sortedNormal.SetTuple3(idx, 128, 128, 255) else: offset = layerIdx * linearSize imageIdx = idx % linearSize vect = normalByLayer.GetTuple3(imageIdx + offset) if not math.isnan(vect[0]) and not math.isnan( vect[1]) and not math.isnan(vect[2]): sortedNormal.SetTuple3(idx, int(127.5 * (vect[0] + 1)), int(127.5 * (vect[1] + 1)), int(255 * vect[2])) else: print('WARNING: encountered NaN in normal of layer ', layerIdx, ': [', vect[0], ',', vect[1], ',', vect[2], ']') sortedNormal.SetTuple3(idx, 128, 128, 255) # Write the sorted data with open(os.path.join(directory, 'normal.uint8'), 'wb') as f: f.write(buffer(sortedNormal)) self.data.append({ 'name': 'normal', 'type': 'array', 'fileName': '/normal.uint8', 'categories': ['normal'] }) # Remove depth files for layerIdx in layerList: os.remove( os.path.join(directory, 'normal_%d_%d.float32' % (layerIdx, 0))) os.remove( os.path.join(directory, 'normal_%d_%d.float32' % (layerIdx, 1))) os.remove( os.path.join(directory, 'normal_%d_%d.float32' % (layerIdx, 2))) # Encode Intensity (sorted order way) if 'intensity' in self.config['light']: sortedIntensity = vtkUnsignedCharArray() sortedIntensity.SetNumberOfTuples(stackSize) intensityLayers = [] for layerIdx in layerList: with open( os.path.join(directory, 'intensity_%d.uint8' % layerIdx), "rb") as f: a = array.array('B') a.fromfile(f, linearSize) intensityLayers.append(a) for idx in range(stackSize): layerIdx = int(orderArray.GetValue(idx)) if layerIdx == 255: sortedIntensity.SetValue(idx, 255) else: imageIdx = idx % linearSize sortedIntensity.SetValue( idx, intensityLayers[layerIdx][imageIdx]) with open(os.path.join(directory, 'intensity.uint8'), 'wb') as f: f.write(buffer(sortedIntensity)) self.data.append({ 'name': 'intensity', 'type': 'array', 'fileName': '/intensity.uint8', 'categories': ['intensity'] }) # Remove depth files for layerIdx in layerList: os.remove( os.path.join(directory, 'intensity_%d.uint8' % layerIdx))
def processDirectory(self, directory): self.imageReader.SetFileName(os.path.join(directory, 'rgb.png')) self.imageReader.Update() rgbArray = self.imageReader.GetOutput().GetPointData().GetArray(0) self.composite.load(os.path.join(directory, 'composite.json')) orderArray = self.composite.getSortedOrderArray() imageSize = self.composite.getImageSize() stackSize = self.composite.getStackSize() # Write order (sorted order way) with open(os.path.join(directory, 'order.uint8'), 'wb') as f: f.write(buffer(orderArray)) self.data.append({ 'name': 'order', 'type': 'array', 'fileName': '/order.uint8' }) # Encode Normals (sorted order way) if 'normal' in self.layers[0]: sortedNormal = vtkUnsignedCharArray() sortedNormal.SetNumberOfComponents(3) # x,y,z sortedNormal.SetNumberOfTuples(stackSize) # Get Camera orientation and rotation information camDir = [0, 0, 0] worldUp = [0, 0, 0] with open(os.path.join(directory, "camera.json"), "r") as f: camera = json.load(f) camDir = normalize([ camera['position'][i] - camera['focalPoint'][i] for i in range(3) ]) worldUp = normalize(camera['viewUp']) # [ camRight, camUp, camDir ] will be our new orthonormal basis for normals camRight = vectProduct(camDir, worldUp) camUp = vectProduct(camRight, camDir) # Tmp structure to capture (x,y,z) normal normalByLayer = vtkFloatArray() normalByLayer.SetNumberOfComponents(3) normalByLayer.SetNumberOfTuples(stackSize) # Capture all layer normals layerIdx = 0 zPosCount = 0 zNegCount = 0 for layer in self.layers: normalOffset = layer['normal'] for idx in range(imageSize): normalByLayer.SetTuple3( layerIdx * imageSize + idx, getScalarFromRGB( rgbArray.GetTuple(idx + normalOffset[0] * imageSize)), getScalarFromRGB( rgbArray.GetTuple(idx + normalOffset[1] * imageSize)), getScalarFromRGB( rgbArray.GetTuple(idx + normalOffset[2] * imageSize))) # Re-orient normal to be view based vect = normalByLayer.GetTuple3(layerIdx * imageSize + idx) if not math.isnan(vect[0]): # Express normal in new basis we computed above rVect = normalize([ -dotProduct(vect, camRight), dotProduct(vect, camUp), dotProduct(vect, camDir) ]) # Need to reverse vector ? if rVect[2] < 0: normalByLayer.SetTuple3(layerIdx * imageSize + idx, -rVect[0], -rVect[1], -rVect[2]) else: normalByLayer.SetTuple3(layerIdx * imageSize + idx, rVect[0], rVect[1], rVect[2]) layerIdx += 1 # Sort normals and encode them as 3 bytes ( -1 < xy < 1 | 0 < z < 1) for idx in range(stackSize): layerIdx = int(orderArray.GetValue(idx)) if layerIdx == 255: # No normal => same as view direction sortedNormal.SetTuple3(idx, 128, 128, 255) else: offset = layerIdx * imageSize imageIdx = idx % imageSize vect = normalByLayer.GetTuple3(imageIdx + offset) if not math.isnan(vect[0]) and not math.isnan( vect[1]) and not math.isnan(vect[2]): sortedNormal.SetTuple3(idx, int(127.5 * (vect[0] + 1)), int(127.5 * (vect[1] + 1)), int(255 * vect[2])) else: print('WARNING: encountered NaN in normal of layer ', layerIdx, ': [', vect[0], ',', vect[1], ',', vect[2], ']') sortedNormal.SetTuple3(idx, 128, 128, 255) # Write the sorted data with open(os.path.join(directory, 'normal.uint8'), 'wb') as f: f.write(buffer(sortedNormal)) self.data.append({ 'name': 'normal', 'type': 'array', 'fileName': '/normal.uint8', 'categories': ['normal'] }) # Encode Intensity (sorted order way) if 'intensity' in self.layers[0]: intensityOffsets = [] sortedIntensity = vtkUnsignedCharArray() sortedIntensity.SetNumberOfTuples(stackSize) for layer in self.layers: intensityOffsets.append(layer['intensity']) for idx in range(stackSize): layerIdx = int(orderArray.GetValue(idx)) if layerIdx == 255: sortedIntensity.SetValue(idx, 255) else: offset = 3 * intensityOffsets[layerIdx] * imageSize imageIdx = idx % imageSize sortedIntensity.SetValue( idx, rgbArray.GetValue(imageIdx * 3 + offset)) with open(os.path.join(directory, 'intensity.uint8'), 'wb') as f: f.write(buffer(sortedIntensity)) self.data.append({ 'name': 'intensity', 'type': 'array', 'fileName': '/intensity.uint8', 'categories': ['intensity'] }) # Encode Each layer Scalar layerIdx = 0 for layer in self.layers: for scalar in layer: if scalar not in ['intensity', 'normal']: offset = imageSize * layer[scalar] scalarRange = self.config['scene'][layerIdx]['colors'][ scalar]['range'] delta = (scalarRange[1] - scalarRange[0] ) / 16777215.0 # 2^24 - 1 => 16,777,215 scalarArray = vtkFloatArray() scalarArray.SetNumberOfTuples(imageSize) for idx in range(imageSize): rgb = rgbArray.GetTuple(idx + offset) if rgb[0] != 0 or rgb[1] != 0 or rgb[2] != 0: # Decode encoded value value = scalarRange[0] + delta * float( rgb[0] * 65536 + rgb[1] * 256 + rgb[2] - 1) scalarArray.SetValue(idx, value) else: # No value scalarArray.SetValue(idx, float('NaN')) with open( os.path.join(directory, '%d_%s.float32' % (layerIdx, scalar)), 'wb') as f: f.write(buffer(scalarArray)) self.data.append({ 'name': '%d_%s' % (layerIdx, scalar), 'type': 'array', 'fileName': '/%d_%s.float32' % (layerIdx, scalar), 'categories': ['%d_%s' % (layerIdx, scalar)] }) layerIdx += 1
def writeArray(self, path, source, name, component=0): rep = simple.Show(source, self.view) rep.Representation = 'Surface' rep.DiffuseColor = [1, 1, 1] dataRange = [0.0, 1.0] fieldToColorBy = ['POINTS', name] self.view.ArrayNameToDraw = name self.view.ArrayComponentToDraw = component pdi = source.GetPointDataInformation() cdi = source.GetCellDataInformation() if pdi.GetArray(name): self.view.DrawCells = 0 dataRange = pdi.GetArray(name).GetRange(component) fieldToColorBy[0] = 'POINTS' elif cdi.GetArray(name): self.view.DrawCells = 1 dataRange = cdi.GetArray(name).GetRange(component) fieldToColorBy[0] = 'CELLS' else: print("No array with that name", name) return realRange = dataRange if dataRange[0] == dataRange[1]: dataRange = [dataRange[0] - 0.1, dataRange[1] + 0.1] simple.ColorBy(rep, fieldToColorBy) # Grab data tmpFileName = path + '__.png' self.view.ScalarRange = dataRange self.view.LockBounds = 1 self.view.StartCaptureValues() simple.SaveScreenshot(tmpFileName, self.view) self.view.StopCaptureValues() self.view.LockBounds = 0 if self.canWrite: # Convert data self.reader.SetFileName(tmpFileName) self.reader.Update() rgbArray = self.reader.GetOutput().GetPointData().GetArray(0) arraySize = rgbArray.GetNumberOfTuples() rawArray = vtkFloatArray() rawArray.SetNumberOfTuples(arraySize) minValue = 10000.0 maxValue = -100000.0 delta = (dataRange[1] - dataRange[0]) / 16777215.0 # 2^24 - 1 => 16,777,215 for idx in range(arraySize): rgb = rgbArray.GetTuple3(idx) if rgb[0] != 0 or rgb[1] != 0 or rgb[2] != 0: value = dataRange[0] + delta * float( rgb[0] * 65536 + rgb[1] * 256 + rgb[2] - 1) rawArray.SetTuple1(idx, value) minValue = min(value, minValue) maxValue = max(value, maxValue) else: rawArray.SetTuple1(idx, float('NaN')) # print ('Array bounds', minValue, maxValue, 'compare to', dataRange) with open(path, 'wb') as f: f.write(buffer(rawArray)) # Delete temporary file if self.cleanAfterMe: os.remove(tmpFileName) # Remove representation from view simple.Hide(source, self.view) return realRange