image.cc

来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· CC 代码 · 共 1,083 行 · 第 1/3 页

CC
1,083
字号
      const int kheight = kernel.size(1);      //output is same size as input      filtered.resize(iwidth,iheight);      filtered.init(0);      // the kernel must not be larger than the image      assert (kwidth <= iwidth);      assert (kheight <= iheight);      // the kernel must be odd in each dimension so it can be centered      // over a pixel      assert ((kwidth % 2) == 1);      assert ((kheight % 2) == 1);      // radius of kernel in each dimension; also the coordinates of the      // kernel's center pixel      const int xr = kwidth / 2;      const int yr = kheight / 2;      //flip the kernel left-right and up-down      Util::Array2D<float> kern(kwidth,kheight);      kern.init(0);      for (int x = 0; x < kwidth; x++)      {        const int xx = kwidth - 1 - x;        for (int y = 0; y < kheight; y++)        {          const int yy = kheight - 1 - y;          kern(xx,yy) = kernel(x,y);        }      }      // padded image dimensions      const int pwidth = iwidth + 2 * xr;      const int pheight = iheight + 2 * yr;      //create image with reflective padding      Util::Array2D<float> pim(pwidth,pheight);      // top left      for (int y = 0; y < yr; y++)      {          const int py = yr - 1 - y;          for (int x = 0; x < xr; x++)            {                const int px = xr - 1 - x;                pim(px,py) = im(x,y);            }      }      // top right      for (int y = 0; y < yr; y++)      {          const int py = yr - 1 - y;          for (int x = 0; x < xr; x++)            {                const int xs = iwidth - 1 - x;                const int xd = xr + iwidth + x;                pim(xd,py) = im(xs,y);            }      }      // bottom left      for (int y = 0; y < yr; y++)      {          const int ys = iheight - 1 - y;          const int yd = yr + iheight + y;          for (int x = 0; x < xr; x++)            {                const int px = xr - 1 - x;                pim(px,yd) = im(x,ys);            }      }      // bottom right      for (int y = 0; y < yr; y++)      {          const int ys = iheight - 1 - y;          const int yd = yr + iheight + y;          for (int x = 0; x < xr; x++)            {                const int xs = iwidth - 1 - x;                const int xd = xr + iwidth + x;                pim(xd,yd) = im(xs,ys);            }      }      // top      for (int y = 0; y < yr; y++)      {          const int py = yr - 1 - y;          for (int x = 0; x < iwidth; x++)            {                const int px = x + xr;                pim(px,py) = im(x,y);            }      }      // bottom      for (int y = 0; y < yr; y++)      {          const int ys = iheight - 1 - y;          const int yd = yr + iheight + y;          for (int x = 0; x < iwidth; x++)            {                const int px = x + xr;                pim(px,yd) = im(x,ys);            }      }      // left       for (int y = 0; y < iheight; y++)      {          const int py = yr + y;          for (int x = 0; x < xr; x++)            {                const int px = xr - 1 - x;                pim(px,py) = im(x,y);            }      }      // right      for (int y = 0; y < iheight; y++)      {          const int py = yr + y;          for (int x = 0; x < xr; x++)            {                const int xs = iwidth - 1 - x;                const int xd = xr + iwidth + x;                pim(xd,py) = im(xs,y);            }      }      // center      for (int y = 0; y < iheight; y++)      {          const int py = yr + y;          for (int x = 0; x < iwidth; x++)          {              const int px = xr + x;              pim(px,py) = im(x,y);          }      }      // use direct access to underlying arrays for speed      float *p_pim = pim.data();      float *p_kern = kern.data();      float *p_filtered = filtered.data();      // do the convolution      // interchange y and ky loops, and unroll ky loop      // gets 371 MFLOPS (including all overhead) on 700MHz PIII (53% of peak)      for (int x = 0; x < iwidth; x++)      {        for (int kx = 0; kx < kwidth; kx++)        {          const int pcol = (x + kx) * pheight;          const int kcol = kx * kheight;          int ky = 0;          while (ky < (kheight & ~0x7))          {            const float k0 = p_kern[kcol + ky + 0];            const float k1 = p_kern[kcol + ky + 1];            const float k2 = p_kern[kcol + ky + 2];            const float k3 = p_kern[kcol + ky + 3];            const float k4 = p_kern[kcol + ky + 4];            const float k5 = p_kern[kcol + ky + 5];            const float k6 = p_kern[kcol + ky + 6];            const float k7 = p_kern[kcol + ky + 7];            float in0 = p_pim[pcol + 0 + ky + 0];            float in1 = p_pim[pcol + 0 + ky + 1];            float in2 = p_pim[pcol + 0 + ky + 2];            float in3 = p_pim[pcol + 0 + ky + 3];            float in4 = p_pim[pcol + 0 + ky + 4];            float in5 = p_pim[pcol + 0 + ky + 5];            float in6 = p_pim[pcol + 0 + ky + 6];            for (int y = 0; y < iheight; y++)            {                const float in7 = p_pim[pcol + y + ky + 7];                p_filtered[x*iheight + y] += k0*in0 + k1*in1 + k2*in2 + k3*in3 +                                             k4*in4 + k5*in5 + k6*in6 + k7*in7;                in0 = in1;                in1 = in2;                in2 = in3;                in3 = in4;                in4 = in5;                in5 = in6;                in6 = in7;            }            ky += 8;          }          while (ky < (kheight & ~0x3))          {            const float k0 = p_kern[kcol + ky + 0];            const float k1 = p_kern[kcol + ky + 1];            const float k2 = p_kern[kcol + ky + 2];            const float k3 = p_kern[kcol + ky + 3];            float in0 = p_pim[pcol + 0 + ky + 0];            float in1 = p_pim[pcol + 0 + ky + 1];            float in2 = p_pim[pcol + 0 + ky + 2];            for (int y = 0; y < iheight; y++)            {                const float in3 = p_pim[pcol + y + ky + 3];                p_filtered[x*iheight + y] += k0*in0 + k1*in1 + k2*in2 + k3*in3;                in0 = in1;                in1 = in2;                in2 = in3;            }            ky += 4;          }          while (ky < (kheight & ~0x1))          {            const float k0 = p_kern[kcol + ky + 0];            const float k1 = p_kern[kcol + ky + 1];            float in0 = p_pim[pcol + 0 + ky + 0];            for (int y = 0; y < iheight; y++)            {                const float in1 = p_pim[pcol + y + ky + 1];                p_filtered[x*iheight + y] += k0*in0 + k1*in1;                in0 = in1;            }            ky += 2;          }          while (ky < kheight)          {            const float k0 = p_kern[kcol + ky];            for (int y = 0; y < iheight; y++)            {                p_filtered[x*iheight + y] += k0*p_pim[pcol + y + ky];            }            ky += 1;          }          assert (ky == kheight);        }      }  }  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // filter at the given radius.  // the resulting value at a pixel is the n'th-order value  // in a circular window cetnered at the pixel  // 0 <= order <= 1, 0 is smallest value, 1 is largest.  // Call with 0.5 to get median filtering.  //  void getPctFiltered(const Image& im, const float radius, const float order, Image& filtered)   {      assert (order >= 0 && order <= 1);      if (radius < 1)      {        filtered = im;        return;      }      //allocate window and filtered image      const int windowRadius = (int) ceil (radius);      const int windowDiam = 2 * windowRadius + 1;      const int windowPixels = windowDiam * windowDiam;      Util::Array1D<float> values(windowPixels);      const int iwidth = im.size(0);      const int iheight = im.size(1);      filtered.resize(iwidth,iheight);      //loop over the image      for (int x = 0; x < iwidth; x++)      {        for (int y = 0; y < iheight; y++)        {          //copy values out of the window          int count = 0;          for (int u = -windowRadius; u <= windowRadius; u++)          {            for (int v = -windowRadius; v <= windowRadius; v++)            {              if ((u * u + v * v) > radius * radius)              {                continue;              }              int yi = y + u;              int xi = x + v;              if (yi < 0 || yi >= iheight)              {                continue;              }              if (xi < 0 || xi >= iwidth)              {                continue;              }              assert (count < windowPixels);              values(count++) = im(xi,yi);            }          }          //sort the values in ascending order          assert (count > 0);          Util::sort(values.data(), count);          assert(values(0) <= values(count - 1));          //pick out percentile value          int index = (int) rint (order * (count - 1));          assert (index >= 0 && index < count);          float pctVal = values(index);          assert (pctVal >= values(0));          assert (pctVal <= values(count - 1));          filtered(x,y) = pctVal;        }      }  }  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // filter at the given radius.  // the resulting value at a pixel is the maximum value  // in a circular window cetnered at the pixel  //  void getMaxFiltered (const Image& im, const float radius, Image& filtered)  {    if (radius < 1)    {      filtered = im;      return;    }    const int iwidth = im.size(0);    const int iheight = im.size(1);    const int windowRadius = (int)ceil(radius);    filtered.resize(iwidth,iheight);    //loop over the image    for (int x = 0; x < iwidth; x++)    {      for (int y = 0; y < iheight; y++)      {        //extract max from window        float maxVal = im(x,y);        for (int u = -windowRadius; u <= windowRadius; u++)        {          for (int v = -windowRadius; v <= windowRadius; v++)          {            if ((u * u + v * v) > radius * radius)            {              continue;            }            int xi = x + u;            int yi = y + v;            if (yi < 0 || yi >= iheight)            {              continue;            }            if (xi < 0 || xi >= iwidth)            {              continue;            }            const float val = im(xi,yi);            maxVal = Util::max(val,maxVal);          }        }        // save max        filtered(x,y) = maxVal;      }    }  }} //namespace Util

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?