static int normalize_timepoints_with_samples(MRI *mri, GCA_SAMPLE *gcas, int nsamples, int nsoap) { int frame, i, x, y, z ; double target, val ; MRI *mri_ctrl, *mri_bias, *mri_target, *mri_frame ; mri_ctrl = MRIcloneDifferentType(mri, MRI_UCHAR) ; mri_bias = MRIcloneDifferentType(mri, MRI_FLOAT) ; mri_target = MRIcloneDifferentType(mri, MRI_FLOAT) ; for (i = 0 ; i < nsamples ; i++) { if (i == Gdiag_no) DiagBreak() ; x = nint(gcas[i].x) ; y = nint(gcas[i].y) ; z = nint(gcas[i].z) ; MRIsetVoxVal(mri_ctrl, x, y, z, 0, CONTROL_MARKED) ; for (target = 0.0, frame = 0 ; frame < mri->nframes ; frame++) target += MRIgetVoxVal(mri, x, y, z, frame) ; target /= mri->nframes ; MRIsetVoxVal(mri_target, x, y, z, 0, target) ; } // build a bias correction for each time point (which each has its own frame) for (frame = 0 ; frame < mri->nframes ; frame++) { MRIclear(mri_bias) ; for (i = 0 ; i < nsamples ; i++) { if (i == Gdiag_no) DiagBreak() ; x = nint(gcas[i].x) ; y = nint(gcas[i].y) ; z = nint(gcas[i].z) ; target = MRIgetVoxVal(mri_target, x, y, z, 0) ; val = MRIgetVoxVal(mri, x, y, z, frame) ; if (FZERO(val)) val = 1.0 ; MRIsetVoxVal(mri_bias, x, y, z, 0, target/val) ; } MRIbuildVoronoiDiagram(mri_bias, mri_ctrl, mri_bias) ; MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, nsoap) ; mri_frame = MRIcopyFrame(mri, NULL, frame, 0) ; MRImultiply(mri_frame, mri_bias, mri_frame) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { char fname[STRLEN] ; sprintf(fname, "frame%d.mgz", frame) ; MRIwrite(mri_frame, fname) ; sprintf(fname, "bias%d.mgz", frame) ; MRIwrite(mri_bias, fname) ; sprintf(fname, "target%d.mgz", frame) ; MRIwrite(mri_target, fname) ; } MRIcopyFrame(mri_frame, mri, 0, frame) ; } MRIfree(&mri_bias) ; MRIfree(&mri_target) ; MRIfree(&mri_ctrl) ; return(NO_ERROR) ; }
int main(int argc, char *argv[]) { char **av ; int ac, nargs, n ; MRI *mri_src, *mri_dst = NULL, *mri_bias, *mri_orig, *mri_aseg = NULL ; char *in_fname, *out_fname ; int msec, minutes, seconds ; struct timeb start ; char cmdline[CMD_LINE_LEN] ; make_cmd_version_string (argc, argv, "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $", "$Name: $", cmdline); /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_normalize.c,v 1.80 2012/10/16 21:38:35 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; mni.max_gradient = MAX_GRADIENT ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) { usage_exit(0) ; } if (argc < 1) { ErrorExit(ERROR_BADPARM, "%s: no input name specified", Progname) ; } in_fname = argv[1] ; if (argc < 2) { ErrorExit(ERROR_BADPARM, "%s: no output name specified", Progname) ; } out_fname = argv[2] ; if(verbose) { printf( "reading from %s...\n", in_fname) ; } mri_src = MRIread(in_fname) ; if (!mri_src) ErrorExit(ERROR_NO_FILE, "%s: could not open source file %s", Progname, in_fname) ; MRIaddCommandLine(mri_src, cmdline) ; if(nsurfs > 0) { MRI_SURFACE *mris ; MRI *mri_dist=NULL, *mri_dist_sup=NULL, *mri_ctrl, *mri_dist_one ; LTA *lta= NULL ; int i ; TRANSFORM *surface_xform ; if (control_point_fname) // do one pass with only file control points first { MRI3dUseFileControlPoints(mri_src, control_point_fname) ; mri_dst = MRI3dGentleNormalize(mri_src, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, NULL, intensity_above, intensity_below/2,1, bias_sigma, mri_not_control); } else { mri_dst = MRIcopy(mri_src, NULL) ; } for (i = 0 ; i < nsurfs ; i++) { mris = MRISread(surface_fnames[i]) ; if (mris == NULL) ErrorExit(ERROR_NOFILE,"%s: could not surface %s", Progname,surface_fnames[i]); surface_xform = surface_xforms[i] ; TransformInvert(surface_xform, NULL) ; if (surface_xform->type == MNI_TRANSFORM_TYPE || surface_xform->type == TRANSFORM_ARRAY_TYPE || surface_xform->type == REGISTER_DAT) { lta = (LTA *)(surface_xform->xform) ; #if 0 if (invert) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { printf( "WARNING:***************************************************************\n"); printf( "WARNING:dst volume infor is invalid. Most likely produce wrong inverse.\n"); printf( "WARNING:***************************************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } #endif } if (stricmp(surface_xform_fnames[i], "identity.nofile") != 0) { MRIStransform(mris, NULL, surface_xform, NULL) ; } mri_dist_one = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ; printf("computing distance transform\n") ; MRIScomputeDistanceToSurface(mris, mri_dist_one, mri_dist_one->xsize) ; if (i == 0) { mri_dist = MRIcopy(mri_dist_one, NULL) ; } else { MRIcombineDistanceTransforms(mri_dist_one, mri_dist, mri_dist) ; } // MRIminAbs(mri_dist_one, mri_dist, mri_dist) ; MRIfree(&mri_dist_one) ; } MRIscalarMul(mri_dist, mri_dist, -1) ; if (nonmax_suppress) { printf("computing nonmaximum suppression\n") ; mri_dist_sup = MRInonMaxSuppress(mri_dist, NULL, 0, 1) ; mri_ctrl = MRIcloneDifferentType(mri_dist_sup, MRI_UCHAR) ; MRIbinarize(mri_dist_sup, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; } else if (erode) { int i ; mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ; MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; for (i = 0 ; i < erode ; i++) { MRIerode(mri_ctrl, mri_ctrl) ; } } else { mri_ctrl = MRIcloneDifferentType(mri_dist, MRI_UCHAR) ; MRIbinarize(mri_dist, mri_ctrl, min_dist, CONTROL_NONE, CONTROL_MARKED) ; } if (control_point_fname) { MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ; } if (mask_sigma > 0) { MRI *mri_smooth, *mri_mag, *mri_grad ; mri_smooth = MRIgaussianSmooth(mri_dst, mask_sigma, 1, NULL) ; mri_mag = MRIcloneDifferentType(mri_dst, MRI_FLOAT) ; mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ; MRIbinarize(mri_mag, mri_mag, mask_thresh, 1, 0) ; MRImask(mri_ctrl, mri_mag, mri_ctrl, 0, CONTROL_NONE) ; MRIfree(&mri_grad) ; MRIfree(&mri_mag) ; MRIfree(&mri_smooth) ; } if (mask_orig_fname) { MRI *mri_orig ; mri_orig = MRIread(mask_orig_fname) ; MRIbinarize(mri_orig, mri_orig, mask_orig_thresh, 0, 1) ; MRImask(mri_ctrl, mri_orig, mri_ctrl, 0, CONTROL_NONE) ; MRIfree(&mri_orig) ; } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_dist, "d.mgz"); MRIwrite(mri_dist_sup, "dm.mgz"); MRIwrite(mri_ctrl, "c.mgz"); } MRIeraseBorderPlanes(mri_ctrl, 4) ; if (aseg_fname) { mri_aseg = MRIread(aseg_fname) ; if (mri_aseg == NULL) { ErrorExit(ERROR_NOFILE, "%s: could not load aseg from %s", Progname, aseg_fname) ; } remove_nonwm_voxels(mri_ctrl, mri_aseg, mri_ctrl) ; MRIfree(&mri_aseg) ; } else { remove_surface_outliers(mri_ctrl, mri_dist, mri_dst, mri_ctrl) ; } mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; if (mri_dist) { MRIfree(&mri_dist) ; } if (mri_dist_sup) { MRIfree(&mri_dist_sup) ; } if (bias_sigma> 0) { MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_bias, "b.mgz") ; } printf("smoothing bias field\n") ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_bias, "bs.mgz") ; } MRIfree(&mri_kernel); } MRIfree(&mri_ctrl) ; mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; printf("writing normalized volume to %s\n", out_fname) ; MRIwrite(mri_dst, out_fname) ; exit(0) ; } // end if(surface_fname) if (!mriConformed(mri_src) && conform > 0) { printf("unconformed source detected - conforming...\n") ; mri_src = MRIconform(mri_src) ; } if (mask_fname) { MRI *mri_mask ; mri_mask = MRIread(mask_fname) ; if (!mri_mask) ErrorExit(ERROR_NOFILE, "%s: could not open mask volume %s.\n", Progname, mask_fname) ; MRImask(mri_src, mri_mask, mri_src, 0, 0) ; MRIfree(&mri_mask) ; } if (read_flag) { MRI *mri_ctrl ; double scale ; mri_bias = MRIread(bias_volume_fname) ; if (!mri_bias) ErrorExit (ERROR_BADPARM, "%s: could not read bias volume %s", Progname, bias_volume_fname) ; mri_ctrl = MRIread(control_volume_fname) ; if (!mri_ctrl) ErrorExit (ERROR_BADPARM, "%s: could not read control volume %s", Progname, control_volume_fname) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, 128) ; mri_dst = MRImultiply(mri_bias, mri_src, NULL) ; scale = MRImeanInLabel(mri_dst, mri_ctrl, 128) ; printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ; scale = 110/scale ; MRIscalarMul(mri_dst, mri_dst, scale) ; MRIwrite(mri_dst, out_fname) ; exit(0) ; } if(long_flag) { MRI *mri_ctrl ; double scale ; mri_bias = MRIread(long_bias_volume_fname) ; if (!mri_bias) ErrorExit (ERROR_BADPARM, "%s: could not read bias volume %s", Progname, long_bias_volume_fname) ; mri_ctrl = MRIread(long_control_volume_fname) ; if (!mri_ctrl) ErrorExit (ERROR_BADPARM, "%s: could not read control volume %s", Progname, long_control_volume_fname) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, 0, CONTROL_MARKED) ; if (mri_ctrl->type != MRI_UCHAR) { MRI *mri_tmp ; mri_tmp = MRIchangeType(mri_ctrl, MRI_UCHAR, 0, 1,1); MRIfree(&mri_ctrl) ; mri_ctrl = mri_tmp ; } scale = MRImeanInLabel(mri_src, mri_ctrl, CONTROL_MARKED) ; printf("mean in wm is %2.0f, scaling by %2.2f\n", scale, 110/scale) ; scale = DEFAULT_DESIRED_WHITE_MATTER_VALUE/scale ; mri_dst = MRIscalarMul(mri_src, NULL, scale) ; MRIremoveWMOutliers(mri_dst, mri_ctrl, mri_ctrl, intensity_below/2) ; mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; MRIsoapBubble(mri_bias, mri_ctrl, mri_bias, 50, 1) ; MRIapplyBiasCorrectionSameGeometry(mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE); // MRIwrite(mri_dst, out_fname) ; // exit(0) ; } // end if(long_flag) if (grad_thresh > 0) { float thresh ; MRI *mri_mag, *mri_grad, *mri_smooth ; MRI *mri_kernel = MRIgaussian1d(.5, -1) ; mri_not_control = MRIcloneDifferentType(mri_src, MRI_UCHAR) ; switch (scan_type) { case MRI_MGH_MPRAGE: thresh = 15 ; break ; case MRI_WASHU_MPRAGE: thresh = 20 ; break ; case MRI_UNKNOWN: default: thresh = 12 ; break ; } mri_smooth = MRIconvolveGaussian(mri_src, NULL, mri_kernel) ; thresh = grad_thresh ; mri_mag = MRIcloneDifferentType(mri_src, MRI_FLOAT) ; mri_grad = MRIsobel(mri_smooth, NULL, mri_mag) ; MRIwrite(mri_mag, "m.mgz") ; MRIbinarize(mri_mag, mri_not_control, thresh, 0, 1) ; MRIwrite(mri_not_control, "nc.mgz") ; MRIfree(&mri_mag) ; MRIfree(&mri_grad) ; MRIfree(&mri_smooth) ; MRIfree(&mri_kernel) ; } #if 0 #if 0 if ((mri_src->type != MRI_UCHAR) || (!(mri_src->xsize == 1 && mri_src->ysize == 1 && mri_src->zsize == 1))) #else if (conform || (mri_src->type != MRI_UCHAR && conform > 0)) #endif { MRI *mri_tmp ; fprintf (stderr, "downsampling to 8 bits and scaling to isotropic voxels...\n") ; mri_tmp = MRIconform(mri_src) ; mri_src = mri_tmp ; } #endif if(aseg_fname) { printf("Reading aseg %s\n",aseg_fname); mri_aseg = MRIread(aseg_fname) ; if (mri_aseg == NULL) ErrorExit (ERROR_NOFILE, "%s: could not read aseg from file %s", Progname, aseg_fname) ; if (!mriConformed(mri_aseg)) { ErrorExit(ERROR_UNSUPPORTED, "%s: aseg volume %s must be conformed", Progname, aseg_fname) ; } } else { mri_aseg = NULL ; } if(verbose) { printf( "normalizing image...\n") ; } fflush(stdout); fflush(stderr); TimerStart(&start) ; if (control_point_fname) { MRI3dUseFileControlPoints(mri_src, control_point_fname) ; } // this just setup writing control-point volume saving if(control_volume_fname) { MRI3dWriteControlPoints(control_volume_fname) ; } /* first do a gentle normalization to get things in the right intensity range */ if(long_flag == 0) // if long, then this will already have been done with base control points { if(control_point_fname != NULL) /* do one pass with only file control points first */ mri_dst = MRI3dGentleNormalize(mri_src, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, NULL, intensity_above, intensity_below/2,1, bias_sigma, mri_not_control); else { mri_dst = MRIcopy(mri_src, NULL) ; } } fflush(stdout); fflush(stderr); if(mri_aseg) { MRI *mri_ctrl, *mri_bias ; int i ; printf("processing with aseg\n"); mri_ctrl = MRIclone(mri_aseg, NULL) ; for (i = 0 ; i < NWM_LABELS ; i++) { MRIcopyLabel(mri_aseg, mri_ctrl, aseg_wm_labels[i]) ; } printf("removing outliers in the aseg WM...\n") ; MRIremoveWMOutliersAndRetainMedialSurface(mri_dst, mri_ctrl, mri_ctrl, intensity_below) ; MRIbinarize(mri_ctrl, mri_ctrl, 1, CONTROL_NONE, CONTROL_MARKED) ; MRInormAddFileControlPoints(mri_ctrl, CONTROL_MARKED) ; if (interior_fname1) { MRIS *mris_interior1, *mris_interior2 ; mris_interior1 = MRISread(interior_fname1) ; if (mris_interior1 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname1) ; mris_interior2 = MRISread(interior_fname2) ; if (mris_interior2 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname2) ; add_interior_points(mri_ctrl, mri_dst, intensity_above, 1.25*intensity_below, mris_interior1, mris_interior2, mri_aseg, mri_ctrl) ; MRISfree(&mris_interior1) ; MRISfree(&mris_interior2) ; } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_ctrl, "norm_ctrl.mgz") ; } printf("Building bias image\n"); fflush(stdout); fflush(stderr); mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; fflush(stdout); fflush(stderr); if (bias_sigma> 0) { printf("Smoothing with sigma %g\n",bias_sigma); MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; MRIfree(&mri_kernel); fflush(stdout); fflush(stderr); } MRIfree(&mri_ctrl) ; MRIfree(&mri_aseg) ; printf("Applying bias correction\n"); mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_dst, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_dst, "norm_1.mgz") ; } fflush(stdout); fflush(stderr); } // if(mri_aseg) else { printf("processing without aseg, no1d=%d\n",no1d); if (!no1d) { printf("MRInormInit(): \n"); MRInormInit(mri_src, &mni, 0, 0, 0, 0, 0.0f) ; printf("MRInormalize(): \n"); mri_dst = MRInormalize(mri_src, NULL, &mni) ; if (!mri_dst) { no1d = 1 ; printf("1d normalization failed - trying no1d...\n") ; // ErrorExit(ERROR_BADPARM, "%s: normalization failed", Progname) ; } } if(no1d) { if ((file_only && nosnr) || ((gentle_flag != 0) && (control_point_fname != NULL))) { if (mri_dst == NULL) { mri_dst = MRIcopy(mri_src, NULL) ; } } else { if (nosnr) { if (interior_fname1) { MRIS *mris_interior1, *mris_interior2 ; MRI *mri_ctrl ; printf("computing initial normalization using surface interiors\n"); mri_ctrl = MRIcloneDifferentType(mri_src, MRI_UCHAR) ; mris_interior1 = MRISread(interior_fname1) ; if (mris_interior1 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname1) ; mris_interior2 = MRISread(interior_fname2) ; if (mris_interior2 == NULL) ErrorExit(ERROR_NOFILE, "%s: could not read white matter surface from %s\n", Progname, interior_fname2) ; add_interior_points(mri_ctrl, mri_dst, intensity_above, 1.25*intensity_below, mris_interior1, mris_interior2, mri_aseg, mri_ctrl) ; MRISfree(&mris_interior1) ; MRISfree(&mris_interior2) ; mri_bias = MRIbuildBiasImage(mri_dst, mri_ctrl, NULL, 0.0) ; if (bias_sigma> 0) { MRI *mri_kernel = MRIgaussian1d(bias_sigma, -1) ; MRIconvolveGaussian(mri_bias, mri_bias, mri_kernel) ; MRIfree(&mri_kernel); } mri_dst = MRIapplyBiasCorrectionSameGeometry (mri_src, mri_bias, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; MRIfree(&mri_ctrl) ; } else if (long_flag == 0) // no initial normalization specified { mri_dst = MRIcopy(mri_src, NULL) ; } } else { printf("computing initial normalization using SNR...\n") ; mri_dst = MRInormalizeHighSignalLowStd (mri_src, mri_dst, bias_sigma, DEFAULT_DESIRED_WHITE_MATTER_VALUE) ; } } if (!mri_dst) ErrorExit (ERROR_BADPARM, "%s: could not allocate volume", Progname) ; } } // else (not using aseg) fflush(stdout); fflush(stderr); if (file_only == 0) MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above, intensity_below/2, file_only, bias_sigma, mri_not_control); mri_orig = MRIcopy(mri_dst, NULL) ; printf("\n"); printf("Iterating %d times\n",num_3d_iter); for (n = 0 ; n < num_3d_iter ; n++) { if(file_only) { break ; } printf( "---------------------------------\n"); printf( "3d normalization pass %d of %d\n", n+1, num_3d_iter) ; if (gentle_flag) MRI3dGentleNormalize(mri_dst, NULL, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above/2, intensity_below/2, file_only, bias_sigma, mri_not_control); else MRI3dNormalize(mri_orig, mri_dst, DEFAULT_DESIRED_WHITE_MATTER_VALUE, mri_dst, intensity_above, intensity_below, file_only, prune, bias_sigma, scan_type, mri_not_control); } printf( "Done iterating ---------------------------------\n"); // this just setup writing control-point volume saving if(control_volume_fname) { MRI3dWriteControlPoints(control_volume_fname) ; } if(bias_volume_fname) { mri_bias = compute_bias(mri_src, mri_dst, NULL) ; printf("writing bias field to %s....\n", bias_volume_fname) ; MRIwrite(mri_bias, bias_volume_fname) ; MRIfree(&mri_bias) ; } if (verbose) { printf("writing output to %s\n", out_fname) ; } MRIwrite(mri_dst, out_fname) ; msec = TimerStop(&start) ; MRIfree(&mri_src); MRIfree(&mri_dst); seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; printf( "3D bias adjustment took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }
static int write_surface_warp_into_volume(MRI_SURFACE *mris, MRI *mri, int niter) { int vno, xvi, yvi, zvi, frame ; VERTEX *v ; double dx, dy, dz, xv, yv, zv, xv1, yv1, zv1 ; MRI *mri_weights, *mri_ctrl, *mri_frame ; float wt ; mri_weights = MRIallocSequence(mri->width, mri->height, mri->depth, MRI_FLOAT, 1) ; mri_ctrl = MRIallocSequence(mri->width, mri->height, mri->depth, MRI_UCHAR, 1) ; MRIcopyHeader(mri, mri_weights) ; MRIcopyHeader(mri, mri_ctrl) ; // build a 3 frame volume with the voxel-coords warp (dx, dy, dz) in frames 0, 1 and 2 respectively for (vno = 0 ; vno < mris->nvertices ; vno++) { v = &mris->vertices[vno] ; if (v->ripflag) continue ; MRISsurfaceRASToVoxelCached(mris, mri, v->origx, v->origy, v->origz, &xv, &yv, &zv) ; MRISsurfaceRASToVoxelCached(mris, mri, v->x, v->y, v->z, &xv1, &yv1, &zv1) ; dx = xv1-xv ; dy = yv1-yv ; dz = zv1-zv ; xvi = nint(xv) ; yvi = nint(yv) ; zvi = nint(zv) ; if (vno == Gdiag_no) { printf("surface vertex %d: inflated (%2.0f, %2.0f, %2.0f), orig (%2.0f, %2.0f, %2.0f), " "dx=(%2.0f, %2.0f, %2.0f)\n", vno, xv1, yv1, zv1, xv, yv, zv, dx, dy, dz) ; DiagBreak() ; } if (xvi < 0 || xvi >= mri->width || yv < 0 || yv >= mri->height || zv < 0 || zv >= mri->depth) { continue ; } MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 0, dx) ; MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 1, dy) ; MRIinterpolateIntoVolumeFrame(mri, xv, yv, zv, 2, dz) ; MRIinterpolateIntoVolume(mri_weights, xv, yv, zv, 1.0) ; } #if 0 // set boundary conditions in the edge planes to be 0 warping for (xvi = 0 ; xvi < mri->width ; xvi++) for (yvi = 0 ; yvi < mri->height ; yvi++) { MRIsetVoxVal(mri_ctrl, xvi, yvi, 0, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, xvi, yvi, 0, 0, 0) ; MRIsetVoxVal(mri, xvi, yvi, 0, 1, 0) ; MRIsetVoxVal(mri, xvi, yvi, 0, 2, 0) ; MRIsetVoxVal(mri_ctrl, xvi, yvi, mri->depth-1, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 0, 0) ; MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 1, 0) ; MRIsetVoxVal(mri, xvi, yvi, mri->depth-1, 2, 0) ; } for (xvi = 0 ; xvi < mri->width ; xvi++) for (zvi = 0 ; zvi < mri->depth ; zvi++) { MRIsetVoxVal(mri_ctrl, xvi, 0, zvi, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, xvi, 0, zvi, 0, 0) ; MRIsetVoxVal(mri, xvi, 0, zvi, 1, 0) ; MRIsetVoxVal(mri, xvi, 0, zvi, 2, 0) ; MRIsetVoxVal(mri_ctrl, xvi, mri->height-1, zvi, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 0, 0) ; MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 1, 0) ; MRIsetVoxVal(mri, xvi, mri->height-1, zvi, 2, 0) ; } for (yvi = 0 ; yvi < mri->width ; yvi++) for (zvi = 0 ; zvi < mri->depth ; zvi++) { MRIsetVoxVal(mri_ctrl, 0, yvi, zvi, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, 0, yvi, zvi, 0, 0) ; MRIsetVoxVal(mri, 0, yvi, zvi, 1, 0) ; MRIsetVoxVal(mri, 0, yvi, zvi, 2, 0) ; MRIsetVoxVal(mri_ctrl, mri->width-1, yvi, zvi, 0, CONTROL_MARKED) ; MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 0, 0) ; MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 1, 0) ; MRIsetVoxVal(mri, mri->width-1, yvi, zvi, 2, 0) ; } #endif // normalize the warp field using a weighted average of all vertices that map to every voxel for (xvi = 0 ; xvi < mri->width ; xvi++) for (yvi = 0 ; yvi < mri->height ; yvi++) for (zvi = 0 ; zvi < mri->depth ; zvi++) { if (xvi == Gx && yvi == Gy && zvi == Gz) DiagBreak() ; wt = MRIgetVoxVal(mri_weights, xvi, yvi, zvi, 0) ; dx = MRIgetVoxVal(mri, xvi, yvi, zvi, 0) ; dy = MRIgetVoxVal(mri, xvi, yvi, zvi, 1) ; dz = MRIgetVoxVal(mri, xvi, yvi, zvi, 2) ; if (FZERO(wt)) continue ; dx /= wt ; dy /= wt ; dz /= wt ; MRIsetVoxVal(mri, xvi, yvi, zvi, 0, dx) ; MRIsetVoxVal(mri, xvi, yvi, zvi, 1, dy) ; MRIsetVoxVal(mri, xvi, yvi, zvi, 2, dz) ; MRIsetVoxVal(mri_ctrl, xvi, yvi, zvi, 0, CONTROL_MARKED) ; // it is a control point } if (Gdiag & DIAG_WRITE) { MRIwrite(mri, "warp0.mgz") ; MRIwrite(mri_ctrl, "ctrl.mgz") ; } for (frame = 0 ; frame < mri->nframes ; frame++) { printf("interpolating frame %d\n", frame+1) ; mri_frame = MRIcopyFrame(mri, NULL, frame, 0) ; MRIbuildVoronoiDiagram(mri_frame, mri_ctrl, mri_frame) ; MRIsoapBubble(mri_frame, mri_ctrl, mri_frame, niter, mri_frame->xsize*.05) ; #if 0 { int x, y, z ; float val ; for (x = 0 ; x < mri_frame->width ; x++) for (y = 0 ; y < mri_frame->height ; y++) for (z = 0 ; z < mri_frame->depth ; z++) { val = MRIgetVoxVal(mri_frame, x, y, z, 0) ; switch (frame) { default: case 0: val += x ; break ; case 1: val += y ; break ; case 2: val += z ; break ; } MRIsetVoxVal(mri_frame, x, y, z, 0, val) ; } } #endif MRIcopyFrame(mri_frame, mri, 0, frame) ; MRIfree(&mri_frame) ; } MRIfree(&mri_weights) ; MRIfree(&mri_ctrl) ; return(NO_ERROR) ; }