bool fillRegularVolumeInfo( VolumeInformation& info ) { info.worldSpacePerVoxel = 1.0f / float( info.voxels.find_max( )); info.worldSize = Vector3f( info.voxels[0], info.voxels[1], info.voxels[2] ) * info.worldSpacePerVoxel; // Create the rootNode of the LOD hierarchy const Vector3ui blockSize = info.maximumBlockSize - info.overlap * 2; const Vector3ui numBlocks( std::ceil( float( info.voxels.x( )) / blockSize.x( )), std::ceil( float( info.voxels.y( )) / blockSize.y( )), std::ceil( float( info.voxels.z( )) / blockSize.z( )) ); const Vector3ui lodLevels( std::ceil( std::log2( numBlocks.x( ))), std::ceil( std::log2( numBlocks.y( ))), std::ceil( std::log2( numBlocks.z( ))) ); const uint32_t depth = lodLevels.find_min(); const Vector3ui rootNodeBlocksCount( std::ceil( float( info.voxels.x() >> depth ) / blockSize.x( )), std::ceil( float( info.voxels.y() >> depth ) / blockSize.y( )), std::ceil( float( info.voxels.z() >> depth ) / blockSize.z( )) ); info.rootNode = RootNode( depth + 1, rootNodeBlocksCount ); return true; }
void SeededRegionGrowing::executeOnHost(T* input, Image::pointer output) { ImageAccess::pointer outputAccess = output->getImageAccess(ACCESS_READ_WRITE); uchar* outputData = (uchar*)outputAccess->get(); // initialize output to all zero memset(outputData, 0, output->getWidth()*output->getHeight()*output->getDepth()); std::stack<Vector3ui> queue; // Add seeds to queue for(int i = 0; i < mSeedPoints.size(); i++) { Vector3ui pos = mSeedPoints[i]; // Check if seed point is in bounds if(pos.x() < 0 || pos.y() < 0 || pos.z() < 0 || pos.x() >= output->getWidth() || pos.y() >= output->getHeight() || pos.z() >= output->getDepth()) throw Exception("One of the seed points given to SeededRegionGrowing was out of bounds."); queue.push(pos); } // Process queue while(!queue.empty()) { Vector3ui pos = queue.top(); queue.pop(); // Add neighbors to queue for(int a = -1; a < 2; a++) { for(int b = -1; b < 2; b++) { for(int c = -1; c < 2; c++) { if(abs(a)+abs(b)+abs(c) != 1) // connectivity continue; Vector3ui neighbor(pos.x()+a,pos.y()+b,pos.z()+c); // Check for out of bounds if(neighbor.x() < 0 || neighbor.y() < 0 || neighbor.z() < 0 || neighbor.x() >= output->getWidth() || neighbor.y() >= output->getHeight() || neighbor.z() >= output->getDepth()) continue; // Check that voxel is not already segmented if(outputData[neighbor.x()+neighbor.y()*output->getWidth()+neighbor.z()*output->getWidth()*output->getHeight()] == 1) continue; // Check condition T value = input[neighbor.x()+neighbor.y()*output->getWidth()+neighbor.z()*output->getWidth()*output->getHeight()]; if(value >= mMinimumIntensity && value <= mMaximumIntensity) { // add it to segmentation outputData[neighbor.x()+neighbor.y()*output->getWidth()+neighbor.z()*output->getWidth()*output->getHeight()] = 1; // Add to queue queue.push(neighbor); } }}} } }
void Dilation::execute() { Image::pointer input = getInputData<Image>(); if(input->getDataType() != TYPE_UINT8) { throw Exception("Data type of image given to Dilation must be UINT8"); } Image::pointer output = getOutputData<Image>(); output->createFromImage(input); SceneGraph::setParentNode(output, input); output->fill(0); OpenCLDevice::pointer device = std::dynamic_pointer_cast<OpenCLDevice>(getMainDevice()); cl::CommandQueue queue = device->getCommandQueue(); cl::Program program = getOpenCLProgram(device); cl::Kernel dilateKernel(program, "dilate"); Vector3ui size = input->getSize(); OpenCLImageAccess::pointer access = input->getOpenCLImageAccess(ACCESS_READ, device); dilateKernel.setArg(0, *access->get3DImage()); dilateKernel.setArg(2, mSize/2); if(!device->isWritingTo3DTexturesSupported()) { OpenCLBufferAccess::pointer access2 = output->getOpenCLBufferAccess(ACCESS_READ_WRITE, device); dilateKernel.setArg(1, *access2->get()); queue.enqueueNDRangeKernel( dilateKernel, cl::NullRange, cl::NDRange(size.x(), size.y(), size.z()), cl::NullRange ); } else { OpenCLImageAccess::pointer access2 = output->getOpenCLImageAccess(ACCESS_READ_WRITE, device); dilateKernel.setArg(1, *access2->get3DImage()); queue.enqueueNDRangeKernel( dilateKernel, cl::NullRange, cl::NDRange(size.x(), size.y(), size.z()), cl::NullRange ); } }
void VTKMeshFileExporter::execute() { if(mFilename == "") throw Exception("No filename given to the VTKMeshFileExporter"); Mesh::pointer surface = getStaticInputData<Mesh>(); // Get transformation AffineTransformation::pointer transform = SceneGraph::getAffineTransformationFromData(surface); std::ofstream file(mFilename.c_str()); if(!file.is_open()) throw Exception("Unable to open the file " + mFilename); // Write header file << "# vtk DataFile Version 3.0\n" "vtk output\n" "ASCII\n" "DATASET POLYDATA\n"; // Write vertices MeshAccess::pointer access = surface->getMeshAccess(ACCESS_READ); std::vector<MeshVertex> vertices = access->getVertices(); file << "POINTS " << vertices.size() << " float\n"; for(int i = 0; i < vertices.size(); i++) { MeshVertex vertex = vertices[i]; vertex.position = (transform->matrix()*vertex.position.homogeneous()).head(3); file << vertex.position.x() << " " << vertex.position.y() << " " << vertex.position.z() << "\n"; } // Write triangles std::vector<Vector3ui> triangles = access->getTriangles(); file << "POLYGONS " << surface->getNrOfTriangles() << " " << surface->getNrOfTriangles()*4 << "\n"; for(int i = 0; i < triangles.size(); i++) { Vector3ui triangle = triangles[i]; file << "3 " << triangle.x() << " " << triangle.y() << " " << triangle.z() << "\n"; } // Write normals file << "POINT_DATA " << vertices.size() << "\n"; file << "NORMALS Normals float\n"; for(int i = 0; i < vertices.size(); i++) { MeshVertex vertex = vertices[i]; // Transform it vertex.normal = transform->linear()*vertex.normal; // Normalize it float length = vertex.normal.norm(); if(length == 0) { // prevent NaN situations file << "0 1 0\n"; } else { file << (vertex.normal.x()/length) << " " << (vertex.normal.y()/length) << " " << (vertex.normal.z()/length) << "\n"; } } file.close(); }
bool checkCompatibility( const Vector3ui& volumeDim, const Vector3ui& blockSize ) { if( volumeDim.x() % blockSize.x() ) return false; if( volumeDim.y() % blockSize.y() ) return false; if( volumeDim.z() % blockSize.z() ) return false; if( !isPowerOfTwo( volumeDim.x() / blockSize.x() ) ) return false; if( !isPowerOfTwo( volumeDim.y() / blockSize.y() ) ) return false; if( !isPowerOfTwo( volumeDim.z() / blockSize.z() ) ) return false; return true; }
void setScalarAsFloat(T* data, uint position, Image::pointer image, float value, uchar channel) { Vector3ui size = image->getSize(); if(position >= size.x()*size.y()*size.z()) throw OutOfBoundsException(); uint address = position*image->getNrOfComponents() + channel; if(image->getDataType() == TYPE_SNORM_INT16) { data[address] = value * 32767.0f;; } else if(image->getDataType() == TYPE_UNORM_INT16) { data[address] = value * 65535.0f;; } else { data[address] = value; } }
float getScalarAsFloat(T* data, uint position, Image::pointer image, uchar channel) { Vector3ui size = image->getSize(); if(position >= size.x()*size.y()*size.z()) throw OutOfBoundsException(); T value = data[position*image->getNrOfComponents() + channel]; float floatValue; if(image->getDataType() == TYPE_SNORM_INT16) { floatValue = std::max(-1.0f, (float)value / 32767.0f); } else if(image->getDataType() == TYPE_UNORM_INT16) { floatValue = (float)value / 65535.0f; } else { floatValue = value; } return floatValue; }
/*===========================================================================*/ void ExtractEdges::calculate_connections( const kvs::StructuredVolumeObject* volume ) { const size_t line_size = volume->numberOfNodesPerLine(); const size_t slice_size = volume->numberOfNodesPerSlice(); const Vector3ui resolution( volume->resolution() ); const size_t nedges = 3 * ( resolution.x() - 1 ) * ( resolution.y() - 1 ) * ( resolution.z() - 1 ) + 2 * ( resolution.x() - 1 ) * ( resolution.y() - 1 ) + 2 * ( resolution.y() - 1 ) * ( resolution.z() - 1 ) + 2 * ( resolution.z() - 1 ) * ( resolution.x() - 1 ) + resolution.x() - 1 + resolution.y() - 1 + resolution.z() - 1; kvs::ValueArray<kvs::UInt32> connections( 2 * nedges ); kvs::UInt32* connection = connections.data(); kvs::UInt32 volume_vertex = 0; kvs::UInt32 connection_index = 0; for ( size_t z = 0; z < resolution.z(); ++z ) { for ( size_t y = 0; y < resolution.y(); ++y ) { for ( size_t x = 0; x < resolution.x(); ++x ) { if ( x != resolution.x() - 1 ) { connection[ connection_index++ ] = volume_vertex; connection[ connection_index++ ] = volume_vertex + 1; } if ( y != resolution.y() - 1 ) { connection[ connection_index++ ] = volume_vertex; connection[ connection_index++ ] = volume_vertex + line_size; } if ( z != resolution.z() - 1 ) { connection[ connection_index++ ] = volume_vertex; connection[ connection_index++ ] = volume_vertex + slice_size; } ++volume_vertex; } } } SuperClass::setConnections( connections ); }
cl::size_t<3> createRegion(Vector3ui size) { return createRegion(size.x(), size.y(), size.z()); }
void SeededRegionGrowing::execute() { if(mSeedPoints.size() == 0) throw Exception("No seed points supplied to SeededRegionGrowing"); Image::pointer input = getStaticInputData<Image>(); if(input->getNrOfComponents() != 1) throw Exception("Seeded region growing currently doesn't support images with several components."); Segmentation::pointer output = getStaticOutputData<Segmentation>(); // Initialize output image output->createFromImage(input, getMainDevice()); if(getMainDevice()->isHost()) { ImageAccess::pointer inputAccess = input->getImageAccess(ACCESS_READ); void* inputData = inputAccess->get(); switch(input->getDataType()) { fastSwitchTypeMacro(executeOnHost<FAST_TYPE>((FAST_TYPE*)inputData, output)); } } else { OpenCLDevice::pointer device = getMainDevice(); recompileOpenCLCode(input); ImageAccess::pointer access = output->getImageAccess(ACCESS_READ_WRITE); uchar* outputData = (uchar*)access->get(); // Initialize to all 0s memset(outputData,0,sizeof(uchar)*output->getWidth()*output->getHeight()*output->getDepth()); // Add sedd points for(int i = 0; i < mSeedPoints.size(); i++) { Vector3ui pos = mSeedPoints[i]; // Check if seed point is in bounds if(pos.x() < 0 || pos.y() < 0 || pos.z() < 0 || pos.x() >= output->getWidth() || pos.y() >= output->getHeight() || pos.z() >= output->getDepth()) throw Exception("One of the seed points given to SeededRegionGrowing was out of bounds."); outputData[pos.x() + pos.y()*output->getWidth() + pos.z()*output->getWidth()*output->getHeight()] = 2; } access->release(); cl::NDRange globalSize; if(output->getDimensions() == 2) { globalSize = cl::NDRange(input->getWidth(),input->getHeight()); OpenCLImageAccess2D::pointer inputAccess = input->getOpenCLImageAccess2D(ACCESS_READ, device); mKernel.setArg(0, *inputAccess->get()); } else { globalSize = cl::NDRange(input->getWidth(),input->getHeight(), input->getDepth()); OpenCLImageAccess3D::pointer inputAccess = input->getOpenCLImageAccess3D(ACCESS_READ, device); mKernel.setArg(0, *inputAccess->get()); } OpenCLBufferAccess::pointer outputAccess = output->getOpenCLBufferAccess(ACCESS_READ_WRITE, device); cl::Buffer stopGrowingBuffer = cl::Buffer( device->getContext(), CL_MEM_READ_WRITE, sizeof(char)); cl::CommandQueue queue = device->getCommandQueue(); mKernel.setArg(1, *outputAccess->get()); mKernel.setArg(2, stopGrowingBuffer); mKernel.setArg(3, mMinimumIntensity); mKernel.setArg(4, mMaximumIntensity); bool stopGrowing = false; char stopGrowingInit = 1; char * stopGrowingResult = new char; int iterations = 0; do { iterations++; queue.enqueueWriteBuffer(stopGrowingBuffer, CL_TRUE, 0, sizeof(char), &stopGrowingInit); queue.enqueueNDRangeKernel( mKernel, cl::NullRange, globalSize, cl::NullRange ); queue.enqueueReadBuffer(stopGrowingBuffer, CL_TRUE, 0, sizeof(char), stopGrowingResult); if(*stopGrowingResult == 1) stopGrowing = true; } while(!stopGrowing); } }