/*----------------------------------------------------- Parameters: Returns value: Description ------------------------------------------------------*/ int MRIsegmentDilate(MRI_SEGMENTATION *mriseg, MRI *mri) { int x, y, z, xk, yk, zk, xi, yi, zi, segno, v, nvox ; MRI_SEGMENT *mseg ; MRI *mri_segments ; float voxel_size ; voxel_size = mri->xsize * mri->ysize * mri->zsize ; mri_segments = MRIclone(mri, NULL) ; /* build image of all other segments to prevent dilation from expanding into other segments */ for (segno = 0 ; segno < mriseg->nsegments ; segno++) MRIsegmentToImage(mri, mri_segments, mriseg, segno) ; for (segno = 0 ; segno < mriseg->nsegments ; segno++) { mseg = &mriseg->segments[segno] ; nvox = mseg->nvoxels ; for (v = 0 ; v < nvox ; v++) { x = mseg->voxels[v].x ; y = mseg->voxels[v].y ; z = mseg->voxels[v].z ; for (xk = -1 ; xk <= 1 ; xk++) { xi = mri->xi[x+xk] ; for (yk = -1 ; yk <= 1 ; yk++) { yi = mri->yi[y+yk] ; for (zk = -1 ; zk <= 1 ; zk++) { if ((fabs(xk) + fabs(yk) + fabs(zk)) != 1) continue ; zi = mri->zi[z+zk] ; if (MRIgetVoxVal(mri, xi, yi, zi,0) && !MRIgetVoxVal(mri_segments,xi,yi,zi,0)) { if (mseg->nvoxels >= mseg->max_voxels) { if (mriSegmentReallocateVoxels (mriseg, segno, mseg->max_voxels*VOX_INCREASE) != NO_ERROR) { /* MRIsegmentFree(&mseg) ;*/ return(Gerror) ; } } mseg->voxels[mseg->nvoxels].x = xi ; mseg->voxels[mseg->nvoxels].y = yi ; mseg->voxels[mseg->nvoxels].z = zi ; MRIsetVoxVal(mri_segments,xi,yi,zi, 0, MRIgetVoxVal(mri, xi, yi, zi,0)) ; mseg->nvoxels++ ; mseg->area += voxel_size ; } } } } } } MRIfree(&mri_segments) ; return(NO_ERROR) ; }
MRI * MRIfillVentricles(MRI *mri_src, MRI *mri_dst) { int width, height, depth, x, y, z, xk, yk, xi, yi, nfilled, total, s ; MRI *mri_filled, *mri_ventricles = NULL ; MRI_SEGMENTATION *mriseg ; MRI_SEGMENT *mseg ; Real xt, yt, zt ; if (!mri_dst) { mri_dst = MRIclone(mri_src, NULL) ; } width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ; MRIcopy(mri_src, mri_dst) ; mri_filled = MRIcopy(mri_src, NULL) ; MRIreplaceValues(mri_filled, mri_filled, VENTRICLE_FILL, VENTRICLE_FILL-1) ; /* first fill each coronal slice starting from a background seed */ for (z = 0 ; z < depth ; z++) { total = 0 ; do { nfilled = 0 ; MRIsetVoxVal(mri_filled, 0, 0, z, 0, VENTRICLE_FILL) ; for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { if (MRIgetVoxVal(mri_filled, x, y, z, 0) == VENTRICLE_FILL) { for (yk = -1 ; yk <= 1 ; yk++) { yi = mri_src->yi[y+yk] ; for (xk = -1 ; xk <= 1 ; xk++) { xi = mri_src->xi[x+xk] ; if (!MRIgetVoxVal(mri_filled, xi, yi, z, 0)) { nfilled++ ; MRIsetVoxVal(mri_filled, xi, yi, z, 0, VENTRICLE_FILL) ; } } } } } } total += nfilled ; } while (nfilled > 0) ; } MRIcomplement(mri_filled, mri_filled) ; MRIreplaceValues(mri_filled, mri_filled, 1, VENTRICLE_FILL) ; mriseg = MRIsegment(mri_filled, 1, 255) ; fprintf(stderr, "%d segments found...\n", mriseg->nsegments) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_filled, "exterior_filled.mgh") ; } for (s = 0 ; s < mriseg->nsegments ; s++) { mseg = &mriseg->segments[s] ; if (mseg->nvoxels < 100 || mseg->z1-mseg->z0 < 7) { continue ; } MRIvoxelToTalairach(mri_src, mseg->cx, mseg->cy, mseg->cz, &xt, &yt, &zt); fprintf(stderr, "added segment %d, nvox=%d, bbox [%d:%d, %d:%d, %d:%d]\n" "\tc = %2.1f, %2.1f, %2.1f (tal = %2.1f, %2.1f, %2.1f)\n", s, mseg->nvoxels, mseg->x0, mseg->x1, mseg->y0,mseg->y1,mseg->z0, mseg->z1, mseg->cx, mseg->cy, mseg->cz, xt, yt, zt) ; mri_ventricles = MRIsegmentToImage(mri_filled, mri_ventricles, mriseg, s) ; } MRIfree(&mri_filled) ; MRIsegmentFree(&mriseg) ; /* remove voxels close to the midline so that the cc can still be found */ for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { MRIvoxelToTalairach(mri_src, x, y, z, &xt, &yt, &zt); if (fabs(xt) < 5) { MRIsetVoxVal(mri_ventricles, x, y, z, 0, 0) ; } } } } if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_ventricles, "ventricles.mgh") ; } MRIunion(mri_ventricles, mri_dst, mri_dst) ; MRIfree(&mri_ventricles) ; return(mri_dst) ; }
MRI * MRIfillBasalGanglia(MRI *mri_src, MRI *mri_dst) { float low_thresh, hi_thresh ; int total_filled, depth, height, width, x, y, z, xi, yi, zi, xk, yk, zk, fill, val0, val, i ; MRI *mri_bg ; Real tx, ty, tz ; MRI_SEGMENTATION *mriseg ; MRI_SEGMENT *mseg ; float dx_left, dx_right, dy, dz, dist_left, dist_right ; if (!mri_dst) { mri_dst = MRIcopy(mri_src, NULL) ; } mri_bg = MRIclone(mri_src, NULL) ; width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ; low_thresh = 85 ; hi_thresh = 105 ; total_filled = 0 ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { if (x == 152 && y == 117 && z == 132) /* 93 */ { DiagBreak() ; } val0 = MRIgetVoxVal(mri_src, x, y, z, 0) ; #if 0 if (val0 >= low_thresh && val0 <= hi_thresh && MRIvox(mri_dst,x,y,z) < WM_MIN_VAL) #else if (val0 >= 85 && val0 <= 105) #endif { #undef WHALF #undef WSIZE #define WSIZE 7 #define WHALF ((WSIZE-1)/2) fill = 1 ; for (zk = -WHALF ; fill && zk <= WHALF ; zk++) { zi = mri_src->zi[z+zk] ; for (yk = -WHALF ; fill && yk <= WHALF ; yk++) { yi = mri_src->yi[y+yk] ; for (xk = -WHALF ; fill && xk <= WHALF ; xk++) { xi = mri_src->xi[x+xk] ; val = MRIgetVoxVal(mri_src, xi, yi, zi, 0) ; if (val < 85 || val > 110) { fill = 0 ; /* not homogeneous enough */ } } } } } else { fill = 0 ; } if (fill) { total_filled++ ; } if (fill) { MRIsetVoxVal(mri_bg, x, y, z, 0, BASAL_GANGLIA_FILL) ; } } } } MRIclose(mri_bg, mri_bg) ; /* remove small holes */ /* segment into connected components */ mriseg = MRIsegment(mri_bg, 1, 255) ; fprintf(stderr, "segmenting thick gray regions: %d %d mm segments found\n", mriseg->nsegments, WSIZE) ; /* dilate into regions that are not on */ for (i = 0 ; i < 2*WSIZE ; i++) { MRIsegmentDilateThreshold(mriseg, mri_src, mri_src, 80, 100) ; } /* fill basal ganglia components */ MRIclear(mri_bg) ; for (total_filled = i = 0 ; i < mriseg->nsegments ; i++) { #define TAL_BG_LEFT_X -30 #define TAL_BG_RIGHT_X 30 #define TAL_BG_Y 5 #define TAL_BG_Z 5 #define MAX_DIST 25 mseg = &mriseg->segments[i] ; MRIvoxelToTalairach(mri_src, mseg->cx, mseg->cy, mseg->cz,&tx, &ty,&tz); dx_left = tx - TAL_BG_LEFT_X ; dx_right = tx - TAL_BG_RIGHT_X ; dy = ty - TAL_BG_Y ; dz = tz - TAL_BG_Z ; dist_left = sqrt(dx_left*dx_left+dy*dy+dz*dz) ; dist_right = sqrt(dx_right*dx_right+dy*dy+dz*dz) ; if (dist_left > MAX_DIST && dist_right > MAX_DIST) { continue ; } fprintf(stderr, "filling segment %d with %d voxels\n\tc = " "(%2.1f,%2.1f,%2.1f) tal (%2.1f,%2.1f,%2.1f), dist %2.1f,%2.1f\n", i, mseg->nvoxels, mseg->cx, mseg->cy, mseg->cz, tx, ty, tz, dist_left, dist_right) ; MRIsegmentToImage(mri_src, mri_bg, mriseg, i) ; total_filled += mseg->nvoxels ; } #if 1 /* MRIremoveIslands(mri_bg, mri_bg, 3, .56) ;*/ MRIbinarize(mri_bg, mri_bg, WM_MIN_VAL, 0, BASAL_GANGLIA_FILL) ; #endif MRIsegmentFree(&mriseg) ; MRIunion(mri_dst, mri_bg, mri_dst) ; MRIfree(&mri_bg) ; if (Gdiag & DIAG_SHOW) { fprintf(stderr, "%d basal ganglia points filled\n", total_filled); } return(mri_dst) ; }
int main(int argc, char *argv[]) { char **av, fname[STRLEN], *T1_fname, *PD_fname, *output_dir, *mdir ; int ac, nargs, msec, s ; MRI_SURFACE *mris ; MRI *mri_flash1, *mri_flash2, *mri_masked, *mri_masked_smooth, *mri_kernel, *mri_mean, *mri_dif, *mri_binary, *mri_distance ; MRI *mri_smooth, *mri_grad, *mri_inner ; struct timeb then ; double l_spring ; MRI_SEGMENTATION *mriseg ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mris_AA_shrinkwrap.c,v 1.5 2011/03/02 00:04:34 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Gdiag |= DIAG_SHOW ; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; memset(&parms, 0, sizeof(parms)) ; parms.projection = NO_PROJECTION ; parms.tol = 0.05 ; parms.check_tol = 1 ; parms.ignore_energy = 1 ; parms.dt = 0.5f ; parms.base_dt = BASE_DT_SCALE*parms.dt ; parms.l_spring_norm = 1 ; parms.l_shrinkwrap = 0 ; parms.l_intensity = 1 ; parms.niterations = 0 ; parms.write_iterations = 0 /*WRITE_ITERATIONS */; parms.integration_type = INTEGRATE_MOMENTUM ; parms.momentum = 0.0 /*0.8*/ ; parms.l_intensity = 1 ; parms.dt_increase = 1.0 /* DT_INCREASE */; parms.dt_decrease = 0.50 /* DT_DECREASE*/ ; parms.error_ratio = 50.0 /*ERROR_RATIO */; /* parms.integration_type = INTEGRATE_LINE_MINIMIZE ;*/ parms.l_surf_repulse = 0.0 ; parms.l_repulse = 0 /*1*/ ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } mdir = getenv("FREESURFER_HOME") ; if (!mdir) ErrorExit(ERROR_BADPARM, "FREESURFER_HOME not defined in environment") ; if (argc < 4) usage_exit() ; /* set default parameters for white and gray matter surfaces */ parms.niterations = 1000 ; if (parms.momentum < 0.0) parms.momentum = 0.0 /*0.75*/ ; TimerStart(&then) ; T1_fname = argv[1] ; PD_fname = argv[2] ; output_dir = argv[3] ; fprintf(stderr, "reading volume %s...\n", T1_fname) ; mri_flash1 = MRIread(T1_fname) ; if (!mri_flash1) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s", Progname, T1_fname) ; mri_flash2 = MRIread(PD_fname) ; if (!mri_flash2) ErrorExit(ERROR_NOFILE, "%s: could not read input volume %s", Progname, T1_fname) ; // setMRIforSurface(mri_flash1); sprintf(fname, "%s/lib/bem/ic%d.tri", mdir, ic_init) ; mris = MRISread(fname) ; if (!mris) ErrorExit(ERROR_NOFILE, "%s: could not read icosahedron %s", Progname, fname) ; mri_mean = MRImean(mri_flash1, NULL, 5) ; MRIwrite(mri_mean, "mean.mgz") ; mri_dif = MRIabsdiff(mri_flash1, mri_flash2, NULL) ; MRIwrite(mri_dif, "dif.mgz") ; mriseg = MRIsegment(mri_mean, 30, 100000) ; s = MRIsegmentMax(mriseg) ; mri_masked = MRIsegmentToImage(mri_flash1, NULL, mriseg, s) ; MRIwrite(mri_masked, "mask.mgz") ; MRIsegmentFree(&mriseg) ; // MRIthresholdMask(mri_dif, mri_masked, mri_dif, 1, 0) ; // MRIwrite(mri_dif, "dif_masked.mgz") ; mri_kernel = MRIgaussian1d(2, 0) ; mri_smooth = MRIconvolveGaussian(mri_dif, NULL, mri_kernel) ; MRIwrite(mri_smooth, "smooth.mgz") ; MRIScopyVolGeomFromMRI(mris, mri_smooth) ; mris->useRealRAS = 1 ; initialize_surface_position(mris, mri_dif, 1, &parms) ; MRISwrite(mris, "init") ; MRISrepositionToInnerSkull(mris, mri_smooth, &parms) ; exit(0) ; mri_grad = MRIsobel(mri_smooth, NULL, NULL) ; MRIwrite(mri_grad, "grad.mgz") ; mri_inner = MRIfindInnerBoundary(mri_dif, mri_grad, NULL, 5.0) ; MRIwrite(mri_inner, "inner.mgz") ; MRIbinarize(mri_inner, mri_inner, 10, 0, 128) ; MRISpositionOptimalSphere(mris, mri_inner, 6) ; MRISwrite(mris, "optimal") ; exit(0) ; parms.sigma = 4 / mri_flash1->xsize ; // mri_dist = create_distance_map(mri_masked, NULL, BORDER_VAL, OUTSIDE_BORDER_STEP) ; MRISsetVals(mris,parms.sigma) ; MRIScopyValToVal2(mris) ; MRISsetVals(mris, 0) ; sprintf(parms.base_name, "%s_inner_skull%s%s", "test", output_suffix, suffix) ; parms.mri_brain = mri_masked ; l_spring = parms.l_spring_norm ; mri_kernel = MRIgaussian1d(parms.sigma, 0) ; mri_binary = MRIbinarize(mri_dif, mri_binary, 40, 0, 128) ; MRIwrite(mri_binary, "bin.mgz") ; mri_distance = MRIdistanceTransform(mri_binary, NULL, 128, 100, DTRANS_MODE_SIGNED, NULL) ; MRIwrite(mri_distance, "dist.mgz") ; mri_masked_smooth = MRIconvolveGaussian(mri_distance, NULL, mri_kernel) ; MRIfree(&mri_kernel) ; MRIwrite(mri_masked_smooth, "dif_smooth.mgz") ; MRISwrite(mris, "inner_skull.tri") ; msec = TimerStop(&then) ; fprintf(stderr,"positioning took %2.1f minutes\n", (float)msec/(60*1000.0f)); exit(0) ; return(0) ; /* for ansi */ }