光栅图形学算法(一)

前言

  随着光栅显示器的出现,为了在计算机上处理、显示图形,需要发展一套与之相适应的算法:光栅图形学算法

光栅图形学算法的研究内容

直线段的扫描转换算法
多边形的扫描转换与区域填充算法
裁剪算法
反走样算法
消隐算法

直线段的扫描转换算法

  在数学上,直线上的点有无穷多个。但要在计算机光栅显示器屏幕上表示这条直线,用有限的点来表示无限的点
      光栅图形学算法(一)_第1张图片
      光栅图形学算法(一)_第2张图片
  为了在光栅显示器上用这些离散的像素点逼近这条直线,需要知道这些像素点的x,y坐标
知道P0和P1的坐标,再通过直线方程来求其他点的坐标
求出P0和P1的直线方程:y=kx+b(斜截式方程,k为斜率,b截距)
k=(y1-y0)/(x1-x0) (x1!=x0)
只有一个方程,但有两个未知量,那么先假设一个量。假设x已知,即从x的起点x0开始,沿x方向前进一个像素(不长=1),可以计算相应的y值。因为像素的坐标是整数,所以y值还要进行取整处理。

如何把整数上的一个点扫描转换一个屏幕像素点?
如 P(1.7,0.8) 取整后为 P(1,0) 但是1.7离2比较近,0.8里1比较近,如果将这两个数取整为(1,0)误差较大,所以一般取整为(2,1),这样更接近实际

  直线是最基本的图形,一个动画或真实感图形往往需要调用成千上万次画线程序,因此直线算法的好坏与效率将直接影响图形的质量和显示速度。

直线绘制的三个著名的常用算法

  使用y=kx+b这个方程画线需要进行一个乘法,再进行一个加法,我们都知道计算机进行加法运算是最快的,那么我们这里就改成加法运算

1、数值微分法(DDA)
2、中点画线发
3、Bresenham算法

数值微分法DDA(Digital Differential Analyzer)法

引进图形学中一个很重要的思想——增量思想
      光栅图形学算法(一)_第3张图片
点(xi+1,yi+1)满足yi+1=kxi+1+b这个方程,前面说过像素点每次加1,所以yi+1=kxi+1+b=k(xi+1)+b=kxi+k+b=yi+k,所以yi+1=yi+k,这个式子的含义是:当前步的y值等于前一步的y值加上斜率k,这样就把原来一个乘法和加法变成了一个加法!这样效率就大大提高了。

中点画线法

这里使用直线的一般方程:F(x,y)=0;Ax+By+C=0
      光栅图形学算法(一)_第4张图片
直线将平面分成三个部分

对于直线上的点:F(x,y)=0
对于直线上方的点:F(x,y)>0
对于直线下方的点:F(x,y)<0

  每次在最大位移方向上走一步,而另一个方向是走步还是不走不要取决于中点误差项的判断。
假定:0<=|k|<=1.因此,每次在x方向上加1,y方向上加1或不变需要判断。
      光栅图形学算法(一)_第5张图片
  已知P点,那么下一点无非是Pu或Pd。理想直线和直线Pu、Pd有一个交点Q,直线Pu、Pd有一个中点M。
当M在Q的下方,则Pu离直线近,应为下一个像素点
当M在Q的上方,应取Pd为下一点。
如果M在Q点,那么说明M离Pu、Pd一样近,那么随便取哪点都可以

如何确定M点,即把M代入理想直线方程:
F(xm,ym)=Axm+Bym+C
di=F(xm,ym)=F(xi+1,yi+0.5)=A(xi+1)+B(yi+0.5)+C

当d<0时:M在Q点下方,应去Pu
当d>0时:M在Q上方,应取Pd
当d=0时:M在直线上,选Pd或Pu均可

Bresenham算法

DDA把算法效率提高到每步只做一个加法
中点算法进一步把效率提高到每步只做一个整数加法
Bresenham提供一个更一般的算法。该算法不仅有好的效率,而且有更广泛的使用范围

Bresenham算法的基本思想
      光栅图形学算法(一)_第6张图片
  该算法的思想是通过各行、各列像素中心构造一组虚拟网络线,按照直线起点到终点的顺序,计算直线与各垂直网络线的交点,然后根据误差项的符号确定该列象素中与此交点最近的象素。图中d为交点与象素点的距离,恰好等于直线的斜率k
      光栅图形学算法(一)_第7张图片
  假设每次x+1,y的递增(减)量为0或1,它取决于实际直线与最近光栅网格点的距离,这个距离的最大误差为0.5。如果d>0.5,则离上面的点近,否则离下面的点近。

