大连理工大学选修课——图形学:第三四章 基本图形生成算法

第三四章 基本图形生成算法

图形生成

概念:如何在指定的输出设备上,根据坐标描述,构造基本二维几何图形

基本二维几何图形:点、直线、圆、多边形域、字符串及相关属性等。

图形生成的概念

是在指定的输出设备上,根据坐标描述构造二维几何图形。

图形的扫描转换:在光栅显示器等数字设备上,确定一个醉驾逼近于图形的像素集的过程。

光栅化

光栅就是德语中屏幕的意思,光栅化就是把图形画在屏幕上的过程,即将几何图形转化为像素化图像的过程。

基本过程:

  1. 确定最佳逼近图形的像素集合。
  2. 用图形的颜色或其它属性,按照扫描顺序,对像素进行某种写操作,完成图形在屏幕上的显示。

直线段和圆的光栅化

直线段和圆是最基本的图形元素,包括以下几种算法:

直线光栅化算法:DDA算法、Bresenham算法

圆光栅化算法:Bresenham画圆算法、中点算法、中点整数算法、中点整数优化算法。

直线的光栅化算法

要求:直、精确的起始点、亮度颜色均匀且沿直线不变,与直线长度、方向无关、快。

DDA算法

David F.Rogers的描述(适用于所有象限)

步骤如下:

  1. 如果已知第 i i i点的坐标,利用步长 S t e p X StepX StepX S t e p Y StepY StepY,得到第 i + 1 i+1 i+1点的坐标, i + 1 i+1 i+1点的坐标为:

x i + 1 = x i + S t e p X y i + 1 = y i + K ⋅ S t e p X x_{i+1}=x_i+StepX\quad y_{i+1}=y_i+K\cdot StepX xi+1=xi+StepXyi+1=yi+KStepX

  1. 如图所示, K < 1 , S t e p X = 1 , S t e p Y = k K<1,StepX=1,StepY=k K<1,StepX=1StepY=k,将直线上每个点的坐标四舍五入,得到光栅点的位置:

    在这里插入图片描述

James D.Foley的描述(只适用于第一象限,且K<1)

令:

k = y 2 − y 1 x 2 − x 1 k=\frac{y_2-y_1}{x_2-x_1} k=x2x1y2y1

有:

y i + 1 = y i + k ⋅ S t e p X y_{i+1}=y_i+k\cdot StepX yi+1=yi+kStepX

0 < k < 1 0<k<1 0<k<1,则 △ x > △ y \triangle x>\triangle y x>y

因为光栅单位为1,每次 x x x方向增加1,y方向增加k,得到下一个直线点。

现有算法描述分析

Rogers:

采用 x i + 1 = x i + S t e p X y i + 1 = y i + K ⋅ S t e p X x_{i+1}=x_i+StepX\quad y_{i+1}=y_i+K\cdot StepX xi+1=xi+StepXyi+1=yi+KStepX,逼近点并不是直线最好的逼近

D.Foley:可能引起累积误差

未分析直线端点不在像素点的情况,且只给出 0 ° 0\degree - 45 ° 45\degree 45°的第一卦限的情况。

每次步长为一个单位,减少累积误差。

本教程描述——任意方向插补算法

if (fabs(dy)<fabs(dx)) {     //X方向长 , 斜率 <=1Length=abs(Round(xe)-Round(xs));Flag=1; //最大的插补长度和方向标记ix= Round(xs); //初始 X点idx=isign(dx); //X方向单位增量y= ys+dy/dx*((float)(ix)-xs); //初始 Y点修正dy=dy/fabs(dx); //Y方向斜率增量
}else { // Y方向长 , 斜率 >1Length=abs(Round(ye)-Round(ys));Flag=0;iy= Round(ys); //初始 Y点idy=isign(dy); //Y方向单位增量x= xs+dx/dy*((float)(iy)-ys); //初始 X点修正dx=dx/fabs(dy); //X方向斜率增量
}

在这里插入图片描述

Bresenham算法

Bresenham算法:

从另一个角度看直线光栅化显示算法的原理:由直线的斜率确定选择在 x x x方向或 y y y方向上每次递增1个单位,另一变量递增量为0或1,取决于实际直线与网格点的距离,四舍五入。

  1. 基本原理

    假定直线斜率k在 0 0 0- 1 1 1之间,此时, x x x方向每次递增一个单位,决定 y y y方向每次递增0或1。

    (斜率大于1,y每次递增1,小于1,x每次递增1)

    假设:当前点为 ( x i , y ) (x_i,y) (xi,y),当前光栅点为 ( x i , y i ) (x_i,y_i) (xi,yi)

    则下一点为: ( x i + 1 , y + k ) , k ∈ { 0 , 1 } (x_i+1,y+k),k\in\{0,1\} (xi+1,y+k),k{0,1}

    在这里插入图片描述

    记直线与它垂直方向最近的下光栅点误差为 d d d

    d < 0.5 d<0.5 d<0.5:下一像素点为 ( x i + 1 , y i ) (x_i+1,y_i) (xi+1,yi)

    d > 0.5 d>0.5 d>0.5:下一像素点为 ( x i + 1 , y i + 1 ) (x_i+1,y_i+1) (xi+1,yi+1)

