计算机视觉
图像处理

【OpenCV】图形生成算法:多边形的扫描转换

文章目录

多边形

扫描线算法是针对计算机中多边形的显示。多边形三条或三条以上的线段首位顺次连接所组成的封闭图形,有凸多边形(任意两顶点间的连线均在多边形内)和凹多边形(任意两顶点间的连线有不在多边形内的部分)。

多边形在计算机中有顶点表示和点阵表示两种。

顶点表示就是用多边形的顶点序列来表示多边形。点阵表示是用位于多边形内的象素集合来表示多边形。顶点表示占内存少,几何意义强,易于进行几何变换;而点阵表示丢失了许多几何信息(如边界、顶点)。但光栅显示图形需要点阵表示形式。

多边形的扫描转换就是把多边形的顶点表示转换为点阵表示。

扫描转换算法

按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色填充这些区间的象素。步骤如下:

求交:计算扫描线与多边形各边的交点;
排序:把所有交点按x值递增顺序排序;
配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边形的一个相交区间,
着色:把相交区间内的象素置成多边形颜色,把相交区间外的象素置成背景色。

其实很好理解,像下面的图:

以倒数第三条扫描线为例,有6个交点,排序之后为 A,B,C,D,E,F

然后配对:(A,B)(C,D)(E,F)也就是要填充(A,B)(C,D)(E,F)之间的部分。

这是扫描线与一条边相交,会出现问题的地方时扫描线与两条边相交,也就是与顶点相交。比如ABCD上面那条线,如果把顶点处看做一个交点,如图,配 对的结果是:(G,H)(I,J)于是(H,I)之间的部分就会被填充为背景;如果吧H看做两个交点,H1,H2。配对结果:(G,H1) (H2,I)。。。把I被看成两个交点也是不科学的,正确的应该是把H看做0个交点,I看做两个。

总结说来,就是判断共享顶点的两个边:

如果共享顶点的两条边分别落在扫描线的两边,交点只算一个;
如果共享顶点的两条边在扫描线的同一边,这时交点作为零个或两个:另外两边都在下面看成0个,都在上面看成2个。
具体实现时,只需检查顶点的两条边的另外两个端点的y值。按这两个y值中大于交点y值的个数是0,1,2来决定。

还是上图GHI那条线,应看做G,I1,I2,J。配对结果:(G,I1)(I2,J)。

上图所有有交点的地方:

边相关扫描填充算法

简单的扫描线填充算法需要一直求扫描线与多边形边的交点。但我们看上图,扫描线与最左边的那条边GA的交点坐标是呈线性关系的。也就是说如果GA的斜率是m,

如果G的交点坐标是x1,假设A是下一条扫描线的交点,则交点就是x1+1/m。即:x(i+1)=x(i)+1/m。

这种性质在遇到顶点的时候会有一些改变,可以通过边的相关性总结规律。简单描述为扫描线上相邻像素的点在多边形内还是多边形外,内,外的关系在遇到顶点时会发生改变。还是上面那张图:

边相关的填充算法描述有点复杂,要维护两张表。回头再重写一章吧。

Opencv中的函数

OpenCV中用 fillPoly() 函数绘制多边形。在core module的部分有所有的基本绘图函数:

直线 line()、圆circle()、椭圆ellipse()、矩形rectangle()、填充多边形fillPoly()

在安装目录的  OpenCV2.3.1samplescpptutorial_codeCxCoreMatrix  的文件夹下有名为  Drawing_1.cpp 的文件,有所有绘图的演示。填充多边形使用如下:

  1. void MyPolygon( Mat img )
  2. {
  3.   int lineType = 8;
  4.   /** Create some points */
  5.   Point rook_points[1][20];
  6.   rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
  7.   rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
  8.   rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
  9.   rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
  10.   rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
  11.   rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
  12.   rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
  13.   rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
  14.   rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
  15.   rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
  16.   rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
  17.   rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
  18.   rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
  19.   rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
  20.   rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
  21.   rook_points[0][15] = Point( w/4.0, w/8.0 );
  22.   rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
  23.   rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
  24.   rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
  25.   rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
  26.   const Point* ppt[1] = { rook_points[0] };
  27.   int npt[] = { 20 };
  28.   fillPoly( img,
  29.         ppt,
  30.         npt,
  31.             1,
  32.         Scalar( 255, 255, 255 ),
  33.         lineType );
  34. }

简单来说就是定义多边形的点就可以直接绘制。

效果如下:

还有一个效果很炫的 Drawing_2.cpp ,里面有Text的演示

尤其喜欢最后的效果:

找不到的,代码可以在这里下载:http://pan.baidu.com/s/1o8CIC6A

转载注明来源:CV视觉网 » 【OpenCV】图形生成算法:多边形的扫描转换

分享到:更多 ()
扫描二维码,给作者 打赏
pay_weixinpay_weixin

请选择你看完该文章的感受:

0不错 0超赞 0无聊 0扯淡 0不解 0路过

评论 5

评论前必须登录!