Games101-作业4-贝塞尔曲线(含提高)

Games101-作业4-贝塞尔曲线(含提高)

分析

这次作业比较简单。
按照说明明白两个函数的用途即可:

  • recursive_bezier:使用de Casteljau算法对控制点和t生成一个贝塞尔曲线点,递归算法。
  • bezier:生成不同的t并传给recursive_bezier函数,根据返回值画出点。
  • native_bezier:写好的函数。直接用代数展开式算出点的位置,用来检验结果。

bezier

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 (float t = 0.0; t <= 1; t += 0.001)
    {
        auto point = recursive_bezier(control_points, t);
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
    }
}

recursize_bezier

重点是递归的写法。

cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{
    // TODO: Implement de Casteljau's algorithm
    // 递归出口条件:一阶贝塞尔曲线
    auto& p = control_points;
    if (p.size() == 2)
        return (1 - t) * p[0] + t * p[1];
    std::vector<cv::Point2f> b;
    for (int i = 0; i < p.size()-1; i++)
        b.push_back((1 - t) * p[i] + t * p[i + 1]);
    return recursive_bezier(b, t);
}

结果

把native_bezier打开,法线曲线吻合。

image-20240322161712797

反走样

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

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

image-20240322161822949

void bezier2(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 (float t = 0.0; t <= 1; t += 0.001)
    {
        auto point = recursive_bezier(control_points, t);
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
        int x = point.x, y = point.y;// 像素位置
        for (int dx = -1; dx <= 1; dx++)
        {
            for (int dy = -1; dy <= 1; dy++)
            {
                if (x + dx > 700 || x + dx < 0 || y + dy > 700 || y + dy < 0) continue;
                double d = std::sqrt(std::pow(point.x - (x + dx+0.5), 2) + std::pow(point.y -(y + dy+0.5), 2));
                double ratio = 1 - sqrt(2) * d / 3;
                window.at<cv::Vec3b>(point.y + dy, point.x + dx)[1] = std::fmax(window.at<cv::Vec3b>(point.y + dy, point.x + dx)[1], 255 * ratio);
            }
        }
    }
}

反走样前:
image-20240322162608633
image-20240322162623320
反走样后:
image-20240322162720103
image-20240322162734609

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值