从等方形

时间:2015-11-02 07:54:25

标签: algorithm math vector geometry 2d

我确信必须有一种方法可以执行以下操作,但我不知道它叫什么,所以我不能谷歌。

我需要一个从A到B的算法。有人知道它叫什么或有链接吗?

enter image description here

编辑:对不起,我不够清楚。图A由正方形组成,我基本上需要一个算法来移除正方形并将其变成多边形(图B)。 输入是轴对齐正方形的普通列表,输出应该是构成多边形的顶点列表。方块总是像网格一样对齐,它们不会重叠。

为了更清楚,我想编写一个这样的函数(伪代码):

struct Square {
    x, y, size: float
}
struct Polygon {
    vertices_x, vertices_y: float[]
}
function convert_to_polygon(IN squares: Square[]) -> OUT Polygon {
    //The algorithm I need goes here
}

1 个答案:

答案 0 :(得分:2)

如果我做得对,你想获得图像的圆周轮廓。

对于矢量和栅格输入,您可以调整/使用finding holes in 2D point set。无论如何,你想要寻找(凸)赫尔算法的某种二维适应...

如果您的输入是光栅:

  1. 您可以使用不同颜色(例如蓝色)填充背景
  2. 重新着色蓝色像素旁边的所有像素(红色)
  3. 将所有非红色像素重新着色为白色
  4. 将所有红色像素重新着色为黑色

    如果您需要在子弹#2处停止的矢量输出并创建红点列表。然后应用连通像素分析来检测线条在多边形中的顺序...对于正方形,这应该很容易,但对于任意图像,您需要line regression Hough变换 ......

  5. 如果您的输入是矢量:

    然后删除所有内线。因此,由 H 形状的其他线条包围的线条。您还可以检测所有小方块,然后删除重复的行。

    [Edit1]您的输入/输出是矢量

    1. 形成所有行的列表
    2. 删除多次出现的所有行

      如果您的方块是任意大小,那么您需要通过剪切重叠的段来更精确地做到这一点......

    3. 将第一行添加到多边形(从行列表中删除)

    4. 查找与上一个添加到“多边形”的行具有相同结束点的行
    5. 将其添加到多边形(从行列表中删除)
    6. 循环#4直到找不到行...
    7. 如果仍有未使用的有效行,则表示有多个多边形,因此添加新的空多边形并转到#3
    8. 在C ++中我破坏了这样的东西:

      // temp structures
      struct _pnt  { float x,y;       _pnt(){}; _pnt(_pnt& a){ *this=a; }; ~_pnt(){}; _pnt* operator = (const _pnt *a) { *this=*a; return this; }; /*_pnt* operator = (const _pnt &a) { ...copy... return this; };*/ };
      struct _lin  { int p0,p1,n;     _lin(){}; _lin(_lin& a){ *this=a; }; ~_lin(){}; _lin* operator = (const _lin *a) { *this=*a; return this; }; /*_lin* operator = (const _lin &a) { ...copy... return this; };*/ };
      // your in/out structures
      struct _sqr  { float x,y,s;     _sqr(){}; _sqr(_sqr& a){ *this=a; }; ~_sqr(){}; _sqr* operator = (const _sqr *a) { *this=*a; return this; }; /*_sqr* operator = (const _sqr &a) { ...copy... return this; };*/ };
      struct _pol { List<float> x,y;  _pol(){}; _pol(_pol& a){ *this=a; }; ~_pol(){}; _pol* operator = (const _pol *a) { *this=*a; return this; }; /*_pol* operator = (const _pol &a) { ...copy... return this; };*/ };
      List<_sqr> sqr; // squares
           _pol  pol; // polygon
      
      void sqr2pol_init()
          {
          _sqr s;
          int i,j,p0,p1,p2,p3;
          float x,y,x0,x1,y0,y1,a=32,d,_zero=1e-3;
          // [init square list to your scenario]
          sqr.num=0; pol.x.num=0; pol.y.num=0;
          s.s=a; s.x=a; s.y=a;
          sqr.add(s); s.x+=a;
          sqr.add(s); s.x+=a;
          sqr.add(s); s.x+=a;
          sqr.add(s); s.x =a; s.y+=a;
          sqr.add(s); s.x =a; s.y+=a;
          sqr.add(s); s.x+=a;
          // [compute point and line lists]
          List<_pnt> pnt; _pnt p;
          List<_lin> lin; _lin l;
          for (pnt.num=0,lin.num=0,i=0;i<sqr.num;i++)
              {
              x=sqr[i].x;
              y=sqr[i].y;
              a=sqr[i].s*0.5;
              x0=x-a; x1=x+a;
              y0=y-a; y1=y+a;
              // add non duplicate points only
              p.x=x0; p.y=y0; for (j=0;j<pnt.num;j++) { x=pnt[j].x-p.x; y=pnt[j].y-p.y; if ((x*x)+(y*y)<=_zero) break; } if (j>=pnt.num) pnt.add(p); p0=j;
              p.x=x0; p.y=y1; for (j=0;j<pnt.num;j++) { x=pnt[j].x-p.x; y=pnt[j].y-p.y; if ((x*x)+(y*y)<=_zero) break; } if (j>=pnt.num) pnt.add(p); p1=j;
              p.x=x1; p.y=y1; for (j=0;j<pnt.num;j++) { x=pnt[j].x-p.x; y=pnt[j].y-p.y; if ((x*x)+(y*y)<=_zero) break; } if (j>=pnt.num) pnt.add(p); p2=j;
              p.x=x1; p.y=y0; for (j=0;j<pnt.num;j++) { x=pnt[j].x-p.x; y=pnt[j].y-p.y; if ((x*x)+(y*y)<=_zero) break; } if (j>=pnt.num) pnt.add(p); p3=j;
              // add non duplicate lines (and update counter n for duplicates)
              l.p0=p0; l.p1=p1; l.n=0; for (j=0;j<lin.num;j++) if (((lin[j].p0==l.p0)&&(lin[j].p1==l.p1))||((lin[j].p0==l.p1)&&(lin[j].p1==l.p0))) { lin[j].n++; break; } if (j>=lin.num) lin.add(l);
              l.p0=p1; l.p1=p2; l.n=0; for (j=0;j<lin.num;j++) if (((lin[j].p0==l.p0)&&(lin[j].p1==l.p1))||((lin[j].p0==l.p1)&&(lin[j].p1==l.p0))) { lin[j].n++; break; } if (j>=lin.num) lin.add(l);
              l.p0=p2; l.p1=p3; l.n=0; for (j=0;j<lin.num;j++) if (((lin[j].p0==l.p0)&&(lin[j].p1==l.p1))||((lin[j].p0==l.p1)&&(lin[j].p1==l.p0))) { lin[j].n++; break; } if (j>=lin.num) lin.add(l);
              l.p0=p3; l.p1=p0; l.n=0; for (j=0;j<lin.num;j++) if (((lin[j].p0==l.p0)&&(lin[j].p1==l.p1))||((lin[j].p0==l.p1)&&(lin[j].p1==l.p0))) { lin[j].n++; break; } if (j>=lin.num) lin.add(l);
              }
          // [copy singular lines only to polygon + connected lines analysis/reorder]
          // add first usable (n==0) line to polygon
          p0=-1;
          for (i=0;i<lin.num;i++)
           if (lin[i].n==0)
              {
              pol.x.add(pnt[lin[i].p0].x);
              pol.y.add(pnt[lin[i].p0].y);
              pol.x.add(pnt[lin[i].p1].x);
              pol.y.add(pnt[lin[i].p1].y);
              p0=lin[i].p0;   // p0 = start of polygon
              p1=lin[i].p1;   // p1 = current end of polygon
              lin[i].n++;     // mark as unusable
              break;
              }
          // add next line to p1 until you can
          for (j=1;j;)
              {
              for (i=0,j=0;i<lin.num;i++)
               if (lin[i].n==0)
                  {
                  p2=-1;
                  if (lin[i].p0==p1) p2=lin[i].p1;
                  if (lin[i].p1==p1) p2=lin[i].p0;
                  if (p2<0) continue;
                  pol.x.add(pnt[p2].x);
                  pol.y.add(pnt[p2].y);
                  lin[i].n++;     // mark as unusable
                  p1=p2;          // update last point
                  j=1;            // continue search
                  break;
                  }
              }
          }
      
      • List<T> l;只是动态线性数组模板(类似于std::vector
      • 代表T[l.num] l;
      • l.num是数组的当前大小
      • l.add(x);将新项x添加到数组的末尾...

      结果如下:

      example]

      • Aqua 行是原始正方形sqr
      • 黄色行是多边形pol输出