コード例 #1
0
ファイル: bigsdcgr.c プロジェクト: jhkoivis/stdic
int bigsdcgr(double *fr,  /* reference image */
	      double *E,   /* the criterion value */
	      double *gr,  /* the gradient */
	      int degc,  /* degree for the coefficients */
	      int frx, int fry, /* size of the reference image */
	      int cx, int cy,    /* size of the image coefficients */
	      double *derw, /* first derivatives */
	      double *fw   /* warped test image */
	      )
{
  double e ; 
  int ix,iy ; int cnum,imcnt ;
  double shift,stepx,stepy,hsupp ;
  double parx,pary ;
  double *derx,*dery ;
  int lowx,lowy,highx,highy ;
  int supp,ind1,ind2,ind3,ind4 ;
  int jx,jy,jxf,jyf ;
  int cnd,cxe,cye ;
  double *tabx,*taby ;
  double ederx ;
  double edery ;
  double betajy,betajxjy ;
  double (*evspln)(double) ;    /* pointer to the evaluation function */

  int (*mfold)(int,int) ; double (*mfoldd)(double,int) ;
  /* for the moment, enforce mirror-off-bound condition */
  mfold=mfoldmirroroffbound ; 
  mfoldd=mfolddmirroroffbound ;


  /* printf("frx=%d fry=%d cx=%d cy=%d degc=%d\n",frx,fry,cx,cy,degc) ; 
   */

  if (choosespln(degc,&evspln,&supp,0)) myErrMsg("Unsupported degc") ;

  hsupp=supp/2.0 ;
  shift=0.0 ; /* we now put the basis function in the corners */
  stepx=(cx-1)/((double)frx-1) ; stepy=(cy-1)/((double)fry-1) ; 
  
  /* printf("stepx=%f stepy=%f\n",stepx,stepy) ;
   */

  cnum=cx*cy ;
  cnd=cnum*2 ; /* 2 is the number of dimensions */
  imcnt=frx*fry ;
  derx=derw ; dery=derx+imcnt ;

  /* zero E and gr */
  for(ix=0;ix<cnd;ix++) gr[ix]=0.0 ;
  *E=0.0 ; 

  /* allocate and precalculate tabx, taby */
  cxe=cx+2*supp ;/* 2*supp is too much but who cares... */
  myMalloc(tabx,cxe,frx) ; 
  for(ix=0;ix<frx;ix++) { 
  	  parx=shift+stepx*ix ; 
	  lowx=(int)floor(parx-hsupp) ; highx=lowx+supp ;
	  for(jx=lowx;jx<=highx;jx++)
	    tabx[ix*cxe+supp+jx]=(*evspln)(parx-jx) ;
  }
  cye=cy+2*supp ;/* 2*supp is too much but who cares... */
  myMalloc(taby,cye,fry) ; 
  for(iy=0;iy<fry;iy++) { 
  	  pary=shift+stepy*iy ; 
	  lowy=(int)floor(pary-hsupp) ; highy=lowy+supp ;
	  for(jy=lowy;jy<=highy;jy++)
	    taby[iy*cye+supp+jy]=(*evspln)(pary-jy) ;
  }
  

  /* 2D case gradient and Hessian calculation starts here */
  for(iy=0;iy<fry;iy++) { /* loop through all pixels */
        pary=shift+stepy*iy ;
	ind4=iy*cye+supp ;
	lowy=(int)floor(pary-hsupp) ; highy=lowy+supp ;
	/*printf("iy=%d pary=%f pary-hsupp=%f lowy=%d highy=%d\n",
	  iy,pary,pary-hsupp,lowy,highy) ;*/
	for(ix=0;ix<frx;ix++) { 
	  ind1=ix+frx*iy ;
	  ind3=ix*cxe+supp ;
	  e=fw[ind1]-fr[ind1] ;
	  (*E)+=e*e ;
	  /* calculate the range of influential parameters */
	  parx=shift+stepx*ix ; 
	  lowx=(int)floor(parx-hsupp) ; highx=lowx+supp ;
	  ederx=2.0*e*derx[ind1] ;
	  edery=2.0*e*dery[ind1] ;
	  /* precalculate tabx */
	  for(jy=lowy;jy<=highy;jy++) { /* loop through influential c's */
	    betajy=taby[ind4+jy] ;
	    jyf=mfold(jy,cy) ;
	    /* printf("mfold(%d,%d)=%d ",jy,cy,jyf) ; */
	    for(jx=lowx;jx<=highx;jx++) { 
	      betajxjy=tabx[ind3+jx]*betajy ;
	      jxf=mfold(jx,cx) ;
	      ind2=jxf+cx*jyf ;
	      gr[ind2]+=betajxjy*ederx ;
	      gr[ind2+cnum]+=betajxjy*edery ;
	    } /* for jx */
	  } /* for jy */
	} /* for ix */
      } /* for iy */
  myFree(tabx) ;
  myFree(taby) ;
  return 0 ;
}
コード例 #2
0
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){
		int i;

    if(nrhs!=1){
			mexPrintf("\nwriteFileNifti(niftiStruct)\n\n");
			mexPrintf("Writes a NIFTI image based on fields of a structure that resembles\n");
			mexPrintf("the NIFTI 1 standard (see http://nifti.nimh.nih.gov/nifti-1/ ).\n");
 		  mexPrintf("See readFileNifti for details about the expected niftiStruct.\n\n");
			return;
    }else if(nlhs>0) { mexPrintf("Too many output arguments"); return; }

    /* The first arg must be a nifti struct. */
		if(!mxIsStruct(prhs[0])) mexErrMsgTxt("First arg must be a nifti struct.");
    const mxArray *mxnim = prhs[0];
		// Sanity check that this is a complete NIFTI struct
		if(mxGetField(mxnim,0,"fname")==NULL || mxGetField(mxnim,0,"data")==NULL)
			myErrMsg("First argument must be a proper NIFTI struct (see readFileNifti).\n\n");

    /* Create an empty NIFTI C struct */
		nifti_image *nim = (nifti_image *)mxCalloc(1, sizeof(nifti_image));
		if(!nim) myErrMsg("failed to allocate nifti image");

		nim->nifti_type = 1; // We only support single-file NIFTI format

		/* Load the C-struct with fields from the matlab struct */
		mxArray *fname =  mxGetField(mxnim,0,"fname");
		mxArray *data = mxGetField(mxnim,0,"data");
    // fname field needs to be allocated
    int buflen = (mxGetN(fname)) + 1;
    nim->fname = (char *)mxCalloc(buflen, sizeof(char));
    if(mxGetString(fname, nim->fname, buflen))
      mexWarnMsgTxt("Not enough space- fname string is truncated.");
		nim->iname = NULL;
		nim->data = mxGetData(data); 
		nim->ndim = mxGetNumberOfDimensions(data);
		nim->dim[0] = nim->ndim;
		const int *dims = mxGetDimensions(data);
		for(i=0; i<nim->ndim; i++) nim->dim[i+1] = dims[i];
		for(i=nim->ndim+1; i<8; i++) nim->dim[i] = 1;
		// Why do I have to assign these explicitly? 
		nim->nx = nim->dim[1];
		nim->ny = nim->dim[2];
		nim->nz = nim->dim[3];
		nim->nt = nim->dim[4];
		nim->nu = nim->dim[5];
		nim->nv = nim->dim[6];
		nim->nw = nim->dim[7];
		//for(i=0; i<8; i++) mexPrintf("%d ",nim->dim[i]); mexPrintf("\n\n");

		nim->nvox = mxGetNumberOfElements(data);
		// *** TO DO: we should support DT_RGB24 type (triplet of uint8)
		if(mxIsComplex(data)){
			switch(mxGetClassID(data)){
			case mxSINGLE_CLASS: nim->datatype=DT_COMPLEX64; nim->nbyper=8; break;
			case mxDOUBLE_CLASS: nim->datatype=DT_COMPLEX128; nim->nbyper=16; break;
			default: myErrMsg("Unknown data type!");
			}
		}else{
			switch(mxGetClassID(data)){
			case mxUINT8_CLASS: nim->datatype=DT_UINT8; nim->nbyper=1; break;
			case mxINT8_CLASS: nim->datatype=DT_INT8; nim->nbyper=1; break;
			case mxUINT16_CLASS: nim->datatype=DT_UINT16; nim->nbyper=2; break;
			case mxINT16_CLASS: nim->datatype=DT_INT16; nim->nbyper=2; break;
			case mxUINT32_CLASS: nim->datatype=DT_UINT32; nim->nbyper=4; break;
			case mxINT32_CLASS: nim->datatype=DT_INT32; nim->nbyper=4; break;
			case mxUINT64_CLASS: nim->datatype=DT_UINT64; nim->nbyper=8; break;
			case mxINT64_CLASS: nim->datatype=DT_INT64; nim->nbyper=8; break;
			case mxSINGLE_CLASS: nim->datatype=DT_FLOAT32; nim->nbyper=4; break;
			case mxDOUBLE_CLASS: nim->datatype=DT_FLOAT64; nim->nbyper=8; break;
			default: mexErrMsgTxt("Unknown data type!");
			}
		}

		double *pdPtr = (double *)mxGetData(mxGetField(mxnim,0,"pixdim"));
		int nPixDim = mxGetM(mxGetField(mxnim,0,"pixdim"))*mxGetN(mxGetField(mxnim,0,"pixdim"));
		if(nPixDim>8) nPixDim=8;
		for(i=0; i<nPixDim; i++) nim->pixdim[i+1] = (float)pdPtr[i];
		// xxx dla fixed bug below (i was not being assigned).
		//  for(nPixDim+1; i<8; i++) nim->pixdim[i] = (float)1.0;
		for(i = nPixDim+1; i<8; i++) nim->pixdim[i] = (float)1.0;
		nim->dx = nim->pixdim[1]; 
		nim->dy = nim->pixdim[2];
		nim->dz = nim->pixdim[3];
		nim->dt = nim->pixdim[4];
		nim->du = nim->pixdim[5];
		nim->dv = nim->pixdim[6];
		nim->dw = nim->pixdim[7];

		nim->scl_slope = mxGetScalar(mxGetField(mxnim,0,"scl_slope"));
		nim->scl_inter = mxGetScalar(mxGetField(mxnim,0,"scl_inter"));
		nim->cal_min = mxGetScalar(mxGetField(mxnim,0,"cal_min"));
		nim->cal_max = mxGetScalar(mxGetField(mxnim,0,"cal_max"));
		nim->qform_code = (int)mxGetScalar(mxGetField(mxnim,0,"qform_code"));
		nim->sform_code = (int)mxGetScalar(mxGetField(mxnim,0,"sform_code"));
		nim->freq_dim = (int)mxGetScalar(mxGetField(mxnim,0,"freq_dim"));
		nim->phase_dim = (int)mxGetScalar(mxGetField(mxnim,0,"phase_dim"));
		nim->slice_dim = (int)mxGetScalar(mxGetField(mxnim,0,"slice_dim"));
		nim->slice_code = (int)mxGetScalar(mxGetField(mxnim,0,"slice_code"));
		nim->slice_start = (int)mxGetScalar(mxGetField(mxnim,0,"slice_start"));
		nim->slice_end = (int)mxGetScalar(mxGetField(mxnim,0,"slice_end"));
		nim->slice_duration = mxGetScalar(mxGetField(mxnim,0,"slice_duration"));
    /* if qform_code > 0, the quatern_*, qoffset_*, and qfac fields determine
     * the qform output, NOT the qto_xyz matrix; if you want to compute these
     * fields from the qto_xyz matrix, you can use the utility function
     * nifti_mat44_to_quatern() */
		nim->quatern_b = mxGetScalar(mxGetField(mxnim,0,"quatern_b"));
		nim->quatern_c = mxGetScalar(mxGetField(mxnim,0,"quatern_c"));
		nim->quatern_d = mxGetScalar(mxGetField(mxnim,0,"quatern_d"));
		nim->qoffset_x = mxGetScalar(mxGetField(mxnim,0,"qoffset_x"));
		nim->qoffset_y = mxGetScalar(mxGetField(mxnim,0,"qoffset_y"));
		nim->qoffset_z = mxGetScalar(mxGetField(mxnim,0,"qoffset_z"));
		nim->qfac = mxGetScalar(mxGetField(mxnim,0,"qfac"));
		nim->pixdim[0] = nim->qfac; // pixdim[0] is the same as qfac (again- why duplicate the field?)

		double *sxPtr = (double *)mxGetData(mxGetField(mxnim,0,"sto_xyz"));
		for(i=0; i<16; i++) nim->sto_xyz.m[i%4][i/4] = (float)sxPtr[i];

		nim->toffset = mxGetScalar(mxGetField(mxnim,0,"toffset"));
		// Allow units to be specified as a string
		char str[16]; 
		mxGetString(mxGetField(mxnim,0,"xyz_units"),str,16);
		nim->xyz_units = getNiftiUnitCode(str);
		mxGetString(mxGetField(mxnim,0,"time_units"),str,16);
		nim->time_units = getNiftiUnitCode(str);
		nim->intent_code = (int)mxGetScalar(mxGetField(mxnim,0,"intent_code"));
		nim->intent_p1 = mxGetScalar(mxGetField(mxnim,0,"intent_p1"));
		nim->intent_p2 = mxGetScalar(mxGetField(mxnim,0,"intent_p2"));
		nim->intent_p3 = mxGetScalar(mxGetField(mxnim,0,"intent_p3"));
		mxGetString(mxGetField(mxnim,0,"intent_name"), nim->intent_name, 16);
		mxGetString(mxGetField(mxnim,0,"descrip"), nim->descrip, 80);
		mxGetString(mxGetField(mxnim,0,"aux_file"), nim->aux_file, 24);
		// *** TO DO: support extended header fileds!
		nim->num_ext = 0;

		/* I assume that we can rely on the nifti routine to byte-swap for us? */
		nifti_image_write(nim);
}