作业描述

Bézier 曲线是一种用于计算机图形学的参数曲线。在本次作业中,你需要实现 de Casteljau 算法来绘制由 4 个控制点表示的 Bézier 曲线 (当你正确实现该算法时,你可以支持绘制由更多点来控制的 Bézier 曲线)。你需要修改的函数在提供的 main.cpp 文件中。

• bezier:该函数实现绘制 Bézier 曲线的功能。它使用一个控制点序列和一个OpenCV::Mat对象作为输入,没有返回值。它会使 t 在 0 到 1 的范围内进行迭代,并在每次迭代中使 t 增加一个微小值。对于每个需要计算的 t,将调用另一个函数 recursive_bezier,然后该函数将返回在 Bézier 曲线上 t处的点。最后,将返回的点绘制在 OpenCV ::Mat 对象上。
• recursive_bezier:该函数使用一个控制点序列和一个浮点数 t 作为输入,实现 de Casteljau 算法来返回 Bézier 曲线上对应点的坐标

De Casteljau 算法说明如下:

  1. 考虑一个 p0, p1, … pn 为控制点序列的 Bézier 曲线。首先,将相邻的点连接起来以形成线段。
  2. 用 t : (1 − t) 的比例细分每个线段,并找到该分割点。
  3. 得到的分割点作为新的控制点序列,新序列的长度会减少一。
  4. 如果序列只包含一个点,则返回该点并终止。否则,使用新的控制点序列并转到步骤 1。使用 [0,1] 中的多个不同的 t 来执行上述算法,你就能得到相应的 Bézier 曲线

bezier

由作业描述中可得,整个De Casteljau算法就是由n个点算出n-1个点,然后不断递归到只剩一个点时即为所求,所以为方便,这里我使用了两个容器points1, points2来记录每次求得的点,用flag来区分每次应该用哪个容器来算。

void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window)
{// TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's // recursive Bezier algorithm.int size = control_points.size();std::vector<cv::Point2f> points1 = control_points, points2;bool flag = true, bflag;for (double t = 0.0; t <= 1.0; t += 0.001) {bflag = false;while(!bflag){if(flag)bflag = recursive_bezier(control_points, points1, points2, t, window);elsebflag = recursive_bezier(control_points, points2, points1, t, window);flag = !flag;}}
}

recursive_bezier

这里我对 recursive_bezier函数做了一点修改,增加了一些参数以方便将点画在屏幕上,同时也将返回类型设置成了bool,方便在bezier中进行结束的判断(若返回true,则证明只剩一个点了,bezier中就结束了一个t点的运算)