在这里插入图片描述

  1. 对bresenham的简化

    e = d − 0.5 e=d-0.5 e=d0.5,关于d的判别式和初值可简化成:

    e < 0 e<0 e<0:取 ( x i + 1 , y i ) (x_i+1,y_i) (xi+1,yi)

    e > 0 e>0 e>0:取 ( x i + 1 , y i + 1 ) (x_i+1,y_i+1) (xi+1,yi+1) e = e − 1 e=e-1 e=e1

  2. 整数Bresenham算法

    上述Bresenham算法在计算直线斜率和误差项时需要浮点运算和除法,采用整数算术运算和避免除法可以加快算法速度。

    只需作以下变换:

    初值:

    E r r o r = △ y / △ x − 0.5 Error=\triangle y/\triangle x-0.5 Error=y/△x0.5

    经过简单变换:

    N E r r o r = 2 ⋅ E r r o r ⋅ △ x = 2 △ y − △ x NError=2\cdot Error\cdot\triangle x=2\triangle y-\triangle x NError=2Errorx=2△yx

    便得到了整数算法。

  3. 一般Bresenham算法

    为了使第一卦限的Bresenham算法适用于一般直线,进行如下改造:

    1. 当直线斜率 ∣ k ∣ > 1 |k|>1 k>1时,改为y的增量总为1,判断 x x x是否需要增加1
    2. x x x y y y的增量可能是1或-1,视直线所在象限决定。

圆光栅化算法

简单方程方法

圆的极坐标方程为:

x = R cos ⁡ θ y = R sin ⁡ θ x=R\cos\theta\\ y=R\sin\theta x=Rcosθy=Rsinθ

每次给 θ \theta θ θ \theta θ θ i + 1 = θ i + △ θ \theta_{i+1}=\theta_i+\triangle\theta θi+1=θi+θ

那么:

x i + 1 = r o u n d ( R cos ⁡ θ i + 1 ) y i + 1 = r o u n d ( R sin ⁡ θ i + 1 ) x_{i+1}=round(R\cos\theta_{i+1})\\ y_{i+1}=round(R\sin\theta_{i+1}) xi+1=round(Rcosθi+1)yi+1=round(Rsinθi+1)

利用圆的八方对称画圆

Bresenham画圆算法

以圆心为坐标原点,建立局部坐标系

先考虑第一象限的八分之一圆弧:

P i − 1 ( x i − 1 , y i − 1 ) P_{i-1}(x_{i-1},y_{i-1}) Pi1(xi1,yi1)为已确定的逼近像素点

x i = x i − 1 + 1 x_i=x_{i-1}+1 xi=xi1+1时,要决定 y i y_i yi的取值

E ( R 2 , R 2 ) E(\frac{R}{\sqrt2},\frac{R}{\sqrt2}) E(2 R,2 R)

D ( S i ) = [ ( x i − 1 + 1 ) 2 + y i − 1 2 ] − R 2 D ( T i ) = [ ( x i − 1 + 1 ) 2 + ( y i − 1 − 1 ) 2 ] − R 2 D(S_i)=[(x_{i-1}+1)^2+y^2_{i-1}]-R^2\\ D(T_i)=[(x_{i-1}+1)^2+(y_{i-1}-1)^2]-R^2 D(Si)=[(xi1+1)2+yi12]R2D(Ti)=[(xi1+1)2+(yi11)2]R2

∣ D ( S i ) ∣ ≥ ∣ D ( T I ) ∣ |D(S_i)|\geq|D(T_I)| D(Si)D(TI),则 T i T_i Ti S i S_i Si更接近实际的圆弧, 应选 T i T_i Ti
反之,选择 S i S_i Si

d i = ∣ D ( S i ) ∣ − ∣ D ( T i ) ∣ d_i=|D(S_i)|-|D(T_i)| di=D(Si)D(Ti)

于是, d i ≥ 0 d_i\geq0 di0时,选 T i T_i Ti,反之,选择 S i S_i Si

在这里插入图片描述

分析情况ABCDE,可以将 d i d_i di改写为:

d i = D ( S i ) + D ( T i ) = [ ( x i − 1 + 1 ) 2 + y i − 1 2 ] − R 2 + [ ( x i − 1 + 1 ) 2 + ( y i − 1 − 1 ) 2 ] − R 2 \begin{align} d_i=&D(S_i)+D(T_i)\\ =&[(x_{i-1}+1)^2+y^2_{i-1}]-R^2+[(x_{i-1}+1)^2+(y_{i-1}-1)^2]-R^2\\ \end{align} di==D(Si)+D(Ti)[(xi1+1)2+yi12]R2+[(xi1+1)2+(yi11)2]R2

i + 1 i+1 i+1代替上式中的 i i i,得:

d i + 1 = [ ( x i + 1 ) 2 + y i 2 ] − R 2 + [ ( x i + 1 ) 2 + ( y i − 1 ) 2 ] − R 2 \begin{align} d_{i+1}=&[(x_{i}+1)^2+y^2_{i}]-R^2+[(x_{i}+1)^2+(y_{i}-1)^2]-R^2\\ \end{align} di+1=[(xi+1)2+yi2]R2+[(xi+1)2+(yi1)2]R2

