GAMES101-Assignment4

一、问题总览

实现de Casteljau算法来绘制由4个控制点表示的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曲线上对应点的坐标。

二、参考答案

2.1 算法思想

De Casteljau 算法说明如下:

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

使用[0,1] 中的多个不同的t来执行上述算法

  • 例子如下
    在这里插入图片描述

    • b 0 b_0 b0, b 1 b_1 b1, b 2 b_2 b2为三个参考点;
      • b 0 b 1 b_0b_1 b0b1 上找一点 b 0 1 b_0^1 b01,使得 b 0 b 0 1 b_0b_0^1 b0b01 : b 0 1 b 1 b_0^1b_1 b01b1 = t : (1 - t)
      • b 1 1 b_1^1 b11 同理
    • b 0 1 b_0^1 b01 b 1 1 b_1^1 b11 作为新的参考点,找点 b 0 2 b_0^2 b02,使比例关系满足t : (1 - t)
    • b 0 2 b_0^2 b02 就是贝塞尔曲线上的一点,使用[0,1] 中的多个不同的t来执行上述算法

2.2 代码实现

2.2.1 Bezier函数的实现

  • t=0 -> t=1, 调用de Casteljau算法
//cv::Mat &window:表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数,RGB三通道,cv::Vec3b)
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.
    for(double t = 0.0; t < 1.0; t += 0.001){
        cv::Point2f point = recursive_bezier(control_points, t);
        // 绘制坐标(point.y, point.x)的颜色为绿色,[1]表示RGB中的G
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
    }
}

2.2.2 Recursive_bezier函数的实现

  • 实现de Casteljau 算法来返回Bézier曲线上对应点的坐标
//cv::Point2f  float类型的二维点坐标
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{
    // TODO: Implement de Casteljau's algorithm
    if(control_points.size() == 1) return control_points[0];
    std::vector<cv::Point2f> next_layer_control_points;
    for(int i = 0; i < control_points.size() - 1; i++){
        cv::Point2f p0 = control_points[i];
        cv::Point2f p1 = control_points[i+1];
        cv::Point2f p2 = p0 + t * (p1 - p0);
        next_layer_control_points.push_back(p2);
    }
    return recursive_bezier(next_layer_control_points, t);
}

2.2.3 实现对贝塞尔曲线的反走样(奖励分数)

  • 对于一个曲线上的点,不只把它对应于一个像
    素,需要根据到像素中心的距离来考虑与它相邻的像素的颜色
    在这里插入图片描述

    • P是贝塞尔曲线上t对应的一点,P0是周围四个像素区域的交点,像素框的中心点为其余四个黑点
    • 像素外框都是处于window矩阵整数部分(默认一个window单元格为一个像素),所以p所在的像素框的较近一竖边为min(floor(p.x), ceil(p.x)),横边min(floor(p.y), ceil(p.y))
      • 计算出p0坐标( min(floor(p.x), ceil(p.x)),min(floor(p.y), ceil(p.y)) )
    • 由于像素框大小为1 * 1,所以知道P0之后可以计算出周围四个像素中心点坐标
    • 根据像素中心点到P点的距离来分配颜色
      • 比如距离p点距离为dist,则该点所在像素的G通道 = 255 * (3 - dist)/3
        • 使用的是哈夫曼距离,p离像素中心点最大哈夫曼距离为3
double get_dist(cv::Point2f point1, cv::Point2f point2){//计算两点的哈夫曼距离
    return fabs(point1.x - point2.x) + fabs(point1.y - point2.y);
}

//cv::Mat &window:表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数,RGB三通道,cv::Vec3b)
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.
    for(double t = 0.0; t < 1.0; t += 0.001){
        cv::Point2f point = recursive_bezier(control_points, t);
        cv::Point2f point0( std::min(floor(point.x), ceil(point.x)), std::min(floor(point.y), ceil(point.y)) );
        double dist;
        std::vector<double> bias{0.5, -0.5};
        for(int i = 0; i < 4; i++){
            cv::Point2f centerPoint(point0.x + bias[i % 2], point0.y + bias[i % 2]);//计算中心点
            dist = get_dist(point, centerPoint);
            window.at<cv::Vec3b>(centerPoint.y, centerPoint.x)[1] = 255 * (3 - dist) / 3;
        } 
    }
}

