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) ;
}
Exemple #2
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) ;
}
Exemple #3
0
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) ;
}
Exemple #4
0
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) ;
}