def getCachedDataArray(self, pMd5, binary=False): cacheObj = self.dataArrayCache[pMd5] array = cacheObj['array'] cacheTime = cacheObj['mTime'] if cacheTime != array.GetMTime(): if context.debugAll: print(' ***** ERROR: you asked for an old cache key! ***** ') if array.GetDataType() == 12: # IdType need to be converted to Uint32 arraySize = array.GetNumberOfTuples( ) * array.GetNumberOfComponents() newArray = vtkTypeUInt32Array() newArray.SetNumberOfTuples(arraySize) for i in range(arraySize): newArray.SetValue( i, -1 if array.GetValue(i) < 0 else array.GetValue(i)) pBuffer = buffer(newArray) else: pBuffer = buffer(array) if binary: # Convert the vtkUnsignedCharArray into a bytes object, required by Autobahn websockets return pBuffer.tobytes() return base64Encode(pBuffer)
def writeLightArray(self, path, source): rep = simple.Show(source, self.view) rep.Representation = 'Surface' rep.DiffuseColor = [1, 1, 1] simple.ColorBy(rep, ('POINTS', None)) # Grab data tmpFileName = path + '__.png' self.view.LockBounds = 1 simple.SaveScreenshot(tmpFileName, self.view) 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 = vtkUnsignedCharArray() rawArray.SetNumberOfTuples(arraySize) for idx in range(arraySize): light = rgbArray.GetTuple3(idx)[0] rawArray.SetTuple1(idx, light) with open(path, 'wb') as f: f.write(buffer(rawArray)) # Delete temporary file if self.cleanAfterMe: os.remove(tmpFileName) simple.Hide(source, self.view)
def writeData(self): self.resamplerFilter.Update() arrays = self.resamplerFilter.GetOutput().GetPointData() for field in self.fieldsToWrite: array = arrays.GetArray(field) if array: b = buffer(array) with open(self.dataHandler.getDataAbsoluteFilePath(field), 'wb') as f: f.write(b) self.DataProber['types'][field] = getJSArrayType(array) if field in self.DataProber['ranges']: dataRange = array.GetRange() if dataRange[0] < self.DataProber['ranges'][field][0]: self.DataProber['ranges'][field][0] = dataRange[0] if dataRange[1] > self.DataProber['ranges'][field][1]: self.DataProber['ranges'][field][1] = dataRange[1] else: self.DataProber['ranges'][field] = [ array.GetRange()[0], array.GetRange()[1] ] else: print('No array for', field) print(self.resamplerFilter.GetOutput())
def getCachedDataArray(self, pMd5): cacheObj = self.dataArrayCache[pMd5] array = cacheObj['array'] cacheTime = cacheObj['mTime'] if cacheTime != array.GetMTime(): if context.debugAll: print(' ***** ERROR: you asked for an old cache key! ***** ') if array.GetDataType() == 12: # IdType need to be converted to Uint32 arraySize = array.GetNumberOfTuples( ) * array.GetNumberOfComponents() newArray = vtkTypeUInt32Array() newArray.SetNumberOfTuples(arraySize) for i in range(arraySize): newArray.SetValue( i, -1 if array.GetValue(i) < 0 else array.GetValue(i)) pBuffer = buffer(newArray) else: pBuffer = buffer(array) return base64Encode(pBuffer)
def getCachedDataArray(self, pMd5, binary = False): cacheObj = self.dataArrayCache[pMd5] array = cacheObj['array'] cacheTime = cacheObj['mTime'] if cacheTime != array.GetMTime(): if context.debugAll: print(' ***** ERROR: you asked for an old cache key! ***** ') if array.GetDataType() == 12: # IdType need to be converted to Uint32 arraySize = array.GetNumberOfTuples() * array.GetNumberOfComponents() newArray = vtkTypeUInt32Array() newArray.SetNumberOfTuples(arraySize) for i in range(arraySize): newArray.SetValue(i, -1 if array.GetValue(i) < 0 else array.GetValue(i)) pBuffer = buffer(newArray) else: pBuffer = buffer(array) if binary: # Convert the vtkUnsignedCharArray into a bytes object, required by Autobahn websockets return pBuffer.tobytes() return base64Encode(pBuffer)
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
def writeData(self): self.resamplerFilter.Update() arrays = self.resamplerFilter.GetOutput().GetPointData() for field in self.fieldsToWrite: array = arrays.GetArray(field) if array: b = buffer(array) with open(self.dataHandler.getDataAbsoluteFilePath(field), 'wb') as f: f.write(b) self.DataProber['types'][field] = getJSArrayType(array) if field in self.DataProber['ranges']: dataRange = array.GetRange() if dataRange[0] < self.DataProber['ranges'][field][0]: self.DataProber['ranges'][field][0] = dataRange[0] if dataRange[1] > self.DataProber['ranges'][field][1]: self.DataProber['ranges'][field][1] = dataRange[1] else: self.DataProber['ranges'][field] = [array.GetRange()[0], array.GetRange()[1]] else: print('No array for', field) print(self.resamplerFilter.GetOutput())
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
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 convert(self, directory): imagePaths = {} depthPaths = {} layerNames = [] for fileName in os.listdir(directory): if '_rgb' in fileName or '_depth' in fileName: fileId = fileName.split('_')[0][0] if '_rgb' in fileName: imagePaths[fileId] = os.path.join(directory, fileName) else: layerNames.append(fileId) depthPaths[fileId] = os.path.join(directory, fileName) layerNames.sort() if len(layerNames) == 0: return # Load data in Memory depthArrays = [] imageReader = vtkPNGReader() numberOfValues = self.width * self.height * len(layerNames) imageSize = self.width * self.height self.layers = len(layerNames) # Write all images as single buffer opacity = vtkUnsignedCharArray() opacity.SetNumberOfComponents(1) opacity.SetNumberOfTuples(numberOfValues) intensity = vtkUnsignedCharArray() intensity.SetNumberOfComponents(1) intensity.SetNumberOfTuples(numberOfValues) for layer in range(self.layers): imageReader.SetFileName(imagePaths[layerNames[layer]]) imageReader.Update() rgbaArray = imageReader.GetOutput().GetPointData().GetArray(0) for idx in range(imageSize): intensity.SetValue((layer * imageSize) + idx, rgbaArray.GetValue(idx*4)) opacity.SetValue((layer * imageSize) + idx, rgbaArray.GetValue(idx*4 + 3)) with open(depthPaths[layerNames[layer]], 'rb') as depthFile: depthArrays.append(depthFile.read()) # Apply pixel sorting destOrder = vtkUnsignedCharArray() destOrder.SetNumberOfComponents(1) destOrder.SetNumberOfTuples(numberOfValues) opacityOrder = vtkUnsignedCharArray() opacityOrder.SetNumberOfComponents(1) opacityOrder.SetNumberOfTuples(numberOfValues) intensityOrder = vtkUnsignedCharArray() intensityOrder.SetNumberOfComponents(1) intensityOrder.SetNumberOfTuples(numberOfValues) for pixelIdx in range(imageSize): depthStack = [] for depthArray in depthArrays: depthStack.append((depthArray[pixelIdx], len(depthStack))) depthStack.sort(key=lambda tup: tup[0]) for destLayerIdx in range(len(depthStack)): sourceLayerIdx = depthStack[destLayerIdx][1] # Copy Idx destOrder.SetValue((imageSize * destLayerIdx) + pixelIdx, sourceLayerIdx) opacityOrder.SetValue((imageSize * destLayerIdx) + pixelIdx, opacity.GetValue((imageSize * sourceLayerIdx) + pixelIdx)) intensityOrder.SetValue((imageSize * destLayerIdx) + pixelIdx, intensity.GetValue((imageSize * sourceLayerIdx) + pixelIdx)) with open(os.path.join(directory, 'alpha.uint8'), 'wb') as f: f.write(buffer(opacityOrder)) with open(os.path.join(directory, 'intensity.uint8'), 'wb') as f: f.write(buffer(intensityOrder)) with open(os.path.join(directory, 'order.uint8'), 'wb') as f: f.write(buffer(destOrder))