精华内容
下载资源
问答
  • 二维表中垂直方向的列
    2021-02-25 18:53:03

    前面介绍的数组容纳的是一串数字,仿佛一根线把这组数字串了起来,故而它只是一维数组。一维数组用来表示简单的数列尚可,要是表达复杂的平面坐标系,那就力不从心了。由于平面坐标系存在水平和垂直两个方向,因此可用二维数组来保存平面坐标系上的一组坐标顶点,其中第一维是顶点队列,第二维是顶点的横纵坐标。许多个平面组合起来变成一幅动画,每个平面都构成动画的一个帧,这样就形成了三维数组。二维数组、三维数组,乃至更多维度的数组,统称为多维数组。多维数组全由一维数组扩展而来,它们的用法大同小异,因而只要学会如何使用二维数组,即可举一反三运用其他多维数组。下面就以二维数组为例,统一介绍多维数组的常见用法。

    如同一维数组那样,二维数组也有两种声明形式,一种是在变量名称后面添加两对方括号,例如“double triangle[][]”;另一种是在类型后面添加两对方括号,例如“int[][] triangle”。前述的二维数组triangle表示平面坐标系上的三角形,其中第一对方括号表示这个三角形有几个顶点,第二对方括号表示每个顶点由几个坐标方向构成。

    给二维数组分配存储空间也有三种方式,分别说明如下:

    1、利用语句“new 变量类型[顶点数量][方向数量]”分配空间,比如三角形triangle有三个顶点,每个顶点由横纵两个坐标方向组成,则可通过下面这行语句实现:

    // 在两对方括号内分别填入数字,表示数组有多少行多少列

    triangle = new double[3][2];

    2、在分配存储空间的时候立即对数组进行初始化赋值,此时方括号中间不填数字,而在方括号后面添加花括号,并且花括号内部是以逗号分隔的几个一维数组。此时初始化赋值的代码如下所示:

    // 方括号内留空,然后紧跟花括号,花括号内部是以逗号分隔的几个一维数组

    double[][] triangle = new double[][]{

    new double[]{-2.0, 0.0},

    new double[]{0.0, -1.0},

    new double[]{2.0, 1.0}

    };

    3、可见上面的第二种写法实在啰嗦,完全可以参照一维数组的简化写法,把多余的“new double***”统统去掉,于是整个初始化代码精简如下:

    // 赋值等号右边直接跟着花括号,花括号又内嵌好几个花括号分别表示对应的一维数组

    double[][] triangle = { {-2.0, 0.0}, {0.0, -1.0}, {2.0, 1.0} };

    以上的赋值等号右边直接跟着花括号,花括号里面又有三组花括号,每组花括号分别容纳两个数字。这便告诉编译器:该二维数组需要分配三个顶点,并且每个顶点都有两个坐标方向。

    若要获取二维数组里面的某个元素,可采取“数组名称[元素行号][元素列号]”的形式,表示当前操作的是第几行第几列的数组元素。与一维数组不同的是,对于二维数组来说,“数组名称.length”不能获得所有元素的数量,而是获得该数组的行数;要想获取某行的列数,则需通过“triangle[行号].length”来得到,把所有行的列数累加起来,才能求得该二维数组的元素个数。下面是声明一个浮点型的二维数组,并对每个数组元素赋值,最后遍历打印各元素的完整代码例子:

    // 以下是声明二维数组的第一种形式:“变量类型 数组名称[][]”

    double triangle[][];

    // 以下是分配二维数组空间的第一种形式

    // 在两对方括号内分别填入数字,表示数组有多少行多少列

    triangle = new double[3][2];

    // 数组名称后面的“[数字1][数字2]”,就是数组元素的行列下标,表示当前操作的是第几行第几列的数组元素

    triangle[0][0] = -2.0;

    triangle[0][1] = 0.0;

    triangle[1][0] = 0.0;

    triangle[1][1] = -1.0;

    triangle[2][0] = 2.0;

    triangle[2][1] = 1.0;

    // 下面通过循环语句依次读出数组中的所有元素。

    // “二维数组名称.length”表示获取该数组的行数

    for (int i=0; i

    // “triangle[i].length”表示获取该数组第i行的列数

    for (int j=0; j

    // 打印第i行第j列的数组元素

    System.out.println("triangle["+i+"]["+j+"]="+triangle[i][j]);

    }

    }

    上述示例代码中的二维数组,存放了平面坐标系上的三个顶点,它们的坐标分别是(-2.0, 0.0)、(0.0, -1.0)、(2.0, 1.0)。这三个坐标点构成了一个三角形的三个顶点,正如下图所示的A点(坐标为(-2,0))、B点(坐标为(0,-1))、C点(坐标为(2,1))。

    4271f6f8c85788ae452d298e5c18c8bc.png

    看到了熟悉的平面坐标图,这下平面几何的知识可派上用场了,例如根据两点的坐标来计算两点之间的距离。既然三角形有三个顶点A、B、C,接下来不妨计算它的三条边长,包括AB、AC和BC三条边的长度。于是分别求得两个顶点在横轴方向的距离,以及在纵轴方向的距离,然后利用勾股定理算出连接两顶点的斜边长度。以下便是由二维数组保存的坐标数值求解三角形各边长的演示代码:

    // 下面通过循环语句依次计算三角形每条边的长度

    // 假设第一个数组元素代表点A,第二个数组元素代表点B,第三个数组元素代表点C,

    // 则本循环将依次求得AB、AC、BC这三条边的长度

    for (int i=0; i

    for (int j=i+1; j

    // 获取两个顶点在横轴方向的距离

    double xDistance = Math.abs(triangle[j][0] - triangle[i][0]);

    // 获取两个顶点在纵轴方向的距离

    double yDistance = Math.abs(triangle[j][1] - triangle[i][1]);

    // 根据勾股定理计算连接两顶点的斜边长度

    double distance = Math.sqrt(xDistance*xDistance + yDistance*yDistance);

    System.out.println("i="+i+",j="+j+",distance="+distance);

    }

    }

    运行上述的演示代码,打印出来的三角形边长计算结果如下所示:

    i=0,j=1,distance=2.23606797749979

    i=0,j=2,distance=4.123105625617661

    i=1,j=2,distance=2.8284271247461903

    更多相关内容
  • 最近在做图像去噪方面涉及到二维空间变换,在此总结 二维空间变换1.综述2.平移仿射变换举例Step 1: 导入要变换的图像Step 2: 定义空间变换Step 3: 创建TFORM结构体Step 4: 执行变换Step 5: 观察输出图像3.定义空间...

    最近在做图像去噪方面涉及到二维空间变换,在此总结

    1.综述

    执行一般的二维空间变换包括如下三步:

    • 定义空间变换的参数;

    • 创建变换结构体TFORM,它定义了你所要执行变换的类型;

      TFORM结构体包含了执行变换需要的所有参数。你可以定义很多类型的空间变换,包括放射变换affine transformations(如平移translation,缩放scaling,旋转rotation,剪切shearing)、投影变换projective transformations和自定义的变换custom transformations。

      创建结构体的方法有两种:使用maketform或者使用cp2tform。

    • 执行变换。

    通过将要变换的图像和TFORM结构体传递给imtransform函数即可实现变换。

    用图来表示就是

    在这里插入图片描述
    下面以一个简单的平移仿射变换来展示空间变换的使用方法。

    2.平移仿射变换举例

    Step 1: 导入要变换的图像

    Matlab提供了一个棋盘图像,可以以此作为例子,它的调用函数为checkerboard,它将创建一个80X80像素的图像。

    % 导入图像
    cb = checkerboard;
    
    figure
    
    imshow(cb)
    

    在这里插入图片描述

    Step 2: 定义空间变换

    • 定义二维的空间变换需要一个3X3的变换矩阵,也可以通过在输入图像和输出图像上指定对应点的方式由maketform自动创建变换矩阵。

    这里使用如下的变换矩阵来定义空间平移变换

    % 定义变换矩阵
    
    xform = [ 1  0  0
    
        	  0  1  0
    
       		 20 40  1 ];
    

    在这个矩阵中,xform(3, 1)定义了图像在水平方向上平移的像素数,xform(3, 2)定义了图像在垂直方向上平移的像素数。

    Step 3: 创建TFORM结构体

    • 使用maketform函数可以创建TFORM结构体,参数为希望执行变换的类型和变换矩阵。
    % 创建TFORM结构体
    
    tform_translate = maketform('affine', xform);
    

    Step 4: 执行变换

    • 使用imtransform函数执行变换,参数为要变换的图像和TFORM结构体,函数将返回变换后的图像。
    % 执行变换
    
    [cb_trans xdata ydata]= imtransform(cb, tform_translate);
    

    返回值中包含的另两个额外输出参数xdata和ydata,表示输出图像在输出坐标空间的位置。xdata包含了输出图像拐角处像素的x坐标,ydata包含了这些像素的y坐标(这里说的x、y坐标是指像素的中点)。

    下图展示了平移变换的效果,可以看到,(1, 1)点的像素转移到了(41, 41)的位置,注意那一点的像素值没有变。
    在这里插入图片描述
    imtransform函数决定输出图像的像素值是把新位置映射回输入图像的相应位置。在平移变换中,由于图像的大小和旋转角度没有变,所以是一一映射;对于其他类型的变换,如放缩、旋转,此函数将在输入图像上插值计算输出图像的像素值。学过图像处理的这个应该很清楚。

    Step 5: 观察输出图像

    使用如下语句显示变换后的图像

            
    
    % 显示变换结果
    
    figure
    
    imshow(cb_trans)
    

    在这里插入图片描述
    从结果看来,貌似变换没有效果,变换后图像和原图像是一样的。但如果你检查xdata和ydata的数值,就会看到图像的空间坐标已经改变了。原始图像左上角的坐标由(1, 1)变为了(41, 41),右下角由(80, 80)变为了(120, 120),40已经被加到了每个像素的空间坐标上。

    >> xdata
    
    xdata =
    
        41   120
    
    >> ydata
    
    ydata =
    
    41   120
    

    而显示结果上没有变化的原因是函数imtransform得到的输出图像足够包含了变换后的图像,但没有包含全部的坐标空间。
    要看到变换的效果,需要使用imtransform函数的额外输入参数来指定输出图像的大小和能包含输出图像的输出空间。

    下面的代码使用了XData和YData两个额外参数来指定能包含输出图像的输出空间,而对于输出空间中不在输出图像上的像素默认为黑色,这可以通过改变imtransform函数的FillValues参数来指定。

    
    % 修正的变换结果
    
    cb_trans2 = imtransform(cb, tform_translate,...
    
        'XData', [1 (size(cb,2)+ xform(3,1))],...
    
        'YData', [1 (size(cb,1)+ xform(3,2))]);
    
    figure,
    
    imshow(cb_trans2)
    

    在这里插入图片描述

    3.定义空间变换的方式

    下面来讨论定义空间变换的两种方式:使用变换矩阵和使用对应点。

    使用变换矩阵

    Maketform函数可以接受一个N维的变换矩阵来产生TFORM结构体。而由于imtransform只能做二维变换,故只能指定3X3的转换矩阵。

    如使用3X3的矩阵来指定任何的仿射变换,而对于仿射变换,最后一列必须是0 0 1,所以你指定3X2的矩阵就足够了,在这种情况下,imtransform会自动添加第三列。

    下面的表格列举了imtransform可以执行的仿射变换以及相应矩阵的定义方法。
    在这里插入图片描述

    使用对应点

    • 除了指定变换矩阵,你还可以通过使用对应点来定义一个变换,让maketform自动生成变换矩阵。

    要对一个仿射变换使用此方法,需要在输入、输出图像上拾取3对非线性的点,而对于投影变换,则需要指定四对点。如

    in_points = [11 11;21 11; 21 21];
    
    out_points = [51 51;61 51;61 61];
    
    tform2 = maketform('affine', in_points, out_points);
    

    4.创建TFORM结构体

    • 有了上面的变换数据,就可以用maketform创建TFORM结构体了,也可以使用cp2tform函数来创建,具体详见Image Registration。

    在使用maketform创建TFORM结构时,需要指定必要的变换方式。如要做平移变换需要指定为仿射变换方式,除此maketform还支持投影变换,另外可以使用custom和composite选项来指定任意的空间变换。下表列出了maketform支持的变换类型
    在这里插入图片描述

    5.执行空间变换

    • 有了上面的TFORM结构体,就可以调用imtransform执行变换了。正如上面例子中所使用的那样
    [cb_trans xdata ydata]= imtransform(cb, tform_translate);
    

    另外,imtransform函数还支持几个可选输入参数来控制转换的不同效果,如输出图像的大小、填充值等。上面例子中的XData和YData就是控制输出图像大小的输入参数。对于填充值可以如下设置。

    指定填充值

    当执行一个变换时,输出图像上有很多像素不在位于原输入图像的位置,这些像素必须被赋予一些值,这就是填充值。默认情况下,imtransform函数设置这些像素为0,显示为黑色。而通过使用FillValues参数可以指定不同的颜色。

    对于灰度图像

    如果待转换的图像是灰度图像,就需要指定一个标量值来设置灰度的阴暗度。如下

    cb_fill = imtransform(cb, tform_translate,...
    
        'XData', [1 (size(cb,2)+xform(3,1))],...
    
        'YData', [1 (size(cb,1)+xform(3,2))],...
    
        'FillValues', .7 );
    
    Figure
    
    imshow(cb_fill)
    

    得到结果为
    在这里插入图片描述

    对于RGB图像

    对于RGB彩色图像,可以使用一个标量值或者一个1X3的向量。如果使用标量,imtransform会使用相应阴暗度的灰度值来填充;如果使用向量,则会将其按RGB彩色值来使用。

    % 彩色图像处理
    
    rgb = imread('onion.png');
    
    xform = [ 1 0 0
    
              0 1 0
    
             40 40 1 ];
    
    tform_translate = maketform('affine',xform);
    
    cb_rgb = imtransform(rgb, tform_translate,...
    
        'XData', [1 (size(rgb,2)+xform(3,1))],...
    
        'YData', [1 (size(rgb,1)+xform(3,2))],...
    
        'FillValues', [187;192;57]);
    
    figure
    
    imshow(cb_rgb)
    
    

    结果如下
    在这里插入图片描述

    原文章链接

    二维空间变换

    展开全文
  • 第7章 二维几何变换 应用于对象几何描述并改变它的位置、方向或大小的操作称为几何变换(geometric transformation)。 几何变换有时也称为建模变换(modeling transformation),但有些图形系统将两者区分开来。...

    第7章 二维几何变换

    应用于对象几何描述并改变它的位置、方向或大小的操作称为几何变换(geometric transformation)

    几何变换有时也称为建模变换(modeling transformation),但有些图形系统将两者区分开来。建模变换一般用于构造场景或给出由多个部分组合而成的复杂对象的层次式描述等。

    基本的二维几何变换

    平移、旋转和缩放是所有图形软件包中都包含的几何变换函数。可能包括在图形软件包中的其他变换函数有反射和错切操作。

    二维平移

    通过将位移量加到一个点的坐标上来生成一个新的坐标位置,可以实现一次平移(translation)。实际上,我们将该点从原始位置沿一直线路径移动到新位置。

    将平移距离(translation distance) t x t_x tx t y t_y ty加到原始坐标 ( x , y ) (x,y) (x,y)上获得一个新的坐标位置 ( x ′ , y ′ ) (x^{'},y^{'}) (xy),可以实现一个二维位置的平移。
    x ′ = x + t x y ′ = y + t y x^{' } = x +t_x \quad y^{' } = y +t_y x=x+txy=y+ty
    一对平移距离 ( t x , t y ) (t_x,t_y) (tx,ty)称为平移向量(translation vector)位移向量(shift vector)

    在这里插入图片描述
    如果用矩阵表示
    P = [ x y ] P ′ = [ x ′ y ′ ] T = [ t x t y ] P = \begin{bmatrix}x \\ y \end{bmatrix} \quad P^{'} = \begin{bmatrix}x^{'} \\ y^{'} \end{bmatrix} \quad T = \begin{bmatrix}t_x \\t_ y \end{bmatrix} P=[xy]P=[xy]T=[txty]
    这样就可以使用矩阵形式来表示二维平移方程:
    P ′ = P + T P^{'} = P+T P=P+T
    下面的程序演示了平移操作。输入的平移向量用来将一个多边形的n个顶点从世界坐标系的一个位置移动到另一个位置,而OpenGL子程序用来重新生成平移后的多边形。

    class wcPt2D(
    	public: GLfloat x,y;
    }; 
    void translatePolygon (wcPt2D"verts, GLint nVerts, GLfloat tx, GLfloat ty){
    	GLint k; 
              for (k=0;k<nVerts:k++){
                  verts [k].x = verts [k].x + tx; 
                  verts [k].y =verts [k].y + ty; 
              }
               g1Begin (GL_POLYGON); 
                           for (k=0;k< nVerts;k++)
    			g1Vertex2f (verts [k].x, verts [k].y); 
               g1End();
    }
    

    二维旋转

    通过指定一个旋转轴(rotation axis)和一个旋转角度(rotation angle),可以进行一次旋转(rotation)变换。在将对象的所有顶点按指定角度绕指定旋转轴旋转后,该对象的所有点都旋转到新位置。

    对象的二维旋转通过在 x y xy xy平面上沿圆路径将对象重定位来实现。此时,我们将对象绕与 x y xy xy平面垂直的旋转轴(与 z z z轴平行)旋转。二维旋转的参数有旋转角 θ \theta θ和称为旋转点(rotation point 或pivot point)的位置 ( x r , y r ) (x_r,y_r) (xr,yr),对象绕该点旋转。基准点是旋转轴与 x y xy xy平面的交点。正角度 θ \theta θ定义绕基准点的逆时针旋转,而负角度将对象沿顺时针方向旋转。

    为了简化模型,我们先假设基准点为原点。
    在这里插入图片描述

    因此旋转后用角度 θ \theta θ ϕ \phi ϕ表示为
    x ′ = r cos ⁡ ( ϕ + θ ) = r cos ⁡ ϕ cos ⁡ θ − r sin ⁡ ϕ sin ⁡ θ y ′ = r sin ⁡ ( ϕ + θ ) = r cos ⁡ ϕ sin ⁡ θ + r sin ⁡ ϕ cos ⁡ θ x^{'} = r\cos(\phi + \theta) = r \cos \phi \cos\theta - r\sin \phi \sin \theta \\ y^{'} = r\sin(\phi + \theta) = r\cos\phi\sin\theta + r \sin\phi \cos \theta x=rcos(ϕ+θ)=rcosϕcosθrsinϕsinθy=rsin(ϕ+θ)=rcosϕsinθ+rsinϕcosθ
    在极坐标系中,点的原始坐标为
    x = r cos ⁡ ϕ y = r sin ⁡ ϕ x = r \cos \phi \quad y = r\sin \phi x=rcosϕy=rsinϕ
    所以可以得到:
    x ′ = x cos ⁡ θ − y sin ⁡ θ y ′ = x sin ⁡ θ + y cos ⁡ θ x^{'} = x\cos \theta - y\sin \theta \\ y^{'}= x \sin \theta +y \cos \theta x=xcosθysinθy=xsinθ+ycosθ
    如果用矩阵的形式表示:
    P ′ = R ⋅ P P^{'} = R\cdot P P=RP
    其中,旋转矩阵为:
    R = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] R = \begin{bmatrix}\cos \theta & -\sin\theta \\ \sin\theta & \cos \theta\end{bmatrix} R=[cosθsinθsinθcosθ]
    但现在OpenGL、Java、PHIGS和GKS都按标准列向量方式表示。

    任意的旋转位置 ( x r , y r ) (x_r,y_r) (xr,yr)旋转点的变换方程:
    x ′ = x r + ( x − x r ) cos ⁡ θ − ( y − y r ) sin ⁡ θ y ′ = y r + ( x − x r ) sin ⁡ θ + ( y − y r ) cos ⁡ θ x^{'} = x_r + (x-x_r)\cos \theta - (y-y_r)\sin\theta \\ y^{'} = y_r + (x-x_r) \sin \theta + (y-y_r)\cos \theta x=xr+(xxr)cosθ(yyr)sinθy=yr+(xxr)sinθ+(yyr)cosθ
    线段的旋转可以通过用于每个线段端点,并重新绘制新端点间的线段而得到。多边形的旋转则是将每个顶点旋转指定的旋转角,并使用新的顶点来生成多边形而实现旋转。曲线的旋转通过重新定位定义的点并重新绘制曲线而完成。例如圆或椭圆,可以通过将中心位置沿指定旋转角对着的弧移动而绕非中心轴旋转。椭圆可通过旋转其长轴和短轴来实现绕其中心位置的旋转。

    class wcPt2D {}
    	public:
    		GLfloat x,y; 
    }; 
    void rotatePolygon (wcPt2D* verts, GLint nVerts, wePt2D pivPt, GLdouble theta)
    {
        wcPt2D* vertsRot; 
        GLint k; 
        for (k=0;k< nVerta:k++){
    	vertsRot [k].x=pivPt.x+(verts [k].x-pivPt.x) * cos (theta)-(verts [k].y-pivpt.y)* sin (theta); 
             vertsRot [k].y=pivPt.y+(verts [k],x-pivPt.x )* sin (theta)+(verts [k].y-pivPt.y)* cos (theta):
        ]
        g1Begin { GL_POLYGON}: 
            for(k=0;k<nVerts;k++)
      		g1Vertex2f (verteRot [k].x, verteRot [k].y): 
        g1End();
    

    二维缩放

    改变一个对象的大小,可使用缩放(scaling)变换。一个简单的二维缩放操作可通过将缩放系数(scaling factor) s x s_x sx s y s_y sy,与对象坐标位置 ( x , y ) (x,y) (x,y)相乘而得:
    x ′ = x ⋅ s x y ′ = y ⋅ s y x^{'} = x \cdot s_x \quad y^{'} = y\cdot s_y x=xsxy=ysy
    矩阵形式如下
    [ x ′ y ′ ] = [ s x 0 0 s y ] ⋅ [ x y ] \begin{bmatrix}x^{'} \\ y^{'}\end{bmatrix} = \begin{bmatrix}s_x & 0 \\ 0 & s_y\end{bmatrix}\cdot \begin{bmatrix}x \\ y\end{bmatrix} [xy]=[sx00sy][xy]
    或者是
    P ′ = S ⋅ P P^{'} = S\cdot P P=SP
    s x s_x sx s y s_y sy相同的值的时候,就会产生保持对象相对比例一致的一致缩放(uniform scaling)。当两个值不相等的时候就是差值缩放(differential scaling)。

    当缩放系数的绝对值小于1时,缩放后的对象向原点靠近;而缩放系数绝对值大于1时,缩放后的坐标位置远离原点。

    我们可以选择一个在缩放变换后不改变位置的点,称为固定点(fixed point),以控制缩放后对象的位置。固定点的坐标 ( x f , y f ) (x_f,y_f) (xf,yf)可以选择对象的中点等位置或任何其他空间位置。这样,多边形通过缩放每个顶点到固定点的距离而相对于固定点进行缩放。对于坐标为 ( x , y ) (x,y) (x,y)的顶点,缩放后的坐标 ( x ′ , y ′ ) (x^{'},y^{'}) (x,y)可计算为
    x ′ − x f = ( x − x f ) s x y ′ − y f = ( y − y f ) s y x^{'} - x_f = (x-x_f)s_x \quad y^{'} - y_f = (y-y_f)s_y xxf=(xxf)sxyyf=(yyf)sy
    可以得到
    x ′ = x ⋅ s x + x f ( 1 − s x ) y ′ = y ⋅ s y + y f ( 1 − s y ) x^{'} = x\cdot s_x + x_f(1-s_x)\\ y^{'} = y\cdot s_y + y_f(1-s_y) x=xsx+xf(1sx)y=ysy+yf(1sy)
    其中 x f ( 1 − s x ) x_f(1-s_x) xf(1sx) y f ( 1 − s y ) y_f(1-s_y) yf(1sy)都是常数。

    在这里插入图片描述

    class wePt2D {
        public: 
        GLfloat x,y; 
    };
    void scalePolygon (wcPt2D· verts, GLint nVerts, wcpt2D fixedPt, GLfloat sx, GLfloat sy)
    {
        wcPt2D vertsNew; 
        GLint k; 
        for (k-0;k<nVerts;k++){
            vertsNew[k].x=verts [k].x* sx+ fixedPt.x*(1-sx); 
            vertaNew[k].y=verts [k].y*sy+fixedPt.y*(1: sy): 
             
        } 
        g1Begin (GL POLYGON]; 
                 for (k-0;k<nVerte;k++) 
                 	g1Vertex2f (vertsNew [k].x, vertsNew [k].y); 
         g1End():
    

    矩阵表示和齐次坐标

    每个基本变换(平移、旋转和缩放)都可以表示为普通矩阵形式
    P ′ = M 1 P + M 2 P^{'} = M_1P+M_2 P=M1P+M2
    P P P P ′ P^{'} P都是坐标的列向量。矩阵 M 1 M_1 M1是一个包含乘法系数的 2 × 2 2\times 2 2×2的矩阵, M 2 M_2 M2是包含平移项的两元素列矩阵。

    对于平移, M 1 M_1 M1是单位矩阵。对于旋转或缩放, M 2 M_2 M2包含与基准点或缩放固定点相关的平移项。

    齐次坐标

    如果将 2 × 2 2\times 2 2×2矩阵表达式扩充为 3 × 3 3\times 3 3×3矩阵,就可以把二维儿何变换的乘法和平移组合成单一矩阵表示。这时将变换矩阵的第三列用于平移项,而所有的变换公式可表达为矩阵乘法。但为了这样操作,必须解释二维坐标位置到三元列向量的矩阵表示。标准的实现技术是将二维坐标位置表示 ( x , y ) (x,y) (x,y)扩充到三维表示 ( x h , y h , h ) (x_h,y_h,h) (xh,yh,h),称为齐次坐标(homogeneous coordinate),这里的齐次参数(homogeneous parameter)h是一个非零值,因此
    x = x h h y = y h h x = \frac{x_h}{h} \quad y = \frac{y_h}{h} x=hxhy=hyh
    普通的二维齐次坐标表示可写为 ( h × x , h × y , h ) (h\times x , h\times y,h) (h×x,h×y,h)。最简单的 h = 1 h=1 h=1。因此每个二维位置都可以用齐次坐标来表示 ( x , y , 1 ) (x,y,1) (x,y,1)来表示。

    二维平移矩阵

    使用齐次坐标方法,坐标位置的二维平移可表示为下面的矩阵乘法:
    [ x ′ y ′ 1 ] = [ 1 0 t x 0 1 t y 0 0 1 ] × [ x y 1 ] \begin{bmatrix}x^{'} \\ y^{'} \\ 1\end{bmatrix} = \begin{bmatrix}1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 &1\end{bmatrix} \times \begin{bmatrix}x \\y \\ 1\end{bmatrix} xy1=100010txty1×xy1
    该平移操作可简写为
    P ′ = T ( t x , t y ) P P^{'} = T(t_x,t_y)P P=T(tx,ty)P

    二维旋转矩阵

    二维的旋转变换公式为
    [ x ′ y ′ 1 ] = [ cos ⁡ θ − sin ⁡ θ 0 sin ⁡ θ cos ⁡ θ 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}x^{'} \\ y^{'} \\ 1 \end{bmatrix} = \begin{bmatrix}\cos \theta & -\sin \theta & 0 \\ \sin \theta & \cos \theta & 0\\0 & 0 &1\end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix} xy1=cosθsinθ0sinθcosθ0001xy1
    其中旋转变换操作 R ( θ ) R(\theta) R(θ)的旋转参数 θ \theta θ

    二维缩矩阵

    相对于坐标原点的缩放变换可以表示为
    [ x ′ y ′ 1 ] = [ s x 0 0 0 s y 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}x^{'} \\ y^{'} \\ 1\end{bmatrix} = \begin{bmatrix}s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0& 0 & 1\end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix} xy1=sx000sy0001xy1

    逆变换

    对于平移变换,我们通过对平移距离取负值而得到逆矩阵。因此,如果二维平移距离是 t x t_x tx t y t_y ty,则其逆平移矩阵是

    T − 1 = [ 1 0 − t x 0 1 − t y 0 0 1 ] T^{-1} = \begin{bmatrix}1 & 0 & -t_x \\ 0 & 1 & -t_y \\ 0 & 0 & 1\end{bmatrix} T1=100010txty1

    逆旋转通过用旋转角度的负角取代该旋转角来实现。例如,绕坐标系原点的角度为0的二维旋转有如下的逆变换矩阵
    R − 1 = [ cos ⁡ θ sin ⁡ θ 0 − sin ⁡ θ cos ⁡ θ 0 0 0 1 ] R^{-1} = \begin{bmatrix} \cos \theta & \sin \theta & 0 \\ -\sin \theta & \cos\theta & 0 \\ 0 & 0 & 1\end{bmatrix} R1=cosθsinθ0sinθcosθ0001
    将缩放系数用其倒数取代就得到了缩放变换的逆矩阵。对以坐标系原点为中心、缩放参数为 s x s_x sx s y s_y sy的二维缩放,其逆变换矩阵为
    S − 1 = [ 1 s x 0 0 0 1 s y 0 0 0 1 ] S^{-1} = \begin{bmatrix}\frac{1}{s_x} & 0 & 0 \\ 0 & \frac{1}{s_y}& 0 \\ 0 & 0 &1\end{bmatrix} S1=sx1000sy10001

    二维复合变换

    利用矩阵表达式,可以通过计算单个变换的矩阵乘积,将任意的变换序列组成复合变换矩阵(composite transformation matrix)。形成变换矩阵的乘积经常称为矩阵的合并(concatenation) 或复合(composition)。由于一个坐标位置用齐次列矩阵表示,我们必须用表达任意变换顺序的矩阵来前乘该列矩阵。由于场景中许多位置用相同的顺序变换,先将所有变换矩阵相乘形成一个复合矩阵将是高效率的方法。因此,如果我们要对点位置P进行两次变换,变换后的位置将用下式计算:
    P ′ = M 2 M 1 P = M P P^{'} = M_2M_1P = MP P=M2M1P=MP

    复合二维平移

    假如将两个连续的平移向量 ( t 1 x , t 1 y ) (t_{1x},t_{1y}) (t1x,t1y) ( t 2 x , t 2 y ) (t_{2x},t_{2y}) (t2x,t2y)用于坐标位置P,那么最后的变换位置 P ′ P^{'} P可以计算为
    P ′ = T ( t 2 x , t 2 y ) { T ( t 1 x , T 1 y ) P } = { T ( t 1 x , t 1 y ) T ( t 2 x , t 2 y ) } P = T ( t 1 x + t 2 x , t 1 y + t 2 y ) P^{'} = T(t_{2x},t_{2y})\{T(t_{1x},T_{1y})P\} = \{T(t_{1x},t_{1y})T(t_{2x},t_{2y})\}P = T(t_{1x}+t_{2x},t_{1y}+t_{2y}) P=T(t2x,t2y){T(t1x,T1y)P}={T(t1x,t1y)T(t2x,t2y)}P=T(t1x+t2x,t1y+t2y)
    这表示两个连续平移是相加的。

    复合二维旋转

    P ′ = R ( θ 2 ) { R ( θ 1 ) P } = { R ( θ 1 ) R ( θ 2 ) } P P^{'} = R(\theta_2)\{R(\theta_1)P\} = \{R(\theta_1)R(\theta_2)\}P P=R(θ2){R(θ1)P}={R(θ1)R(θ2)}P

    并且
    R ( θ 1 ) R ( θ 2 ) = R ( θ 1 + θ 2 ) R(\theta_1) R(\theta_2) = R(\theta_1+\theta2) R(θ1)R(θ2)=R(θ1+θ2)

    复合二维缩放

    [ s 2 x 0 0 0 s 2 y 0 0 0 1 ] [ s 1 x 0 0 0 s 1 y 0 0 0 1 ] = [ s 1 x s 2 x 0 0 0 s 1 y s 2 y 0 0 0 1 ] \begin{bmatrix}s_{2x} & 0 & 0 \\ 0 & s_{2y} & 0 \\ 0 & 0 &1\end{bmatrix} \begin{bmatrix}s_{1x} & 0 & 0 \\ 0 & s_{1y}& 0 \\ 0 & 0 & 1\end{bmatrix} = \begin{bmatrix}s_{1x}s_{2x} & 0 &0 \\ 0 & s_{1y}s_{2y} & 0 \\ 0 & 0 &1\end{bmatrix} s2x000s2y0001s1x000s1y0001=s1xs2x000s1ys2y0001

    或者是
    S ( s 2 x , s 2 y ) ⋅ S ( s 1 x , s 1 y ) = S ( s 1 x ⋅ s 2 x , s 1 y ⋅ s 2 y ) S(s_{2x},s_{2y})\cdot S(s_{1x},s_{1y}) = S(s_{1x}\cdot s_{2x} , s_{1y}\cdot s_{2y}) S(s2x,s2y)S(s1x,s1y)=S(s1xs2x,s1ys2y)

    通用二维基准点旋转

    当图形软件包仅提供绕坐标系原点的旋转函数时,我们可通过完成下列平移-旋转-平移操作序列来实现绕任意选定的基准点 ( x r , y r ) (x_r,y_r) (xr,yr)的旋转。

    1. 平移对象使基准点位置移动到坐标原点;
    2. 绕坐标原点旋转;
    3. 平移对象使基准点回到其原始位置。

    [ 1 0 x r 0 1 y r 0 0 1 ] ⋅ [ cos ⁡ θ − sin ⁡ θ 0 sin ⁡ θ cos ⁡ θ 0 0 0 1 ] ⋅ [ 1 0 − x r 0 1 − y r 0 0 1 ] = [ cos ⁡ θ − sin ⁡ θ x r ( 1 − cos ⁡ θ ) + y r sin ⁡ θ sin ⁡ θ cos ⁡ θ y r ( 1 − cos ⁡ θ ) − x r sin ⁡ θ 0 0 1 ] \begin{bmatrix}1 & 0 & x_r \\0 & 1 & y_r \\ 0 & 0 & 1\end{bmatrix}\cdot \begin{bmatrix}\cos \theta & -\sin \theta & 0 \\\sin\theta & \cos \theta & 0\\ 0 & 0 & 1\end{bmatrix}\cdot \begin{bmatrix}1 & 0 & -x_r \\0 & 1 & -y_r \\ 0 & 0 & 1\end{bmatrix} = \begin{bmatrix}\cos\theta & -\sin\theta & x_r(1-\cos\theta) + y_r\sin \theta \\\sin\theta & \cos\theta & y_r(1-\cos\theta)-x_r\sin\theta \\ 0 & 0 & 1\end{bmatrix} 100010xryr1cosθsinθ0sinθcosθ0001100010xryr1=cosθsinθ0sinθcosθ0xr(1cosθ)+yrsinθyr(1cosθ)xrsinθ1

    该等式可以使用下列形式表示:
    T ( x r , y r ) R ( θ ) T ( − x r , − y r ) = R ( x r , y r , θ ) T(x_r,y_r)R(\theta)T(-x_r,-y_r) = R(x_r,y_r,\theta) T(xr,yr)R(θ)T(xr,yr)=R(xr,yr,θ)
    其中 T ( − x r , − y r ) = T − 1 ( x r , y r ) T(-x_r, -y_r) = T^{-1}(x_r,y_r) T(xr,yr)=T1(xr,yr)

    在这里插入图片描述

    通用二维基准点缩放

    在只有相对于坐标原点缩放的缩放函数时,缩放的变换序列:

    1. 平移对象使固定点与坐标原点重合;
    2. 对于坐标原点进行缩放;
    3. 使用步骤1的反向平移将对象返回到原始位置。

    [ 1 0 x f 0 1 y f 0 0 1 ] ⋅ [ s x 0 0 0 s y 0 0 0 1 ] ⋅ [ 1 0 − x f 0 1 − y f 0 0 1 ] = [ s x 0 x f ( 1 − s x ) 0 s y y f ( 1 − s y ) 0 0 1 ] ⋅ \begin{bmatrix}1& 0 & x_f \\ 0 & 1 & y_f \\ 0 & 0 &1\end{bmatrix}\cdot \begin{bmatrix}s_x& 0 &0 \\ 0 & s_y & 0 \\ 0 & 0 &1\end{bmatrix}\cdot \begin{bmatrix}1& 0 & -x_f \\ 0 & 1 & -y_f \\ 0 & 0 &1\end{bmatrix} = \begin{bmatrix}s_x& 0 & x_f(1-s_x) \\ 0 & s_y & y_f(1-s_y) \\ 0 & 0 &1\end{bmatrix}\cdot 100010xfyf1sx000sy0001100010xfyf1=sx000sy0xf(1sx)yf(1sy)1


    T ( x f , y f ) ⋅ S ( s x , s y ) ⋅ T ( − x f , − y f ) = S ( x f , y f , s x , s y ) T(x_f,y_f)\cdot S(s_x,s_y) \cdot T(-x_f,-y_f) = S(x_f,y_f,s_x,s_y) T(xf,yf)S(sx,sy)T(xf,yf)=S(xf,yf,sx,sy)

    在这里插入图片描述

    通用二维定向缩放

    参数 s x s_x sx s y s_y sy沿x和y方向缩放对象,可以通过在应用缩放变换之前,将对象所希望的缩放方向旋转到与坐标轴一致来实现在其他方向上缩放对象。

    首先完成旋转操作,使 s 1 s_1 s1 s 2 s_2 s2的方向分别与x和y轴重合。然后应用缩放变换 S ( s 1 , s 2 ) S(s_1,s_2) S(s1,s2),再进行反向旋转回到其原始位置。从这三个变换的乘积得到的复合矩阵为
    R − 1 ( θ ) ⋅ S ( s 1 , s 2 ) ⋅ R ( θ ) = [ s 1 cos ⁡ 2 θ + s 2 sin ⁡ 2 θ ( s 2 − s 1 ) cos ⁡ θ sin ⁡ θ 0 ( s 2 − s 1 ) cos ⁡ θ sin ⁡ θ s 1 sin ⁡ 2 θ + s 2 cos ⁡ 2 θ 0 0 0 1 ] R^{-1}(\theta) \cdot S(s_1,s_2)\cdot R(\theta) = \begin{bmatrix} s_1\cos^2\theta+s_2\sin^2\theta & (s_2-s_1)\cos\theta\sin\theta & 0 \\ (s_2-s_1)\cos\theta\sin\theta & s_1\sin^2\theta + s_2\cos^2\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} R1(θ)S(s1,s2)R(θ)=s1cos2θ+s2sin2θ(s2s1)cosθsinθ0(s2s1)cosθsinθs1sin2θ+s2cos2θ0001

    矩阵合并特性

    矩阵相乘符合结合律,对于任何三个矩阵 M 1 M_1 M1 M 2 M_2 M2 M 3 M_3 M3。矩阵积 M 3 M 2 M 1 M_3M_2M_1 M3M2M1可以写成
    M 3 M 2 M 1 = ( M 3 M 2 ) M 1 = M 3 ( M 2 M 1 ) M_3M_2M_1 = (M_3M_2)M_1 = M_3(M_2M_1) M3M2M1=(M3M2)M1=M3(M2M1)
    因此,依靠变换的描述顺序,我们既可以使用从左到右(前乘),也可以使用从右到左(后乘)的结合分组来求矩阵乘积。有些图形软件包要求变换按应用的顺序描述。

    二维刚体变换

    如果一个变换矩阵仅包含平移和旋转参数,则它是一个刚体变换矩阵(rigid-body transformation matrix)。二维刚体变换矩阵的一般形式为
    [ r x x r x y t r x r y x r y y t r y 0 0 1 ] \begin{bmatrix} r_{xx} & r_{xy} & tr_{x} \\ r_{yx} & r_{yy} & tr_y \\ 0 & 0 & 1 \end{bmatrix} rxxryx0rxyryy0trxtry1
    其中,4个元素 r j k r_{jk} rjk是多重旋转项,元素 t r x tr_x trx t r y tr_y try是平移项。坐标位置的刚体变换有时也称为刚体运动(rigid motion)。变换后的坐标位置间的所有角度和距离都不变化。

    因此上述左上角的 2 × 2 2\times 2 2×2矩阵是一个正交矩阵(orthogonal matrix)的特性。说明,如果将子矩阵的每一行(或每一列)作为向量,那么两个行向量 ( r x x , r x y ) (r_{xx}, r_{xy}) (rxx,rxy) ( r y x , r y y ) (r_{yx},r_{yy}) (ryx,ryy)形成单位向量的正交组。这样的一组向量也称为正交向量组。每个向量具有单位长度。
    r x x 2 + r x y 2 = r y x 2 + r y y 2 = 1 r^2_{xx} + r^2_{xy} = r^2_{yx} + r^2_{yy} = 1 rxx2+rxy2=ryx2+ryy2=1
    并且向量相互垂直
    r x x r y x + r x y r y y = 0 r_{xx}r_{yx} + r_{xy}r_{yy} = 0 rxxryx+rxyryy=0

    二维复合矩阵编程

    其他二维变换

    反射

    产生对象镜像的变换称为反射(reflection)。对于二维反射而言,其反射镜像通过将对象绕反射轴旋转 18 0 ∘ 180^{\circ} 180而生成。我们选择的反射轴(axis of reflection)可以是在 x y xy xy平面内的一条直线或者是垂直 x y xy xy平面的一条直线。当反射轴是 x y xy xy平面内的一条直线时,绕这个轴的旋转路径在垂直于 x y xy xy平面的平面中;而对于垂直于 x y xy xy平面的反射轴,旋转路径在 x y xy xy平面内。下面举出一些普通的反射例子。

    关于直线 y = 0 y=0 y=0( x x x轴)的反射,可以由下列的变换矩阵完成。
    [ 1 0 0 0 − 1 0 0 0 1 ] \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & 1 \end{bmatrix} 100010001
    对于 x = 0 x=0 x=0(y轴)的反射,翻动 x x x的坐标而保持 y y y坐标不变,这种变换的矩阵是
    [ − 1 0 0 0 1 0 0 0 1 ] \begin{bmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} 100010001

    在这里插入图片描述
    关于 x y xy xy的平面内任意直线 y = m x + b y=mx+b y=mx+b 的反射,可以使用平移-旋转-反射变换的组合来完成的。

    通常,我们先平移直线使其经过原点。然后将直线旋转到坐标轴之一,并进行相对于坐标轴的反射。最后利用逆旋转和逆平移变换将直线还原到原来位置。

    错切

    错切(shear) 是一种使对象形状发生变化的变换,经过错切的对象好像是由已经相互滑动的内部夹层组成。两种常用的错切变换是移动 x x x坐标值的错切和移动 y y y坐标值的错切。

    相对于 x x x轴的 x x x方向错切由下列变换矩阵产生:
    [ 1 s h x 0 0 1 0 0 0 1 ] \begin{bmatrix} 1 & sh_x & 0 \\ 0 & 1 & 0 \\ 0 & 0 &1 \end{bmatrix} 100shx10001
    该矩阵将坐标位置转换成
    x ′ = x + s h x ⋅ y y ′ = y x^{'} = x + sh_x \cdot y \quad y^{'} = y x=x+shxyy=y
    可以将任意实数赋给错切参数 s h sh sh.。然后将坐标位置 ( x , y ) (x,y) (x,y)水平地移动与其到 x x x轴的距离( y y y值)成正比的量。

    在这里插入图片描述
    错切操作可以表示为基本变换的序列。

    几何变换的光栅方法

    光栅系统的特殊功能为特定的二维变换提供了另一种方法。光栅系统将图像信息作为颜色图案存储在帧缓冲器中。控制矩形像素数组的光栅功能通常称为光栅操作(raster operation),将一块像素从一个位置移动到另一个位置的过程也称为像素值的块移动(block transfer,bitblt或pixblt)。图形软件中通常包含完成某些光栅操作的子程序。

    90°倍数的旋转可以很容易地利用重新安排像素矩阵的元素而实现。通过首先将阵列的每一行的像素值颠倒,然后交换其行和列来将对象逆时针旋转90°;通过颠倒阵列的每一行中元素的顺序,然后将行的顺序颠倒来得到180°的旋转。

    像素块的光栅缩放采用类似方法实现。我们用指定的 s x s_x sx s y s_y sy值对原始块中的像素区域进行缩放,并将缩放的矩形映射到一组目标像素上,然后按照其与缩放像素区域的重叠区域,设置每个目标像素的亮度。

    OpenGL光栅变换

    像素颜色值的矩形数组从一个缓存到另一个的平移可以作为如下的OpenGL复制操作来完成:

    g1CopyPixe1s (xmin, ymin, width, height. GL_COLOR):

    前面4个参数给出了像素块的位置和尺寸。而OpenGL符号常量GL_COLOR指定要复制的颜色值。该像素数组复制到刷新缓存中由当前光栅位置指定的左下角的一个矩形区域内。像素颜色值依赖于颜色模式的当前设定,按RGBA或颜色表进行复制。提供复制的区域(源)和复制目标区域均应位于屏幕坐标边界内。该平移可作用于任何刷新缓存或不同缓存之间。g1CopyPixels函数的源缓存用g1ReadBuffer 子程序选择,而目标缓存用g1DrawBuffer子程序选择。

    缓存中的一个RGB颜色块可以用下列函数存入一个数组:

    g1ReadPixels (xmin, ymin, width. height, GL_RGB.GL_UNSIGNED_BYTE, colorArray):

    如果颜色表索引存于像素位置,则将GL_COLOR_INDEX取代GL_RGB。为了旋转颜色值,必须如前一节所述重新安排颜色数组的行与列。然后使用下列语句将旋转后的数组放回缓存:

    g1DrawPixe1s (width,height,GL_RGB,GL_UNSIGNED_BYTE, colorArray);

    该数组的左下角放到当前光栅位置。我们用g1ReadBuffer选择包含原来的像素值块的源缓存,用g1DrawBuffer指定目标缓存。

    二维缩放变换通过指定缩放因子然后引用g1Copypixe1s或g1Drawpixe1s按OpenGL中的光栅操作来完成。对于光栅操作,使用下列函数来设定缩放因子:

    g1Pixe1zoom(sx,sy):

    这里,参数sx和sy可赋以任何非零浮点值。大于1.0的正值增太源数组元素的尺对,而小于1.0的正值减少元素尺寸。sx或sy中有负值或两个都为负值则生成该数组元素的反射及缩放。因此,如果sx=sy=-3.0,则源数组相对于当前光栅位置反射且数组的每一颜色元素映射到目标缓存中的3×3像素块。如果目标像素的中心位于一数组缩放颜色元素的矩形区域,则用该数组元素给它赋值。中心在缩放数组元素左边界或上边界的目标像素也赋以该元素的颜色。sx和sy的默认值均为1.0。

    二维坐标系间的变换

    非笛卡儿系统的例子有极坐标系统、球面坐标系统、椭圆坐标系统和抛物线坐标系统。

    给出了一个在笛卡儿坐标系 x y xy xy中用坐标原点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)及方向角 θ \theta θ指定的笛卡儿坐标系 x ′ y ′ x^{'}y^{'} xy。为了将对象描述从 x y xy xy坐标变换到 x ′ y ′ x^{'}y^{'} xy坐标,必须建立把 x ′ y ′ x^{'}y^{'} xy轴叠加到 x y xy xy轴的变换,这需要分两步进行:

    1. x ′ y ′ x^{'}y^{'} xy系统的坐标原点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)平移到 x y xy xy系统的原点 ( 0 , 0 ) (0,0) (0,0)
    2. x ′ x' x轴旋转到 x x x轴上

    坐标原点的平移可以使用下列矩阵操作表示:
    T ( − x 0 , − y 0 ) = [ 1 0 − x 0 0 1 − y 0 0 0 1 ] T(-x_0,-y_0) = \begin{bmatrix} 1 & 0 & -x_0 \\ 0 & 1 & -y_0 \\ 0 & 0 & 1 \end{bmatrix} T(x0,y0)=100010x0y01
    为了将两个系统的轴重合,可以顺时针旋转:
    R ( − θ ) = [ cos ⁡ θ sin ⁡ θ 0 − sin ⁡ θ cos ⁡ θ 0 0 0 1 ] R(-\theta) = \begin{bmatrix} \cos \theta & \sin \theta & 0 \\ -\sin \theta & \cos \theta & 0 \\ 0 & 0 & 1 \end{bmatrix} R(θ)=cosθsinθ0sinθcosθ0001
    把这两个变换矩阵合并起来,就给出了将对象描述从 x y xy xy系统转换到 x ′ y ′ x^{'}y^{'} xy系统的完整复合矩阵。
    M x y , x ′ y ′ = R ( − θ ) T ( − x 0 , − y 0 ) M_{xy,x^{'}y^{'}} = R(-\theta)T(-x_0,-y_0) Mxy,xy=R(θ)T(x0,y0)

    在这里插入图片描述

    OpenGL二维几何变换函数

    在OpenGL的核心库中,每一种基本的几何变换都有一个独立的函数。由于OpenGL是作为三维图形应用编程接口(APl)来设计的,所有变换都在三维空间中定义。在内部,所有坐标均使用4元素列向量表示,而所有变换均使用4×4矩阵表示。因此,二维变换可以通过在OpenGL中选择使第三维(z)不改变的z值来实现。

    基本的OpenGL几何变换

    4 × 4 4\times 4 4×4平移矩阵用下列子程序构造

    g1Translate*(tx,ty,tz)

    平移参数tx、ty和tz可赋予任意的实数值,附加于该函数的单个后缀码或者是f(浮点)或者是d。

    旋转矩阵 4 × 4 4\times 4 4×4下列函数生成:

    glRotate*(theta,vx,vy,vz)

    向量 v = ( v x , v y , v z ) v=(vx,vy,vz) v=vxvyvz的分量可以有任意的浮点数值。该向量用于定义通过坐标原点的旋转轴的方向。

    用下列函数可得到相对于坐标原点的4×4缩放矩阵:

    glScale*(sx, sy, sz)

    OpenGL矩阵操作

    将该矩阵看做建模观察矩阵(modelview matrix),它用于存储和组合几何变换,也用于将几何变换与向观察坐标系的变换进行组合。建模观察模式用下列语句指定:

    g1MatrixMode (GL_MODELVIEW)

    该语句指定一个4×4建模观察矩阵作为当前矩阵(current matrix)

    在这个调用后的OpenGL变换子程序用来修改建模观察矩阵,而后该矩阵用来变换场景中的坐标位置。用g1MatrixMode函数还可以设定另外两个模式:纹理模式(texture mode)颜色模式(color mode)。纹理模式用于映射表面的纹理图案,而颜色模式用于从一个颜色模型转换到另一个。后面几章将讨论观察、投影、纹理和颜色变换。

    建立建模观察模式(或任何其他模式)后,调用变换子程序所生成的矩阵要与该模式的当前矩阵相乘。另外,我们可以对当前矩阵的元素赋值,OpenGL库中有两个函数可用于此目的。使用下列函数可设定当前矩阵为单位矩阵:

    glLoadIdentity():

    也可以为当前矩阵的元素赋其他值:

    g1LoadMatrix*(elements16):

    参数elements16指定了一个单下标、16元素的浮点值数组,而后缀f或d用来指定数据类型。该数组的元素必须按列优先顺序指定。即先列出第一列的4个元数,接着列出第二列的4个元素,然后是第三列,而最后是第四列。

    也可以将指定的矩阵与当前矩阵合并:

    glMultMatrix*(otherElements16):

    实例

    from OpenGL.GL import *
    from OpenGL.GLU import *
    from OpenGL.GLUT import *
    import math
    
    winWidth, winHeight = 600, 600
    xwcMin, xwcMax = 0.0, 300.0
    ywcMin, ywcMax = 0.0, 300.0
    pi = 3.14159
    matComposite = [[0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0]]
    
    def init():
        glClearColor(1.0, 1.0, 1.0, 0.0)
    
    
    def get3x3Matfloat():
        temp = [[0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0]]
        return temp
    
    
    # 矩阵初始化
    def matrix3x3SetIndentity(matIdent3x3):
        for row in range(3):
            for col in range(3):
                matIdent3x3[row][col] = (row == col)
    
    # 显示三角形
    def triangle(verts):
        glBegin(GL_TRIANGLES)
        for k in range(3):
            glVertex2f(verts[k][0], verts[k][1])
        glEnd()
    
    
    def matrix3x3PreMultiply(m1, m2):
        mattemp = get3x3Matfloat()
        for row in range(3):
            for col in range(3):
                mattemp[row][col] = m1[row][0] * m2[0][col] + m1[row][1] * m2[1][col] + m1[row][2] * m2[2][col]
    
        for row in range(3):
            for col in range(3):
                m2[row][col] = mattemp[row][col]
    
    def rotate2D(pivotPt, theta):
        global matComposite
        matRot = get3x3Matfloat()
        matrix3x3SetIndentity(matRot)
        matRot[0][0] = math.cos(theta)
        matRot[0][1] = -math.sin(theta)
        matRot[0][2] = pivotPt[0] * (1-math.cos(theta)) + pivotPt[1] * math.sin(theta)
    
        matRot[1][0] = math.sin(theta)
        matRot[1][1] = math.cos(theta)
        matRot[1][2] = pivotPt[0] * (1-math.cos(theta)) - pivotPt[1]*math.sin(theta)
    
        matrix3x3PreMultiply(matRot, matComposite)
    
    def scale2D(sx, sy, fixedPt):
        global matComposite
        matScale = get3x3Matfloat()
        matrix3x3SetIndentity(matScale)
        matScale[0][0] = sx
        matScale[0][2] = (1-sx)*fixedPt[0]
        matScale[1][1] = sy
        matScale[1][2] = (1-sy) * fixedPt[1]
        matrix3x3PreMultiply(matScale, matComposite)
    
    
    def translate2D(tx, ty):
        global matComposite
        matTrans1 = get3x3Matfloat()
        matrix3x3SetIndentity(matTrans1)
        matTrans1[0][2] = tx
        matTrans1[1][2] = ty
        matrix3x3PreMultiply(matTrans1, matComposite)
    
    def transformVerts2D(nVerts, verts):
        global matComposite
        for k in range(nVerts):
            temp = matComposite[0][0] * verts[k][0] + matComposite[0][1] * verts[k][1] + matComposite[0][2]
            verts[k][1] = matComposite[1][0] * verts[k][0] + matComposite[1][1] * verts[k][1] + matComposite[1][2]
            verts[k][0] = temp
    
    def dispalyFcn():
        global pi,matComposite
        nVerts = 3
        verts = [[50.0, 25.0],[150.0, 25.0],[100.0, 100.0]]
        xsum , ysum = 0,0
        for k in range(nVerts):
            xsum += verts[k][0]
            ysum += verts[k][1]
        centroidPt = [0,0]
        centroidPt[0] = xsum/nVerts
        centroidPt[1] = ysum/nVerts
        pivPt = centroidPt[:]
        fixedPt = centroidPt[:]
        tx = 0.0
        ty = 100.0
        sx = 0.5
        sy = 0.5
        theta = pi/2.0
        glClear(GL_COLOR_BUFFER_BIT)
        glColor3f(0.0, 0.0, 1.0)
        triangle(verts)
        matrix3x3SetIndentity(matComposite)
    
        scale2D(sx, sy, fixedPt)
    
        rotate2D(pivPt, theta)
    
        translate2D(tx, ty)
    
        transformVerts2D(nVerts, verts)
    
        glColor3f(1.0, 0.0, 0.0)
        triangle(verts)
        glFlush()
    
    
    
    def winReshapeFcn(newWidth, newHeight):
        global xwcMax, xwcMin, ywcMax, ywcMin
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax)
        glClear(GL_COLOR_BUFFER_BIT)
    
    
    if __name__ == '__main__':
        glutInit()
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
        glutInitWindowPosition(50, 50)
        glutInitWindowSize(winWidth, winHeight)
        glutCreateWindow("几何变换".encode('gbk'))
        init()
        glutDisplayFunc(dispalyFcn)
        glutReshapeFunc(winReshapeFcn)
        glutMainLoop()
    
    

    在这里插入图片描述

    展开全文
  • 本文将重点讲解向量和二维图形的变换。5.1 向量基础知识我们所使用的所有点和向量都是基于某一坐标系定义的,比如左手坐标系或者右手坐标系。从几何的角度来看,向量是具有长度和方向的实体,但是没有位置,而点是...

    接上文 计算机图形学 学习笔记(六):消隐算法:Z-buffer,区间扫描线,Warnock,光栅图形学小结


    在图形学中,有两大基本工具:向量分析,图形变换。本文将重点讲解向量和二维图形的变换。

    5.1 向量基础知识

    我们所使用的所有点和向量都是基于某一坐标系定义的,比如左手坐标系或者右手坐标系。

    这里写图片描述

    从几何的角度来看,向量是具有长度和方向的实体,但是没有位置,而点是只有位置,没有长度和方向。

    在几何中,把向量看成是从一个点到另一个点的位移。向量算法提供了一种统一的方法来对几何思想进行代数的表示。

    向量的表示

    从点 P 到点 Q的位移用向量 V 表示。两个点的差是一个向量,V=Q-P,V=(3,-2)。

    这里写图片描述

    换个角度来说,可以说点 Q是由点 P 平移向量 V 得到的,Q=P+V。

    向量基本运算

    向量允许两个基本操作:向量相加,标量(实数)的数乘。

    例子:

    如果 a 和 b 是两个向量, s 是一个标量。a+b 和 sa都是有意义的。

    a=(2,6),b=(3,1),a+b=(5,7),2a=(4,12)

    除了直接的进行数值运算以外,向量的加(减)法可以采用“平行四边形法则”,在几何图形中表示结果。如下图所示:

    这里写图片描述

    这里写图片描述

    向量线性组合

    掌握了向量的加法和数乘后,就可以定义任意多个向量的线性组合了。

    这里写图片描述

    有两种特殊的线性组合在计算机图形学中很重要:仿射组合,凸组合

    仿射组合

    如果线性组合的系数的和等于1,那么它就是仿射组合。

    这里写图片描述

    向量的凸组合

    凸组合在数学中具有重要的位置,在图形学中也有很多应用。凸组合是对仿射组合加以更多的限制得来的。

    这里写图片描述

    向量的点积和叉积

    有两个功能强大的工具一直推动着向量的应用:点积,叉积。

    点积得到一个标量,叉积产生一个新的向量。

    点积

    点积:只需将两个向量对应的分量相乘,然后将结果相加。

    这里写图片描述

    点积最重要的应用就是计算两个向量的夹角,或者两条直线的夹角。

    这里写图片描述

    由于两个向量的点积和它们之间夹角的余弦成正比,可以得出以下关于两个非零向量夹角与点积的关系:

    这里写图片描述

    叉积

    两个向量的叉积是另一个三维向量。叉积只对三维向量有意义。它有许多有用的属性,但最常用的一个是它与原来的两个向量都相交。

    这里写图片描述

    两个向量的叉积 aXb 是另外一个向量,但是这个向量与原来的两个向量在几何上有什么关系?为什么我们说这种运算很重要呢?

    这里写图片描述

    利用叉积求平面的法向量

    法向量是空间解析几何的一个概念,垂直于平面的直线所表示的向量就是该平面的法向量。

    这里写图片描述

    5.2 图形坐标系

    坐标系的基本概念

    坐标系是建立图形与数之间对应联系的参考系。

    坐标系的分类

    从维度上来看,可以分为一维、二维、三维坐标系。

    从坐标轴之间的空间关系来看,可以分为直角坐标系,极坐标系,圆柱坐标系,球坐标系等。

    在计算机图形学中,从物体(场景)的建模,到在不同显示设备上显示、处理图形时,我们经常使用一系列不同的坐标系。图形显示的过程就是几何(对象)模型在不同坐标系之间的映射变换。

    计算机图形学中的坐标系

    世界坐标系

    程序员可以用最适合他们手中问题的坐标系来描述对象,并且可以自动的缩放和平移图形,使得其能正确地在屏幕窗口中显示。

    这个描述对象的空间被称为世界坐标系,即场景中物体在实际世界中的坐标。

    世界坐标系是一个公共坐标系,是现实中物体或场景的统一参考系,计算机图形系统中涉及到的其他坐标系都是参照它进行定义的。

    这里写图片描述

    建模坐标系(局部坐标系)

    每个物体(对象)都有它自己的局部中心和坐标系。建模坐标系独立于世界坐标系,来定义物体的几何特性。

    这里写图片描述

    一旦定义了“局部”物体,就很容易地将“局部”物体放入世界坐标系内,使它由局部上升为全局的。

    这里写图片描述

    观察坐标系

    观察坐标系主要用于从观察者的角度对整个世界坐标系内的对象进行重新定位和描述。

    依据观察窗口的方向和形状在世界坐标系中定义的坐标系称为观察坐标系。观察坐标系用于指定图形的输出范围。

    二维观察变换的一般方法是:在世界坐标系中指定一个观察坐标系,以该坐标系为参考通过选定方向和位置来制定矩形剪裁窗口。

    这里写图片描述

    要想建立观察坐标系,需要已知三个要素

    1. 观察点的位置
    2. 观察的方向
    3. 世界坐标系上的向量

    观察坐标系通常以视点的位置为原点,由视点的位置和观察的方向即可确定 Z 轴。确定与 X 轴垂直的平面,世界坐标系上的向量在该平面上的投影即为 Y 轴。由 Z 轴和 Y 轴,通过左手定则即可确定 X 轴。

    设备坐标系

    适合特定输出设备输出对象的坐标系,比如屏幕坐标系。

    在多数情况下,对于每一个具体的显示设备,都会有一个单独的坐标系统。注意:设备坐标是整数。

    规范化坐标系

    规范化坐标系独立于设备外,能很容易地转变为设备坐标系,是一个中键坐标系。

    为使图形软件能在不同的设备之间移植,采用规范化坐标,坐标轴取值范围是 0~1。

    这里写图片描述

    5.3 二维图形变换原理及齐次坐标

    图形变换

    图形变换的用途

    图形变换和观察是计算机图形学的基础内容之一,也是图形显示过程中不可缺少的一个环节。一个简单的图形,通过各种变化(如:比例、旋转、镜像、错切、平移等)可以形成一个丰富多彩的图形或图案。

    (1)由一个基本的图案,经过变换组合成另外一个复杂图形。

    这里写图片描述

    (2)用很少的物体组成一个场景

    这里写图片描述

    (3)可以通过图形变化组合得到动画效果

    在计算机动画中,经常有几个物体之间的相对运动,可以通过平移和旋转这些物体的局部坐标系得到这种动画效果。

    图形变化的基本原理

    可以看下面两个例子。

    这里写图片描述

    可以发现:

    1. 图形变化了,但原图形的连边规则没有改变
    2. 图形的变化,是因为顶点位置的改变决定的

    变换图形就是要变换图形的集合关系,即改变顶点的坐标,同时保持图形的原拓扑关系不变。

    仿射变换是一种二维坐标到二维坐标之间的线性变换。

    1. 平直性:直线经过变换之后依然是直线
    2. 平行性:平行线依然是平行线且直线上点的位置顺序不变

    下面介绍一个方程组,称为二维仿射变换

    这里写图片描述

    齐次坐标

    在二维平面内,我们用一对坐标值(x,y)来表示一个点在平面内的确切位置,或者说是用一个向量(x,y)来标定一个点的位置。

    假如变换前的点的坐标为(x,y),变换后的点坐标为(x*,y *),这个变换过程可以写成如下矩阵形式:

    这里写图片描述

    这种用三维向量表示二维向量,或者一般而言,用一个 n+1维的向量表示一个 n 维向量的方法称为齐次坐标表示法

    n 维向量的变换是在 n+1 维的空间进行的,变换后的 n 维结果是被反投回到特定维空间内而得到的。

    这里写图片描述

    为什么要采用齐次坐标

    在笛卡尔坐标系内,向量(x,y)是高于 z=0 平面上的点,而向量(x,y,1)是位于 z=1 的等高平面上的点。

    对于图形来说,没有实质性的差别,但是却给后面的矩阵运算提供了可行性和方便性。

    采用了齐次坐标表示法,就可以统一的把二维线性变换表示为如下所示的规格化形式:

    这里写图片描述

    对于一个图形,可以用顶点表来描述图形的几何关系,用连边表来描述图形的拓扑关系。所以对图形的变化,最后转变成,只是要变化图形的顶点表。

    5.4 二维图形几何变化

    图形的集合变化是指对图形的几何信息经过平移、比例、旋转等变换后产生新的图形。

    这里写图片描述

    平移变换

    平移是指将 P 点沿直线路径从一个坐标位置移到另一个坐标位置的重定位过程。

    这里写图片描述

    齐次坐标计算形式如下:

    这里写图片描述

    平移是一种不产生变形而移动物体的刚体变换,即物体上的每个点移动相同数量的坐标。

    比例变换

    这里写图片描述

    齐次坐标计算形式如下:

    这里写图片描述

    缩放系数Sx,Sy可赋予任何正整数。值小于1,则会缩小物体的尺寸。值大于1,则会放大物体。都指定为1,物体尺寸就不会改变。

    (1)Sx = Sy 比例
    这里写图片描述

    (2)Sx <> Sy 比例
    这里写图片描述

    当 Sx = Sy 时,比例变换成为整体比例变换,用以下矩阵进行计算:

    这里写图片描述

    整体比例变换时,若S>1,图形整体缩小,若0

    对称变换

    对称变换也称为反射变化或镜像变换,变换后的图形是原图形关于某一轴线或原点的镜像。

    这里写图片描述
    这里写图片描述

    关于x轴对称

    这里写图片描述

    关于y轴对称

    这里写图片描述

    旋转变换

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    错切变换

    在图形学的应用中,有时需要产生弹性物体的变形处理,这就要用到错切变换。

    这里写图片描述

    变换矩阵中的非对角线元素大都为0,若变换矩阵中的非对角元素不为0,则意味着 x,y 同时对图形的变换起作用。也就是说,变换矩阵中非对角线元素起着把图形沿 x 方向或 y 方向错切的作用。

    这里写图片描述

    x 值或 y 值越小,错切量越小。x 值或 y 值越大,错切量越大。其变换矩阵为:

    这里写图片描述

    沿x方向错切

    这里写图片描述

    复合变换

    复合变换是指图形做一次以上的几何变换,变换结果是每次的变换矩阵相乘。

    从另一方面看,任何一个复杂的几何变换都可以看做是基本几何变换的组合形式。

    二维复合平移变换

    P 点经过两次连续平移后,其变换矩阵可以写成:

    这里写图片描述

    二维复合比例变换

    P 点经过两个连续比例变换后,其变换矩阵可写成:

    这里写图片描述

    二维复合旋转变换

    P 点经过两个连续旋转变换后,其变换矩阵可写成:

    这里写图片描述

    坐标系之间的变换

    图形变换经常需要从一个坐标系变换到另外一个坐标系。

    这里写图片描述

    相对任意参考点的二维几何变换

    这里写图片描述

    二维变换矩阵

    这里写图片描述
    这里写图片描述

    二维图形几何变换的计算

    这里写图片描述

    点的变换

    这里写图片描述

    直线的变换

    直线的变换可以通过对直线两个端点进行变换,从而改变直线的位置和方向。

    这里写图片描述

    多边形的变化

    多边形变化是将变换矩阵作用到每个顶点的坐标位置并按新的顶点坐标值和当前属性设置来生成新的多边形。

    这里写图片描述

    5.5 窗口、视区及变化

    窗口和视区

    世界坐标系中药显示的区域称为窗口。

    窗口映射到显示器上的区域称为视区。

    这里写图片描述

    世界坐标系中的一个窗口可以对应于多个视区。

    这里写图片描述

    如何将窗口内的图形在视区中显示出来呢?必须经过将窗口到视区的变化处理,这种变换就是观察变换。

    观察变换

    将窗口到视区的变化处理,这种变换就是观察变换。

    变焦距效果

    这里写图片描述

    当窗口变小时,由于视区大小不变,就可以放大图形对象的某一部分,从而观察到在较大的窗口时未显示出的细节。

    整体缩放效果

    当窗口大小不变而视区大小发生变化时,得到整体缩放效果。这种缩放不改变观察对象的内容。

    这里写图片描述

    窗口到视区的变换

    为了全部且如实的在视区中显示出窗口内的图形对象,就必须求出图形在窗口和视区间的映射关系。

    需要根据用户所定义的参数,找到窗口和视区之间的坐标对应关系。

    这里写图片描述

    窗口到视区的映射是基于一个等式,即对每一个在世界坐标下的点(x,y),产生屏幕坐标系中的一个点(sx,sy)。

    这种映射是“保持比例”的映射。

    保持比例的性质使得这个映射有线性形式:

    这里写图片描述

    接下来通过证明,得到A、B、C、D的值。

    这里写图片描述
    这里写图片描述
    这里写图片描述

    5.6 二维图形变换小结

    主要讲解了向量的基本知识、坐标系的分类、齐次坐标、二维变换等、窗口与视区

    一、向量基本知识

    为了处理二维、三维图形,向量是很重要的一个分析计算工具。讲述了向量的定义、基本运算、线性组合、叉积、点积等。

    二、坐标系的分类

    坐标系是建立图形与数之间对应联系的参考系。在计算机图形学中,从物体(场景)的建模到在不同显示设备上显示,需要使用一系列不同的坐标系。

    1. 世界坐标系:是一个公共坐标系,是显示中物体或场景的统一参考系
    2. 局部坐标系:每个物体(对象)都有它自己的局部中心和坐标系
    3. 观察坐标系、设备坐标系、规格化坐标系

    三、二维图形几何变换
    图形变换和观察是计算机图形学的基础内容之一,也是图形显示过程中不可缺少的一个环节。

    1. 齐次坐标:用一个 n+1 维的向量来表示一个 n 维向量的方法
    2. 二维几何变换
      这里写图片描述
    3. 物体变换和坐标变换
      物体变换使用同一个规则改变物体上所有的点,但是保证底层坐标系不变。
      坐标变换按照原坐标系定义了一个全新的坐标系,然后在新坐标系下表示物体上所有的点。
    4. 复合坐标
      也称为组合变化。组合变换的变换矩阵是几个单独变换矩阵的乘积。由于矩阵乘法不满足交换律,因此在进行复合变换时,需要注意矩阵相乘的顺序

    四、窗口视区及变换

    1. 窗口:世界坐标系中要显示的区域
    2. 视区:窗口映射到显示器上的区域
    3. 窗口到视区的变换:为了全部且如实的在视区中显示出窗口内的图形对象,就必须求出图形在窗口和视区间的映射关系。
    展开全文
  • 在三空间表示平面和直线

    千次阅读 2022-02-03 00:53:31
    平面和直线是三计算机视觉和计算机图形学有用的几何实体。将它们表示为一组点是低效的,这会导致很大的内存需求,具体取决于用于生成点的步长。在本文,我将讨论如何使用向量方程表示平面和直线。...
  • 点击上方“3D视觉工坊”,选择“星标”干货第一时间送达今天分享的是:深度学习领域基于图像的三物体重建最新方法及未来趋势综述。原文:Image-based 3D Object Recon...
  • 二维数据曲线图1.1 绘制二维曲线的基本函数1.plot()函数2. 含多个输入参数的plot函数3. 含选项的plot函数4. 双纵坐标函数plotyy1.2 绘制图形的辅助操作1.图形标注2. 坐标控制1.3 绘制二维图形的其他函数1....
  • 随着地理空间信息服务产业的快速发展,地理空间数据的要求越来越高。对地理空间数据的要求正朝着大信息量、高精度、可视...、地面三激光扫描仪测量原理;三、三激光扫描系统分类;四、三激光扫描系统特点;五、
  • 二维图形变换原理及齐次坐标

    千次阅读 2018-10-09 16:52:00
    二维图形变换通过学习【向量分析】和【图形变换】,可以设计出一些方法来描述我们所遇见的各种几何对象,并学会如何把这些几何方法转换成数字。一、向量从几何角度看,向量是具有长度和方向的实体,但是没有位置。而...
  • 我们进一步将单镜头技术分为三大类:使用连续变化的结构光模式的技术、使用一维编码方案的技术(条带索引)和使用二维编码方案的技术(网格索引)。每种技术都有自己的优缺点,具体取决于具体的应用。 2. Sequential...
  • n数组是NumPy的核心概念,大部分数据的操作都是基于n数组完成的。本系列内容覆盖到1数组操作、2数组操作、3数组操作方法,本篇讲解Numpy与2数组操作——向量初始化、矩阵操作等。......
  • 清华山EPS次开发基础篇

    万次阅读 2017-06-22 21:22:43
     ...对于编码列表已经存在的地物,使用编码直接创建,则图层颜色等属性自动关联   CreateNewObjByCode( code) 参数 code 创建地物的编码 注1:对于含有破折号的地物编码,
  • 二维旋转  通过指定一个 旋转轴(rotation axis) 和一个 旋转角度(rotation angle) ,可以进行一次旋转(rotation)变换。在将对象的所有顶点按指定角度绕指定旋转轴旋转后,该对象的所有点都旋转到新位置。  一...
  • 游戏的三数学

    千次阅读 2015-08-31 09:45:29
    一、点和矢量 ...在三笛卡尔坐标系又分为左右手坐标系,用左右手来方便做记忆,大拇指指向X轴,食指指向Y轴,中指指向Z轴,3指垂直即可建立模型。左右坐标系的转换只需要把一个轴转换,保留另外两个轴的
  • OpenCV--Python 图像平滑之二维离散卷积

    千次阅读 多人点赞 2018-09-21 20:01:49
    每一幅图像都包含某种程度的噪声,噪声可以理解为由一...常用的平滑处理算法包括基于二维离散卷积的高斯平滑、均值平滑,基于统计学方法的中值平滑,具备保持边缘作用的平滑算法的双边滤波。 在介绍基于二维离散卷...
  • 第六章 [键入文字 ] 数据库 1数据库 DB数据库系统 DBMS三者间的关系是 B A. DB 包括 DBS和 DBMS B. DBS包括 DB 和 DBMS C. DBS就是 DB,也就是 DBMS D.... 域 3 一个关系就是一张二维表垂直方向上的称为属性
  • numpy和pandas数组的合并和拆分合并numpynumpy可以通过concatenate,指定参数axis=0 或者 axis=1,在纵轴和横轴上合并两个数组。import numpy as np import pandas as pd arr1=np.ones((3,5)) arr1 Out[5]: ...
  • MATLAB三曲线与曲面绘图

    千次阅读 2020-07-31 09:58:39
    曲线 plot3函数 plot3(x, y, z) 其中,参数x、y、z组成一组曲线的坐标。 若 x , y, z 是等长行向量,则根据向量的位置确定坐标, 如 (x1, y1, z1) x=[0.2, 1.8, 2.5]; y=[1.3, 2.8, 1.1]; z=[0.4, 1.2, 1.6]; ...
  • 在这篇文章,笔者将介绍一篇论文,论文提出了一种由法向量恢复深度的方法:论文为Surface-from-...数学上,由三表面生成的梯度场是可积的,但实际上,由于噪声导致不可积。以前的处理方法,有强制可积性约束
  • 本文依托于综述性文章,首先回顾了可解释性方法的主要分类以及可解释深度学习在医疗图像诊断领域应用的主要方法。然后,结合三篇文章具体分析了可解释深度学习模型在医疗图像分析的应用。 作为一种领先的...
  • 【物联网】矩阵式二维条码 介绍

    千次阅读 2017-08-11 15:33:07
    QR Code是由日本Denso公司于1994年9月研制的一种矩阵式二维条码,它除具有二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种信息、保密防伪性强等优点外,还具有以下特点: 超高速识读:QR Code码的超...
  • 第3章 二维绘图

    2020-03-22 19:36:40
    但plot函数的 X 和 Y 也可以是一般的二维数组,这时候就是对 X 和 Y 的对应画线。特别的,当 X 是一个向量, Y 是一个在某一方向和 X 具有相同长度的二维数组时,plot(X,Y)则是对 X 和 Y 的每一行(或)画...
  • 在本章中,我们考虑二维细胞自动机,特别是 John Conway 的生命游戏(GoL)。 像上一章的一些 CA 一样,GoL 遵循简单的规则并产生令人惊讶的复杂行为。 就像沃尔夫勒姆的规则 110 一样,事实证明 Go...
  • 在三个细胞的邻域,有 8 种可能的配置,因此规则表中有 8 个条目。由于每个条目都占一个位,我们可以使用 8 位指定一个。使用 8 位,我们可以指定 256 个不同的规则。 Wolfram 的第一个 CA 实验就是测试所有 ...
  • 浙江大学软件学院三维动画与交互技术考试概念整理第一讲1.增强现实技术AR:--融合了三维动画、立体视觉和图像处理;--建模、渲染、位置标定、图像融合...--在计算机屏幕上显示的二维图像,提供深度(或第三维)的错觉...
  • 第一讲1. 增强现实技术AR:--融合了三维动画、立体视觉和图像处理;--建模、渲染、位置标定、图像融合;...--在计算机屏幕上显示的二维图像,提供深度(或第三维)的错觉;2D+透视 = 3D透视使人产生深度的错觉。
  •  执行一般的二维空间变换包括如下三步: 1. 定义空间变换的参数; 2. 创建变换结构体TFORM,它定义了你所要执行变换的类型; TFORM结构体包含了执行变换需要的所有参数。你可以定义很多类型的空间变换,...
  • T矩阵一共有12个有效参数,然而我们只需要6个量来获取位姿,感觉很不划算,而且有些参数根本用不上。因此有两位大佬,D大佬和H大佬提出了DH法。写这部分的时候,我拿出了两本书Introduction to Robotics, ...
  • 数灾难问题及数据分析的降维方法一、数灾难(curse of dimentionality)降维的主要方法1. 投影(Projection)2. 流形学习、降维方法1. 什么是降维2. 为什么要降维3. PCA主成分分析(Principal components ...
  • MATLAB 的绘图:维和三

    千次阅读 2016-05-02 15:44:32
    plot 是绘制二维图形的最基本函数,它是针对向量或矩阵的来绘制曲线的。也就是 说,使用plot 函数之前,必须首先定义好曲线上每一点的x 及y 坐标,常用格式为: (1)plot(x) 当x 为一向量时,以x 元素的值为纵...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,433
精华内容 5,773
热门标签
关键字:

二维表中垂直方向的列