Beispiel #1
0
        internal static int lfs_detect_minutiae_V2(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap,
                                                   ref int[,] ohcmap, ref int[,] obdata, Bitmap idata, int iw, int ih, ref int mw, ref int mh, string name)
        {
            int[,] pdata = new int[iw, ih];
            int[,] bdata = new int[iw, ih];
            DIR2RAD  dir2rad     = new DIR2RAD();
            DFTWAVES dftwaves    = new DFTWAVES();
            ROTGRIDS dftgrids    = new ROTGRIDS();
            ROTGRIDS dirbingrids = new ROTGRIDS();

            int[,] direction_map    = new int[iw, ih];
            int[,] low_contrast_map = new int[iw, ih];
            int[,] low_flow_map     = new int[iw, ih];
            int[,] high_curve_map   = new int[iw, ih];
            int maxpad = 0;

            int pw = 0, ph = 0;

            // initialization
            maxpad = get_max_padding_V2(lfsparms.windowsize, lfsparms.windowoffset,
                                        lfsparms.dirbin_grid_w, lfsparms.dirbin_grid_h);
            dir2rad  = init_dir2rad(lfsparms.num_directions);
            dftwaves = init_dftwaves(dft_coefs, lfsparms.num_dft_waves, lfsparms.windowsize);
            dftgrids = init_rotgrids(iw, ih, maxpad, lfsparms.start_dir_angle,
                                     lfsparms.num_directions, lfsparms.windowsize, lfsparms.windowsize, RELATIVE2ORIGIN);

            if (maxpad > 0)
            {
                // печать
                pdata = pad_uchar_image(ref pw, ref ph, idata, iw, ih, maxpad, lfsparms.pad_value);
                // PrintMap(pdata, "pdata");
            }
            else
            {
                for (int i = 0; i < iw; i++)
                {
                    for (int j = 0; j < ih; j++)
                    {
                        pdata[i, j] = idata.GetPixel(i, j).R;
                    }
                }

                pw = iw;
                ph = ih;
            }

            gen_image_maps(ref direction_map, ref low_contrast_map, ref low_flow_map, ref high_curve_map,
                           ref mw, ref mh, pdata, pw, ph, dir2rad, dftwaves, dftgrids, name);

            /* Assign results to output pointers. */
            odmap  = direction_map;
            olcmap = low_contrast_map;
            olfmap = low_flow_map;
            ohcmap = high_curve_map;
            obdata = bdata;

            return(0);
        }
    internal static int lfs_detect_minutiae_V2(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap,
        ref int[,] ohcmap, ref int[,] obdata, Bitmap idata, int iw, int ih, ref int mw, ref int mh, string name)
    {
      int[,] pdata = new int[iw, ih];
      int[,] bdata = new int[iw, ih];
      DIR2RAD dir2rad = new DIR2RAD();
      DFTWAVES dftwaves = new DFTWAVES();
      ROTGRIDS dftgrids = new ROTGRIDS();
      ROTGRIDS dirbingrids = new ROTGRIDS();
      int[,] direction_map = new int[iw, ih];
      int[,] low_contrast_map = new int[iw, ih];
      int[,] low_flow_map = new int[iw, ih];
      int[,] high_curve_map = new int[iw, ih];
      int maxpad = 0;

      int pw = 0, ph = 0;

      // initialization
      maxpad = get_max_padding_V2(lfsparms.windowsize, lfsparms.windowoffset,
          lfsparms.dirbin_grid_w, lfsparms.dirbin_grid_h);
      dir2rad = init_dir2rad(lfsparms.num_directions);
      dftwaves = init_dftwaves(dft_coefs, lfsparms.num_dft_waves, lfsparms.windowsize);
      dftgrids = init_rotgrids(iw, ih, maxpad, lfsparms.start_dir_angle,
          lfsparms.num_directions, lfsparms.windowsize, lfsparms.windowsize, RELATIVE2ORIGIN);

      if (maxpad > 0)
      {
        // печать
        pdata = pad_uchar_image(ref pw, ref ph, idata, iw, ih, maxpad, lfsparms.pad_value);
        // PrintMap(pdata, "pdata");
      }
      else
      {
        for (int i = 0; i < iw; i++)
        {
          for (int j = 0; j < ih; j++)
          {
            pdata[i, j] = idata.GetPixel(i, j).R;
          }
        }

        pw = iw;
        ph = ih;
      }

      gen_image_maps(ref direction_map, ref low_contrast_map, ref low_flow_map, ref high_curve_map,
          ref mw, ref mh, pdata, pw, ph, dir2rad, dftwaves, dftgrids, name);

      /* Assign results to output pointers. */
      odmap = direction_map;
      olcmap = low_contrast_map;
      olfmap = low_flow_map;
      ohcmap = high_curve_map;
      obdata = bdata;

      return (0);
    }