d i + 1 − d i d_{i+1}-d_i di+1di,得:

d i + 1 − d i = 2 [ ( x i + 1 ) 2 − ( x i − 1 + 1 ) 2 ] + ( y i 2 − y i − 1 2 ) + ( y i − 1 ) 2 − ( y i − 1 − 1 ) 2 d_{i+1}-d_i=2[(x_i+1)^2-(x_{i-1}+1)^2]+(y_i^2-y_{i-1}^2)+(y_i-1)^2-(y_{i-1}-1)^2 di+1di=2[(xi+1)2(xi1+1)2]+(yi2yi12)+(yi1)2(yi11)2

改进:

d i ≥ 0 , d_i\ge0, di0, T i T_i Ti,此时:

x i = x i − 1 + 1 y i = y i − 1 − 1 d i + 1 = d i + 4 ( x i − 1 − y i − 1 ) + 10 x_i=x_{i-1}+1\\ y_i=y_{i-1}-1\\ d_{i+1}=d_i+4(x_{i-1}-y_{i-1})+10 xi=xi1+1yi=yi11di+1=di+4(xi1yi1)+10

反之,选 S i S_i Si,此时

x i = x i − 1 + 1 y i = y i − 1 d i + 1 = d i + 4 x i − 1 + 6 x_i=x_{i-1}+1\\ y_i=y_{i-1}\\ d_{i+1}=d_i+4x_{i-1}+6 xi=xi1+1yi=yi1di+1=di+4xi1+6

d i d_i di的初值 d 1 d_1 d1可以由 ( 1 ) (1) (1)求出,将 i = 1 , x 0 = 0 , y 0 = R i=1,x_0=0,y_0=R i=1,x0=0,y0=R带入,得:

d 1 = 3 − 2 R d_1=3-2R d1=32R

显然,改进方法的计算量更小,效率高。

中点圆算法

d d d为点 p ( x , y ) p(x,y) p(x,y)到圆心的距离,有:

d = F ( x , y ) = x 2 + y 2 − R 2 d=F(x,y)=x^2+y^2-R^2 d=F(x,y)=x2+y2R2

以圆的下 2个可选像素 中点的函数值 d的符号 决定选择 2个可选像素 T和 B中哪一个更接近圆而作为圆的显示点 :

在这里插入图片描述

d M = F ( x M , y M ) = F ( x p + 1 , y p − 0.5 ) = ( x p + 1 ) 2 + ( y p − 0.5 ) 2 − R 2 d_M=F(x_M,y_M)=F(x_p+1,y_p-0.5)=(x_p+1)^2+(y_p-0.5)^2-R^2 dM=F(xM,yM)=F(xp+1,yp0.5)=(xp+1)2+(yp0.5)2R2

如果 d M ≤ 0 d_M\le0 dM0,表示下一个中点M在圆内,用T逼近,得:

d M T = F ( x M T , y M T ) = F ( x p + 2 , y p − 0.5 ) = ( x p + 2 ) 2 + ( y p − 0.5 ) 2 − R 2 △ d M T = d M T − d M = 2 x p + 3 d_{MT}=F(x_{MT},y_{MT})=F(x_p+2,y_p-0.5)=(x_p+2)^2+(y_p-0.5)^2-R^2\\ \triangle d_{MT}=d_{MT}-d_{M}=2x_p+3 dMT=F(xMT,yMT)=F(xp+2,yp0.5)=(xp+2)2+(yp0.5)2R2dMT=dMTdM=2xp+3

反之,表示下一中点M在园外,用B逼近,得:

d M B = F ( x M B , y M B ) = F ( x p + 2 , y p − 1.5 ) △ d M B = d M B − d M = 2 x p − 2 y p + 5 d_{MB}=F(x_{MB},y_{MB})=F(x_p+2,y_p-1.5)\\ \triangle d_{MB}=d_{MB}-d_{M}=2x_p-2y_p+5 dMB=F(xMB,yMB)=F(xp+2,yp1.5)dMB=dMBdM=2xp2yp+5

综上,中点圆算法为:

根据中点d的值,决定显示的光栅点,更新 △ d \triangle d d ( △ d M T 或 △ M B ) (\triangle d_{MT}或\triangle_{MB}) (dMTMB),更新d。

初值

x 0 = 0 , y 0 = R x_0=0,y_0=R x0=0,y0=R
x M 0 = 0 + 1 = 1 , y M 0 = R − 0.5 x_{M0}=0+1=1,y_{M0}=R-0.5 xM0=0+1=1,yM0=R0.5
d M 0 = F ( x M 0 , y M 0 ) = 1.25 − R d_{M0}=F(x_{M0},y_{M0})=1.25-R dM0=F(xM0,yM0)=1.25R

中点圆整数算法

为了将其改造为整数计算,定义新变量: D = d − 0.25 D=d-0.25 D=d0.25
判别式 d < 0 d<0 d<0等价于 D < − 0.25 D<-0.25 D<0.25
在D为整数的情况下, D < − 0.25 D<-0.25 D<0.25等价于 D < 0 D<0 D<0
仍将D写为d(新的初值 d = 1 − r a d i u s d=1-radius d=1radius),可得到中点圆整数算法

