//---------------------------------------------------------------------------- void AdaptiveSkeletonClimbing3::CreateImage (ImageInt3D& image) { // Create an image by sampling a Gaussian distribution. int bound = image.GetBound(0); float a0 = 256.0f, a1 = 128.0f; float x0 = 0.5f*bound, y0 = 0.0f, z0 = 0.0f; float x1 = 0.75f*bound, y1 = 0.0f, z1 = 0.0f; float xs0 = 2.0f*bound, ys0 = 4.0f*bound, zs0 = 8.0f*bound; float xs1 = 8.0f*bound, ys1 = 4.0f*bound, zs1 = 2.0f*bound; image = (Eint)0; for (int z = 0; z < bound; ++z) { float vz0 = (z - z0)/zs0, vz1 = (z - z1)/zs1; vz0 *= vz0; vz1 *= vz1; for (int y = 0; y < bound; ++y) { float vy0 = (y - y0)/ys0, vy1 = (y - y1)/ys1; vy0 *= vy0; vy1 *= vy1; for (int x = 0; x < bound; ++x) { float vx0 = (x - x0)/xs0, vx1 = (x - x1)/xs1; vx0 *= vx0; vx1 *= vx1; float g0 = a0*Mathf::Exp(-(vx0 + vy0 + vz0)); float g1 = a1*Mathf::Exp(-(vx1 + vy1 + vz1)); image(x, y, z) = (int)(g0 + g1); } } } image.Save("gauss.im"); }
//---------------------------------------------------------------------------- void Binary3D::GetComponents (int& riQuantity, ImageInt3D& rkComponents) const { // Create a temporary copy of image to store intermediate information // during component labeling. The original image is embedded in an image // with two more slices, two more rows, and two more columns so that the // image boundary pixels are properly handled. This copy is initially // zero. ImageInt3D kTemp(GetBound(0)+2,GetBound(1)+2,GetBound(2)+2); int iX, iY, iZ, iXP, iYP, iZP; for (iZ = 0, iZP = 1; iZ < GetBound(2); iZ++, iZP++) { for (iY = 0, iYP = 1; iY < GetBound(1); iY++, iYP++) { for (iX = 0, iXP = 1; iX < GetBound(0); iX++, iXP++) kTemp(iXP,iYP,iZP) = ( (*this)(iX,iY,iZ) ? 1 : 0 ); } } // label connected components in 1D array int i, iComponent = 0; for (i = 0; i < kTemp.GetQuantity(); i++) { if ( kTemp[i] ) { iComponent++; while ( kTemp[i] ) { // loop terminates since kTemp is zero on its boundaries kTemp[i++] = iComponent; } } } if ( iComponent == 0 ) { // input image is identically zero riQuantity = 0; rkComponents = (Eint)0; return; } // associative memory for merging int* aiAssoc = new int[iComponent+1]; for (i = 0; i < iComponent + 1; i++) aiAssoc[i] = i; // Merge equivalent components. Voxel (x,y,z) has previous neighbors // (x-1,y-1,z-1), (x,y-1,z-1), (x+1,y-1,z-1), (x-1,y,z-1), (x,y,z-1), // (x+1,y,z-1), (x-1,y+1,z-1), (x,y+1,z-1), (x+1,y+1,z-1), (x-1,y-1,z), // (x,y-1,z), (x+1,y-1,z), (x-1,y,z) [13 of 26 voxels visited before // (x,y,z) is visited, get component labels from them]. for (iZ = 1; iZ < kTemp.GetBound(2)-1; iZ++) { for (iY = 1; iY < kTemp.GetBound(1)-1; iY++) { for (iX = 1; iX < kTemp.GetBound(0)-1; iX++) { int iValue = kTemp(iX,iY,iZ); if ( iValue > 0 ) { AddToAssociative(iValue,kTemp(iX-1,iY-1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX, iY-1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX+1,iY-1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX-1,iY ,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX ,iY ,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX+1,iY ,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX-1,iY+1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX ,iY+1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX+1,iY+1,iZ-1),aiAssoc); AddToAssociative(iValue,kTemp(iX-1,iY-1,iZ ),aiAssoc); AddToAssociative(iValue,kTemp(iX ,iY-1,iZ ),aiAssoc); AddToAssociative(iValue,kTemp(iX+1,iY-1,iZ ),aiAssoc); AddToAssociative(iValue,kTemp(iX-1,iY ,iZ ),aiAssoc); } } } } // replace each cycle of equivalent labels by a single label riQuantity = 0; for (i = 1; i <= iComponent; i++) { if ( i <= aiAssoc[i] ) { riQuantity++; int iCurrent = i; while ( aiAssoc[iCurrent] != i ) { int iNext = aiAssoc[iCurrent]; aiAssoc[iCurrent] = riQuantity; iCurrent = iNext; } aiAssoc[iCurrent] = riQuantity; } } // pack a relabeled image in smaller size output for (iZ = 0, iZP = 1; iZ < rkComponents.GetBound(2); iZ++, iZP++) { for (iY = 0, iYP = 1; iY < rkComponents.GetBound(1); iY++, iYP++) { for (iX = 0, iXP = 1; iX < rkComponents.GetBound(0); iX++, iXP++) rkComponents(iX,iY,iZ) = aiAssoc[kTemp(iXP,iYP,iZP)]; } } delete[] aiAssoc; }