Beispiel #3
0
        internal static DIR2RAD init_dir2rad(int ndirs)
        {
            DIR2RAD dir2rad = new DIR2RAD();
            double  theta, pi_factor;
            double  cs, sn;

            dir2rad.ndirs = ndirs;
            pi_factor     = 2.0 * M_PI / (double)ndirs;
            dir2rad.cos   = new List <double>();
            dir2rad.sin   = new List <double>();

            for (int i = 0; i < ndirs; ++i)
            {
                theta = (double)(i * pi_factor);
                cs    = Math.Cos(theta);
                sn    = Math.Sin(theta);
                cs    = trunc_dbl_precision(cs, TRUNC_SCALE);
                sn    = trunc_dbl_precision(sn, TRUNC_SCALE);
                dir2rad.cos.Add(cs);
                dir2rad.sin.Add(sn);
            }

            return(dir2rad);
        }
        internal static DIR2RAD init_dir2rad(int ndirs)
        {
            DIR2RAD dir2rad = new DIR2RAD();
            double theta, pi_factor;
            double cs, sn;

            dir2rad.ndirs = ndirs;
            pi_factor = 2.0 * M_PI / (double)ndirs;
            dir2rad.cos = new List<double>();
            dir2rad.sin = new List<double>();

            for (int i = 0; i < ndirs; ++i)
            {
                theta = (double)(i * pi_factor);
                cs = Math.Cos(theta);
                sn = Math.Sin(theta);
                cs = trunc_dbl_precision(cs, TRUNC_SCALE);
                sn = trunc_dbl_precision(sn, TRUNC_SCALE);
                dir2rad.cos.Add(cs);
                dir2rad.sin.Add(sn);
            }

            return dir2rad;
        }
    internal static void smooth_direction_map(ref int[,] direction_map, ref int[,] low_contrast_map,
            int mw, int mh, DIR2RAD dir2rad)
    {
      int avrdir = 0, nvalid = 0;
      double dir_strength = 0;

      /* Foreach block in maps ... */
      for (int my = 0; my < mh; my++)
      {
        for (int mx = 0; mx < mw; mx++)
        {
          /* If the current block does NOT have LOW CONTRAST ... */
          if (low_contrast_map[mx, my] == 0)
          {
            /* Compute average direction from neighbors, returning the */
            /* number of valid neighbors used in the computation, and  */
            /* the "strength" of the average direction.                */
            average_8nbr_dir(ref avrdir, ref dir_strength, ref nvalid, direction_map, mx, my, mw, mh, dir2rad);

            /* If average direction strength is strong enough */
            /*    (Ex. thresh==0.2)...                        */
            if (dir_strength >= lfsparms.dir_strength_min)
            {
              /* If Direction Map direction is valid ... */
              if (direction_map[mx, my] != INVALID_DIR)
              {
                /* Conduct valid neighbor test (Ex. thresh==3)... */
                if (nvalid >= lfsparms.rmv_valid_nbr_min)
                {
                  /* Reassign valid direction with average direction. */
                  direction_map[mx, my] = avrdir;
                }
              }
              /* Otherwise direction is invalid ... */
              else
              {
                /* Even if DIRECTION_MAP value is invalid, if number of */
                /* valid neighbors is big enough (Ex. thresh==7)...     */
                if (nvalid >= lfsparms.smth_valid_nbr_min)
                {
                  /* Assign invalid direction with average direction. */
                  direction_map[mx, my] = avrdir;
                }
              }
            }
          }
          /* Otherwise, block has LOW CONTRAST, so keep INVALID direction. */
        }
      }
    }
    internal static void average_8nbr_dir(ref int avrdir, ref double dir_strength, ref int nvalid,
                  int[,] imap, int mx, int my, int mw, int mh, DIR2RAD dir2rad)
    {
      double pi2, pi_factor, theta;
      double avr;

      /* Compute neighbor coordinates to current IMAP direction */
      int e = mx + 1;  /* East */
      int w = mx - 1;  /* West */
      int n = my - 1;  /* North */
      int s = my + 1;  /* South */

      /* Intialize accumulators */
      nvalid = 0;
      double cospart = 0.0;
      double sinpart = 0.0;

      /* 1. Test NW */
      /* If NW point within IMAP boudaries ... */
      if ((w >= 0) && (n >= 0) && (imap[w, n] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[w, n]];
        sinpart += dir2rad.sin[imap[w, n]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 2. Test N */
      /* If N point within IMAP boudaries ... */
      if ((n >= 0) && (imap[mx, n] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[mx, n]];
        sinpart += dir2rad.sin[imap[mx, n]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 3. Test NE */
      /* If NE point within IMAP boudaries ... */
      if ((e < mw) && (n >= 0) && (imap[e, n] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[e, n]];
        sinpart += dir2rad.sin[imap[e, n]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 4. Test E */
      /* If E point within IMAP boudaries ... */
      if ((e < mw) && (imap[e, my] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[e, my]];
        sinpart += dir2rad.sin[imap[e, my]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 5. Test SE */
      /* If SE point within IMAP boudaries ... */
      if ((e < mw) && (s < mh) && (imap[e, s] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[e, s]];
        sinpart += dir2rad.sin[imap[e, s]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 6. Test S */
      /* If S point within IMAP boudaries ... */
      if (s < mh && imap[mx, s] != INVALID_DIR)
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[mx, s]];
        sinpart += dir2rad.sin[imap[mx, s]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 7. Test SW */
      /* If SW point within IMAP boudaries ... */
      if ((w >= 0) && (s < mh) && imap[w, s] != INVALID_DIR)
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[w, s]];
        sinpart += dir2rad.sin[imap[w, s]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* 8. Test W */
      /* If W point within IMAP boudaries ... */
      if ((w >= 0) && (imap[w, my] != INVALID_DIR))
      {
        /* Accumulate cosine and sine components of the direction */
        cospart += dir2rad.cos[imap[w, my]];
        sinpart += dir2rad.sin[imap[w, my]];
        /* Bump number of accumulated directions */
        nvalid++;
      }

      /* If there were no neighbors found with valid direction ... */
      if (nvalid == 0)
      {
        /* Return INVALID direction. */
        dir_strength = 0;
        avrdir = INVALID_DIR;
        return;
      }

      /* Compute averages of accumulated cosine and sine direction components */
      cospart /= (double)nvalid;
      sinpart /= (double)nvalid;

      /* Compute directional strength as hypotenuse (without sqrt) of average */
      /* cosine and sine direction components.  Believe this value will be on */
      /* the range of [0 .. 1].                                               */
      dir_strength = (cospart * cospart) + (sinpart * sinpart);
      /* Need to truncate precision so that answers are consistent   */
      /* on different computer architectures when comparing doubles. */
      dir_strength = trunc_dbl_precision(dir_strength, TRUNC_SCALE);

      /* If the direction strength is not sufficiently high ... */
      if (dir_strength < DIR_STRENGTH_MIN)
      {
        /* Return INVALID direction. */
        dir_strength = 0;
        avrdir = INVALID_DIR;
        return;
      }

      /* Compute angle (in radians) from Arctan of avarage         */
      /* cosine and sine direction components.  I think this order */
      /* is necessary because 0 direction is vertical and positive */
      /* direction is clockwise.                                   */
      theta = Math.Atan2(sinpart, cospart);

      /* Atan2 returns theta on range [-PI..PI].  Adjust theta so that */
      /* it is on the range [0..2PI].                                  */
      pi2 = 2 * M_PI;
      theta += pi2;
      theta = theta % pi2;

      /* Pi_factor sets the period of the trig functions to NDIRS units in x. */
      /* For example, if NDIRS==16, then pi_factor = 2(PI/16) = .3926...      */
      /* Dividing theta (in radians) by this factor ((1/pi_factor)==2.546...) */
      /* will produce directions on the range [0..NDIRS].                     */
      pi_factor = pi2 / (double)dir2rad.ndirs; /* 2(M_PI/ndirs) */

      /* Round off the direction and return it as an average direction */
      /* for the neighborhood.                                         */
      avr = theta / pi_factor;
      /* Need to truncate precision so that answers are consistent */
      /* on different computer architectures when rounding doubles. */
      avr = trunc_dbl_precision(avr, TRUNC_SCALE);
      avrdir = Sround(avr);

      /* Really do need to map values > NDIRS back onto [0..NDIRS) range. */
      avrdir %= dir2rad.ndirs;
    }
    internal static bool remove_dir(ref int[,] imap, int mx, int my, int mw, int mh, DIR2RAD dir2rad)
    {
      int avrdir = 0, nvalid = 0;
      double dir_strength = 0;

      /* Compute average direction from neighbors, returning the */
      /* number of valid neighbors used in the computation, and  */
      /* the "strength" of the average direction.                */
      average_8nbr_dir(ref avrdir, ref dir_strength, ref nvalid, imap, mx, my, mw, mh, dir2rad);

      /* Conduct valid neighbor test (Ex. thresh==3) */
      if (nvalid < lfsparms.rmv_valid_nbr_min)
      {
        // return 1
        return true;
      }

      /* If stregnth of average neighbor direction is large enough to */
      /* put credence in ... (Ex. thresh==0.2)                        */
      if (dir_strength >= lfsparms.dir_strength_min)
      {
        /* Conduct direction distance test (Ex. thresh==3) */
        /* Compute minimum absolute distance between current and       */
        /* average directions accounting for wrapping from 0 to NDIRS. */
        int dist = Math.Abs(avrdir - imap[mx, my]);
        dist = Min(dist, dir2rad.ndirs - dist);

        if (dist > lfsparms.dir_distance_max)
        {
          // return 2
          return true;
        }
      }

      // return 0
      return false;
    }
    internal static int test_left_edge(int lbox, int tbox, int rbox, int bbox, ref int[,] imap,
        int mw, int mh, DIR2RAD dir2rad)
    {
      /* Initialize number of directions removed on edge to 0 */
      int nremoved = 0;

      /* Set start pointer to bottom-leftmost point of box, or set it to */
      /* the bottommost point in IMAP column (lasty=mh-1), whichever     */
      /* is smaller.                                                     */
      int sy = Min(bbox, mh - 1);

      /* Set end pointer to either 1 point short of the top-leftmost */
      /* point of box, or set it to the topmost point in the IMAP    */
      /* column (y=0), whichever is larger.                          */
      int ey = Max(tbox - 1, 0);

      /* For each point on box's edge ... */
      for (int bx = lbox, by = sy;
          by >= ey && by >= 0;
          by--)
      {
        /* If valid IMAP direction and test for removal is true ... */
        if ((imap[bx, by] != INVALID_DIR) && (remove_dir(ref imap, bx, by, mw, mh, dir2rad)))
        {
          /* Set to INVALID */
          imap[bx, by] = INVALID_DIR;
          /* Bump number of removed IMAP directions */
          nremoved++;
        }
      }

      /* Return the number of directions removed on edge */
      return (nremoved);
    }
    internal static int test_bottom_edge(int lbox, int tbox, int rbox, int bbox, ref int[,] imap,
        int mw, int mh, DIR2RAD dir2rad)
    {
      /* Initialize number of directions removed on edge to 0 */
      int nremoved = 0;

      /* Set start pointer to bottom-rightmost point of box, or set it to the */
      /* rightmost point in the IMAP ROW (lastx=mw-1), whichever is smaller.  */
      int sx = Min(rbox, mw - 1);

      /* Set end pointer to either 1 point short of the bottom-    */
      /* lefttmost point of box, or set it to the leftmost point   */
      /* in the IMAP row (x=0), whichever is larger.               */
      int ex = Max(lbox - 1, 0);

      /* For each point on box's edge ... */
      for (int bx = sx, by = bbox;
          bx >= 0 && bx >= ex && by >= bbox;
          bx--)
      {
        /* If valid IMAP direction and test for removal is true ... */
        if ((imap[bx, by] != INVALID_DIR) && (remove_dir(ref imap, bx, by, mw, mh, dir2rad)))
        {
          /* Set to INVALID */
          imap[bx, by] = INVALID_DIR;
          /* Bump number of removed IMAP directions */
          nremoved++;
        }
      }

      /* Return the number of directions removed on edge */
      return (nremoved);
    }
Beispiel #10
0
    internal static int test_top_edge(int lbox, int tbox, int rbox,
             int bbox, ref int[,] imap, int mw, int mh, DIR2RAD dir2rad)
    {
      /* Initialize number of directions removed on edge to 0 */
      int nremoved = 0;

      /* Set start pointer to top-leftmost point of box, or set it to */
      /* the leftmost point in the IMAP row (0), whichever is larger. */
      int sx = Max(lbox, 0);

      /* Set end pointer to either 1 point short of the top-rightmost */
      /* point of box, or set it to the rightmost point in the IMAP   */
      /* row (lastx=mw-1), whichever is smaller.                      */
      int ex = Min(rbox - 1, mw - 1);

      /* For each point on box's edge ... */
      for (int bx = sx, by = tbox;
          bx <= ex && bx < imap.GetLength(0);
          bx++)
      {
        /* If valid IMAP direction and test for removal is true ... */
        if ((imap[bx, by] != INVALID_DIR) && (remove_dir(ref imap, bx, by, mw, mh, dir2rad)))
        {
          imap[bx, by] = INVALID_DIR;
          nremoved++;
        }
      }

      /* Return the number of directions removed on edge */
      return (nremoved);
    }
Beispiel #11
0
    /// <summary>
    /// Вычисляем карты для изображения (для Version 2 of the NIST LFS System)
    /// карта направлений (Direction Map) - матрица, целые значения, доминирующее направление
    /// карта контрастов (Low Contrast Map) - матрица, помечены блоки низкого контраста
    /// карта потоков (Low Flow Map) - нет выделенного направления
    /// карта кривизны (High Curve Map) - блоки высокой кривизны
    /// Изображение: произвольное, не квадратное
    /// </summary>
    /// <param name="odmap">карта направлений</param>
    /// <param name="olcmap">карта контраста</param>
    /// <param name="olfmap">карта потоков</param>
    /// <param name="ohcmap">карта кривизны</param>
    /// <param name="omw"> количество блоков по горизонтали</param>
    /// <param name="omh">количество блоков по вертикали</param>
    /// <param name="pdata">padded входное изображение</param>
    /// <param name="pw">padded ширина</param>
    /// <param name="ph">padded высота</param>
    /// <param name="dir2rad">Поисковая таблица преобразования целых направлений</param>
    /// <param name="dftwaves">структура для DFT сигналов (wave forms)</param>
    /// <param name="dftgrids">структура смещений для повёрнутых пикселей окна\грида  (rotated pixel grid offsets)</param>
    internal static void gen_image_maps(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap, ref int[,] ohcmap,
       ref int omw, ref int omh, int[,] pdata, int pw, int ph,
       DIR2RAD dir2rad, DFTWAVES dftwaves, ROTGRIDS dftgrids, string name)
    {
      int[,] direction_map = new int[omw, omh];
      int[,] low_contrast_map = new int[omw, omh];
      int[,] low_flow_map = new int[omw, omh];
      int mw = 0, mh = 0;

      if (dftgrids.grid_w != dftgrids.grid_h)
      {
        throw new Exception("ERROR : gen_image_maps : DFT grids must be square\n");
      }

      int iw = pw - (dftgrids.pad << 1);
      int ih = ph - (dftgrids.pad << 1);
      // int blkoffsCount = ((int)Math.Ceiling(iw / (double)lfsparms.blocksize)) *
      //                    (int)Math.Ceiling(ih / (double)lfsparms.blocksize);

      // blkoffsCount = blkoffs.GetLength(0) * blkoffs.GetLength(1)  - проверено
      // считаем смещения для блоков
      // предполагая, что у нас +12 пикселей со всех сторон изображения со значениями 128
      // чтобы нормально считать в окнах
      int[,] blkoffs = block_offsets(ref mw, ref mh, iw, ih, dftgrids.pad, lfsparms.blocksize);

      //  PrintMap(blkoffs, "blkoffs");

      gen_initial_maps(ref direction_map, ref low_contrast_map, ref low_flow_map,
          blkoffs, mw, mh, ref pdata, pw, ph, dftwaves, dftgrids);

      // печать
      //  PrintMap(direction_map, "direction_map");
      //  PrintMap(low_contrast_map, "low_contrast_map");
      //  PrintMap(low_flow_map, "low_flow_map");

      // direction_map не меняется, также low_flow = 0
      // но low_contrast = 1

      morph_TF_map(ref low_flow_map, mw, mh);
      remove_incon_dirs(ref direction_map, mw, mh, dir2rad);
      smooth_direction_map(ref direction_map, ref low_contrast_map, mw, mh, dir2rad);
      interpolate_direction_map(ref direction_map, ref low_contrast_map, mw, mh);
      remove_incon_dirs(ref direction_map, mw, mh, dir2rad);
      smooth_direction_map(ref direction_map, ref low_contrast_map, mw, mh, dir2rad);
      set_margin_blocks(ref direction_map, mw, mh, INVALID_DIR);

      int[,] high_curve_map = gen_high_curve_map(ref direction_map, mw, mh);

      odmap = direction_map;
      olcmap = low_contrast_map;
      olfmap = low_flow_map;
      ohcmap = high_curve_map;
      omw = mw;
      omh = mh;

      // печать
      //PrintMap(direction_map, name + "_direction_map");
      //PrintMap(low_contrast_map, name + "_low_contrast_map");
      //PrintMap(low_flow_map, name + "_low_flow_map");
      //PrintMap(high_curve_map, name + "_high_curve_map");
    }
Beispiel #12
0
    internal static void remove_incon_dirs(ref int[,] imap, int mw, int mh, DIR2RAD dir2rad)
    {
      int nremoved;
      int lbox, rbox, tbox, bbox;

      /* Compute center coords of IMAP */
      int cx = mw >> 1;
      int cy = mh >> 1;

      /* Do pass, while directions have been removed in a pass ... */
      do
      {
        /* Reinitialize number of removed directions to 0 */
        nremoved = 0;

        /* If valid IMAP direction and test for removal is true ... */
        if ((imap[cx, cy] != INVALID_DIR) && remove_dir(ref imap, cx, cy, mw, mh, dir2rad))
        {
          /* Set to INVALID */
          imap[cx, cy] = INVALID_DIR;
          /* Bump number of removed IMAP directions */
          nremoved++;
        }

        /* Initialize side indices of concentric boxes */
        lbox = cx - 1;
        tbox = cy - 1;
        rbox = cx + 1;
        bbox = cy + 1;

        /* Grow concentric boxes, until ALL edges of imap are exceeded */
        while ((lbox >= 0) || (rbox < mw) || (tbox >= 0) || (bbox < mh))
        {

          /* test top edge of box */
          if (tbox >= 0)
            nremoved += test_top_edge(lbox, tbox, rbox, bbox, ref imap, mw, mh, dir2rad);

          /* test right edge of box */
          if (rbox < mw)
            nremoved += test_right_edge(lbox, tbox, rbox, bbox, ref imap, mw, mh, dir2rad);

          /* test bottom edge of box */
          if (bbox < mh)
            nremoved += test_bottom_edge(lbox, tbox, rbox, bbox, ref imap, mw, mh, dir2rad);

          /* test left edge of box */
          if (lbox >= 0)
            nremoved += test_left_edge(lbox, tbox, rbox, bbox, ref imap, mw, mh, dir2rad);

          /* Resize current box */
          lbox--;
          tbox--;
          rbox++;
          bbox++;
        }
      } while (nremoved != 0);
    }