椭圆光栅化算法

设椭圆方程为:

F ( x , y ) = b 2 x 2 + a 2 y 2 − a 2 b 2 = 0 F(x,y)=b^2x^2+a^2y^2-a^2b^2=0 F(x,y)=b2x2+a2y2a2b2=0

该椭圆上一点 ( x , y ) (x,y) (x,y)处的法向量为:

N ( x , y ) = ∂ F ∂ x i + ∂ F ∂ y j = 2 b 2 x i + 2 a 2 y j N(x,y)=\frac{\partial F}{\partial x}i+\frac{\partial F}{\partial y}j=2b^2xi+2a^2yj N(x,y)=xFi+yFj=2b2xi+2a2yj

在这里插入图片描述

在上半部分,法向量y的分量更大而在下部分, 法向量的x分量更大, 因而, 在上部分若当前最佳逼近理想椭圆弧的像素(xP,yP)满足下列不等式:

b 2 ( x p + 1 ) < a 2 ( y p − 0.5 ) b^2(x_p+1)<a^2(y_p-0.5) b2(xp+1)<a2(yp0.5)

在上半部分,假设横坐标为 x p x_p xp的像素中,与椭圆弧更接近的点是 ( x p , y p ) (x_p,y_p) (xp,yp),那么下一对候选像素的中点为 ( x p + 1 , y p − 0.5 ) (x_p+1,y_p-0.5) (xp+1,yp0.5),判别式为:

d 1 = F ( x p + 1 , y p − 0.5 ) = b 2 ( x p + 1 ) 2 + a 2 ( y p − 0.5 ) 2 − a 2 b 2 d_1=F(x_p+1,y_p-0.5)=b^2(x_p+1)^2+a^2(y_p-0.5)^2-a^2b^2 d1=F(xp+1,yp0.5)=b2(xp+1)2+a2(yp0.5)2a2b2

d 1 < 0 d_1<0 d1<0,中点在椭圆内,则取正右方像素,判别式更新:

d 1 , = F ( x p + 2 , y p − 0.5 ) d_1^,=F(x_p+2,y_p-0.5) d1,=F(xp+2,yp0.5)

d 1 ≥ 0 d_1\ge0 d10,中点在椭圆外,此时取右下方像素,更新判别式:

d 1 ′ = F ( x p + 2 , y p − 1.5 ) d_1'=F(x_p+2,y_p-1.5) d1=F(xp+2,yp1.5)

由于弧的起点为 ( 0 , b ) (0,b) (0,b),第一中点为 ( 1 , b − 0.5 ) (1,b-0.5) (1,b0.5),对应判别式为:

d 10 = F ( 1 , b − 0.5 ) d_{10}=F(1,b-0.5) d10=F(1,b0.5)

**在下部分,**改为从正下方和右下方两个像素选择下一像素,计算与上半部分类似。

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

多边形的扫描转换,主要通过确定穿越区域的扫描线覆盖区间来填充。

区域填充是从给定的位置开始涂描,直到指定的边界条件为止。

多边形的扫描转换

顶点表示:用多边形的顶点序列刻画多边形。

点阵表示:用位于多边形内的像素集合来刻画多边形。

扫描转换多边形:从多边形的顶点信息出发,求出位于其内部的各个像素,并将颜色值写入帧缓存中相应单元的过程。

基本问题有:

  1. 如何判断一个点是否位于多边形区域内?

    点在多边形内的包含性检验方法:检验夹角之和、射线法检验交点数。

转角法:若夹角和为0,则点 p p p在多边形外;若夹角和为360,则点 p p p在多边形内。

在这里插入图片描述

射线法:交点数为偶数,点在多边形外;交点数为奇数,点在多边形之内。

在这里插入图片描述

  1. 逐点测试效率太低

采用包围盒法:对凸多边形效果好,但凹多边形效率仍然低下。

在这里插入图片描述

扫描线填充算法:

扫描线填充算法:按扫描线顺序,测试点的连贯性。

种子填充算法:从内部一个种子点出发,测试点的连贯性。

X-扫描线算法

基本思想:

按扫描线顺序,计算扫描线与多边形的相交区间;再用要求的颜色显示区间的所有像素。

在这里插入图片描述

算法步骤:

  1. 确定多边形所占有的最大扫描线数,得到多边形顶点的最小、最大 y y y ( y m i n 和 y m a x ) (y_{min}和y_{max}) (yminymax)
  2. y = y m i n y=y_{min} y=ymin y = y m a x y=y_{max} y=ymax,每次用一条扫描线进行填充。
  3. 对一条扫描线填充的过程分为四个步骤:求交、排序、交点配对、区间填色。

取整规则

交点的取整规则:使生成的像素全部位于多边形之内。

为什么不采用四舍五入的规则?四舍五入可能导致部分像素位于多边形之外,从而不可用。

