3.8【Q】cv

news2025/3/9 21:21:36

这个draw_line函数的逻辑和功能是什么?代码思路是什么?怎么写的?

这个t是什么?t.v[0]和t.v[1],[2]又是什么?

void rst::rasterizer::draw(rst::pos_buf_id pos_buffer, rst::ind_buf_id ind_buffer, rst::Primitive type)
{
    if (type != rst::Primitive::Triangle)
    {
        throw std::runtime_error("Drawing primitives other than triangle is not implemented yet!");
    }
    auto& buf = pos_buf[pos_buffer.pos_id];
    auto& ind = ind_buf[ind_buffer.ind_id];

    float f1 = (100 - 0.1) / 2.0;
    float f2 = (100 + 0.1) / 2.0;

    Eigen::Matrix4f mvp = projection * view * model;
    for (auto& i : ind)
    {
        Triangle t;

        Eigen::Vector4f v[] = {
                mvp * to_vec4(buf[i[0]], 1.0f),
                mvp * to_vec4(buf[i[1]], 1.0f),
                mvp * to_vec4(buf[i[2]], 1.0f)
        };

        for (auto& vec : v) {
            vec /= vec.w();
        }

        for (auto & vert : v)
        {
            vert.x() = 0.5*width*(vert.x()+1.0);
            vert.y() = 0.5*height*(vert.y()+1.0);
            vert.z() = vert.z() * f1 + f2;
        }

        for (int i = 0; i < 3; ++i)
        {
            t.setVertex(i, v[i].head<3>());
            t.setVertex(i, v[i].head<3>());
            t.setVertex(i, v[i].head<3>());
        }

        t.setColor(0, 255.0,  0.0,  0.0);
        t.setColor(1, 0.0  ,255.0,  0.0);
        t.setColor(2, 0.0  ,  0.0,255.0);

        rasterize_wireframe(t);
    }
}

这个draw函数的输入参数都是什么?有什么意义?内部处理逻辑是什么?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle

    // If so, use the following code to get the interpolated z value.
    //auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    //float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    //float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    //z_interpolated *= w_reciprocal;

    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

这里为什么有一个“  auto v = t.toVector4();”操作?作用是什么?

什么叫“支持透视投影下的正确深度插值透视校正属性插值”?还是没理解,形象地说明?为什么要拓展到四维?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto& v0 = t.v;
    auto& v1 = t.v;
    auto& v2 = t.v;

    // 计算三角形的包围盒
    float min_x = std::min({v0.x(), v1.x(), v2.x()});
    float max_x = std::max({v0.x(), v1.x(), v2.x()});
    float min_y = std::min({v0.y(), v1.y(), v2.y()});
    float max_y = std::max({v0.y(), v1.y(), v2.y()});

这些 v0,v1,v2是什么意思?原代码里写的不是 auto v = t.toVector4();吗?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
       // 计算包围盒
    float min_x = std::min({t.a().x(), t.b().x(), t.c().x()});
    float max_x = std::max({t.a().x(), t.b().x(), t.c().x()});
    float min_y = std::min({t.a().y(), t.b().y(), t.c().y()});
    float max_y = std::max({t.a().y(), t.b().y(), t.c().y()});
    // 转换为整数像素范围并钳位
    int x_begin = std::max(static_cast<int>(std::floor(min_x)), 0);
    int x_end = std::min(static_cast<int>(std::ceil(max_x)), width);
    int y_begin = std::max(static_cast<int>(std::floor(min_y)), 0);
    int y_end = std::min(static_cast<int>(std::ceil(max_y)), height);
    // 遍历包围盒内的所有像素
    for (int x = x_begin; x < x_end; ++x) {
        for (int y = y_begin; y < y_end; ++y) {
            float center_x = x + 0.5f;
            float center_y = y + 0.5f;

            if (insideTriangle(center_x, center_y, t)) {
                // 计算重心坐标
                Eigen::Vector2f A(v0.x(), v0.y());
                Eigen::Vector2f B(v1.x(), v1.y());
                Eigen::Vector2f C(v2.x(), v2.y());
                Eigen::Vector2f P(center_x, center_y);

                float denominator = (B.y() - C.y()) * (A.x() - C.x()) + (C.x() - B.x()) * (A.y() - C.y());
                if (denominator == 0) continue;

                float u = ((B.y() - C.y()) * (P.x() - C.x()) + (C.x() - B.x()) * (P.y() - C.y())) / denominator;
                float v = ((C.y() - A.y()) * (P.x() - C.x()) + (A.x() - C.x()) * (P.y() - C.y())) / denominator;
                float w = 1 - u - v;

                if (u >= 0 && v >= 0 && w >= 0) {
                    // 插值深度
                    float z_interpolated = u * v0.z() + v * v1.z() + w * v2.z();
                    int index = get_index(x, y);

                    // 深度测试
                    if (z_interpolated < depth_buf[index]) {
                        // 颜色插值
                        Eigen::Vector3f color = u * t.color + v * t.color + w * t.color;
                        set_pixel(Eigen::Vector3f(x, y, 1.0f), color);
                        depth_buf[index] = z_interpolated;
                    }
                }
            }
        }
    }  
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle

    // If so, use the following code to get the interpolated z value.
    //auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    //float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    //float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    //z_interpolated *= w_reciprocal;

    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

