VImage VCopyImage (VImage src, VImage dest, VBand band) { VImage result; if (src == dest && (band == VAllBands || (band == 0 && VImageNBands (src) == 1))) return src; if ((result = VCopyImagePixels (src, dest, band)) != 0) VCopyImageAttrs (src, result); return result; }
VImage VAniso3d(VImage src,VImage dest,VShort numiter, VShort type,VFloat kappa,VFloat alpha) { VImage tmp1=NULL,tmp2=NULL; int nbands,nrows,ncols; int b,r,c,iter; float delta; float dx,dy,dz,d,u,v; float ux1,ux2,uy1,uy2,uz1,uz2; float b1,b2,r1,r2,c1,c2; VDouble xmax,xmin; VBoolean ignore = TRUE; nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); if (nbands < 3) VError(" min number of slices is 3"); tmp1 = VConvertImageCopy(src,NULL,VAllBands,VFloatRepn); tmp2 = VCreateImage(nbands,nrows,ncols,VFloatRepn); VFillImage(tmp2,VAllBands,0); xmax = VPixelMaxValue (tmp1); xmin = VPixelMinValue (tmp1); delta = 1.0 / 7.0; dx = dy = dz = 0; for (iter=0; iter < numiter; iter++) { for (b=1; b<nbands-1; b++) { for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { u = VPixel(tmp1,b,r,c,VFloat); if (ignore && ABS(u) < 1.0e-10) continue; c1 = VPixel(tmp1,b,r,c+1,VFloat); c2 = VPixel(tmp1,b,r,c-1,VFloat); r1 = VPixel(tmp1,b,r+1,c,VFloat); r2 = VPixel(tmp1,b,r-1,c,VFloat); b1 = VPixel(tmp1,b+1,r,c,VFloat); b2 = VPixel(tmp1,b-1,r,c,VFloat); /* col-dir */ dx = c1-u; dy = r1-r2; dz = b1-b2; d = diffusion3d(dx,dy,dz,type,kappa,alpha); ux1 = d*(c1 - u); dx = u-c2; d = diffusion3d(dx,dy,dz,type,kappa,alpha); ux2 = d*(u - c2); /* row-dir */ dx = c1-c2; dy = r1-u; dz = b1-b2; d = diffusion3d(dx,dy,dz,type,kappa,alpha); uy1 = d*(r1 - u); dy = u-r2; d = diffusion3d(dx,dy,dz,type,kappa,alpha); uy2 = d*(u - r2); /* slice-dir */ dx = c1-c2; dy = r1-r2; dz = b1-u; d = diffusion3d(dx,dy,dz,type,kappa,alpha); uz1 = d*(b1 - u); dz = u-b2; d = diffusion3d(dx,dy,dz,type,kappa,alpha); uz2 = d*(u - b2); /* sum */ v = u + delta*(ux1 - ux2 + uy1 - uy2 + uz1 - uz2); if (v > xmax) v = xmax; if (v < xmin) v = xmin; VPixel(tmp2,b,r,c,VFloat) = v; } } } tmp1 = VCopyImagePixels(tmp2,tmp1,VAllBands); } /* ** output */ dest = VCopyImage(src,dest,VAllBands); xmax = VPixelMaxValue (dest); xmin = VPixelMinValue (dest); for (b=1; b<nbands-1; b++) { for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { v = VPixel(tmp2,b,r,c,VFloat); if (v > xmax) v = xmax; if (v < xmin) v = xmin; VSetPixel(dest,b,r,c,(VDouble) v); } } } VDestroyImage(tmp1); VDestroyImage(tmp2); return dest; }
/*! \fn VImage VAniso2d(VImage src,VImage dest,VShort numiter, VShort type,VFloat kappa,VFloat alpha); \param src input image \param dest output image \param numiter number of iterations \param type type of diffusion function (0 or 1) \param kappa parameter for diffusion function \param alpha parameter for diffusion function */ VImage VAniso2d(VImage src,VImage dest,VShort numiter, VShort type,VFloat kappa,VFloat alpha) { VImage tmp1=NULL,tmp2=NULL; int nbands,nrows,ncols; int b,r,c,iter; float delta; float dx,dy,dz,d,u,v; float ux1,ux2,uy1,uy2; float r1,r2,c1,c2; VDouble xmax,xmin; nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); tmp1 = VCreateImage(1,nrows,ncols,VFloatRepn); tmp2 = VCreateImage(1,nrows,ncols,VFloatRepn); xmax = VPixelMaxValue (tmp1); xmin = VPixelMinValue (tmp1); dest = VCopyImage(src,dest,VAllBands); delta = 1.0 / 6.0; dz = 0; for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { VPixel(tmp1,0,r,c,VFloat) = VGetPixel(src,b,r,c); } } for (iter=0; iter < numiter; iter++) { for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { u = VPixel(tmp1,0,r,c,VFloat); c1 = VPixel(tmp1,0,r,c+1,VFloat); c2 = VPixel(tmp1,0,r,c-1,VFloat); r1 = VPixel(tmp1,0,r+1,c,VFloat); r2 = VPixel(tmp1,0,r-1,c,VFloat); /* col-dir */ dx = c1-u; dy = r1-r2; d = diffusion2d(dx,dy,type,kappa,alpha); ux1 = d*(c1 - u); dx = u-c2; d = diffusion2d(dx,dy,type,kappa,alpha); ux2 = d*(u - c2); /* row-dir */ dx = c1-c2; dy = r1-u; d = diffusion2d(dx,dy,type,kappa,alpha); uy1 = d*(r1 - u); dy = u-r2; d = diffusion2d(dx,dy,type,kappa,alpha); uy2 = d*(u - r2); /* sum */ v = u + delta*(ux1 - ux2 + uy1 - uy2); if (v > xmax) v = xmax; if (v < xmin) v = xmin; VPixel(tmp2,0,r,c,VFloat) = v; } } tmp1 = VCopyImagePixels(tmp2,tmp1,VAllBands); } /* ** output */ for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { v = VPixel(tmp2,0,r,c,VFloat); if (v > VPixelMaxValue (dest)) v = VPixelMaxValue (dest); if (v < VPixelMinValue (dest)) v = VPixelMinValue (dest); VSetPixel(dest,b,r,c,(VDouble) v); } } } VDestroyImage(tmp1); VDestroyImage(tmp2); return dest; }
void VSpatialFilter(VAttrList list,VDouble fwhm) { VAttrListPosn posn; VImage src[NSLICES],xsrc=NULL,tmp=NULL,dest=NULL,kernel=NULL,tmp2d=NULL; VString str=NULL; float v0,v1,v2,v3; int b,r,c,i,size; int n,nslices,nrows,ncols,dim; double u, sigma=0; extern VImage VGaussianConv (VImage,VImage,VBand,double,int); /* get image dimensions */ dim = 3; v0 = v1 = v2 = v3 = 1; n = i = nrows = ncols = 0; str = VMalloc(100); for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn)) { if (i >= NSLICES) VError(" too many slices"); if (VGetAttrRepn (& posn) != VImageRepn) continue; VGetAttrValue (& posn, NULL,VImageRepn, & xsrc); if (VPixelRepn(xsrc) != VShortRepn) continue; if (VImageNBands(xsrc) > n) n = VImageNBands(xsrc); if (VImageNRows(xsrc) > nrows) nrows = VImageNRows(xsrc); if (VImageNColumns(xsrc) > ncols) ncols = VImageNColumns(xsrc); if (VGetAttr (VImageAttrList (xsrc), "voxel", NULL,VStringRepn, (VPointer) & str) == VAttrFound) { sscanf(str,"%f %f %f",&v1,&v2,&v3); } src[i] = xsrc; i++; } nslices = i; /* in general, apply 3D spatial filtering */ dim = 3; /* only if clearly non-isotropic apply 2D filtering */ v0 = 0.5*(v1+v2); if (ABS(v0-v3) > 0.5) dim = 2; /* ** Sigma */ sigma = fwhm/sqrt(8.0*log(2.0)); sigma /= (double)v1; /* ** 2D gauss filtering */ if (dim==2) { fprintf(stderr," 2D spatial filter: fwhm= %.3f mm sigma= %.3f vox\n",fwhm,sigma); size = (int)(6.0 * sigma + 1.5); if ((size & 1) == 0) size++; fprintf(stderr," size= %d\n",size); for (b=0; b<nslices; b++) { if (VImageNRows(src[b]) < 2) continue; tmp2d = VGaussianConv(src[b],tmp2d, VAllBands, sigma, size); src[b] = VCopyImagePixels(tmp2d,src[b],VAllBands); } VDestroyImage(tmp2d); } /* ** 3D gauss filtering */ if (dim==3) { fprintf(stderr," 3D spatial filter: fwhm= %.3f mm sigma= %.3f vox\n",fwhm,sigma); kernel = VSGaussKernel(sigma); tmp = VCreateImage(nslices,nrows,ncols,VFloatRepn); VFillImage(tmp,VAllBands,0); for (i=0; i<n; i++) { if (i%20 == 0) fprintf(stderr," i= %5d\r",i); VFillImage(tmp,VAllBands,0); for (b=0; b<nslices; b++) { if (VImageNRows(src[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { u = VPixel(src[b],i,r,c,VShort); VPixel(tmp,b,r,c,VFloat) = u; } } } dest = VGauss3d (tmp,dest,kernel); for (b=0; b<nslices; b++) { if (VImageNRows(src[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { u = VPixel(dest,b,r,c,VFloat); VPixel(src[b],i,r,c,VShort) = u; } } } } } }