00001 /* 00002 Segmentation of simply connected spaces in 3D data. 00003 00004 Copyright (C) 2010 - 2014 Christoph Haenisch 00005 00006 Chair of Medical Engineering (mediTEC) 00007 RWTH Aachen University 00008 Pauwelsstr. 20 00009 52074 Aachen 00010 Germany 00011 00012 Version 0.1.0 (2011-10-14) 00013 */ 00014 00020 #ifndef SURFACE_EXTRACTION_3D_7431089643 00021 #define SURFACE_EXTRACTION_3D_7431089643 00022 00023 #include <cstddef> 00024 00025 #include "Coordinate.hpp" 00026 00027 00028 namespace TRTK 00029 { 00030 00031 00186 template <class DataType> 00187 class SurfaceExtraction3D 00188 { 00189 public: 00190 typedef DataType data_type; 00191 00192 SurfaceExtraction3D(); 00193 SurfaceExtraction3D(const DataType * data, const unsigned width, const unsigned height, const unsigned depth); 00194 virtual ~SurfaceExtraction3D(); 00195 00196 void compute(); 00197 00198 void setData(const DataType * data, const unsigned width, const unsigned height, const unsigned depth); 00199 const DataType * getSurface() const; 00200 00201 private: 00202 void initSurfaceData(); 00203 unsigned int toIndex(const DataType x, const DataType y, const DataType z); 00204 00205 unsigned height; 00206 unsigned width; 00207 unsigned depth; 00208 00209 const DataType * data; 00210 DataType * surfaceData; 00211 }; 00212 00213 00216 template <class DataType> 00217 SurfaceExtraction3D<DataType>::SurfaceExtraction3D() : 00218 height(0), 00219 width(0), 00220 depth(0), 00221 data(NULL), 00222 surfaceData(NULL) 00223 { 00224 } 00225 00226 00235 template <class DataType> 00236 SurfaceExtraction3D<DataType>::SurfaceExtraction3D(const DataType * data, const unsigned width, const unsigned height, const unsigned depth) : 00237 height(height), 00238 width(width), 00239 depth(depth), 00240 data(data) 00241 { 00242 surfaceData = new DataType[width * height * depth]; 00243 initSurfaceData(); 00244 } 00245 00246 00249 template <class DataType> 00250 SurfaceExtraction3D<DataType>::~SurfaceExtraction3D() 00251 { 00252 if (surfaceData) delete[] surfaceData; 00253 } 00254 00255 00265 template <class DataType> 00266 void SurfaceExtraction3D<DataType>::compute() 00267 { 00268 assert(width > 0); 00269 assert(height > 0); 00270 assert(depth > 0); 00271 00272 // Do nothing in the case of a 0-dimensional data set. 00273 00274 if (width * height * depth == 0) return; 00275 00276 // Copy the boundary elements (sides of the data volume) since these are 00277 // surface elements by definition. 00278 00279 // Note: toIndex(x, y, z) = z * width * height + y * width + x 00280 00281 unsigned index = 0; 00282 00283 // front and back 00284 00285 for (unsigned x = 0; x < width; ++x) 00286 { 00287 for (unsigned y = 0; y < height; ++y) 00288 { 00289 index = toIndex(x, y, 0); 00290 surfaceData[index] = data[index]; 00291 00292 index = toIndex(x, y, depth - 1); 00293 surfaceData[index] = data[index]; 00294 } 00295 } 00296 00297 // top and bottom 00298 00299 for (unsigned x = 0; x < width; ++x) 00300 { 00301 for (unsigned z = 0; z < depth; ++z) 00302 { 00303 index = toIndex(x, 0, z); 00304 surfaceData[index] = data[index]; 00305 00306 index = toIndex(x, height - 1, z); 00307 surfaceData[index] = data[index]; 00308 } 00309 } 00310 00311 // left and right side 00312 00313 for (unsigned y = 0; y < height; ++y) 00314 { 00315 for (unsigned z = 0; z < depth; ++z) 00316 { 00317 index = toIndex(0, y, z); 00318 surfaceData[index] = data[index]; 00319 00320 index = toIndex(width - 1, y, z); 00321 surfaceData[index] = data[index]; 00322 } 00323 } 00324 00325 // Compute the surface elements. 00326 00327 for (unsigned z = 1; z < depth - 1; ++z) 00328 { 00329 for (unsigned y = 1; y < height - 1; ++y) 00330 { 00331 for (unsigned x = 1; x < width - 1; ++x) 00332 { 00333 // If there is a voxel in the neighborhood which does not own 00334 // the same label (might be zero or another region label), then 00335 // the current voxel must be a surface voxel. 00336 00337 const data_type label = data[toIndex(x, y, z)]; 00338 00339 if (!(data[toIndex(x - 1, y, z)] == label && 00340 data[toIndex(x + 1, y, z)] == label && 00341 data[toIndex(x, y - 1, z)] == label && 00342 data[toIndex(x, y + 1, z)] == label && 00343 data[toIndex(x, y, z - 1)] == label && 00344 data[toIndex(x, y, z + 1)] == label )) 00345 { 00346 // surface voxel 00347 00348 surfaceData[toIndex(x, y, z)] = data[toIndex(x, y, z)]; 00349 } 00350 else 00351 { 00352 // voxel completely surrounded by other (identically labeled) voxels 00353 // --> must be inner volume voxel 00354 00355 surfaceData[toIndex(x, y, z)] = 0; 00356 } 00357 } 00358 } 00359 } 00360 } 00361 00364 template <class DataType> 00365 const DataType * SurfaceExtraction3D<DataType>::getSurface() const 00366 { 00367 return surfaceData; 00368 } 00369 00370 00376 template <class DataType> 00377 void SurfaceExtraction3D<DataType>::initSurfaceData() 00378 { 00379 for (unsigned i = 0; i < width * height * depth; ++i) 00380 { 00381 surfaceData[i] = DataType(0); 00382 } 00383 } 00384 00385 00394 template <class DataType> 00395 void SurfaceExtraction3D<DataType>::setData(const DataType * data, const unsigned width, const unsigned height, const unsigned depth) 00396 { 00397 this->data = data; 00398 this->width = width; 00399 this->height = height; 00400 this->depth = depth; 00401 00402 if (surfaceData) delete[] surfaceData; 00403 00404 surfaceData = new DataType[width * height * depth]; 00405 initSurfaceData(); 00406 } 00407 00408 00415 template <class DataType> 00416 inline unsigned int SurfaceExtraction3D<DataType>::toIndex(const DataType x, const DataType y, const DataType z) 00417 { 00418 return z * width * height + y * width + x; 00419 } 00420 00421 00422 } // namespace TRTK 00423 00424 #endif // SURFACE_EXTRACTION_3D_7431089643
Documentation generated by Doxygen