在遍历包围盒内所有像素时,为什么要定义出center_x和center_y?在计算重心坐标时,各行代码操作的意义和作用又是什么?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {

    auto v = t.toVector4();中,为什么一开始要定义出一个v?v在后续的计算中有什么用?

这个v的w维度,是在传入t后进行扩展的,并没有经过mvp矩阵的变化,那么三个点的w维度上的值不都是1吗?后面 float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());又有什么意义?

不是,mvp矩阵是在draw函数中进行计算的,在draw函数最后调用了rasterize_triangle(t);,在rasterize_triangle(t);中配置auto v = t.toVector4();,那么t的第四维度w不该是1吗?mvp矩阵并没有在此时发挥作用?

static bool insideTriangle(int x, int y,const Vector3f* _v)
{   
    Vector3f P(x+0.5f,y+0.5f,1.0f);
    const Vector3f& A = _v[0];
    const Vector3f& B = _v[1];
    const Vector3f& C = _v[2];


    // 计算三个边的向量和点P到顶点的向量
    Vector3f AB =  B - A;
    Vector3f BC =  C - B;
    Vector3f CA =  A - C;

    Vector3f AP = P - A;
    Vector3f BP = P - B;
    Vector3f CP = P - C;

    // 计算叉积符号
    float cross1 = AB.cross(AP).z();
    float cross2 = BC.cross(BP).z();
    float cross3 = CA.cross(CP).z();

    // 检查符号是否一致
    return (cross1 > 0 && cross2 > 0 && cross3 > 0) || (cross1 < 0 && cross2 < 0 && cross3 < 0);
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
}

这段代码能实现判断点是否在内外部的原理是什么?cross1等取z是什么意思?有什么意义?

为什么Vector3f P(x+0.5f,y+0.5f,1.0f);可以确保测试点为像素中心?什么叫像素中心?为什么要保证在像素中心?

static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector3f* v)
{
    float c1 = (x*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*y + v[1].x()*v[2].y() - v[2].x()*v[1].y()) / (v[0].x()*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*v[0].y() + v[1].x()*v[2].y() - v[2].x()*v[1].y());
    float c2 = (x*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*y + v[2].x()*v[0].y() - v[0].x()*v[2].y()) / (v[1].x()*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*v[1].y() + v[2].x()*v[0].y() - v[0].x()*v[2].y());
    float c3 = (x*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*y + v[0].x()*v[1].y() - v[1].x()*v[0].y()) / (v[2].x()*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*v[2].y() + v[0].x()*v[1].y() - v[1].x()*v[0].y());
    return {c1,c2,c3};
}

这个函数是在干什么?有什么用?传入参数的意义和输出是什么意思?

