/*! \fn int CCSegment(MRI *seg, int segid, int segidunknown) Constraints a sementation ID to consist of voxels that are spatially contiguous (6 face neighbors, not edge or corner). The voxels in the largest cluster are not changed. The voxels in the other clusters are set to segidunknown. */ int CCSegment(MRI *seg, int segid, int segidunknown) { MRI_SEGMENTATION *sgmnt; int k,kmax,index,c,r,s; sgmnt = MRIsegment(seg,segid-.5,segid+.5); printf(" Found %d clusters\n",sgmnt->nsegments); kmax = 0; for (k=0; k < sgmnt->nsegments; k++) if (sgmnt->segments[k].nvoxels > sgmnt->segments[kmax].nvoxels) { kmax = k; } for (k=0; k < sgmnt->nsegments; k++) { printf(" %d k %f\n",k,sgmnt->segments[k].area); if (k==kmax) { continue; } for (index = 0; index < sgmnt->segments[k].nvoxels; index++) { c = sgmnt->segments[k].voxels[index].x; r = sgmnt->segments[k].voxels[index].y; s = sgmnt->segments[k].voxels[index].z; MRIsetVoxVal(seg,c,r,s,0,segidunknown); } } MRIsegmentFree(&sgmnt); return(0); }
MRI_SEGMENTATION * MRIsegment(MRI *mri, float low_val, float hi_val) { MRI_SEGMENTATION *mriseg ; MRI_SEGMENT *mseg, *mseg2 ; int x, y, z, width, height, depth, xi, yi, zi, xk, yk, zk, border_labels[NBR_VOX], nlabels, label, nvox ; MRI *mri_labeled ; float voxel_size, val ; int max; int count =0; voxel_size = mri->xsize * mri->ysize * mri->zsize ; width = mri->width ; height = mri->height ; depth = mri->depth ; mriseg = MRIsegmentAlloc(MAX_SEGMENTS, MAX_VOXELS) ; mriseg->mri = mri ; /* mri_labeled will contain the label number for each voxel (if it has been assigned to a segment). */ mri_labeled = MRIalloc(width, height, depth, MRI_SHORT) ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) MRISvox(mri_labeled, x, y, z) = -1 ; } } for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { val = MRIgetVoxVal(mri, x, y, z, 0) ; // if within the range if (val >= low_val && val <= hi_val) { count++; // initializer for border_labels memset(border_labels, -1, NBR_VOX*sizeof(int)) ; for (nvox = 0, zk = -1 ; zk <= 1 ; zk++) { zi = z+zk ; if ((zi < 0) || (zi >= depth)) continue ; for (yk = -1 ; yk <= 1 ; yk++) { yi = y+yk ; if ((yi < 0) || (yi >= height)) continue ; // increment nvox count here for (xk = -1 ; xk <= 1 ; xk++, nvox++) { #if 1 if ((abs(xk) + abs(yk) + abs(zk)) > 1) continue ; /* only allow 4 (6 in 3-d) connectivity */ #endif xi = x+xk ; if ((xi < 0) || (xi >= width)) continue ; // get the neighbor label label = MRISvox(mri_labeled, xi, yi, zi) ; if (label >= 0) border_labels[nvox] = label ; } } } // count nonzero labels in nbrs for (nlabels = nvox = 0 ; nvox < NBR_VOX ; nvox++) { label = border_labels[nvox] ; if ((label >= 0) && (!mriseg->segments[label].found)) { mriseg->segments[label].found = 1 ; nlabels++ ; } } // reset found for (nvox = 0 ; nvox < NBR_VOX ; nvox++) { label = border_labels[nvox] ; if (label >= 0) mriseg->segments[label].found = 0 ; /* for next time */ } // label = 0 ; // create labels for those points which are not connected switch (nlabels) { case 0: /* allocate a new segment */ label = mriSegmentNew(mriseg) ; // returns this added segment position mseg = &mriseg->segments[label] ; if (DIAG_VERBOSE_ON && 0) fprintf(stdout, "allocating new label %d (%d total)\n", label, mriseg->nsegments) ; break ; case 1: /* assign this voxel to the one that it borders */ for (nvox = 0 ; nvox < NBR_VOX ; nvox++) if (border_labels[nvox] >= 0) { label = border_labels[nvox] ; break ; } // points to the same label position mseg = &mriseg->segments[label] ; break ; default: /* merge segments and assign to lowest number */ mseg = NULL ; for (nvox = 0 ; nvox < NBR_VOX ; nvox++) { if (border_labels[nvox] >= 0) { // the 1st encountered label case if (!mseg) { // set the first index position label = border_labels[nvox] ; mseg = &mriseg->segments[label] ; mseg->found = 1 ; } // the rest else { mseg2 = &mriseg->segments[border_labels[nvox]] ; if (mseg2->found == 0) { mseg2->found = 1 ; /* prevent merging more than once */ // merge to the label position if (mriSegmentMerge(mriseg, label, border_labels[nvox], mri_labeled) != NO_ERROR) { // nsegments decreased by one MRIsegmentFree(&mriseg) ; return(NULL) ; } } } } } // reset found for (nvox = 0 ; nvox < NBR_VOX ; nvox++) if (border_labels[nvox] >= 0) mriseg->segments[border_labels[nvox]].found = 0 ; break ; } /* add it to the existing list */ if (mseg->nvoxels >= mseg->max_voxels) { // this max could be the same as mseg->max_voxels // this is taken care in mriSegmentReallocateVoxels() max = nint(mseg->max_voxels*VOX_INCREASE); // if (mriSegmentReallocateVoxels(mriseg, label, // nint(mseg->max_voxels*VOX_INCREASE)) // != NO_ERROR) if (mriSegmentReallocateVoxels(mriseg, label, max) != NO_ERROR) { MRIsegmentFree(&mriseg) ; return(NULL) ; } } mseg->voxels[mseg->nvoxels].x = x ; mseg->voxels[mseg->nvoxels].y = y ; mseg->voxels[mseg->nvoxels].z = z ; mseg->nvoxels++ ; mseg->area += voxel_size ; // voxel_size = volume #if 0 // this is for only 1mm voxel case if (mseg->nvoxels != (int)mseg->area) DiagBreak() ; #endif MRISvox(mri_labeled, x, y, z) = label ; } } } } MRIcompactSegments(mriseg) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON && 0) MRIwrite(mri_labeled, "labeled.mgh") ; MRIfree(&mri_labeled) ; mriComputeSegmentStatistics(mriseg) ; return(mriseg) ; }
// the following only cares about finding the max segments // ignoring the rest MRI_SEGMENTATION * MRImaxsegment(MRI *mri, float low_val, float hi_val) { MRI_SEGMENTATION *mriseg ; MRI_SEGMENT *mseg, *mseg2 ; int x, y, z, width, height, depth, xi, yi, zi, xk, yk, zk, val, border_labels[NBR_VOX], nlabels, label, nvox ; MRI *mri_labeled ; float voxel_size ; int max; int count =0; int totcount = 0; int mem =0; int maxarea=0; voxel_size = mri->xsize * mri->ysize * mri->zsize ; width = mri->width ; height = mri->height ; depth = mri->depth ; mriseg = MRIsegmentAlloc(MAX_SEGMENTS, MAX_VOXELS) ; mriseg->mri = mri ; for (z =0; z < depth; z++) for (y=0; y < height; y++) for (x=0; x < width; x++) { val = MRIgetVoxVal(mri, x, y, z, 0) ; if (val >= low_val && val <= hi_val) totcount++; } /* mri_labeled will contain the label number for each voxel (if it has been assigned to a segment). */ mri_labeled = MRIalloc(width, height, depth, MRI_SHORT) ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) MRISvox(mri_labeled, x, y, z) = -1 ; } } for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { val = MRIgetVoxVal(mri, x, y, z, 0) ; // if within the range if (val >= low_val && val <= hi_val) { count++; // initializer for border_labels memset(border_labels, -1, NBR_VOX*sizeof(int)) ; for (nvox = 0, zk = -1 ; zk <= 1 ; zk++) { zi = z+zk ; if ((zi < 0) || (zi >= depth)) continue ; for (yk = -1 ; yk <= 1 ; yk++) { yi = y+yk ; if ((yi < 0) || (yi >= height)) continue ; // increment nvox count here for (xk = -1 ; xk <= 1 ; xk++, nvox++) { #if 1 if ((abs(xk) + abs(yk) + abs(zk)) > 1) continue ; /* only allow 4 (6 in 3-d) connectivity */ #endif xi = x+xk ; if ((xi < 0) || (xi >= width)) continue ; // get the neighbor label label = MRISvox(mri_labeled, xi, yi, zi) ; if (label >= 0) border_labels[nvox] = label ; } } } // count nonzero labels in nbrs for (nlabels = nvox = 0 ; nvox < NBR_VOX ; nvox++) { label = border_labels[nvox] ; if ((label >= 0) && (!mriseg->segments[label].found)) { mriseg->segments[label].found = 1 ; nlabels++ ; } } // reset found for (nvox = 0 ; nvox < NBR_VOX ; nvox++) { label = border_labels[nvox] ; if (label >= 0) mriseg->segments[label].found = 0 ; /* for next time */ } // label = 0 ; // create labels for those points which are not connected switch (nlabels) { case 0: /* allocate a new segment */ if (mriseg->nsegments >= mriseg->max_segments) { mem = getMemoryUsed(); // only Linux gives the correct value // (the rest returns -1 // mem > 800*1024) // 800 Mbytes virtual memory usage if (mriseg->max_segments > MAX_SEGMENTS*VOX_INCREASE) { if (mem > 0) // only Linux can do this fprintf(stdout, "\n " "heap usage = %d Kbytes.", mem); // find the region with the largest area maxarea = MRImaxSegmentArea(mriseg); fprintf (stdout, "\n current max segment has " "%d voxels", maxarea); // the second max area can have area up to // (current - maxarea) + (total - maxarea) // = total + current - 2*maxarea // if this value is less than maxarea, // then the second candidate never // becomes the top. Thus I can remove // small segments // if (count+totcount < 3*maxarea) // // For those which has < 100*N % of maxarea, // the possible max count is // = maxarea*N + remaining voxels // = maxarea*N + (total - count) // Thus I can remove those when // maxarea*N + (total-count) < maxarea // or total - count < maxarea*(1 - N) // // Note that if you remove too much, // then possbile merging voxels will be lost // if (totcount - count < maxarea*0.99) { int i,j,k; fprintf(stdout, "\n removing " "small segments (less than 1 " "percent of maxarea)."); MRIremoveSmallSegments(mriseg, maxarea*0.01); // this does compactify // go through mri_labeled to // remove this label value s for (k=0; k < mri_labeled->depth; ++k) for (j=0; j < mri_labeled->height; ++j) for (i=0; i < mri_labeled->width; ++i) { if (MRISvox(mri_labeled, i,j,k) >= mriseg->nsegments) MRISvox(mri_labeled, i,j,k) = -1; } } } } label = mriSegmentNew(mriseg) ; // returns this added segment position mseg = &mriseg->segments[label] ; if (DIAG_VERBOSE_ON && 0) fprintf(stdout, "allocating new label %d (%d total)\n", label, mriseg->nsegments) ; break ; case 1: /* assign this voxel to the one that it borders */ for (nvox = 0 ; nvox < NBR_VOX ; nvox++) if (border_labels[nvox] >= 0) { label = border_labels[nvox] ; break ; } // points to the same label position mseg = &mriseg->segments[label] ; break ; default: /* merge segments and assign to lowest number */ mseg = NULL ; for (nvox = 0 ; nvox < NBR_VOX ; nvox++) { if (border_labels[nvox] >= 0) { // the 1st encountered label case if (!mseg) { // set the first index position label = border_labels[nvox] ; mseg = &mriseg->segments[label] ; mseg->found = 1 ; } // the rest else { mseg2 = &mriseg->segments[border_labels[nvox]] ; if (mseg2->found == 0) { mseg2->found = 1 ; /* prevent merging more than once */ // merge to the label position if (mriSegmentMerge(mriseg, label, border_labels[nvox], mri_labeled) != NO_ERROR) { // nsegments decreased by one MRIsegmentFree(&mriseg) ; return(NULL) ; } } } } } // reset found for (nvox = 0 ; nvox < NBR_VOX ; nvox++) if (border_labels[nvox] >= 0) mriseg->segments[border_labels[nvox]].found = 0 ; break ; } /* add it to the existing list */ if (mseg->nvoxels >= mseg->max_voxels) { // this max could be the same as mseg->max_voxels // this is taken care in mriSegmentReallocateVoxels() max = nint(mseg->max_voxels*VOX_INCREASE); // if (mriSegmentReallocateVoxels(mriseg, label, // nint(mseg->max_voxels*VOX_INCREASE)) // != NO_ERROR) if (mriSegmentReallocateVoxels(mriseg, label, max) != NO_ERROR) { MRIsegmentFree(&mriseg) ; return(NULL) ; } } mseg->voxels[mseg->nvoxels].x = x ; mseg->voxels[mseg->nvoxels].y = y ; mseg->voxels[mseg->nvoxels].z = z ; mseg->nvoxels++ ; mseg->area += voxel_size ; // voxel_size = volume #if 0 // this is for only 1mm voxel case if (mseg->nvoxels != (int)mseg->area) DiagBreak() ; #endif MRISvox(mri_labeled, x, y, z) = label ; } } } } mem = getMemoryUsed(); if (mem > 0) // only Linux can do this fprintf(stdout, "\n heap usage = %d Kbytes.", mem); maxarea = MRImaxSegmentArea(mriseg); fprintf(stdout, "\n removing small segments (less " "than 1 percent of maxarea)."); MRIremoveSmallSegments(mriseg, 0.01*maxarea); // MRIcompactSegments(mriseg) ; if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON && 0) MRIwrite(mri_labeled, "labeled.mgh") ; MRIfree(&mri_labeled) ; mriComputeSegmentStatistics(mriseg) ; return(mriseg) ; }
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) ; }
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) ; }
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 */ }
static int augment_thicknesses(FCD_DATA *fcd, MRI *mri_pvals, double min_dist, double max_dist, double thresh) { int h, vno ; VERTEX *v ; MRI_SURFACE *mris ; MRI *mri_thickness ; double nx, ny, nz, x0, y0, z0, d, x, y, z, val ; MRI_SEGMENTATION *mriseg ; mriseg = MRIsegment(mri_pvals, thresh, 1e10) ; MRIeraseSmallSegments(mriseg, mri_pvals, 20) ; MRIremoveSmallSegments(mriseg, 100) ; if (Gdiag & DIAG_WRITE) { MRIwrite(mri_pvals, "pvals.mgz") ; } MRIsegmentFree(&mriseg) ; for (h = 0 ; h <= 1 ; h++) // do each hemi { if (h == 0) // left hemi { mri_thickness = fcd->lh_thickness_on_lh ; mris = fcd->mris_lh ; } else // right hemi { mri_thickness = fcd->rh_thickness_on_rh ; mris = fcd->mris_rh ; } for (vno = 0 ; vno < mris->nvertices ; vno++) { if (vno == Gdiag_no) { DiagBreak() ; } v = &mris->vertices[vno] ; if (v->ripflag) { continue ; } MRISvertexNormalInVoxelCoords(mris, mri_pvals, vno, &nx, &ny, &nz) ; MRISvertexToVoxel(mris, v, mri_pvals, &x0, &y0, &z0) ; for (d = 0 ; d <= max_dist ; d += 0.5) { x = x0+d*nx ; y = y0+d*ny ; z = z0+d*nz ; MRIsampleVolume(mri_pvals, x, y, z, &val) ; if (val < thresh) { break ; } } if (d > min_dist) // a string of unlikely values { val = MRIgetVoxVal(mri_thickness, vno, 0, 0, 0) ; MRIsetVoxVal(mri_thickness, vno, 0, 0, 0, val+d) ; } } } return(NO_ERROR) ; }
int FCDcomputeThicknessLabels(FCD_DATA *fcd, double thickness_thresh, double sigma, int size_thresh) { MRI *mri_lh, *mri_rh, *mri_lh_diff, *mri_rh_diff ; int niter, vno, s ; MRI_SEGMENTATION *mriseg ; fcdFreeLabels(fcd) ; // free old ones if they exist niter = SIGMA_TO_SURFACE_SMOOTH_STEPS(sigma) ; // do LH mri_lh = MRIclone(fcd->lh_thickness_on_lh, NULL) ; mri_rh = MRIclone(fcd->lh_thickness_on_lh, NULL) ; exec_progress_callback(1, 8, 0, 1) ; MRISwriteFrameToValues(fcd->mris_lh, fcd->lh_thickness_on_lh, 0) ; MRISaverageVals(fcd->mris_lh, niter) ; MRISreadFrameFromValues(fcd->mris_lh, mri_lh, 0) ; exec_progress_callback(2, 8, 0, 1) ; MRISwriteFrameToValues(fcd->mris_lh, fcd->rh_thickness_on_lh, 0) ; MRISaverageVals(fcd->mris_lh, niter) ; MRISreadFrameFromValues(fcd->mris_lh, mri_rh, 0) ; mri_lh_diff = MRIsubtract(mri_lh, mri_rh, NULL) ; // lh minus rh on lh MRIfree(&mri_lh); MRIfree(&mri_rh) ; // do RH mri_lh = MRIclone(fcd->lh_thickness_on_rh, NULL) ; mri_rh = MRIclone(fcd->lh_thickness_on_rh, NULL) ; exec_progress_callback(3, 8, 0, 1) ; MRISwriteFrameToValues(fcd->mris_rh, fcd->lh_thickness_on_rh, 0) ; MRISaverageVals(fcd->mris_rh, niter) ; MRISreadFrameFromValues(fcd->mris_rh, mri_lh, 0) ; exec_progress_callback(4, 8, 0, 1) ; MRISwriteFrameToValues(fcd->mris_rh, fcd->rh_thickness_on_rh, 0) ; MRISaverageVals(fcd->mris_rh, niter) ; MRISreadFrameFromValues(fcd->mris_rh, mri_rh, 0) ; mri_rh_diff = MRIsubtract(mri_rh, mri_lh, NULL) ; // lh minus rh on rh MRIfree(&mri_lh); MRIfree(&mri_rh) ; MRIclear(fcd->mri_thickness_increase) ; MRIclear(fcd->mri_thickness_decrease) ; exec_progress_callback(5, 8, 0, 1) ; // process left hemisphere #if 1 #ifdef HAVE_OPENMP #pragma omp parallel for shared(fcd, mri_lh_diff, Gdiag_no, thickness_thresh) schedule(static,1) #endif #endif for (vno = 0 ; vno < fcd->mris_lh->nvertices ; vno++) { double d ; float val, val2, thickness; int base_label ; VERTEX *v ; v = &fcd->mris_lh->vertices[vno] ; if (v->ripflag) { continue ; } thickness = MRIgetVoxVal(fcd->lh_thickness_on_lh, vno, 0, 0, 0) ; if (vno == Gdiag_no) { DiagBreak() ; } val = MRIgetVoxVal(mri_lh_diff, vno, 0, 0, 0) ; if (fabs(val) < thickness_thresh) { continue ; } for (d = 0, base_label = 0 ; d < thickness ; d += 0.25) { double xv, yv, zv; double xs = v->x+d*v->nx ; double ys = v->y+d*v->ny ; double zs = v->z+d*v->nz ; MRISsurfaceRASToVoxel(fcd->mris_lh, fcd->mri_thickness_increase, xs, ys, zs, &xv, &yv, &zv) ; int xvi = nint(xv) ; int yvi = nint(yv) ; int zvi = nint(zv) ; int label = MRIgetVoxVal(fcd->mri_aparc, xvi, yvi, zvi, 0) ; if (IS_WM(label) == 0 && label >= MIN_CORTICAL_PARCELLATION && label != ctx_lh_unknown) { if (label != base_label) { if (base_label) { break ; } } else { base_label = label ; } if (val >= 0) { val2 = MRIgetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0) ; // check another thread already populated this voxel if (val > val2) { MRIsetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0, val) ; } } else { val2 = MRIgetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0) ; // check if another thread already populated this voxel if (val < val2) { MRIsetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0, val) ; } } } } } exec_progress_callback(6, 8, 0, 1) ; // now do right hemisphere #if 1 #ifdef HAVE_OPENMP #pragma omp parallel for shared(fcd, mri_rh_diff, Gdiag_no, thickness_thresh) schedule(static,1) #endif #endif for (vno = 0 ; vno < fcd->mris_rh->nvertices ; vno++) { double d ; float val, val2, thickness; int base_label ; VERTEX *v ; v = &fcd->mris_rh->vertices[vno] ; if (v->ripflag) { continue ; } if (vno == Gdiag_no) { DiagBreak() ; } val = MRIgetVoxVal(mri_rh_diff, vno, 0, 0, 0) ; if (fabs(val) < thickness_thresh) { continue ; } thickness = MRIgetVoxVal(fcd->rh_thickness_on_rh, vno, 0, 0, 0) ; for (d = 0, base_label = 0; d < thickness ; d += 0.25) { double xv, yv, zv; double xs = v->x+d*v->nx ; double ys = v->y+d*v->ny ; double zs = v->z+d*v->nz ; MRISsurfaceRASToVoxel(fcd->mris_rh, fcd->mri_thickness_increase, xs, ys, zs, &xv, &yv, &zv) ; int xvi = nint(xv) ; int yvi = nint(yv) ; int zvi = nint(zv) ; int label = MRIgetVoxVal(fcd->mri_aparc, xvi, yvi, zvi, 0) ; if (IS_WM(label) == 0 && label >= MIN_CORTICAL_PARCELLATION && label != ctx_rh_unknown) { if (label != base_label) { if (base_label) { break ; } } else { base_label = label ; } if (val >= 0) { val2 = MRIgetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0) ; if (val > val2) { MRIsetVoxVal(fcd->mri_thickness_increase, xvi, yvi, zvi, 0, val) ; } } else { val2 = MRIgetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0) ; if (val < val2) { MRIsetVoxVal(fcd->mri_thickness_decrease, xvi, yvi, zvi, 0, val) ; } } } } } exec_progress_callback(7, 8, 0, 1) ; mriseg = MRIsegment(fcd->mri_thickness_increase, thickness_thresh, 1e10) ; MRIeraseSmallSegments(mriseg, fcd->mri_thickness_increase, thickness_thresh) ; MRIsegmentFree(&mriseg) ; MRIclose(fcd->mri_thickness_increase, fcd->mri_thickness_increase) ; mriseg = MRIsegment(fcd->mri_thickness_increase, thickness_thresh, 1e10) ; MRIremoveSmallSegments(mriseg, size_thresh) ; printf("segmenting volume at threshold %2.1f with %d " "smoothing iters yields %d segments\n", thickness_thresh, niter,mriseg->nsegments) ; fflush(stdout) ; exec_progress_callback(8, 8, 0, 1) ; fcd->nlabels = mriseg->nsegments ; for (s = 0 ; s < mriseg->nsegments ; s++) { int label ; fcd->labels[s] = MRIsegmentToLabel(mriseg, fcd->mri_thickness_increase, s) ; label = most_frequent_label(fcd->mri_aparc, &mriseg->segments[s]) ; strcpy(fcd->labels[s]->name, cma_label_to_name(label)) ; } sort_labels(fcd) ; MRIadd(fcd->mri_thickness_increase, fcd->mri_thickness_decrease, fcd->mri_thickness_difference); for (s = 0 ; s < mriseg->nsegments ; s++) { printf("%s: %2.3fmm\n", fcd->label_names[s], fcd->labels[s]->avg_stat) ; fflush(stdout) ; } MRIfree(&mri_lh_diff) ; MRIfree(&mri_rh_diff) ; MRIsegmentFree(&mriseg) ; return(fcd->nlabels) ; }