假定非水平边和扫描线y=e相交,交点横坐标为 x x x,规则如下:

  1. x x x为小数,即交点落在扫描线上两个相邻像素间时:

    1. 交点位于左边界上,向右取整。

    2. 交点位于右边界上,向左取整。

      在这里插入图片描述

  2. 边界上像素的取舍:为了避免填充扩大化,规定落在右边边界上的像素不予填充。

    • 具体实现时,对扫描线与多边形相交区间左闭右开。

      在这里插入图片描述

  3. 当扫描线与多边形顶点相交时:交点的取舍,保证交点正确配对。

    • 交点配对:当扫描线与多边形的顶点相交时:

      • 若共享顶点的两条边落在扫描线两边,交点只算一个。
      • 若共享顶点的两条边落在扫描线同一边,交点作为零或两个。
    • 实际处理中,只要检查顶点的两条边的另外两个端点的Y值,两个Y值中,大于交点Y值的个数为0\1\2,来决定取0\1\2个交点。

      在这里插入图片描述

改进的有效边表算法(Y连贯性算法)

改进原理:

  • 处理一条扫描线时,仅对有效边求交。
  • 利用扫描线的连贯性。
  • 利用多边形边的连贯性。

有效边:与当前扫描线相交的多边形的边,也称为活性边。
有效边表:把有效边按与扫描线交点x坐标递增的顺序存放在一个链表中,此链表称为有效边表。

有效边表中,每个结点的存储方式:

x ∣ y m i n y m a x 1 k n e x t x|_{y_{min}}\quad y_{max}\quad \frac{1}{k}\quad next xyminymaxk1next

构造边表:

  1. 首先构造一个纵向链表,链表的长度为多边形所占有的最大扫描线数,链表的每个结点,称为一个桶,对应多边形覆盖的每一条扫描线。

  2. 将每条边的信息链入与该边最小y坐标( y m i n y_{min} ymin )相对应的桶处。
    (也就是说,若某边的较低端点为 y m i n y_{min} ymin,则该边放在相应的扫描线桶中。)

  3. 每条数据边形成一个结点,内容包括:

    1. 扫描线与该边的初始交点x(较低端点的x值)
    2. 1 k \frac{1}{k} k1
    3. 该边的最大 y y y y m a x y_{max} ymax
  4. 同一桶中,若干条边按 x x x由小到大排序,若相等,按照 1 k \frac{1}{k} k1由小到大排序。

    在这里插入图片描述

在这里插入图片描述

算法步骤:

  1. 初始化:构造边表,AET表置空。
  2. 将第一个不空的ET表中的边与AET表合并。
  3. 由AET表中取出交点对进行填充。填充之后删除 y = y m a x y=y_{max} y=ymax的边。
  4. y i + 1 = y i + 1 y_{i+1}=y_i+1 yi+1=yi+1,根据 x i + 1 = x i + 1 / k x_{i+1}=x_i+1/k xi+1=xi+1/k计算并修改AET表,同时合并ET表中 y = y i + 1 y=y_i+1 y=yi+1桶中的边,按次序插入到AET表中,形成新的AET表。
  5. AET表不为空则转到3,否则end。

边缘填充算法

基本思想:按任意顺序,处理多边形的每条边。

处理时,先求出该边与扫描线的交点,再对扫描线上交点右方的所有像素取反。

算法简单,但对于复杂图形,每一个像素可能被访问多次。

在这里插入图片描述

栅栏填充算法

栅栏指的是一条过多边形顶点且与扫描线垂直的直线。它把多边形分为两半。

基本思想:按任意顺序处理多边形的每一条边,但处理每条边与扫描线的交点时,将交点与栅栏之间的像素取反。
这种算法尽管减少了被重复访问像素的数目,但仍有一些像素被重复访问。

在这里插入图片描述

边界标志算法

基本思想:先用特殊的颜色在帧缓存中将多边形的边界勾画出来,然后将着色的像素点依 x 坐标递增的顺序配对,再把每一对像素构成的区间置为填充色。
分为两个步骤:打标记-多边形扫描转化(利用直线的扫描转换实现),填充。

当用软件实现本算法时,速度与改进的有效边表算法相当,但本算法用硬件实现后速度会有很大提高

区域填充

基本概念:从区域内的某一个像素点(种子点)开始,由内向外将填充色扩展到整个区域内的过程
区域:已经表示成点阵形式的填充图形,它是相互连通的一组像素的集合。

在这里插入图片描述

边界表示法:把位于给定区域的边界上的像素一一列举出来的方法。
边界表示法中,由于边界由特殊颜色指定,填充算法可以逐个像素地向外处理,直到遇到边界颜色为止,这种方法称为边界填充算法。

内点表示法:枚举出给定区域内所有像素的表示方法。

以内点表示法为基础的区域填充算法称为泛填充算法。

4连通区域、8连通区域:

在这里插入图片描述

连通性:4连通可看作8连通区域,但对边界有要求。

在这里插入图片描述

边界填充算法

算法的输入:种子点坐标(x,y),填充色以及边界颜色。

利用堆栈实现简单的种子填充算法。

  • 算法从种子点开始检测相邻位置是否是边界颜色。
  • 若不是就用填充色着色。
  • 检测该像素点的相邻位置。
  • 直到检测完区域边界颜色范围内的所有像素为止。