std::tie(alpha, beta, gamma) = tup;

 这句什么意思?tie什么意思?

 //MSAA 4X
 if (MSAA) {
  // 格子里的细分四个小点坐标
  std::vector<Eigen::Vector2f> pos
  {
   {0.25,0.25},
   {0.75,0.25},
   {0.25,0.75},
   {0.75,0.75},
  };
  for (int x = min_x; x <= max_x; x++) {
   for (int y = min_y; y <= max_y; y++) {
    // 记录最小深度
    float minDepth = FLT_MAX;
    // 四个小点中落入三角形中的点的个数
    int count = 0;
    // 对四个小点坐标进行判断 
    for (int i = 0; i < 4; i++) {
     // 小点是否在三角形内
     if (insideTriangle((float)x + pos[i][0], (float)y + pos[i][1], t.v)) {
      // 如果在,对深度z进行插值
      auto tup = computeBarycentric2D((float)x + pos[i][0], (float)y + pos[i][1], t.v);
      float alpha;
      float beta;
      float gamma;
                        // std::tie表示打散tup到 alpha beta gamma三个分量
      std::tie(alpha, beta, gamma) = tup;

                        // reciprocal 倒数
      float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());

                        // 按照三角形三个点的权重,对当前点插值,求出z值,注意,这里的reciprocal用的有点莫名其妙,先不用管
                        // 而且alpha beta gamma用起来是需要矫正的
                        // 此处留个疑问:为什么不能在投影变换时,求出每个点的z坐标映射值呢?
      float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
      z_interpolated *= w_reciprocal;
                        // 求出当前点中四个小点对应的深度,以代表当前点的z值,用来和其他点的z做对比
      minDepth = std::min(minDepth, z_interpolated);
                        // 包含一个点count +1
      count++;
     }
    }
    if (count != 0) {
     if (depth_buf[get_index(x, y)] > minDepth) {

                        // 简单的对color/4也可以,处理的比较粗糙。
                        // 注意getColor其实就只用了一个值,三角形三个点的颜色相同
                        // 这里还考虑了当前缓冲里面存贮的颜色值
      Vector3f color = t.getColor()*count/4 + (4-count)*frame_buf[get_index(x,y)]/4;
      Vector3f point(3);
      point << (float)x, (float)y, minDepth;
      // 替换深度
      depth_buf[get_index(x, y)] = minDepth;
      // 修改颜色
      set_pixel(point, color);
     }
    }
   }
  }
 }

详细解释这段代码每一句的作用和意义?如何实现MSAA抗锯齿的?

 Vector3f color = t.getColor()*count/4 + (4-count)*frame_buf[get_index(x,y)]/4;这个color的计算是什么意思?怎么做的?

为什么不能在投影变换时,求出每个点的z坐标映射值呢?什么意思?思路是什么?

当前代码开启了超采样,但是if (count != 4)std::cout << "current count test: " << count << '\n';并没有输出,说明count要么是0要么是4,为什么会发生这种情况?为什么?如何处理?使其去锯齿?

就是这个函数static bool insideTriangle(float x, float y,const Vector3f* _v)的传入参数一开始设置为int的原因;此外,想要进一步提升抗锯齿的效果,该怎么做?给出修改代码


/ 修改后的抗锯齿核心逻辑
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // 8x旋转采样点布局
    std::vector<Eigen::Vector2f> pos { /* 上述8个点 */ };
    
    // 包围盒扩展(增加1像素冗余)
    min_x = static_cast<int>(std::floor(min_x - 1.0f));
    max_x = static_cast<int>(std::ceil(max_x + 1.0f));
    
    for (int x = min_x; x <= max_x; x++) {
        for (int y = min_y; y <= max_y; y++) {
            int count = 0;
            float minDepth = FLT_MAX;
            
            // 第一层8x采样
            for (int i=0; i<8; ++i) {
                float sx = x + pos[i][0], sy = y + pos[i][1];
                if (insideTriangle(sx, sy, t.v)) {
                    // 计算深度...
                    count++;
                }
            }
            
            // 边缘区域二次采样
            if (count>0 && count<8) {
                std::vector<Eigen::Vector2f> edge_pos {/* 4个点 */};
                for (auto& ep : edge_pos) {
                    if (insideTriangle(x+ep[0], y+ep[1], t.v)) count++;
                }
            }
            
            // 深度加权颜色混合
            if (count > 0) {
                float weight = count / 12.0; // 最大12采样
                Vector3f color = /* 加权混合公式 */;
                set_pixel(point, color);
            }
        }
    }
    
    // 后处理阶段
    post_process(); 
}