误差项d的初值d0=0
d=d+k
一旦d>=1,就把它减去1,保证d的相对性,且在0、1之间。

如何把这个算法的效率也提高到整数加法?
改进1:令e=d-0.5
e>0,y方向递增1;e<0,y方向不递增
e=0时,可任取上、下光栅点显示

 e初=-0.5 (原来d的初值为0.现在e=d-0.5) 
 每走一步有e=e+k
 ife>0)then e=e-1 (保证0<e<1

改进2:
      光栅图形学算法(一)_第8张图片
算法步骤:
      光栅图形学算法(一)_第9张图片

Bresenham算法很像DDA算法,都是加斜率
但DDA算法是每次求出一个新的y以后取整来画;而Bresenham算法是判符号来决定上下两个点。所以该算法集中了DDA和中点两个算法的优点,而且应用范围广泛。

小结

计算机科学问题的核心就是算法

Y=kx+b

领会算法中所蕴含的创新思想
  改进和完善算法的过程中所体现出来的一些闪光的思想是我们所要认识和领会的
科学研究无止境,学术面前人人平等
  这些算法都很好,但还是有很大的改进空间

多边形的扫描转换与区域填充

多边形的扫描转换

  画直线是一维的,多边形的扫面转换和区域填充这个问题是怎么样在离散像素集上表示一个连续的二维图形。比画直线要复杂
多边形分为凸多边形、凹多边形、含内环的多边形等:

(1)凸多边形
任意两顶点间的连线均在多边形内
(2)凹多边形
任意两顶点间的连线有不在多边形内
(3)含内环的多边形
多边形内包含多边形

多边形有两种重要的表示方法:定点表示点阵表示
      光栅图形学算法(一)_第10张图片
  定点表示优点:是用多边形的定点序列来表示多边形。这种表示直观、几何意义强、占内存少,易于进行几何变换
缺点:由于它没有明确指出哪些象素在多边形内,故不能直接用于面着色
点阵表示是用位于多边形内的象素集合来刻画多边形。这种表示丢失了许多几何信息(如边界、顶点等),但它却是光栅显示系统显示时所需的表示形式。

这涉及到两个问题:第一问题是如果知道边界,能否求出哪些像素在多边形内?

第二个问题是知道多边形内部的像素,反过来如何求多边形的边界?
      光栅图形学算法(一)_第11张图片
上图中知道多边形内部的像素,但是得不到多边形的边界
所以第二个问题不属于计算机图形学的问题,是图形识别的问题

  光栅图形的一个基本问题是把多边形的定点表示转换为点阵表示。这种转换称为多边形的扫描转换
      光栅图形学算法(一)_第12张图片

X-扫描线算法

  X-扫描线算法填充多边形的基本思想是按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的像素,即完成填充工作
      光栅图形学算法(一)_第13张图片
  已知多边形的顶点,要求得多边形内部的像素点
  扫描线与多边形有4个交点,左边两个交点区域填充一个颜色,右边两个交点区域填充另一个颜色,又有很多扫描线从下往上扫描,从而填充整个图形,转换为点阵表示。
  区间的端点就可以通过计算扫描线与多边形边界线的交点获得

如扫描线y=3与多边形的边界相交于4点:
      光栅图形学算法(一)_第14张图片
  因为像素点都为整数,所以这里取点(2,3)、(4,3)、(7,3)、(9,3)这四点定义了扫描线从x=2到x=4,从x=7到x=9两个落在多边形内的区间,该区间内像素应取填充色。

  算法的核心是按x递增顺序排列交点的x坐标序列。由此,可得到X-扫描线算法步骤如下:

确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值。
从y=ymin到y=ymax,每次用一条扫描线进行填充
对一条扫描线填充的过程可分为四个步骤:
A.求交:计算扫描线与多边形各边的交点
B.排序:把所有交点按递增顺序进行排序
C.交点配对:第一个与第二个,第三个与第四个(保证交点的个数为偶数个)
D.区间填色:把这些相交区间内的像素置成不同与背景色的填充色

多边形的扫描转换算法的改进

  因为X-扫描线算法需要进行求交,而求交的计算量非常的大
扫描转换算法重要意义是提出来图形学里两个重要的思想:

扫描线:当处理图形图像时按一条条扫描线处理
增量的思想

从三个方面考虑加以改进:

在处理一条扫描线时,仅对与它相交的多边形的边(有效边)进行求交
考虑扫描线的连贯性(即当前扫描线与各边的交点顺序与下一条扫描线与各边的交点顺序很可能相同或非常相似)
最后考虑多边形的连贯性(即当某条边与当前扫描线相交时,它很可能也与下一条扫描线相交)

为避免求交运算,需要引进一套特殊的数据结构
数据结构:
活性边表(AET):把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中
      光栅图形学算法(一)_第15张图片
图中边P1、P4和P2、P3就是活性边
结点内容(一个结点在数据结构里可用结构来表示)
      光栅图形学算法(一)_第16张图片
  为了方便活性边表的建立与更新,需构造一个新边表(NET),用来存放多边形的边的信息,分为4个步骤:

首先构造一个纵向链表,链表的长度为多边形所占有的最大扫描线数,链表的每个结点称为一个吊桶,对应多边形覆盖的每一条扫描线
NET挂在与该边低端y值相同的扫描线桶中。也就是说,存放在该扫描线第一次出现的边。

每做一次新的扫描时,要对已有的边进行三个处理:

是否被去除掉
如果不被去除,第二就要对它的数据进行更新。
看有没有新的边进来,新的边在NET里,可以插入排序插进来。

多边形扫描转换算法小结

  扫描线法可以实现已知任意多边形域边界的填充。该填充算法是按扫描线的顺序,计算扫描线与待填充区域的相交区间,再用要求的颜色显示这些区间的像素,即完成填充工作。
为了提高算法效率:

增量的思想
连贯性思想
构建了一套特殊的数据结构

这里区间的端点通过计算扫描线与多边形边界的交点获得。所以填充区域的边界线必须事先知道,因此它的缺点是无法实现对未知边界的区域填充

边缘填充算法

  其基本思想是按任意顺序处理多边形的每条边。在处理每条边时,首先求出该边与扫描线的交点,然后将每一条扫描线上交点右方的所有像素取补。多边形的所有边处理完毕之后,填充即完成

栅栏填充法

  栅栏指的是一条过多边形顶点且与扫描线垂直的直线。它把多边形分为两半。在处理每条边与扫描线的交点时,讲交点与栅栏之间的像素取补

边界标志算法

  帧缓冲器中对多边形的每条边进行直线扫描转换,亦即对多边形边界所经过的象素打上标志
  然后再采用和扫描线算法类似的方法将为与多边形内的各个区段着上所需颜色
  由于边界标志算法不必建立维护边表以及对它进行排序,所以边界标志算是更适合硬件实现,这事它的执行速度比有序边算法快一至两个数量级。

区域填充

区域——指已经表示成点阵形式的填充图形,是象素的集合
区域填充是指将区域内的一点(常称种子店)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。
  区域可采用内点表示边界表示两种表示形式
光栅图形学算法(一)_第17张图片
内点表示:枚举出区域内部的所有像素,内部的所有像素着同一个颜色,边界像素着与内部像素不同的颜色
边界表示:枚举出边界上的所有像素,边界上的所有像素着同一个颜色,内部像素着与边界像素不同的颜色
  区域填充算法要求区域是连通的,因为只有在连通区域中,才可能将种子点的颜色扩展到区域内的其它点。
区域可分为4向连通区域和8向连通区域
光栅图形学算法(一)_第18张图片

  4向连通区域指的是从区域上一点出发,可通过四个方向,即上、下、左、右移动的组合,在不越出区域的前提下,到达区域内的任意像素
  8向连通区域指的是从区域内每一象素出发,可通过八个方向,即上、下、左、右、左上、右上、左下、右下这八个方向的移动的组合来到达

简单四连通种子填充算法(区域填充递归算法)

  种子填充算法的原理是:假设在多边形区域内部有一像素已知,由此出发找到区域内的所有像素,用一定的颜色或灰度来填充
  假设区域采用边界定义,即区域边界上所有像素均具有某个特定值,区域内部所有像素均不取这一特定值,而边界外的像素则可具有与边界相同的值

使用栈结构来实现简单的种子填充算法

算法原理如下:
种子像素入栈,当栈非空时重复执行如下三步操作:

栈顶像素出栈
将出栈像素置成要填充色
按左、上、右、下顺序检查与栈像素相邻的四个像素,若其中某个像素不在边界且未置成填充色,则把该像素入栈

种子填充算法的不足之处

有些像素会入栈多次,降低算法效率;栈结构占空间
递归执行,算法简单,但效率不高。区域内每一像素有引进一次递归,进/出栈,费时费内存
改进算法,减少递归次数,提高效率

多边形的扫描转换与区域填充算法小结

基本思想不同

  • 多边形扫描转换是指讲多边形的顶点表示转化为点阵表示
  • 区域填充只改变区域的填充颜色,不改变区域表示方法

基本条件不同

  • 在区域填充算法中,要求给定区域内一点作为种子点,然后从这一点根据连通性将新的颜色扩散到整个区域
  • 扫描转移多边形是从多边形的边界(顶点)信息出发,利用多种形式的连贯性进行填充的

  扫描转换区域填充的核心是知道多边形的边界,要得到多边形内部的像素集,有多种方法。其中扫描线算法是利用一套特殊的数据结构,避免求交,然后一条条扫描线确定
  区域填充条件更强一些,不但知道边界,而且还知道区域内的一点,可以利用四连通或八连通区域不断往外扩展

反走样

光栅图形学算法对直线、圆及椭圆这些最基本元素的生成速度和显示质量的改进,在图形处理系统中具有重要的应用价值
但它们生成的线条具有明显的“锯齿形”即会发生(Liasing)现象

走样

光栅图形学算法(一)_第19张图片
  如图,我们在画图的时候是用有限的象素去逼近无限的点,所以会产生走样。“锯齿”是“走样”的一种形式。而走样是光栅显示的一种固有性质。产生走样现象的原因是像素本质上的离散性。所以走样是数字化的必然产物

走样现象

光栅图形产生的阶梯形(锯齿形)
图形中包含相对微小的物体时,这些物体在静态图形中容易被丢弃或忽略
在动画序列中时隐时现,产生闪烁

简单地说,如果对一个快速变化的信号采样频率过低,所得样本表示的会是低频变化的信号:原始信号的频率看起来被较低的“走样”频率所代替
光栅图形学算法(一)_第20张图片
上面是一个矩形波,红色的采样点。下面是采样点形成的波形,可以看出波形产生了走样

反走样技术

用于减少或消除走样效果的技术,称为反走样(Antialiasing)技术
由于图形的走样现象对图形的质量有很大影响,几乎所有图形处理系统都要对基本图形进行反走样处理
采用分辨率更高的显示设备,对解决走样现象有所帮助,因为可以使锯齿相对物体会更小一些。该反走样方法是以4倍的存储器代价和扫描转换时间获得的,为了稳定屏幕上的图像,电子枪至少要1/24秒时间轰击屏幕上所有像素一次,如果像素提高一倍,电子枪就要快4倍。但是无论从存储器还是电子设备来看,所付出的代价太高,所以该方法不可取

反走样技术涉及到某种形式的“模糊”来产生更平滑的图像
对于在百色背景中的黑色矩形,通过在矩形的边界附近掺入一些灰色像素,可以柔化从黑到白的尖锐变化
从远处观察这幅图像时,人眼能够把这些缓和变化的暗影融合在一起,从而看到了更加平滑的边界。如下图
      光栅图形学算法(一)_第21张图片

两种反走样方法:

非加权区域采用方法
加权区域采样方法

非加权区域采样方法
根据物体的覆盖率(coverage)计算像素的颜色、覆盖率是指某个像素区域被物体覆盖的比例
缺点:

像素的亮度与相交区域的面积成正比,而与相交区域落在像素内的位置无关,这仍然会导致锯齿效应
直线条上沿理想直线方向的相邻两个象素有时会有较大的灰度差

每个像素的权值是一样的,这是它的主要缺点。所以也称非加权区域采样方法
加权区域采样方法
这种方法更符合人视觉系统对图像信息的处理方式,反走样效果更好
光栅图形学算法(一)_第22张图片
* 将直线段看作是具有一定宽度的狭长矩形;当直线段与像素有交时,根据相交区域与像素中心的距离来决定其对象素亮度的贡献。
* 直线段对一个象素亮度的贡献正比于相交区域与像素中心的距离
* 设置相交区域面积与像素中心距离的权函数(高斯函数)反映相交面积对整个像素亮度的贡献大小
* 利用权函数积分求相交区域面积,用它乘以像素可设置的最大亮度值,即可得到该像素实际显示的亮度值

该方法比较复杂,为了简化可采用离散计算方法
光栅图形学算法(一)_第23张图片
将一个像素划分为n=3x3个子象素,加权表可以取作:
光栅图形学算法(一)_第24张图片
加权方案:中心像素的加权是角子像素的4倍,是其他像素的2倍,对九个子像素的每个网格所计算出的亮度进行平均
然后求出所有中心落于直线段内的子像素
最后计算所有这些子象素对原象素亮度贡献之和

你可能感兴趣的:(计算机图形学)