特点:

  • 可以用于填充带有内孔的平面区域。
  • 把太多的像素压入堆栈,降低了效率,同时需要较大的存储空间。
  • 递归执行,算法简单,但效率不高,区域内每一像素都引起一次递归,进/出栈费时费内存。
  • 通过沿扫描线填充水平像素段,来代替处理4-邻接点和8-邻接点。

扫描线种子算法

扫描线通过在任意不间断扫描线区间中只取一个种子像素的方法使堆栈的尺寸极小化。
不间断区间是指在一条扫描线上的一组相邻像素。

在这里插入图片描述

基本过程:当给定种子点时,首先填充种子点所在的扫描线上的位于给定区域的一个区段,然后确定与这一区段相通的上下两条扫描线上位于给定区域内的区段,并依次保存下来,重复以上过程。

算法步骤:在任意一个扫描线与多边形的相交区间中, 只取一个种子像素, 并将种子像素入栈, 当栈非空时作如下四步操作:

  1. 栈顶像素出栈
  2. 沿扫描线对出栈像素的左右像素进行填充, 直至遇到边界像素为止, 也就是对包含出栈像素的整个区间进行填充
  3. 上述区间内最左最右的像素分别记为xl和xr
  4. 在区间[xl, xr]中检查与当前扫描线相邻的上下两条扫描线的有关像素是否全为边界像素或已填充的像素, 若存在非边界、 非填充的像素, 则把每一区间的最右像素入栈。

字符处理

ASCII码:“美国信息交换用标准代码集”(American Standard Code for Information Interchange)

国际码:“中华人民共和国国家标准信息交换编码,简称为国际码,代号GB2312-80

字库:字库中储存了每个字符的图形信息

点阵字符

在点阵表示中,每个字符由一个点阵位图来表示,显示时,形成字符的像素图案。

在这里插入图片描述

特点: 定义和显示直接、简单、存储需要耗费大量空间。

改进:从一组点阵字符生成不同尺寸和不同字体的其他字符、采用压缩技术。

矢量字符

矢量字符采用直线和曲线段来描述字符形状,矢量字符库中记录的是笔划信息;显示时:解释字符的每个笔划信息。

在这里插入图片描述

轮廓字型法采用直线或二、三次曲线的集合来描述一个字符的轮廓线,轮廓线构成了一个或若干个封闭区域,显示时只要填充这些区域就可产生相应的字符

  • 显示时可以“无极放缩”
  • 占用空间少,美观,变换方便

属性处理

图素或图段的外观由其属性决定。

图形软件中实现属性选择的方法是提供一张系统当前属性值表,通过调用标准函数提供属性值表的设置和修改。进行扫描转换时,系统使用属性值表中的当前属性值进行显示和输出。

线宽

线刷子:垂直刷子、水平刷子

在这里插入图片描述

线刷子特点:

  • 实现简单、效率高
  • 斜线与水平(或垂直)线不一样粗
  • 当线宽为偶数个像素时,线的中心将偏移半个像素
  • 利用线刷子生成线的始末端总是水平或垂直的,看起来不太自然

解决方法:添加线帽

方帽:调整端点位置,使粗线的显示具有垂直于线段路径的正方形端点。

凸方帽:简单将线向两头延伸一半线宽并添加方帽。

圆帽:通过对每个方帽添加一个填充的半圆得到。

在这里插入图片描述

当比较接近水平的线与比较接近垂直的线汇合时,汇合处外角将有缺口。

在这里插入图片描述

解决方法:斜角连接、圆角连接、斜切连接。

在这里插入图片描述

方刷子:

方刷子绘制的线条(斜线)比用线刷子所绘制的线条要粗一些,斜线与水平(或垂直)线不一样粗。线条自然地带有一个“方线帽”。

利用像素模板进行线宽处理:

在这里插入图片描述

用等距线方法:
线宽均匀、端口处与边垂直、生成的图形质量高。

在这里插入图片描述

线型

用位屏蔽器实现

位屏蔽器中每一位对应的是一个像素,而不是单位长度,不能满足要求
线型中的笔划长度与直线长度有关
斜线笔划长度比水平或垂直线笔划长
对工程图,这种变化是不允许的,不符合国标规定

用像素段方法实现:针对不同的线型,画线程序沿路径输出一些连续像素段,在每两个实心段之间有一段中间空白段,他们的长度(像素数目)可用像素模板(pixel mask)指定
如何保证任何方向的划线长度近似相等呢?

  • 可根据线的斜率来调整实心段和中间空白段的像素数目。

在这里插入图片描述

曲线的线性和线宽

采用像素模板的方法对圆的线型处理:

在这里插入图片描述

  • 从一个八分象限转入下一个八分象限时要交换像素的位置,以保持划线长度近似相等。
  • 在沿圆周移动时调整画每根划线的像素数目以保证划线长度近似相等。
  • 改进:采用沿等角弧画像素代替用等长区间的像素模板来生成等长划线。

曲线的线宽

线刷子:经过曲线斜率为1和-1处,必须切换刷子
(曲线接近水平与垂直的地方,线条更粗)

方刷子:接近水平垂直的地方,线条更细
(要显示一致的曲线宽度可通过旋转刷子方向以使其在沿曲线移动时与斜率方向一致)