三、编译

如往常一样

$ mkdir build
$ cd build
$ cmake ..
$ make


$ ./BezierCurve  

通过点击屏幕来设置控制点


附件

作业4连接

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)

YOLOv5改进点 2022.10.30 复现TPH-YOLOv5 2022.10.31 完成替换backbone为Ghostnet 2022.11.02 完成替换backbone为Shufflenetv2 2022.11.05 完成替换backbone为Mobilenetv3Small 2022.11.10 完成EagleEye对YOLOv5系列剪枝支持 2022.11.14 完成MQBench对YOLOv5系列量化支持…

Qt之基本数据类型

Qt 基本数据类型定义在#include <QtGlobal>中&#xff0c;如表下表所示。 (1)打开Qt Creator&#xff0c;新建一个控制台项目&#xff0c;项目名为test。 (2)在 main.cpp 中输入如下代码: #include <QCoreApplication> #include <QtGlobal> int main(int…

《数据结构、算法与应用C++语言描述》-红黑树的C++实现-百万级数据量测试通过

红黑树 完整可编译运行代码见仓库&#xff1a;GitHub - Jasmine-up/Data-Structures-Algorithms-and-Applications/_3matrix。 如有问题请在评论区指出。另外&#xff0c;Github仓库会根据我的学习情况持续更新&#xff0c;欢迎大家点star&#xff0c;谢谢。 基本概念 红-黑…

实验笔记之——服务器链接

最近需要做NeRF相关的开发,需要用到GPU,本博文记录本人配置服务器远程链接的过程,本博文仅供本人学习记录用~ 连上服务器 首先先确保环境是HKU的网络环境(HKU AnyConnect也可)。伙伴已经帮忙创建好用户(第一次登录会提示重新设置密码)。用cmd ssh链接ssh -p 60001 <u…

软件测试|MySQL逻辑运算符使用详解

简介 在MySQL中&#xff0c;逻辑运算符用于处理布尔类型的数据&#xff0c;进行逻辑判断和组合条件。逻辑运算符主要包括AND、OR、NOT三种&#xff0c;它们可以帮助我们在查询和条件语句中进行复杂的逻辑操作。本文将详细介绍MySQL中逻辑运算符的使用方法和示例。 AND运算符 …

Spark SQL基础知识

一.DataFrame详解 1.清洗相关的API 去重API:dropDuplicates 总结:用来删除重复数据,如果没有指定参数subset,那么要比对行中的所有字段内容,如果全部相同,就认为是重复数据,会被删除;如果有指定参数subset,那么只比对subset中指定的字段范围,如果指定不存在的字段会报错. 删…

小红书素人种草笔记铺量推广,有素人资源合作吗?

小红书&#xff0c;作为国内领先的社交电商平台&#xff0c;以其独有的口碑效应和海量素人资源&#xff0c;成为了品牌推广界的新宠。如何利用小红书素人笔记进行铺量推广&#xff0c;提升品牌知名度呢&#xff1f;本文伯乐网络传媒将来给大家进行全面解析。 一、小红书素人笔记…

C#封装服务

C#封装服务 新建服务项目&#xff1b;重构 OnStart 和 OnStop using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; using S…

进阶学习——Linux网络

目录 一、网络配置命令 1.ifconfig——IP地址 1.1ifconfig的基础用法 1.1.1ifconfig命令详解 1.2常用格式 1.3修改网卡名称 1.3.1临时修改 1.3.2永久修改 1.4临时修改网卡 1.4.1设置虚拟网卡 1.4.2延伸——ethtool 1.5永久修改网卡 1.6实验 —— 双网卡配置 1.…

@PolarDB,你的动手体验搭子,来啦