完成这个代码里省略的部分

增加采样数量后,在原来4*的基础上,8*的图形边缘出现了黑边,且抗锯齿效果并没有显著提升,甚至有所倒退,这是为什么?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

upload-labs文件上传

第一关 上传一个1.jpg的文件&#xff0c;在里面写好一句webshell 保留一个数据包&#xff0c;将其中截获的1.jpg改为1.php后重新发送 可以看到&#xff0c;已经成功上传 第二关 写一个webshell如图&#xff0c;为2.php 第二关在过滤tpye的属性&#xff0c;在上传2.php后使用b…

C++20 格式化库:强大的字符串格式化工具

文章目录 格式化语法常见用法1. 填充和对齐2. 数值格式化3. 进制格式化4. 自定义类型 示例代码注意事项 C20 的格式化库是一个强大的工具&#xff0c;用于处理字符串的格式化操作。它提供了类似于 Python 中 str.format() 的功能&#xff0c;但语法和用法更符合 C 的风格。以下…

[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中

[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中 将MathType公式编辑器内嵌到WPS工具栏中 下载好所需文件 我用夸克网盘分享了「mathtype安装教程超简单易上手.zip」&#xff0c;点击链接即可保存。打开「夸克APP」 链接&#xff1a;https://pan.quark.cn/s/4726c684…

分析TCP三次握手与四次挥手

TCP&#xff08;传输控制协议&#xff09;通过三次握手建立连接&#xff0c;四次挥手终止连接&#xff0c;确保数据传输的可靠性。 TCP的三个控制标志位&#xff1a; SYN——用于建立连接&#xff0c;同步序列号。 ACK——用于确认收到的数据。 FIN——用于终止连接。 ISN…

【深度学习】宠物品种分类Pet Breeds Classifier

文章目录 宠物品种数据集制作宠物品种标签图像预处理Presizing 损失函数loss观察模型的性能提升模型的性能learning rate finder使用CLR算法训练选择学习率的策略重新训练 迁移学习微调fine_tunefit_one_cycle有判别力的学习率 选择epoch的数量更深的网络架构 宠物品种数据集 …

【从零开始学习计算机科学】HLS算子调度

算子调度 调度是HLS 中的核心问题,为无时序或部分时序的输入指定时钟边界,其对最终结果质量具有很大的影响。调度会影响时钟频率、延时、吞吐率、面积、功耗等多种因素。 调度的输入是控制数据流图,其节点表示算子/操作,有向边表示数据依赖,控制依赖,优先依赖。如果没有…

centos 安装composer 教程

打开命令行 php -r "copy(https://getcomposer.org/installer, composer-setup.php);" sudo php composer-setup.php --install-dir/usr/local/bin --filenamecomposer composer --version sudo chmod us /usr/local/bin/composer Super18120/article/details/14388…

C语言_数据结构总结2:动态分配方式的顺序表

0——静态分配内存的顺序表和动态分配内存的顺序表的相同之处和不同之处 相同之处 基本操作逻辑相同&#xff1a;无论是静态分配还是动态分配的顺序表&#xff0c;其核心的操作逻辑是一致的。例如插入操作都需要将插入位置之后的元素依次后移&#xff0c;删除操作都需要将删除…

WSL安装及问题

1 概述 Windows Subsystem for Linux&#xff08;简称WSL&#xff09;是一个在Windows 10\11上能够运行原生Linux二进制可执行文件&#xff08;ELF格式&#xff09;的兼容层。它是由微软与Canonical公司合作开发&#xff0c;开发人员可以在 Windows 计算机上同时访问 Windows 和…

基于SpringBoot的商城管理系统(源码+部署教程)

运行环境 数据库&#xff1a;MySql 编译器&#xff1a;Intellij IDEA 前端运行环境&#xff1a;node.js v12.13.0 JAVA版本&#xff1a;JDK 1.8 主要功能 基于Springboot的商城管理系统包含管理端和用户端两个部分&#xff0c;主要功能有&#xff1a; 管理端 首页商品列…

HeidiSQL:一款免费的数据库管理工具

HeidiSQL 是一款免费的图形化数据库管理工具&#xff0c;支持 MySQL、MariaDB、Microsoft SQL、PostgreSQL、SQLite、Interbase 以及 Firebird&#xff0c;目前只能在 Windows 平台使用。 HeidiSQL 的核心功能包括&#xff1a; 免费且开源&#xff0c;所有功能都可以直接使用。…

Ae 效果详解:VR 色差

Ae菜单&#xff1a;效果/沉浸式视频/VR 色差 Immersive Video/VR Chromatic Aberrations VR 色差 VR Chromatic Aberrations效果用于模拟镜头色散现象&#xff0c;在 VR 视频中制造 RGB 通道错位的色彩偏移&#xff0c;以增强视觉风格或创造数字失真效果。 本效果适用于所有色深…

计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【Linux内核系列】:深入解析输出以及输入重定向

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz ★★★ 本文前置知识&#xff1a; 文件系统以及文件系统调用接口 用c语言简单实现一个shell外壳程序 内容回顾 那么在此前的学习中&#xff0c;我们对于Linux的文件系统已经有了…

PyTorch系列教程:Tensor.view() 方法详解

这篇简明扼要的文章是关于PyTorch中的tensor.view()方法的介绍与应用&#xff0c;与reshape()方法的区别&#xff0c;同时给出示例进行详细解释。 Tensor基础 Tensor(张量)的视图是一个新的Tensor&#xff0c;它与原始Tensor共享相同的底层数据&#xff0c;但具有不同的形状或…

软件测试的基础入门(二)

文章目录 一、软件&#xff08;开发&#xff09;的生命周期什么是生命周期软件&#xff08;开发&#xff09;的生命周期需求分析计划设计编码测试运行维护 二、常见的开发模型瀑布模型流程优点缺点适应的场景 螺旋模型流程优点缺点适应的场景 增量模型和迭代模型流程适应的场景…

地下变电站如何实现安全智能运营-以110kV站为例看环境监测与设备联控

1、地下变电站简介 在经济发达的地区&#xff0c;由于城市中心土地资源紧张、征地拆迁费用昂贵&#xff0c;因此采用地下变电站来解决这些问题不失为一个好的途径和思路。地下变电站一般采用室内全封闭式组合电气设备&#xff0c;&#xff12;&#xff12;&#xff10;&#x…

windows无界面后台定时任务 (重启自启动,ODBS为例)

一、前言 mdb(Microsoft Database)是Microsoft Access中使用的一种数据存储格式,可以通过ODBC驱动程序进行访问和操作,在Python中也可以安装相应模块打开。 这是我在项目中更新bs数据的一个实践记录,结合windows定时一起记录一下,方便以后照搬~ 二、安装 Python安装库…

FPGA 实验报告:四位全加器与三八译码器仿真实现

目录 安装Quartus软件 四位全加器 全加器、半加器 半加器&#xff1a; 全加器&#xff1a; 四位全加器电路图 创建项目 半加器 全加器 四位全加器 代码实现 半加器 全加器 四位全加器 三八译码器 创建项目 代码展示 modelsim仿真波形图 四位全加器 三八译码…

win11 Visual Studio 17 2022源码编译 opencv4.11.0 + cuda12.6.3 启用GPU加速

win11 Visual Studio 17 2022 源码编译 opencv4.11.0 cuda12.6.3 启用GPU加速 配置: 生成 opencv 生成 opencv-python 1 下载源码和安装软件 win11 x64 系统 安装Visual Studio 17 2022 下载opencv4.11.0 源码 https://github.com/opencv/opencv/releases/tag/4.11.0 下载…