圆弧刷子:采用填充方法

区域填充属性

区域填充属性选择包括颜色、图案和透明度。

确定区域与模板之间的位置关系(对齐方式)

在这里插入图片描述

反走样

用离散量表示连续量引起的失真,就叫做走样。

产生原因:数学意义上的图形是由无限多个连续的、面积为零的点构成;
光栅显示器上,用有限多个离散的,具有一定面积的像素来近似地表示他们

走样现象:

  1. 光栅图形产生的阶梯形
  2. 图形中包含相对微小的物体时

在这里插入图片描述

用于减少或消除这种效果的技术,称为反走样

简单的方法:过取样(后滤波)、区域取样(前滤波)

分辨率提高一倍,阶梯程度减小一倍

在这里插入图片描述

过取样

在高于显示分辨率的较高分辨率下用点取样方法计算,然后对几个像素的属性进行平均得到较低分辨率下的像素属性。

简单过取样:在x,y方向把分辨率都提高一倍,使每个像素对应4个子像素,然后扫描转换求得各子像素的颜色亮度,再对4个像素的颜色亮度进行平均,得到较低分辨率下的像素颜色亮度。。

在这里插入图片描述

在这里插入图片描述

重叠过取样

为了得到更好的效果,在对一个像素点进行着色处理时,不仅仅只对其本身的子像素进行采样,同时对其周围的多个像素的子像素进行采样,来计算该点的颜色属性

在这里插入图片描述

基于加权模板的过取样

前面在确定像素的亮度时,仅仅是对所有子像素的亮度进行简单的平均。更常见的做法是给接近像素中心的子像素赋予较大的权值,即对所有子像素的亮度进行加权平均。

在这里插入图片描述

简单的区域取样

在整个像素区域内进行采样,这种技术称为区域取样。

由于像素的亮度是作为一个整体被确定的,不需要划分子像素,故也被称为前置滤波。

如何计算直线段与像素相交区域的面积?

在这里插入图片描述

  1. 将屏幕像素分割成n个更小的子像素
  2. 计算中心落在直线段内的子像素的个数m
  3. m/n为线段与像素相交区域面积的近似值。

在过取样中,我们对所有子像素的亮度进行简单平均或加权平均来确定像素的亮度。

在区域取样中,我们使用覆盖像素的连续的加权函数(Weighting Function)或滤波函数(Filtering Function)来确定像素的亮度。

将加权函数在整个二维显示图形上积分,得到具有一定体积的滤波器(Filter),该滤波器的体积为1
将加权函数在显示图形上进行积分,得到滤波器的一个子体,该子体的体积介于0到1之间,用它来表示像素的亮度。

特点:

接近理想直线的像素将被分配更多的灰度值。
相邻两个像素的滤波器相交,有利于缩小直线条上相邻像素的灰度差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/82108.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/82108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样避免住宅IP被平台识别

要有效避免住宅IP被平台识别&#xff0c;需从IP质量选择、环境参数伪装、行为模式模拟、技术细节处理等多维度构建防御体系。以下是基于行业实践的综合性解决方案&#xff1a; 一、确保住宅IP的高纯净度 选择真实家庭网络IP 验证IP是否归属真实家庭宽带&#xff08;非机房IP伪装…

WPF 触发器 Trigger

触发器 Trigger 触发器&#xff08;Trigger&#xff09;是 WPF 中的一种机制&#xff1a; 当某个条件满足时&#xff0c;自动改变控件的某些属性&#xff0c;比如颜色、大小、透明度等。 换句话说&#xff0c;就是"如果……那么就……" 的一种规则。 常见触发器类…

NLP核心技术解析:大模型与分词工具的协同工作原理

文章目录 一、核心关系概述二、分词工具的核心作用三、未登录词&#xff08;OOV&#xff09;问题3.1 问题本质分析3.2 解决方案3.2.1 预对齐词汇表&#xff08;最优解&#xff09;3.2.2 子词回退策略3.2.3 词汇表扩展&#xff08;适合专业领域&#xff09; 3.3 技术选型建议3.4…

vscode预览模式(点击文件时默认覆盖当前标签,标签名称显示为斜体,可通过双击该标签取消)覆盖标签、新窗打开

文章目录 VS Code 预览模式如何取消预览模式&#xff08;即“固定”标签页&#xff09;&#xff1f;预览模式有什么用&#xff1f; VS Code 预览模式 在 VS Code 中&#xff0c;当你单击文件浏览器&#xff08;例如&#xff0c;资源管理器侧边栏&#xff09;中的某个文件时&am…

MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - user/_sleep 是什么?做什么?

接上文 MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - sleep 是怎样练成的&#xff1f; user/_sleep 是什么&#xff1f; book-riscv-rev3.pdf 3.8节有对Xv6 binary文件的格式描述 Xv6 binaries are formatted in the widely-used ELF format, defined in (kernel/elf.h). An …

【AI科技】AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI

AMD ROCm 6.4 新功能&#xff1a;突破性推理、即插即用容器和模块化部署&#xff0c;可在 AMD Instinct GPU 上实现可扩展 AI 现代 AI 工作负载的规模和复杂性不断增长&#xff0c;而人们对性能和部署便捷性的期望也日益提升。对于在 AMD Instinct™ GPU 上构建 AI 和 HPC 未来…

