1. 图形学基本问题(15分)
在右手坐标系A内,P点的坐标是(1, 1, 1 ), M点坐标是(3, 4, 5), N点坐标是(6, 7, 8)
a) 求P点一M点为中心,绕Y轴旋转30°,再绕Z轴旋转-- 60°后的坐标点Q
b) 求P点以MN为轴,旋转—45°所获得的坐标点。
c) 假设B坐标系是有A坐标系经过如下步骤变换获得:
i. 绕X轴旋转α°
ii. 绕Z轴旋转β°
iii. 再平移
对于B坐标系内任意一点(x,y,z),求其在A坐标系内的坐标值表达式。
1.解答如下
a) 先把坐标系平移到M点,然后绕y,z轴旋转后再平移回去,矩阵左乘向量,公式如下:
平移到M点的平移矩阵:
绕y轴旋转30度
绕z轴旋转-60度
平移坐标系到原点
复合旋转矩阵
b) 讲一下方法,同时给出公式,
上图中,MN向量已知为(3, 3, 3)如果以M点为原点,MN为Z轴建立局部坐标系,则把P点变换到局部坐标系中,然后绕MN轴旋转,最后再变换到xyz坐标系中即可.
(1) 求局部坐标系如下:
向量MN的x分量为(1,0,0),可以用MG表示,向量ML=MN*MG,向量MK = ML*MN,*表示叉乘.
ML = MN*MG= =(0, 3, -3);
MK=ML*MN= =(18, -9, -9);
以向量MK,ML,MN为坐标轴,以M点为原点建立坐标系,用矩阵M表示
M
M表示一个坐标系,同时M表示一组线性无关的基向量,把M的三个列向量单位化,得到
(2)p点在 ,E中坐标系相互转换可以用线性相关和无关的概念推导:
p=(1, 1, 1)表示向量OP在E中的坐标, 表示向量OP在 中的坐标则
Ep=P;
=P;
由于 表示正交单位向量组,因此它逆等于它的转置
则 = * P= * Ep= * p;
而p= * ;
(3)先平移坐标到M点,然后把p点变换到局部坐标系中,在局部坐标系中绕MN旋转,然后再把p点变换到原坐标系中,再把把坐标系平移到原点即得到结果
复合矩阵如下:
复合矩阵如下:
R = * * * *T
c) 用线性相关及无关的概念推导,思想如下,每一次变换都形成一个新的坐标系,新的坐标系的三个分量可以用旧的坐标系线性表出,而表出系数就是旋转矩阵,或者平移矩阵。根据题意知道,表出系数如下
如果坐标系B就用矩阵B的三个列向量表示,则B=A* * *T;
则对于B坐标系内任意一点 (x,y,z),其向量用P表示,其在A坐标系内的坐标值p表达式推导入下:
Ap = P;
B =P;
因此Ap= B 得到p= *B= * A* * *T= * *T* 。
2. 图像处理基本问题(15分)
写一程序实现图像的简单缩放,假设RGB24格式的图像A的宽度是Wa,高度是Ha, 保存在char* 类型的Buffer内,写一个函数将其缩放为宽度是Wb,高度是Hb的图像。自行设计接口和代码实现。
2.解答如下
答:数字图像的变换分两步,第一步,空间变换,规定了图像像素的移动方式,与像素的存储方法有关,第二步,插值方法。决定了图像变换的精度。常用的有近邻取样法,双线性内插法,三次卷积法。为了简单其见,本文采用近邻取样法。
如果从源像素推导目标像素,则可能会出现一个像素对应多个像素,或者多个像素对应一个像素的问题,因此必需采用反向变换的办法,即从目标像素循环推导源像素。
所谓近邻取样法指的是,从目标像素推导源像素的时候,直接把推导的浮点数取整即可得到。
矩形Wb,Hb,缩放成Wa,Ha的缩放矩阵是
S = 其中 =Wa/Wb, =Ha/Hb;
颜色用连续一维数组存取,用一个工具类即可实现,如下c++语言实现
具体如下
//为了简单,要类采取取整的插值方法,所以图像的效果不够精确,如果要
//更加精确,可以采用双线性插值或者其它的方法,针对24位位图所以不考虑颜色表项
class CDibBitmap : public CObject
{
public:
CDibBitmap();
virtual ~CDibBitmap();
public:
void BitScale(float x, float y, int cy, CDC*pDC);//x ,y为缩放系数
};
CDibBitmap::CDibBitmap()
{
}
CDibBitmap::~CDibBitmap()
{
}
void CDibBitmap::BitScale(int Wa, int Ha, char *buffer, int Wb, int Hb, char *bufferDest)//
{
for (int i = 0; i < hb; i++)
{
for (int j = 0; j < wb; j++)
{
int wa = floor(Wa/Wb * j );
int hb = floor(Ha/Hb * i);//直接取整,用近邻法插值计算
*bufferDest++ = * (buffer + 3 *wa + hb) ;
*bufferDest++ = * (buffer + 3 *wa + hb + 1)
*bufferDest ++= * (buffer + 3 *wa + hb + 2)
}
}
}
3. 图像处理编程题
a) 用c++定一个Image类,包含一个图像基本必备的基本属性
b) 编写LoadImage的函数,读取一个BMP图像,要求根据BMP头定义通过分析文件头的方式自行获取正确的图像信息,不可使用现成的BMP读取函数。
c) 在界面内正确显示图像(Win32或者MFC均可)
d) 实现图像缩放算法,并显示缩放后的图像
3.解答如下
答:a)简单起见,只考虑24位位图,没有颜色表项。
b) 见源代码。
c) 直接用函数把图像从buffer读入并用函数在屏幕上扫描出来即可。主要考虑扫描行对齐。
d) 此处为了简单起见,只考虑取整,并不用复杂的插值算法。具体见代码。
读入bmp文件用视类里面的CCReadBitView::OnRead(),函数,文件名为da.bmp,同时缩