MRI * MRIfindBrightNonWM(MRI *mri_T1, MRI *mri_wm) { int width, height, depth, x, y, z, nlabeled, nwhite, xk, yk, zk, xi, yi, zi; BUFTYPE val, wm ; MRI *mri_labeled, *mri_tmp ; mri_labeled = MRIclone(mri_T1, NULL) ; width = mri_T1->width ; height = mri_T1->height ; depth = mri_T1->depth ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { val = MRIgetVoxVal(mri_T1, x, y, z, 0) ; wm = MRIgetVoxVal(mri_wm, x, y, z, 0) ; if (x == 110 && y == 125 && z == 172) /* T1=148 */ { DiagBreak() ; } /* not white matter and bright (e.g. eye sockets) */ if ((wm < WM_MIN_VAL) && (val > 125)) { nwhite = 0 ; for (xk = -1 ; xk <= 1 ; xk++) { xi = mri_T1->xi[x+xk] ; for (yk = -1 ; yk <= 1 ; yk++) { yi = mri_T1->yi[y+yk] ; for (zk = -1 ; zk <= 1 ; zk++) { zi = mri_T1->zi[z+zk] ; if (MRIgetVoxVal(mri_wm, xi, yi, zi, 0) >= WM_MIN_VAL) { nwhite++ ; } } } } #define MIN_WHITE ((3*3*3-1)/2) if (nwhite < MIN_WHITE) { MRIsetVoxVal(mri_labeled, x, y, z, 0, BRIGHT_LABEL) ; } } } } } /* find all connected voxels that are above 115 */ MRIdilateThreshLabel(mri_labeled, mri_T1, NULL, BRIGHT_LABEL, 10,115); MRIclose(mri_labeled, mri_labeled) ; /* expand once more to all neighboring voxels that are bright. At worst we will erase one voxel of white matter. */ mri_tmp = MRIdilateThreshLabel(mri_labeled, mri_T1, NULL, BRIGHT_LABEL,1,100); MRIxor(mri_labeled, mri_tmp, mri_tmp, 1, 255) ; MRIreplaceValues(mri_tmp, mri_tmp, 1, BRIGHT_BORDER_LABEL) ; MRIunion(mri_tmp, mri_labeled, mri_labeled) ; #if 0 fprintf(stderr, "selectively smoothing volume....\n") ; MRIsoapBubbleLabel(mri_T1, mri_labeled, mri_T1, BRIGHT_LABEL, 200) ; #endif if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON) { MRIwrite(mri_labeled, "label.mgh") ; } /* MRIwrite(mri_tmp, "tmp.mgh") ;*/ nlabeled = MRIvoxelsInLabel(mri_labeled, BRIGHT_LABEL) ; fprintf(stderr, "%d bright non-wm voxels segmented.\n", nlabeled) ; MRIfree(&mri_tmp) ; return(mri_labeled) ; }
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 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) ; }