bool recursive_bezier(const std::vector<cv::Point2f> &control_points, std::vector<cv::Point2f> &points1, std::vector<cv::Point2f> &points2, float t, cv::Mat &window){int size;size = points1.size();if(size == 1){window.at<cv::Vec3b>(points1[0].y, points1[0].x)[1] = 255;//设置该点的绿通道为255points2 = control_points;points1.clear();//结束计算后记得初始化容器return true;}for(int i = 0; i < size - 1; i++)points2.push_back((1 - t) * points1[i] + t * points1[i + 1]);points1.clear();return false;
}

效果

只用bezier:

naive_bezier和bezier一起用:

发现画出的曲线颜色为黄色,说明计算结果一致,算法无误

同时还可以尝试八个控制点的效果:

提高

要求:实现对 Bézier 曲线的反走样。(对于一个曲线上的点,不只把它对应于一个像素,你需要根据到像素中心的距离来考虑与它相邻的像素的颜色。)

根据要求中的提示,每得到一个曲线上的点时,我们就根据它到自己周围的3×3个像素中心的距离d来为这些像素填色以达到平滑过渡的效果(每个像素的颜色是255*ratio,d的范围是[0,3/√2],ratio的范围是[0,1],那么ratio关于d的函数就是ratio=1-√2/3d),重复计算的点就按照该点的颜色最大值算,这样就不会在线段中间出现暗点了,按道理这样应该就能达成反走样的要求:

bool recursive_bezier(const std::vector<cv::Point2f> &control_points, std::vector<cv::Point2f> &points1, std::vector<cv::Point2f> &points2, float t, cv::Mat &window){int size;size = points1.size();double ratio = 1;if(size == 1){for(int i = -1; i <= 1; i++){for(int j = -1; j <= 1; j++){//遍历9个像素if(points1[0].y + j > 700 || points1[0].y + j < 0 || points1[0].x + i > 700 || points1[0].x + i < 0)//不处理越界像素continue;ratio = 1 - sqrt(2)*sqrt(pow(points1[0].y - int(points1[0].y + j) - 0.5, 2) + pow(points1[0].x - int(points1[0].x + i) - 0.5, 2)) / 3;//计算ratiowindow.at<cv::Vec3b>(points1[0].y + j, points1[0].x + i)[1] = std::fmax(window.at<cv::Vec3b>(points1[0].y + j, points1[0].x + i)[1], 255 * ratio);//计算像素颜色}}points2 = control_points;points1.clear();return true;}for(int i = 0; i < size - 1; i++)points2.push_back((1 - t) * points1[i] + t * points1[i + 1]);points1.clear();return false;
}

反走样前:

反走样后:

可以看到,曲线的锯齿效果的确被优化了许多

附件

附上源代码,有兴趣的朋友可以自己尝试一下效果:
CSDN:【GAMES101】作业4(提高)
GITHUB:【GAMES101】作业合集

【GAMES101】作业4(提高)含Bazier曲线的反走样处理相关推荐

  1. [の白嫖站]计算机图形学作业 瞎写的 区域填充字符生成反走样

    [奶妈の白嫖站]计算机图形学作业 瞎写的 区域填充字符生成反走样 奶妈の白嫖站 16_01第七题.docx 瞎写的答案 16_02都是一题 瞎写的答案

  2. GAMES101作业7提高-实现微表面模型你需要了解的知识

    目录 微表面材质模型 微平面理论 Microfacet Theory BSDF(浅浅的提一下) 微表面BRDF的实现 Cook-Torrance BRDF 漫反射的BRDF 镜面反射的BRDF 1 法 ...

  3. Games101 作业6 提高内容(SAH算法)

    本文只应用于个人学习总结. 目录 一.模型分析 1.按空间平均分配(NAIVE) 2.按物体平均分配 二.SAH 1.原理分析 2.代码实现 在作业7​​​​​​中的BVHAccel模块中已经分析了B ...

  4. GAMES101-现代计算机图形学-闫令琪 作业2 反走样 antialiasing 抗锯齿

    文章目录 简介 MSAA问题 1.黑边情况1 2.黑边情况2 3.灰边情况 SSAA 总结 MSAA SSAA 最后 参考 简介 本文章主要内容为作业二的最后一个题目:反走样的处理.本文使用了两种反走 ...

  5. 【GAMES101 作业4】贝塞尔曲线+反走样

    一.样例函数naive_bezier解读 函数名为"简单贝塞尔曲线". 传入的参数有2,其中: const std::vector<cv::Point2f> & ...

  6. games101 作业4

    games101 作业4 任务说明 Bézier 曲线是一种用于计算机图形学的参数曲线.在本次作业中,你需要实现 de Casteljau 算法来绘制由 4 个控制点表示的 Bézier 曲线 (当你 ...

  7. GAMES101作业7-路径追踪实现过程代码框架超全解读

    目录 Path Tracing算法过程讨论 蒙特卡洛积分 直接光照 direct illumination 间接光照 indirect illumination ​编辑 合成全局光照 解决一些存在的问 ...

  8. 西安交通大学17年9月课程考试计算机应用基础,西安交通大学17年9月课程考试《计算机应用基础》作业考核试题 (含主观题)...

    奥鹏17春西交在线作业参考答案 西安交通大学17年9月课程考试<计算机应用基础>作业考核试题(含主观题) 一.单选题 1.B 2.D 3.B 4.A 5.A 一.单选题 一.单选题(共 2 ...

  9. GAMES101作业5-从头到尾理解代码Whitted光线追踪

    目录 Whitted Ray-Tracing Whitted光线追踪 What Why How 1 发射主射线primary ray 实现步骤 (1)定义相机 (2)计算primary主射线的方向 R ...

  10. 计算机图形学学习笔记——Whitted-Style Ray Tracing(GAMES101作业5讲解)

    计算机图形学学习笔记--Whitted-Style Ray Tracing GAMES101作业5讲解 遍历所有的像素生成光线 光线与平面求交 遍历所有的像素生成光线 关于作业五中如何遍历所有的像素, ...

最新文章

  1. Java集合中的排序API分析
  2. MongoDB中如何优雅地删除大量数据
  3. 虚幻四如何实现第一人称_虚幻周报20200930 | 双节快乐么么哒!
  4. invalid currency could not be saved in AG3
  5. 【推荐实践】“全能选手”召回表征算法实践.pdf(附下载链接)
  6. 技术总监谈好的程序员如何写代码[转]
  7. % 取余运算 取模运算
  8. python程序设计期末作业_Python高级应用程序设计任务期末作业
  9. html登陆滑动验证,js实现滑动滑块验证登录的方法
  10. 股票自动交易软件API使用流程
  11. 简明python教程 答案1
  12. java中raiseSalary_用Java编写常用的工资管理系统,目的是把每个人的工资上涨百分之五...
  13. 华氏温度与摄氏温度转换 java_用JAVA写一个将华氏温度转换成摄氏温度的程序
  14. CISCO 6509 三层交换机配置
  15. Concatenated Multiples(思维,数学)
  16. WHERE语句中BETWEEN与IN的使用教程-MySQL
  17. 设计模式之模板模式和工厂模式
  18. IDL批量计算栅格数据平均值
  19. 【面试】面试反问环节
  20. 【PS】Adobe Photoshop 2020中扣名字

热门文章

  1. 方舟同步服务器信息,方舟服务器备份和数据库备份
  2. 心理测试单机小软件,十个有趣的心理小测试 好玩的心理测试题
  3. 车牌识别相机4G、WiFi联网功能
  4. 车牌识别技术应用场景
  5. PyG搭建GCN实现节点分类(GCNConv参数详解)
  6. CyanogenMod - All the source code for CyanogenMod
  7. Vue中Class和Style几种v-bind绑定的用法-详解案例
  8. HDC1080 驱动程序代码(C语言版)
  9. 用计算机怎么刷试听量,QQ音乐怎么刷播放次数,快速增加播放量
  10. DetectoRS: Detecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution