Exemplo n.º 1
0
int
main(int argc, char *argv[])
{
  char        **av, *in_vol, *out_vol;
  int         ac, nargs;

  MRI         *mri_in, *mri_out, *mri_tmp ;
  LTA         *lta = 0;
  MATRIX *i_to_r_src = 0; /* src geometry of the input LTA */
  MATRIX *V_to_V = 0; /* Final voxel-to-voxel transform */
  MATRIX *r_to_i_dst = 0; /* dst geometry of the input LTA */
  MATRIX *m_tmp = 0;
  MATRIX *i_to_r_reg = 0; /* i_to_r of the volume after registration */
  MATRIX *r_to_i_out = 0; /* r_to_i of the final output volume */
  VOL_GEOM vgm_in;
  int x, y, z;
  double maxV, minV, value;
  //  MATRIX *i_to_r, *r_to_i;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mri_transform_to_COR.c,v 1.8 2011/03/02 00:04:55 nicks Exp $", "$Name: stable5 $");
  if (nargs && argc - nargs == 1)
    usage_exit (0);
  argc -= nargs;

  Progname = argv[0] ;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;

  ac = argc ;
  av = argv ;
  for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++)
  {
    nargs = get_option(argc, argv) ;
    argc -= nargs ;
    argv += nargs ;
  }

  if (argc < 3)
    usage_exit(0) ;

  in_vol = argv[1] ;
  out_vol = argv[2] ;

  printf("reading volume from %s...\n", in_vol) ;
  mri_in = MRIread(in_vol) ;
  if (!mri_in)
    ErrorExit(ERROR_NOFILE, "%s: could not read MRI volume %s", Progname,
              in_vol) ;

  /* Convert mri_in to float type */
  /* double would be more accurate */
  if (mri_in->type != MRI_FLOAT)
  {
    printf("Input volume type is %d\n", mri_in->type);
    printf("Change input volume to float type for convenience and accuracy");
    mri_tmp = MRIchangeType(mri_in, MRI_FLOAT, 0, 1.0, 1);
    MRIfree(&mri_in);
    mri_in = mri_tmp; //swap
  }

  /* Get input volume geometry, which is needed to compute i_to_r
   * and r_to_i of input volume. Note that i_to_r and r_to_i assumed
   * a certain prespecified c_r, c_a, c_s
   */
  getVolGeom(mri_in, &vgm_in);

  maxV = -10000.0;
  minV = 10000.0;
  for (z=0; z < mri_in->depth; z++)
    for (y=0; y< mri_in->height; y++)
      for (x=0; x < mri_in->width; x++)
      {
        if (MRIFvox(mri_in, x, y, z) > maxV )
          maxV = MRIFvox(mri_in, x, y,z) ;
        if (MRIFvox(mri_in, x, y, z) < minV )
          minV = MRIFvox(mri_in, x, y,z) ;
      }

  printf("Input volume has max = %g, min =%g\n", maxV, minV);

  printf("Scale input volume by %g \n", scale);

  maxV = -10000.0;
  minV = 10000.0;
  for (z=0; z < mri_in->depth; z++)
    for (y=0; y< mri_in->height; y++)
      for (x=0; x < mri_in->width; x++)
      {
        MRIFvox(mri_in, x, y, z) *= scale;
        if (MRIFvox(mri_in, x, y, z) > maxV )
          maxV = MRIFvox(mri_in, x, y,z) ;
        if (MRIFvox(mri_in, x, y, z) < minV )
          minV = MRIFvox(mri_in, x, y,z) ;
      }

  printf("Input volume after scaling has max = %g, min =%g\n", maxV, minV);

  /* Try to compute the Voxel_to_Voxel transform from the input volume
   * and the registration target/reference volume!
   * If no registration is involved, vox_to_vox is simply identity
   */
  /* Things become more complicated when allowing inverse transform */
  if (transform_flag)
  {
    int transform_type;

    printf("INFO: Applying transformation from file %s...\n",
           transform_fname);
    transform_type =  TransformFileNameType(transform_fname);

    /* Read in LTA transform file name */
    if (transform_type == MNI_TRANSFORM_TYPE ||
        transform_type == TRANSFORM_ARRAY_TYPE ||
        transform_type == REGISTER_DAT ||
        transform_type == FSLREG_TYPE
       )
    {

      printf("Reading transform ...\n");
      lta = LTAreadEx(transform_fname) ;

      if (!lta)
        ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s",
                  Progname, transform_fname) ;

      if (transform_type == FSLREG_TYPE)
      {
        if (lta_src == 0 || lta_dst == 0)
        {
          fprintf(stderr, "ERROR: fslmat does not have information on the src and dst volumes\n");
          fprintf(stderr, "ERROR: you must give options '-src' and '-dst' to specify the src and dst volume infos for the registration\n");
        }


        LTAmodifySrcDstGeom(lta, lta_src, lta_dst); // add src and dst information
        //The following is necessary to interpret FSLMAT correctly!!!
        LTAchangeType(lta, LINEAR_VOX_TO_VOX);
      }
      if (lta->xforms[0].src.valid == 0)
      {
        if (lta_src == 0)
        {
          fprintf(stderr, "The transform does not have the valid src volume info.\n");
          fprintf(stderr, "Either you give src volume info by option -src or\n");
          fprintf(stderr, "make the transform to have the valid src info.\n");
          ErrorExit(ERROR_BAD_PARM, "Bailing out...\n");
        }
        else
        {
          LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information
        }
      }
      if (lta->xforms[0].dst.valid == 0)
      {
        if (lta_dst == 0)
        {
          fprintf(stderr, "The transform does not have the valid dst volume info.\n");
          fprintf(stderr, "Either you give src volume info by option -dst or\n");
          fprintf(stderr, "make the transform to have the valid dst info.\n");
          fprintf(stderr, "If the dst was average_305, then you can set\n");
          fprintf(stderr, "environmental variable USE_AVERAGE305 true\n");
          fprintf(stderr, "instead.\n");
          ErrorExit(ERROR_BAD_PARM, "Bailing out...\n");
        }
        else
        {
          LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add  dst information
        }
      }


      // The following procedure aims to apply an LTA computed from COR format to a volume in non-COR format, or vice versa, as long as they share the same RAS
      // first change to LINEAR RAS_TO_RAS using old info
      if (lta->type != LINEAR_RAS_TO_RAS)
      {
        LTAchangeType(lta, LINEAR_RAS_TO_RAS);
      }

      // now possiblly reset the src and dst
      if (lta_src != NULL)
      {
        //always trust the user
        LTAmodifySrcDstGeom(lta, lta_src, NULL);
      }
      if (lta_dst != NULL)
      {
        //always trust the user
        LTAmodifySrcDstGeom(lta, NULL, lta_dst);
      }

      if (lta->type == LINEAR_RAS_TO_RAS)
      {
        /* Convert it to VOX_TO_VOX */
        /* VOXELsrc_to_VOXELdst = R2Vdst*R2Rlta*V2Rsrc */
        /* Note whether the input should be identical to src or dst here depends
         * on whether the LTA here is the direct or inverse transform
         */
        i_to_r_src = vg_i_to_r(&lta->xforms[0].src);
        r_to_i_dst = vg_r_to_i(&lta->xforms[0].dst);

        if (!r_to_i_dst || !i_to_r_src)
          ErrorExit(ERROR_BADFILE, "%s: failed to extract volume geometries from input LTA file",Progname);
        m_tmp = MatrixMultiply(lta->xforms[0].m_L, i_to_r_src, NULL);
        V_to_V = MatrixMultiply(r_to_i_dst, m_tmp, NULL);
        MatrixFree(&m_tmp);

        MatrixFree(&i_to_r_src);
        MatrixFree(&r_to_i_dst);
      }
    }
    else
    {
      fprintf(stderr, "unknown transform type in file %s\n",
              transform_fname);
      exit(1);
    }

    if (invert_flag)
    {
      /* Geometry of input volume should match that of the dst of the LTA */
      if (MYvg_isEqual(&lta->xforms[0].dst, &vgm_in) == 0)
      {
        ErrorExit(ERROR_BADFILE, "%s: dst volume of lta doesn't match that of input volume",Progname);
      }

      i_to_r_reg = vg_i_to_r(&lta->xforms[0].src);

      if (!i_to_r_reg)
        ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname);

      m_tmp =  MatrixInverse(V_to_V, NULL);
      if (!m_tmp)
        ErrorExit(ERROR_BADPARM, "%s: transform is singular!", Progname);

      MatrixFree(&V_to_V);
      V_to_V = m_tmp;
    }
    else
    {
      /* Geometry of input volume should match that of the src of the LTA */
      if (MYvg_isEqual(&lta->xforms[0].src, &vgm_in) == 0)
      {
        ErrorExit(ERROR_BADFILE, "%s: src volume of lta doesn't match that of input volume",Progname);
      }

      i_to_r_reg = vg_i_to_r(&lta->xforms[0].dst);

      if (!i_to_r_reg)
        ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname);
    }

  }
  else
  {
    /* No registration transform need be applied */
    V_to_V = MatrixIdentity(4, NULL);
    i_to_r_reg = extract_i_to_r(mri_in);
    if (!i_to_r_reg)
      ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r from input volume",Progname);
  }

  /* Now need to find the vox-to-vox transformation between registered volume
   * (or input volume itself if no registration involved) and the output
   * volume, either in COR format or as the out-like volume
   */
  /* Given a volume with a certain i_to_r, we need to compute the necessary
   * vox-to-voxel transform to change its i_to_r to like another volume.
   * The vox-to-vox is equal to R2V(r_to_i)_likevol*i_to_r_current_vol.
   */
  if (out_like_fname)
  {
    mri_tmp = MRIread(out_like_fname) ;
    if (!mri_tmp)
      ErrorExit(ERROR_NOFILE, "%s: could not read template volume from %s",out_like_fname) ;

    /* out_type = mri_tmp->type; */

    /* specify the out-type to float initially so as not to lose accuracy
     * during reslicing, will change type to correct type later.
     */
    mri_out = MRIalloc(mri_tmp->width, mri_tmp->height, mri_tmp->depth, MRI_FLOAT) ;

    MRIcopyHeader(mri_tmp, mri_out) ;
    MRIfree(&mri_tmp);
  }
  else  /* assume output is in COR format */
  {
    mri_out = MRIalloc(256, 256, 256, MRI_FLOAT) ;
    /* out_type = MRI_UCHAR; */

    /* Who says MRIlinearTransformInterp will change the header??
     * I don't think so!
     */
    //E/ set xyzc_ras to coronal ones.. - these'll get zorched
    //by MRIlinearTransformInterp() - copy again later - is there
    //any use in having them here now?  yes, so we can pass mri_out
    //to the ras2vox fns.


    mri_out->imnr0 = 1; /* what's this? */
    mri_out->imnr1 = 256; /* what's this? */
    mri_out->thick = 1.0;
    mri_out->ps = 1.0; /* what's this? */
    mri_out->xsize = mri_out->ysize = mri_out->zsize = 1.0;
    mri_out->xstart = mri_out->ystart = mri_out->zstart = -128.0;
    mri_out->xend = mri_out->yend = mri_out->zend = 128.0;
    mri_out->x_r =-1;
    mri_out->y_r = 0;
    mri_out->z_r = 0;
    mri_out->x_a = 0;
    mri_out->y_a = 0;
    mri_out->z_a = 1;
    mri_out->x_s = 0;
    mri_out->y_s =-1;
    mri_out->z_s = 0;

    /* In this case, the RAS itself is not fully determined, i.e., c_ras.
     * It's quite arbitrary, different values just change the final
     * sitting of the volume inside the RAS system.
     */
    /* NO! The C_RAS has to be set correctly, depending which target
     * volume the previous Vox_to_Vox transformation assumes!
     * When a registration is involved, the target volume is either
     * the src of LTA (direct) or the dst (inverse transform). When
     * just change format, the target volume is the input itself!!
     */
    if (transform_flag)
    {
      if (invert_flag)
      {
        mri_out->c_r = lta->xforms[0].src.c_r;
        mri_out->c_a = lta->xforms[0].src.c_a;
        mri_out->c_s = lta->xforms[0].src.c_s;

      }
      else
      {
        mri_out->c_r = lta->xforms[0].dst.c_r;
        mri_out->c_a = lta->xforms[0].dst.c_a;
        mri_out->c_s = lta->xforms[0].dst.c_s;
      }
    }
    else
    {
      mri_out->c_r = mri_in->c_r;
      mri_out->c_a = mri_in->c_a;
      mri_out->c_s = mri_in->c_s;
    }

    mri_out->ras_good_flag=1; /* What does this flag mean ? */

    /* since output is just transformed input */
    MRIcopyPulseParameters(mri_in, mri_out) ;

  }

  /* Compute the final input-to-output VOX_to_VOX transformation matrix */
  r_to_i_out = extract_r_to_i(mri_out);

  m_tmp = MatrixMultiply(r_to_i_out, i_to_r_reg, NULL);
  V_to_V = MatrixMultiply(m_tmp, V_to_V, V_to_V);
  MatrixFree(&m_tmp);

  printf("InterpMethod = %d\n", InterpMethod);

  /* Modify the MyMRIlinearTr... if I want to implement my cubic-B-spline
   * interpolation method. Otherwise, unnecessary
   */
  /* mri_out = MyMRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod); */
  if (InterpMethod == SAMPLE_BSPLINE)
    mri_out = MRIlinearTransformInterpBSpline(mri_in, mri_out, V_to_V,
              SplineDegree);
  else
    mri_out = MRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod);

  maxV = -10000.0;
  minV = 10000.0;
  for (z=0; z < mri_out->depth; z++)
    for (y=0; y< mri_out->height; y++)
      for (x=0; x < mri_out->width; x++)
      {
        if (MRIFvox(mri_out, x, y, z) > maxV )
          maxV = MRIFvox(mri_out, x, y,z) ;
        if (MRIFvox(mri_out, x, y, z) < minV )
          minV = MRIFvox(mri_out, x, y,z) ;
      }

  if (autoscale)
  {
    noscale = 1;

    /* compute histogram of output volume */
    HISTOGRAM *h, *hsmooth ;
    float fmin, fmax, val, peak, smooth_peak;
    int i, nbins, bin;

    fmin = minV;
    fmax = maxV;
    if (fmin < 0) fmin = 0;
    nbins = 256 ;
    h = HISTOalloc(nbins) ;
    hsmooth = HISTOcopy(h, NULL) ;
    HISTOclear(h, h) ;
    h->bin_size = (fmax-fmin)/255.0 ;

    for (i = 0 ; i < nbins ; i++)
      h->bins[i] = (i+1)*h->bin_size ;

    for (z=0; z < mri_out->depth; z++)
      for (y=0; y< mri_out->height; y++)
        for (x=0; x < mri_out->width; x++)
        {
          val = MRIFvox(mri_out, x, y, z);
          if (val <= 0) continue;

          bin = nint((val - fmin)/h->bin_size);
          if (bin >= h->nbins)
            bin = h->nbins-1;
          else if (bin < 0)
            bin = 0;

          h->counts[bin] += 1.0;
        }
    HISTOfillHoles(h) ;
    HISTOsmooth(h, hsmooth, 5)  ;
    peak =
      hsmooth->bins[HISTOfindHighestPeakInRegion(h, 1, h->nbins)] ;
    //   smooth_peak =
    //  hsmooth->bins[HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins)] ;

    smooth_peak =
      hsmooth->bins[HISTOfindLastPeak(hsmooth, 5, 0.8)] ;

    /*
      bin = nint((smooth_peak - fmin)/hsmooth->bin_size) ;

      printf("Highest peak has count = %d\n", (int)hsmooth->counts[bin]);

      bin = nint((420 - fmin)/hsmooth->bin_size) ;

      printf("bin at 420 has count = %d\n", (int)hsmooth->counts[bin]);
    */

    scale =  110.0/smooth_peak;
    printf("peak of output volume is %g, smooth-peak is %g, multiply by %g to scale it to 110\n", peak, smooth_peak, scale);
    for (z=0; z < mri_out->depth; z++)
      for (y=0; y< mri_out->height; y++)
        for (x=0; x < mri_out->width; x++)
        {
          val = MRIFvox(mri_out, x, y, z);
          MRIFvox(mri_out, x, y, z) = val*scale;
        }

  }


  printf("Output volume (before type-conversion) has max = %g, min =%g\n", maxV, minV);

  /* Finally change type to desired */
  if (mri_out->type != out_type)
  {
    printf("Change output volume to type %d\n", out_type);
    /* I need to modify the MIRchangeType function to make sure
     * it does roundoff instead of simple truncation!
     */
    /* Note if the last flag is set to 1, then it won't do scaling
       and small float numbers will become zero after convert to
       BYTE
    */
    if (out_type == 0 && noscale == 1)
    {
      //convert data to UCHAR
      mri_tmp = MRIalloc(mri_out->width, mri_out->height, mri_out->depth, out_type) ;
      MRIcopyHeader(mri_out, mri_tmp);
      for (z=0; z < mri_out->depth; z++)
        for (y=0; y< mri_out->height; y++)
          for (x=0; x < mri_out->width; x++)
          {
            value = floor(MRIgetVoxVal(mri_out, x, y, z, 0) + 0.5);
            if (value < 0 ) value = 0;
            if (value > 255) value = 255;
            MRIvox(mri_tmp,x,y,z) = (unsigned char)value;
          }
    }
    else
      mri_tmp = MRIchangeType(mri_out, out_type, thred_low, thred_high, noscale);

    MRIfree(&mri_out);
    mri_out = mri_tmp; //swap
  }

  MRIwrite(mri_out, out_vol) ;

  MRIfree(&mri_in);
  MRIfree(&mri_out);

  if (lta_src)
    MRIfree(&lta_src);
  if (lta_dst)
    MRIfree(&lta_dst);

  MatrixFree(&V_to_V);

  if (!r_to_i_out)
    MatrixFree(&r_to_i_out);

  if (!i_to_r_reg)
    MatrixFree(&i_to_r_reg);

  return(0) ;  /* for ansi */
}
Exemplo n.º 2
0
static MRI *
MRIremoveWMOutliers(MRI *mri_src, MRI *mri_src_ctrl, MRI *mri_dst_ctrl,
                    int intensity_below)
{
  MRI       *mri_bin, *mri_outliers = NULL ;
  float     max, thresh, val;
  HISTOGRAM *histo, *hsmooth ;
  int       wm_peak, x, y, z, nremoved = 0, whalf = 5, total  ;

  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_src_ctrl, "sc.mgz") ;
  }

  if (mri_dst_ctrl == NULL)
  {
    mri_dst_ctrl = MRIcopy(mri_src_ctrl, NULL) ;
  }
  mri_bin = MRIbinarize(mri_src_ctrl, NULL, 1, 0, CONTROL_MARKED) ;
  histo = MRIhistogramLabel(mri_src, mri_bin, 1, 256) ;
  hsmooth = HISTOcopy(histo, NULL) ;
  HISTOsmooth(histo, hsmooth, 2) ;
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    HISTOplot(histo, "h.plt") ;
    HISTOplot(hsmooth, "hs.plt") ;
  }
  wm_peak = HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins-1) ;
  wm_peak = hsmooth->bins[wm_peak] ;
  thresh = wm_peak-intensity_below ;

  HISTOfree(&histo) ;
  HISTOfree(&hsmooth) ;
  if (Gdiag & DIAG_WRITE)
  {
    mri_outliers = MRIclone(mri_dst_ctrl, NULL) ;
  }
  for (total = x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
        {
          DiagBreak() ;
        }
        if (nint(MRIgetVoxVal(mri_dst_ctrl, x, y, z, 0)) == 0)
        {
          continue ;
        }
        max = MRImaxInLabelInRegion(mri_src, mri_bin, 1, x, y, z, whalf);
        val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
        total++ ;
        if (val+intensity_below < max && val < thresh)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          if (mri_outliers)
          {
            MRIsetVoxVal(mri_outliers, x, y, z, 0, 128) ;
          }
          nremoved++ ;
        }
      }
    }
  }

  printf( "%d control points removed (%2.1f%%)\n",
          nremoved, 100.0*(double)nremoved/(double)total) ;
  if (mri_outliers)
  {
    printf( "writing out.mgz outlier volume\n") ;
    MRIwrite(mri_outliers, "out.mgz") ;
    MRIfree(&mri_outliers) ;
  }
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_dst_ctrl, "dc.mgz") ;
  }
  MRIfree(&mri_bin) ;
  return(mri_dst_ctrl);
}
Exemplo n.º 3
0
static MRI *
MRIremoveWMOutliersAndRetainMedialSurface(MRI *mri_src,
                                          MRI *mri_src_ctrl,
                                          MRI *mri_dst_ctrl,
                                          int intensity_below)
{
  MRI  *mri_inside, *mri_bin ;
  HISTOGRAM *histo, *hsmooth ;
  int   wm_peak, x, y, z, nremoved ;
  float thresh, hi_thresh ;
  double val, lmean, max ;

  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_src_ctrl, "sc.mgz") ;
  }
  if (mri_dst_ctrl != mri_src_ctrl)
  {
    mri_dst_ctrl = MRIcopy(mri_src_ctrl, mri_dst_ctrl) ;
  }
  mri_inside = MRIerode(mri_dst_ctrl, NULL) ;
  MRIbinarize(mri_inside, mri_inside, 1, 0, 1) ;

  histo = MRIhistogramLabel(mri_src, mri_inside, 1, 256) ;
  hsmooth = HISTOcopy(histo, NULL) ;
  HISTOsmooth(histo, hsmooth, 2) ;
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    HISTOplot(histo, "h.plt") ;
    HISTOplot(hsmooth, "hs.plt") ;
  }
  printf("using wm (%d) threshold %2.1f for removing exterior voxels\n",
         wm_peak, thresh) ;
  wm_peak = HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins-1) ;
  wm_peak = hsmooth->bins[wm_peak] ;
  thresh = wm_peak-intensity_below ;
  hi_thresh = wm_peak-.5*intensity_below ;
  printf("using wm (%d) threshold %2.1f for removing exterior voxels\n",
         wm_peak, thresh) ;

  // now remove stuff that's on the border and is pretty dark
  for (nremoved = x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
        {
          DiagBreak() ;
        }
        /* if it's a control point,
            it's not in the interior of the wm,
            and it's T1 val is too low */
        if (MRIgetVoxVal(mri_dst_ctrl, x, y, z, 0) == 0)
        {
          continue ;  // not a  control point
        }

        /* if it's way far from the wm mode
            then remove it even if it's in the interior */
        val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
        if (val < thresh-5)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          nremoved++ ;
        }

        if (nint(MRIgetVoxVal(mri_inside, x, y, z, 0)) > 0)
          // don't process interior voxels further
        {
          continue ;  // in the interior
        }
        if (val < thresh)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          nremoved++ ;
        }
        else
        {
          lmean =
            MRImeanInLabelInRegion(mri_src, mri_inside, 1, x, y, z, 7);
          if (val < lmean-10)
          {
            MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
            nremoved++ ;
          }
        }
      }
    }
  }