前言 PolarDB是阿里云自研的新一代云原生数据库&#xff0c;在计算存储分离架构下&#xff0c;利用了软硬件结合的优势&#xff0c;为用户提供具备极致弹性、高性能、海量存储、安全可靠的数据库服务。100%兼容MySQL和PostgreSQL生态&#xff0c;高度兼容Oracle语法。 1月17日…

vivado 创建编译后工程

创建后期合成项目 合成后项目以合成网表、完全生成的块设计、完全生成的IP以及相应的约束。然后&#xff0c;您可以分析、布局和实施设计 注意&#xff1a;您可以使用XST或第三方合成工具来创建合成网表。 重要&#xff01;使用EDIF和NGC文件时&#xff0c;顶部单元格名称必…

“器官短缺”将被打破 基因编辑猪成为人类的“二师兄”

器官移植被称为生命之灯。但是&#xff0c;受制于传统观念及对人体器官捐献意义的不了解&#xff0c;人体器官捐献的数量&#xff0c;还远远达不到需求。目前&#xff0c;全国有近30万的患者在等待器官移植&#xff0c;但每年只有近一万的患者能真正得到器官移植&#xff0c;缺…

高性能、可扩展、支持二次开发的企业电子招标采购系统源码

在数字化时代&#xff0c;企业需要借助先进的数字化技术来提高工程管理效率和质量。招投标管理系统作为企业内部业务项目管理的重要应用平台&#xff0c;涵盖了门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理等…

JSON数据处理

1.添加json依赖 springmvc 默认使用jackson作为json类库,不需要修改applicationContext-servlet.xml任何配置&#xff0c;只需引入以下类库springmvc就可以处理json数据&#xff1a; <!--spring-json依赖--> <dependency><groupId>com.fasterxml.jackson.c…

宝塔上的琉璃灯(for循环试炼)

8层宝塔上共有765盏琉璃灯&#xff0c;每层灯数都是上层的一倍&#xff0c;编程输出每层灯数。 (笔记模板由python脚本于2024年01月09日 16:41:22创建&#xff0c;本篇笔记适合熟悉循环编程的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python…

全新链动2+1模式,提升用户粘性度,增加产品复购率!

在互联网电商行业中&#xff0c;消费增值模式已经成为一种强大的营销工具。通过将消费者所消费的金额转化为积分&#xff0c;再利用平台的销售业绩作为托底&#xff0c;使得积分的价值不断增长&#xff0c;从而增加了消费者的忠诚度和黏性。然而&#xff0c;在实际操作中&#…

C++力扣题目-- 二叉树层序遍历

102.二叉树的层序遍历(opens new window)107.二叉树的层次遍历II(opens new window)199.二叉树的右视图(opens new window)637.二叉树的层平均值(opens new window)429.N叉树的层序遍历(opens new window)515.在每个树行中找最大值(opens new window)116.填充每个节点的下一个右…

1883_把FreeRTOS中的heap_4作为一个通用模块使用并初步测试

全部学习汇总&#xff1a; GreyZhang/c_units: A small piece of code which can be reuse anywhere, I call it a unit. This is a collection of unit in C language! Ok, yes, it would be my toolbox. (github.com) 在嵌入式&#xff0c;尤其是控制类的嵌入式中很少有mallo…

SUDA-计算机网路-期末复习提纲

写在前面 帮苏大的同学整理的计网复习材料&#xff0c;用的是他们老师划定的范围。 1.负责互联网协议开发、标准制定、地址分配的国际组织名称及其主要职责 (1) 地址支持组织&#xff08;ASO&#xff09;负责IP地址系统的管理。 (2) 域名支持组织&#xff08;DNSO&#xff09;…

CMU15-445-Spring-2023-Project #1 - 前置知识(lec01-06)

Lecture #01_ Relational Model & Relational Algebra Databases 数据库是相互关联的数据的有组织集合&#xff0c;对现实世界的某些方面进行建模。区别于DBMS&#xff08;MySQL、Oracle&#xff09;。 Flat File Strawman 数据库以CSV文件的形式存储&#xff0c;并由D…