简述题(10分×4题,共40分)
计算题(共10分)
Bézier样条的计算表达
编程题(共30分)
好好做实验题,但没有书上和习题的原题
问答题(共20分)
第一章和第十章内容,考得宽泛,无需写具体知识点,但回答尽量多写字数
简述题或者最后的问答题
是研究怎样利用计算机表示、生成、处理和显示图形的原理、算法、方法和技术的一门学科(计算机图形学=造型+绘制)。
几何要素
刻画形状的点、线、面、体等。
非几何要素
反映物体表面属性和材质的灰度、颜色等。
方程x+y=1确定的图形由满足这个方程并具有一定颜色信息的点构成。
要具体展开说明分别是什么
用图形的形状参数和属性参数来表示图形。
形状参数
属性参数
参数法描述的图形叫做参数图或简称为图形。
通过列出图形中所有的点来表示图形。点阵法强调的是:
点阵法描述的图形叫做像素图或图像。
如何开发和利用图形输入设备及相关软件把图形输入到计算机中,以便进行各种处理。
包括对图形进行变换(如几何变换、投影变换)和运算(如图形的并、交、差运算)等处理。
如何将图形的特定表示形式转换成图形输出系统便于接受的表示形式,并将图形在显示器或打印机等输出设备上输出。
图形学、数字图像处理、相关学科之间的关系,分别研究什么,在相关学科中处于什么位置(1.1节)
此部分可能出问答题,囿于篇幅,此处不详细展开,详细内容请移步教材P2-P3
不会考具体的知识点,主要通过编程题体现
为第5章铺垫,不考
看明白程序片段,只需写核心OpenGL代码(注意顺序),不需要写矩阵的数学变换步骤,在编程题中考察
用T(tx,ty,tz)表示。
用S(sx,sy,sz)表示。
分别用Rx(θ)、Ry(θ)和Rz(θ)表示绕x轴、y轴和z轴的旋转。
表示绕旋转轴(0,0,0)—(x,y,z)旋转th角度。
已知P0={x0,y0,z0},P1={x1,y1,z1},旋转轴为P0P1,旋转角为θ。求该旋转变换的变换矩阵。
glTranslated(x0, y0, z0); // (5) 使旋转轴回到原来的位置
glMultMatrixd((const double[]){ // (4) 使旋转轴回到原来的方向
u1, u2, u3, 0,
v1, v2, v3, 0,
n1, n2, n3, 0,
0, 0, 0, 1
});
glRotated(th, 0, 0, 1); // (3) 绕坐标轴完成指定的旋转(th=θ)
glMultMatrixd((const double[]){ // (2) 使旋转轴与某坐标轴重合
u1, v1, n1, 0,
u2, v2, n2, 0,
u3, v3, n3, 0,
0, 0, 0, 1
});
glTranslated(-x0, -y0, -z0); // (1) 使旋转轴通过坐标原点
已知反射轴为P0P1,P0={x0,y0,z0},P1={x1,y1,z1}。求该反射变换的变换矩阵。
glTranslated(x0, y0, z0); // (5) 使反射轴回到原来的位置
glMultMatrixd((const double[]){ // (4) 使反射轴回到原来的方向
u1, u2, u3, 0,
v1, v2, v3, 0,
n1, n2, n3, 0,
0, 0, 0, 1
});
glScaled(-1, -1, 1); // (3) 关于坐标轴完成指定的反射(关于Z轴反射)
glMultMatrixd((const double[]){ // (2) 使反射轴与某坐标轴重合(Z轴)
u1, v1, n1, 0,
u2, v2, n2, 0,
u3, v3, n3, 0,
0, 0, 0, 1
});
glTranslated(-x0, -y0, -z0); // (1) 使反射轴通过坐标原点
已知反射面的方程为ax+by+cz+d=0 ,且点(x0,y0,z0)在反射面上。求该反射变换的变换矩阵。
glTranslated(x0, y0, z0); // (5) 使反射面回到原来的位置
glMultMatrixd((const double[]){ // (4) 使反射面回到原来的方向
u1, u2, u3, 0,
v1, v2, v3, 0,
n1, n2, n3, 0,
0, 0, 0, 1
});
glScaled(1, 1, -1); // (3) 关于坐标平面完成指定的反射(XY平面)
glMultMatrixd((const double[]){ // (2) 使反射面与某坐标平面重合(XY平面)
u1, v1, n1, 0,
u2, v2, n2, 0,
u3, v3, n3, 0,
0, 0, 0, 1
});
glTranslated(-x0, -y0, -z0); // (1) 使反射面通过坐标原点
基础概念和理解。没有详细说怎么考,也没有往年试题参考,只能自己猜了
从模型坐标系到世界坐标系的变换。
3D建模之初,模型有自己的坐标系,以及相应的点坐标。如果放到一个世界坐标系中,需要将它自身的坐标点全部移动到给定位置。
首先构造从世界坐标系到模型坐标系的变换,然后计算该变换的逆变换。(M = (RT)-1 = T-1R-1)
世界坐标系→观察坐标系
观察坐标系→投影坐标系
将三维场景投影到二维平面上。
投影坐标系→规范化坐标系
将坐标值缩放到一定的范围,比如[-1, 1]或[0, 1]。
规范化坐标系→屏幕/设备坐标系
将规范化坐标映射到屏幕或设备坐标系,通常包括缩放和平移等操作,以适应实际显示设备的尺寸和位置。
可见面判别算法/隐藏面消除算法用于判断场景中各个面片的可见性
物空间算法
将场景中各物体和各组成部分相互进行比较,以判别哪些面可见。例如后向面判别算法。
像空间算法
在投影平面上逐点判断各像素对应的可见面。例如深度缓冲器算法。
光照模型(也称明暗模型)
用于物体表面某点处的光强度计算。
面绘制算法(也称渲染算法)
通过光照模型中的光强度计算,确定场景中物体表面所有投影像素点的光强度。
计算题
问答题。此章老师说结合课程PPT和另外发的补充PPT复习,没有给出明确考点,因此将一些基本知识点整合至此。
数字图像
凡是记录在纸上,拍摄在照片上,显示在屏幕上的所有具有视觉效果的画面都可以称为图像。
图像的灰度信息是指图像中各点处的颜色深浅程度信息(也就是明暗程度信息或亮度信息)。
视觉特点
图像记录方式
模拟图像
通过某种物理量(光、电)的强弱变化来记录图像上各点的灰度信息(如模拟相机和模拟电视等)。
数字图像
用数值记录图像的灰度信息。数字图像比模拟图像更容易保存,不会因为保存时间过长而失真。
黑白图像/二值图像
指图像的每个像素只能是黑或者白,没有中间的过渡。二值图像的像素值为0、1。
灰度图像
指各像素信息由一个量化的灰度级来描述的图像,没有彩色信息。灰度取值范围为[0(黑)~255(白)]。
索引图像/映射图像
包括存放图像数据的二维矩阵和颜色索引矩阵(MAP)。
彩色图像
指每个像素的信息由RGB三原色构成的图像,其中R、G、B是由不同的灰度级来描述的。
利用计算机对图像进行去除噪声、 增强、 复原、分割、提取特征等的理论、方法和技术
数字图像处理(Digital Image Processing)通常是用计算机和实时硬件实现的,因此也称之为计算机图像处理(Computer Image Processing)。
航空和航天领域
生物和医学领域
军事和公安领域
工业和工程领域
通信领域
电子商务与文化艺术领域
数字图像在计算机上是以位图形式存在的。位图是一个矩形点阵,每一个点都称为一个像素。像素是数字图像中的基本单位。一幅W×H大小的图像,是由W×H个明暗不等的像素组成的。
基于调色板的BMP文件由文件头、信息头、调色板和图像的像素数据四个部分组成,而真彩色的BMP文件则由文件头、信息头和图像的BGR像素数据组成。
不会考具体的知识点,基本函数要会写,会考核心代码,主要通过编程题体现
这章老师说不明确考,也没有明确考点,因此根据基本概念和平时作业补充资料,仅供参考。
对图像的像素位置或像素值进行的某种变换。
对像素位置的变换。
逐一计算每个像素的新位置,用于改变像素的位置、图像的大小和形状等,通常使用图像的仿射变换和透视变换实现。
对单一像素值的变换。
每个新像素值都通过对应的单一源像素值获得,通常使用图像的线性变换实现。
对像素块的变换。
每个新像素值都通过对应的源像素块获得,通常使用图像的空域滤波和频域滤波等变换实现。
空域与空域的转换
常见的是颜色空间转换,使用线性变换实现。
空域与频域的转换
通常使用离散傅立叶变换或离散余弦变换等方法实现。
1、计算对下列实数矩阵进行傅立叶正变换后的变换结果(不缩放结果)。
2、计算对下列实数矩阵进行傅立叶逆变换后的变换结果(缩放结果,i为虚数单位)。
此题给出个人答案,仅供参考,如有错误请联系指正(确信)
简答题
图像增强是图像处理的基础,它是对图像施加的某种数学变换,其目的通常是为了除去图像中的噪音,强调或抽取图像的轮廓特征等。
指在图像生成、保存和传递过程中由外部干扰在图像中加入的冗余信息。
例如,电视画面上常见的雪花点就是一种典型的噪音。
平滑处理是一种简单且使用频率很高的图像处理方法,是除去图像中点状噪音的一个有效方法。
平滑化是指使图像上任何一个像素与其相邻像素的灰度值的大小不会出现陡变的一种处理方法。
这种处理会使得图像变模糊,所以图像的平滑化也称为图像的模糊化。
概念,编程题
特点是模板系数之和为1。模板系数全相同的归一化块滤波器称为均值模糊器或简单模糊器,是最简单的滤波器。
最常用
高斯滤波器是一种通过指定参数计算模板系数的归一化块滤波器,是最有用的滤波器(尽管不是最快的)。
不光简答题可能出,编程题也可能体现
中值滤波是一种非线性处理技术,可用来抑制图像中的噪音,而且保持轮廓的清晰。中值滤波使用当前像素近旁nx×ny个像素的灰度值的中值(不是平均值)作为当前像素的新灰度值。
中值滤波具有不损失有效信息的优点。
掌握函数,编程题
【函数原型】
void?blur(InputArray?src,?OutputArray?dst,?Size?ksize);
【参数】
【函数原型】void?median(BlurInputArray?src,?OutputArray?dst,?int?ksize);
【参数】
【函数原型】void?GaussianBlur(InputArray?src,OutputArray?dst,Size?ksize,?double?sigmaX,?double?sigmaY=0);
【参数】
【说明】如果sigmaY=0,则使用sigmaY=sigmaX。如果标准差都是0,则使用公式σ=0.3(0.5n-1)+0.8由内核尺寸计算标准差。
对一幅含有噪音的灰度图像进行简单模糊、中值模糊和高斯模糊:
#include<opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat X = imread("lena-n.jpg", 0); // 含噪声的灰度图像
if(X.empty())
return -1;
imshow("源图像", X);
Mat Y; // 结果图像
blur(X, Y, {5, 5}); // 简单模糊
imshow("简单模糊", Y);
medianBlur(X, Y, 5);// 中值模糊
imshow("中值模糊", Y);
GaussianBlur(X, Y, {5, 5}, 0, 0); // 高斯模糊, 标准差都是0
imshow("高斯模糊", Y);
waitKey();
}
概念,简述题
是突出图像中的细节或者增强被模糊化了的细节,一般情况下图像的锐化被用于景物边界的检测与提取,把景物的结构轮廓清晰地表现出来。
使用锐化方法处理后的图像,轮廓线条将明显得到增强。轮廓线以外的部分将变得较暗,而轮廓线部分将变得比较明亮。
有时需要在图像中抽出某一特定方向的轮廓线,这时可以使用方向模板来达到这一目的。根据所需的方向,可从下列8种模板中选取合适的模板。
简答题
概念、操作、功能、效果
此外还有3种高级形态学操作(形态学梯度、顶帽、黑帽)可以根据情况看教材了解。
编程题可能会用到
对低通滤波器来说,H(u,v)应该对高频成分有衰减作用而又不影响低频分量。通常使用低通滤波器实现图像平滑,滤除噪音。
过滤了高频成分,高频成分的滤除使图像变模糊,但过滤后的图像往往含有“抖动”或“振铃”现象。
“振铃”:指输出图像的灰度剧烈变化处产生的震荡,就好像钟被敲击后产生的空气震荡。
与理想低通滤波器相比,经ButterWorth低通滤波器处理的图像模糊程度会大大减少,并且过滤后的图像没有“抖动”或“振铃”现象。
平滑效果与ButterWorth低通滤波器大致相同。
高通频域滤波是加强高频成分的方法,它使高频成分相对突出,低频成分相对抑制,从而实现图像锐化。常用于提升图像的边缘和轮廓等特征。
理想高通滤波器只保留了高频成分。
与理想高通滤波器相比,经ButterWorth高通滤波器处理的图像会更平滑。
指数高通滤波器的锐化效果与ButterWorth高通滤波器大致相同。
(1)使用ButterWorth低通滤波对一幅含噪音的灰度图像进行平滑操作
#include "cvv.hpp"
using namespace cv;
int main() {
Mat X = imread("lena-n.jpg", 0); // 含噪声的灰度图像
if(X.empty())
return -1;
imshow("源图像", X);
filter_dft(X, X, 25, BUTTER_L); // ButterWorth低通滤波
normalize(X, X, 255, 0, NORM_INF); // 增大亮度以便于观察
imshow("结果图像", X);
waitKey();
}
(2)使用ButterWorth高通滤波对一幅灰度图像进行锐化操作
#include "cvv.hpp"
using namespace cv;
int main() {
Mat X = imread("lena.jpg", 0); // 灰度图像
if(X.empty())
return -1;
imshow("源图像", X);
filter_dft(X, X, 60, BUTTER_H); // ButterWorth高通滤波
normalize(X, X, 255, 0, NORM_INF); // 增大亮度以便于观察
imshow("高通滤波", X);
waitKey();
}
了解直方图的计算和作用并用程序表达
假设有一幅4×4的8灰度级图像,图像数据及其灰度直方图分别如左图和右图所示:
根据图像数据,灰度值为0, 1, 2, 3, 4, 5, 6, 7的像素的频度分别是1, 2, 6, 2, 3, 1, 0, 1,因此在灰度刻度的0~7处分别作一条以该灰度值对应的频度值为长度的直线即可完成该图像的灰度直方图。
假设有一个矩阵包含一张图像的灰度值(如左图所示):
灰度值的范围包含256个值,可以将这个范围均匀分割成若干子区域,如8个均匀子区域,即[0,256)=[0,32)∪[32,64)∪…∪[224,256)。
将灰度值范围均匀分割成若干子区域以后,统计灰度值属于每一个子区域的像素数目。
采用这一方法来统计上面的数字矩阵,可以得到如右图所示的直方图(x轴表示子区域,y轴表示属于各个子区域的像素个数)。
// 计算一个单通道图像的直方图(源图像, 直方图, 大小, 范围)
void MyCalcHist(Mat image, Mat &hist, int size, vector<float> range) {
float a = range[0], b = range[1]; // 下界, 上界
if(b < a)
swap(a, b);
Mat1f H(1, size, 0.0); // 直方图初始值为0
for(auto v : Mat1f(image)) {
int i = (v - a) * size / (b - a); // 当前像素所在子区域
++H(i); // 相应子区域的像素数目增加1
}
hist = H; // 记录结果
}
此部分为老师提到的编程题可能涉及的基础部分知识,定位为教材第2、3、11、12章,具体掌握情况以大致可以完成课程实验为标准即可,故在此进行大致整理,所涉及的知识点不一定覆盖所有实际所需内容,因此具体复习参考教材和课程实验,以及涉及编程题考点的示例代码即可。
一组功能相同或相近的函数的函数名使用不同的后缀以支持不同的数据类型和格式,如glEvalCoord2f()、glEvalCoord2d()和glEvalCoord2dv()等,其中2表示有2个参数,f、d分别表示参数的类型是GLfloat和GLdouble,v表示参数以向量形式出现。
OpenGL定义了一些特殊的类型名,如GLint和GLfloat。其实就是32位C语言中的float和int等类型。
// Frame.c
#include <GL/freeglut.h>
void init() {
/* 全局初始化。主要用于设置一些全局的状态,
如颜色模式、窗口的初始位置和大小等。
使用默认值时不需要定义该函数。
*/
}
void init2() {
/* 当前窗口初始化。主要用于设置一些与当前窗口关联的状态或开关,
如光照处理、光源特性、深度检测和裁剪等。
使用默认值时不需要定义该函数。
*/
}
void Reshape(int w, int h) {
/* 设置投影方式和观察体。主要使用
glViewport()、glOrtho()、glFrustum()、gluPerspective()和gluOrtho2D()等。
使用默认值时不需要定义该函数。
*/
}
void Paint() {
/* 使用OpenGL库函数构造对象的数学描述,
包括点线面的位置、几何变换和光照处理等,是OpenGL的主要部分。
*/
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv); // 初始化GLUT, 记录main()的参数
init(); // 全局初始化, 使用默认值时不是必需的
glutCreateWindow("窗口标题"); // 创建程序窗口,指定窗口标题
init2(); // 当前窗口初始化, 使用默认值时不是必需的
// 注册回调函数
glutDisplayFunc(Paint); // 指定场景绘制函数,必需
glutReshapeFunc(Reshape); // 指定窗口变化回调函数,缺省则使用默认值
glutMainLoop(); // 开始循环执行OpenGL命令
}
① glFlush()
② glFinish()
【函数原型】void?glBegin(GLenum?mode);
【功能】表示一个基本图元定义的开始。
【参数】mode可选下列符号常量。
【函数原型】void?glEnd(void);
【功能】表示一个基本图元定义的结束。
预定义的几何形体详见教材。
#include <gl/freeglut.h>
void Viewport(int x, int y, // 视口左下角在程序窗口中的坐标
int w, int h) { // 视口的宽和高
glViewport(x, y, w, h); // 定义视口
glLoadIdentity(); // 消除其他视口的影响, 函数介绍见后续章节
}
void Paint(){
int w = glutGet(GLUT_WINDOW_WIDTH) / 2; // 计算视区宽度
int h = glutGet(GLUT_WINDOW_HEIGHT) / 2; // 计算视区高度
glClearColor(1, 1, 1, 1); // 白色背景
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓存
Viewport(0, 0, w, h); // 左下方视口
glColor3f(1, 0.8, 0.6); // 设置当前颜色, 茶色
glRectf(-0.8, -0.8, 0.8, 0.8); // 定义正方形(左下角,右上角坐标)
Viewport(w, 0, w, h); // 右下方视口
glColor3f(0, 1, 0); // 设置当前颜色, 绿色
glutSolidTeapot(0.6); // 定义犹他茶壶
Viewport(0, h, w, h); // 左上方视口
glColor3f(0, 0, 1); // 设置当前颜色, 蓝色
glRotatef(45, 1, 1, 0); // 调整立方体方向, 函数介绍见后续章节
glutWireCube(1); // 线框立方体, 边长为1
Viewport(w, h, w, h); // 右上方视口
glColor3f(1, 0, 1); // 设置当前颜色, 紫色
glRotatef(-90, 1, 0, 0); // 调整两极方向, 函数介绍见后续章节
glutWireSphere(0.8, 24, 12); // 线框球体, 半径, 经线数, 纬线数
glFlush(); // 强制OpenGL命令序列在有限的时间内完成执行
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv); // 初始化GLUT, 记录main()的参数
glutCreateWindow("四个预定义几何形体"); // 指定窗口标题
glutDisplayFunc(Paint); // 指定场景绘制函数
glutMainLoop(); // 开始执行
}
使用()运算。
// 在源图像中选取一个矩形子集,并将该矩形子集乘以0.75,然后显示图像
#include<opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat im = imread("lena.jpg"); // 载入彩色图像
if(im.empty())
return -1; // 载入失败
Mat roi = im({ 125, 125, 100, 50 }); // 选取矩形子集
roi *= 0.75; // 降低选取区域亮度
imshow("SubMat", im); // 显示图像
waitKey();
}