#if 0
  for (x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
        {
          DiagBreak() ;
        }
        /* if it's a control point,
            it's not in the interior of the wm,
            and it's T1 val is too low */
        if (MRIgetVoxVal(mri_dst_ctrl, x, y, z, 0) == 0)
        {
          continue ;  // not a  control point
        }
        if (MRIcountNonzeroInNbhd(mri_dst_ctrl,3, x, y, z)<=2)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          nremoved++ ;
        }
      }
    }
  }
#endif

  /* now take out voxels that have too big an intensity diff
     with surrounding ones */
  mri_bin = MRIbinarize(mri_dst_ctrl, NULL, 1, 0, 1) ;
  for (x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
        {
          DiagBreak() ;
        }
        /* if it's a control point,
            it's not in the interior of the wm,
            and it's T1 val is too low */
        if (MRIgetVoxVal(mri_dst_ctrl, x, y, z, 0) == 0)
        {
          continue ;  // not a  control point
        }
        val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
        max = MRImaxInLabelInRegion(mri_src, mri_bin, 1, x, y, z, 3);
        if (val+7 < max && val < hi_thresh)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          nremoved++ ;
        }
      }
    }
  }
  MRIfree(&mri_bin) ;

  printf( "%d control points removed\n", nremoved) ;
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_dst_ctrl, "dc.mgz") ;
  }
  HISTOfree(&histo) ;
  HISTOfree(&hsmooth) ;
  MRIfree(&mri_inside) ;
  return(mri_dst_ctrl) ;
}
Exemplo n.º 4
0
static MRI *
MRIremoveWMOutliersAndRetainMedialSurface(MRI *mri_src,
                                          MRI *mri_src_ctrl,
                                          MRI *mri_dst_ctrl,
                                          int intensity_below)
{
  MRI       *mri_bin, *mri_dist, *mri_dist_sup, *mri_outliers = NULL ;
  float     max, thresh, val;
  HISTOGRAM *histo, *hsmooth ;
  int       wm_peak, x, y, z, nremoved = 0, whalf = 5 ;

  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_src_ctrl, "sc.mgz") ;
  }

  mri_bin = MRIbinarize(mri_dst_ctrl, NULL, 1, 0, 1) ;
  mri_dist = MRIdistanceTransform(mri_bin, NULL, 1, -1,
                                  DTRANS_MODE_SIGNED, NULL);
  MRIscalarMul(mri_dist, mri_dist, -1) ;
  mri_dist_sup = MRInonMaxSuppress(mri_dist, NULL, 0, 1) ;
  mri_dst_ctrl = MRIbinarize(mri_dist_sup, mri_dst_ctrl, 1, 0, 1) ;
  histo = MRIhistogramLabel(mri_src, mri_src_ctrl, 1, 256) ;
  hsmooth = HISTOcopy(histo, NULL) ;
  HISTOsmooth(histo, hsmooth, 2) ;
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    HISTOplot(histo, "h.plt") ;
    HISTOplot(hsmooth, "hs.plt") ;
  }
  wm_peak = HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins-1) ;
  wm_peak = hsmooth->bins[wm_peak] ;
  thresh = wm_peak-intensity_below ;

  HISTOfree(&histo) ;
  HISTOfree(&hsmooth) ;
  if (Gdiag & DIAG_WRITE)
  {
    mri_outliers = MRIclone(mri_dst_ctrl, NULL) ;
  }
  for (x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
        {
          DiagBreak() ;
        }
        if (nint(MRIgetVoxVal(mri_dst_ctrl, x, y, z, 0)) == 0)
        {
          continue ;
        }
        max = MRImaxInLabelInRegion(mri_src, mri_dst_ctrl, 1, x, y, z, whalf);
        val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
        if (val+intensity_below < max && val < thresh)
        {
          MRIsetVoxVal(mri_dst_ctrl, x, y, z, 0, 0) ;
          if (mri_outliers)
          {
            MRIsetVoxVal(mri_outliers, x, y, z, 0, 128) ;
          }
          nremoved++ ;
        }
      }
    }
  }

  printf( "%d control points removed\n", nremoved) ;
  if (mri_outliers)
  {
    printf( "writing out.mgz outlier volume\n") ;
    MRIwrite(mri_outliers, "out.mgz") ;
    MRIfree(&mri_outliers) ;
  }
  if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
  {
    MRIwrite(mri_dst_ctrl, "dc.mgz") ;
  }
  MRIfree(&mri_bin) ;
  MRIfree(&mri_dist);
  MRIfree(&mri_dist_sup);
  return(mri_dst_ctrl);
}