【含文档+PPT+源码】基于微信小程序连锁药店商城

项目介绍 本课程演示的是一款基于微信小程序连锁药店商城&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附带的…

node.js模块化步骤(各标准区别)CommonJS规范、AMD规范、UMD规范、ES Modules (ESM)

前后端建议统一使用ESM 文章目录 Node.js模块化发展历程与标准对比一、模块化的意义1.1 解决的核心问题1.2 没有模块化的问题 二、CommonJS规范2.1 核心特征2.2 实现示例 三、AMD (Asynchronous Module Definition)3.1 特点3.2 代码示例 四、UMD (Universal Module Definition)…

人工智能与智能合约:如何用AI优化区块链技术中的合约执行?

引言&#xff1a;科技融合的新风口 区块链和人工智能&#xff0c;是当前最受瞩目的两大前沿技术。一个以去中心化、可溯源的机制重构信任体系&#xff0c;另一个以智能学习与决策能力重塑数据的价值。当这两项技术相遇&#xff0c;会碰撞出什么样的火花&#xff1f; 智能合约作…

RabbitMQ-api开发

前言 MQ就是接收并转发消息 核心概念 admin是用户 每个虚拟机上都有多个交换机 快速入门 引入依赖 <dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.22.0</version></dependen…

PostgreSQL Patroni集群组件作用介绍:Patroni、etcd、HAProxy、Keepalived、Watchdog

1. Watchdog 简介 1.1 核心作用 • 主节点故障检测 Watchdog 会定时检测数据库主节点&#xff08;或 Pgpool 主节点&#xff09;的运行状态。 一旦主节点宕机&#xff0c;它会发起故障切换请求。 • 协调主备切换 多个 Pgpool 节点时&#xff0c;Watchdog 保证只有一个 Pg…

【多种不同提交方式】通过springboot实现与前端网页数据交互(非常简洁快速)

【多种不同提交方式】通过springboot实现与前端网页数据交互 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系列文章】&am…

使用 AI 如何高效解析视频内容?生成思维导图或分时段概括总结

一、前言 AI 发展的如此迅速&#xff0c;有人想通过 AI 提效对视频的解析&#xff0c;怎么做呢&#xff1f; 豆包里面有 AI 视频总结的功能&#xff0c;可以解析bilibili网站上部分视频&#xff0c;如下图所示&#xff1a; 但有的视频解析时提示&#xff1a; 所以呢&#x…

鞅与停时 - 一种特别的概率论问题

讨论一个有趣的概率问题&#xff1a; [P3334 ZJOI2013] 抛硬币 - 洛谷 实际上是一个猴子打字问题&#xff0c;考虑一直无规律随即打字的猴子&#xff0c;键盘上只有A-Z一共26个字母&#xff0c;对于一个特定的字符串 S S S &#xff1a; ABCABCAB &#xff0c;能否在有限的打…

arcgis和ENVI中如何将数据输出为tif

一、arcgis中转换为tif 右键图层&#xff1a; Data -> Export Data, 按照图示进行选择&#xff0c;选择tiff格式导出即可&#xff0c;还可以选择其他类型的格式&#xff0c;比如envi。 二、 ENVI中转换为tif File -> Save As -> Save As (ENVI, NITF, TIFF, DTED) …

如何用命令行判断一个exe是不是c#wpf开发的

在powershell下执行 $assembly [Reflection.Assembly]::ReflectionOnlyLoadFrom("你的exe全路径") $references $assembly.GetReferencedAssemblies() echo $assembly $references | Where-Object { $_.Name -match "PresentationFramework|PresentationCore…

2025.05.07-华为机考第三题300分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 城市紧急救援队伍协同规划 问题描述 智慧城市建设中,卢小姐负责设计一套紧急救援队伍协同系统。城市被规划为一个 n n n \times n

深入理解Redis SDS:高性能字符串的终极设计指南

&#x1f4cd; 文章提示 10分钟掌握Redis核心字符串设计 | 从底层结构到源码实现&#xff0c;揭秘SDS如何解决C字符串七大缺陷&#xff0c;通过20手绘图示与可运行的C代码案例&#xff0c;助你彻底理解二进制安全、自动扩容等核心机制&#xff0c;文末附实战优化技巧&#xff…

jupyter notebook汉化教程

本章教程记录&#xff0c;jupyter notebook汉化步骤&#xff0c;如果对汉化有需求的小伙伴可以看看。 一、安装jupyter 如果你是安装的anaconda的那么默认是包含了Jupyter notebook的&#xff0c;如果是miniconda或者基础python&#xff0c;默认是不包含的jupyter组件的&#x…

模拟设计中如何减小失配

Xx 芯片测试结果显示&#xff0c;offset 指标偏高&#xff0c;不符合指标要求。所以查看了资料&#xff0c;温习了减小的失配的方法。 注意点一&#xff1a; 将所有offet折算到输入端&#xff0c;得到以下公式&#xff1a; 可以看到a&#xff09;阈值电压失配直接折算成输…