int main(int argc, char *argv[]) { double thresh ; MRI *mri, *mri_abs ; char *out_stem, fname[STRLEN] ; MRI_SEGMENTATION *mriseg ; int s ; LABEL *area ; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; mri = MRIread(argv[1]) ; if (mri == NULL) ErrorExit(ERROR_NOFILE, "%s: could not load MRI from %s\n", Progname, argv[1]) ; if (use_abs) mri_abs = MRIabs(mri, NULL) ; else mri_abs = MRIcopy(mri, NULL) ; thresh = atof(argv[2]) ; out_stem = argv[3] ; mriseg = MRIsegment(mri, thresh, 1e10) ; MRIremoveSmallSegments(mriseg, size_thresh) ; printf("segmenting volume at threshold %2.1f yields %d segments\n", thresh, mriseg->nsegments) ; for (s = 0 ; s < mriseg->nsegments ; s++) { area = MRIsegmentToLabel(mriseg, mri_abs, s) ; sprintf(fname, "%s.%3.3d.label", out_stem, s) ; LabelWrite(area, fname) ; } return(0) ; }
// 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) ; }
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) ; }