GAMES101(0~1作业)

news2024/11/14 3:29:27

搭建虚拟机环境

  1. 安装Oracle VM VirtualBox虚拟机,安装虚拟硬盘,配置Linux Ubuntu-64 bit系统,
  2. 启动虚拟机,发生冲突错误:
    1. 将Vmware虚拟设备取消挂起状态,关机
    2. 确保 Hyper-V 完全关闭:bcdedit /set hypervisorlaunchtype off
    3. 重启计算机
  3. 安装增强功能,未找到iso错误:ISO下载地址:Index of http://download.virtualbox.org/virtualbox
    1. 首先升级虚拟机版本置7.0.2
    2. 通过update Guest additions
    3. 最后安装增强功能
  4. 通过终端调用cmake编译文件,
    1. 使用硬盘中的vscode编写main.cpp
    2. 通过终端创建文件touch CMakeLists.txt
    3. 编写文件(作业框架里有)
    4. cmake编译目录
    5. make编译
    6. 执行运行程序
# 指定最低版本要求
cmake_minimum_required(VERSION 2.8.5)
# 项目名称
project(Hello)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
#
find_package(Eigen3 REQUIRED)
include_directories(EIGEN3_INCLUDE_DIR)
# 添加源文件
add_executable(pa0 main.cpp)

 作业0:

题目

给定一个点 P=(2,1), 将该点绕原点先逆时针旋转 45◦,再平移 (1,2), 计算出 变换后点的坐标(要求用齐次坐标进行计算)。

首先为向量增加一个分量(1),将变换的值带入,SL:3*3的旋转(绕z) * 平移矩阵公式中,最后乘以具有3个分量的向量

    auto angle = 45 * 3.14 / 180.0f;
    Eigen::Matrix3f R_Mat3;
    R_Mat3 <<
        std::cos(angle),-std::sin(angle),0,
        std::sin(angle), std::cos(angle),0,
        0,0,1;
    Eigen::Matrix3f T_Mat3;
    T_Mat3 <<
        1,0,1,
        0,1,2,
        0,0,1;
    Eigen::Vector3f p(2.0f,1.0f,1.0f);
    auto result = T_Mat3 * R_Mat3* p;
    std::cout << result;

作业1(OpenCV,Eigen):

题目

在给定作业框架填写一个旋转矩阵get_model_matrix()和一个透视投影矩阵get_projection_matrix(),给定三维下三个 点 v0(2.0, 0.0, −2.0), v1(0.0, 2.0, −2.0), v2(−2.0, 0.0, −2.0), 你需要将这三个点的坐 标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形

解:

旋转矩阵:就是利用绕z旋转矩阵公式

    double fangle = rotation_angle / 180 * MY_PI;
    Eigen::Matrix4f rotation;
    rotation << 
        cos(fangle), -sin(fangle), 0, 0,
        sin(fangle), cos(fangle), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1;
    model = rotation * model;

透视投影矩阵:同样带入公式即可

    Eigen::Matrix4f proj, ortho;
    proj << 
        zNear, 0, 0, 0,
        0, zNear, 0, 0,
        0, 0, zNear + zFar, -zNear * zFar,
        0, 0, 1, 0;

    double w, h, z;
    h = zNear * tan(eye_fov / 2) * 2;
    w = h * aspect_ratio;
    z = zFar - zNear;
    
    ortho << 
        2 / w, 0, 0, 0,
        0, 2 / h, 0, 0,
        0, 0, 2 / z, -(zFar+zNear) / 2,
        0, 0, 0, 1;
             				
    projection = ortho * proj * projection;
标题

提高部分题目:

在 main.cpp 中构造一个函数,该函数的作用是得到绕任意 过原点的轴的旋转变换矩阵。Eigen::Matrix4f get_rotation(Vector3f axis, float angle)

解:

很明显从函数参数可以看出应用的是罗德里格斯公式,所以这里其实就是带入公式

Eigen::Matrix4f get_rotation(Vector3f axis, float angle) {
    double fangle = angle / 180 * MY_PI;
    Eigen::Matrix4f I, N, Rod;
    Eigen::Vector4f axi;
    Eigen::RowVector4f taxi;

    axi << axis.x(), axis.y(), axis.z(), 0;

    I=Eigen::Matrix4f::Identity();

    N << 0, -axis.z(), axis.y(), 0,
         axis.z(), 0, -axis.x(), 0,
         -axis.y(), axis.x(), 0, 0,
         0, 0, 0, 1;
    
    Rod = cos(fangle) * I + (1 - cos(fangle)) * axi * axi.transpose() + sin(fangle) * N;
    Rod(3, 3) = 1;
    return Rod;
}

理解代码

对于c语言使用.h,.c的扩展名,而对于c++使用.h,hpp(为了区分 C 和 C++ 代码),.cpp扩展名

main.cpp:变换矩阵的计算,模拟了图形管线,旋转三角形的控制

int argc,命令行参数的个数 const char** argv |const char* argv[]是一个数组,每个元素都是指向常量字符的指针

为什么argv[2]没有解引用?因为std::cout 会自动将 const char* 解释为一个以 \0 结尾的字符串。

int main(int argc, const char** argv)//在运行是输入命令行参数
{
    float angle = 0;//摄像机角度
    bool command_line = false;//设置命令行开关
    std::string filename = "output.png";//字符串

    if (argc >= 3) {//当3个参数
        command_line = true;
        angle = std::stof(argv[2]); // -r by default//从命令行获取旋转角度
        if (argc == 4) {//当4个参数
            filename = std::string(argv[3]);//从命令行获取文件名
        }
        else
            return 0;
    }

    rst::rasterizer r(700, 700);//光栅化器类的实例,传入视口大小

    Eigen::Vector3f eye_pos = {0, 0, 5};//相机未知

    std::vector<Eigen::Vector3f> pos{{2, 0, -2}, {0, 2, -2}, {-2, 0, -2}};//3个顶点

    std::vector<Eigen::Vector3i> ind{{0, 1, 2}};//顶点索引

    auto pos_id = r.load_positions(pos);//保存顶点
    auto ind_id = r.load_indices(ind);//保存索引

    int key = 0;//键盘输入
    int frame_count = 0;

    if (command_line) {//如果传入参数>=3
        r.clear(rst::Buffers::Color | rst::Buffers::Depth);
        
        r.set_model(get_model_matrix(angle));
        r.set_view(get_view_matrix(eye_pos));
        r.set_projection(get_projection_matrix(45, 1, 0.1, 50));

        r.draw(pos_id, ind_id, rst::Primitive::Triangle);
        cv::Mat image(700, 700, CV_32FC3, r.frame_buffer().data());
        image.convertTo(image, CV_8UC3, 1.0f);

        cv::imwrite(filename, image);

        return 0;
    }

    while (key != 27) {//非ECS
        r.clear(rst::Buffers::Color | rst::Buffers::Depth);

        //计算模型、视图和投影矩阵,并传入光栅化器中,光栅化器在屏幕上显示出变换的结果
        r.set_model(get_model_matrix(angle));
        r.set_view(get_view_matrix(eye_pos));
        r.set_projection(get_projection_matrix(45, 1, 0.1, 50));

        r.draw(pos_id, ind_id, rst::Primitive::Triangle);//绘制三角形

        cv::Mat image(700, 700, CV_32FC3, r.frame_buffer().data());
        image.convertTo(image, CV_8UC3, 1.0f);
        cv::imshow("image", image);//显示图像
        key = cv::waitKey(10);

        std::cout << "frame count: " << frame_count++ << '\n';

        if (key == 'a') {//逆时针旋转10
            angle += 10;
        }
        else if (key == 'd') {//顺时针旋转10
            angle -= 10;
        }
    }

    return 0;
}

rasterizer.hpp , rasterizer.cpp光栅器 | 渲染器,生成渲染器界面与绘制。 

rst::pos_buf_id rst::rasterizer::load_positions(const std::vector<Eigen::Vector3f> &positions) // 保存到
{
    auto id = get_next_id();        // 从0开始分配,每次调用后索引增加
    pos_buf.emplace(id, positions); // 存放到顶点数组中

    return {id};
}

rst::ind_buf_id rst::rasterizer::load_indices(const std::vector<Eigen::Vector3i> &indices)
{
    auto id = get_next_id();
    ind_buf.emplace(id, indices);

    return {id};
}

// Bresenham's line drawing algorithm,
// Bresenham算法,绘制线
// Code taken from a stack overflow answer: https://stackoverflow.com/a/16405254
void rst::rasterizer::draw_line(Eigen::Vector3f begin, Eigen::Vector3f end)
{
    /* 起点和终点坐标 */
    auto x1 = begin.x();
    auto y1 = begin.y();
    auto x2 = end.x();
    auto y2 = end.y();
    /* 颜色 */
    Eigen::Vector3f line_color = {255, 255, 255};
    /*x, y当前绘制的像素点的坐标,
    dx, dy直线在 x 和 y 方向上的增量,
    dx1, dy1用于计算偏移量,
    px, py用于确定下一个像素点的坐标 ,
    xe, ye: 用于循环控制,表示直线的终点*/
    int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;

    dx = x2 - x1;
    dy = y2 - y1;
    dx1 = fabs(dx);
    dy1 = fabs(dy);
    px = 2 * dy1 - dx1;
    py = 2 * dx1 - dy1;

    if (dy1 <= dx1)/* 如果在y轴上的偏移量比x轴上要小,更趋向于水平线 */
    {
        if (dx >= 0)/* 从起点坐标开始 */
        {
            x = x1;
            y = y1;
            xe = x2;
        }
        else/* 从终点坐标开始 */
        {
            x = x2;
            y = y2;
            xe = x1;
        }
        Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);/* 创建起点 */
        set_pixel(point, line_color);/* 设置为白色 */
        for (i = 0; x < xe; i++)/* 通过迭代来逐步绘制直线的每个像素点。 */
        {
            x = x + 1;
            if (px < 0)/* 像素的 y 坐标不需要改变 */
            {
                px = px + 2 * dy1;/* 更新 px 的值 */
            }
            else
            {
                if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))/* 表示 y 方向向上移动 */
                {
                    y = y + 1;
                }
                else/* 表示 y 方向向下移动。 */
                {
                    y = y - 1;
                }
                px = px + 2 * (dy1 - dx1);/* 更新 px 的值 */
            }
            //delay(0);
            Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);/* 新的点绘制到屏幕上 */
            set_pixel(point, line_color);
        }
    }
    else
    {
        ……
    }
}

auto to_vec4(const Eigen::Vector3f &v3, float w = 1.0f) // 默认创建点,引入齐次坐标
{
    return Vector4f(v3.x(), v3.y(), v3.z(), w);
}

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!");
    }
    //2维数组
    auto &buf = pos_buf[pos_buffer.pos_id];/* 根据id访问实际数据,3个顶点的坐标 */
    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; // MVP
    for (auto &i : ind)//第一次为{0,1,2}
    {
        Triangle t;/* 三角形对象 */
        /* MVP变换 ,对3个顶点 */
        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();
        }
        /* 对每个顶点,分解为xyz,变换到视口,应用视口矩阵 */
        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); // 绘制
    }
}

void rst::rasterizer::rasterize_wireframe(const Triangle &t) // 绘制三角形
{
    draw_line(t.c(), t.a());/* abc为3个顶点 */
    draw_line(t.c(), t.b());
    draw_line(t.b(), t.a());
}

void rst::rasterizer::set_model(const Eigen::Matrix4f &m) // 设置成员变量
{
    model = m;
}

void rst::rasterizer::set_view(const Eigen::Matrix4f &v)
{
    view = v;
}

void rst::rasterizer::set_projection(const Eigen::Matrix4f &p)
{
    projection = p;
}

void rst::rasterizer::clear(rst::Buffers buff) // 清理颜色和深度缓冲区
{
    if ((buff & rst::Buffers::Color) == rst::Buffers::Color)
    {
        std::fill(frame_buf.begin(), frame_buf.end(), Eigen::Vector3f{0, 0, 0});
    }
    if ((buff & rst::Buffers::Depth) == rst::Buffers::Depth)
    {
        std::fill(depth_buf.begin(), depth_buf.end(), std::numeric_limits<float>::infinity());
    }
}

rst::rasterizer::rasterizer(int w, int h) : width(w), height(h) // 根据宽高比设置帧缓冲大小和深度缓冲大小
{
    frame_buf.resize(w * h);
    depth_buf.resize(w * h);
}

int rst::rasterizer::get_index(int x, int y) // 根据坐标求像素在缓冲区的序号
{
    return (height - y) * width + x;
}

void rst::rasterizer::set_pixel(const Eigen::Vector3f &point, const Eigen::Vector3f &color) // 将屏幕像素点 (x, y) 设 为 (r, g, b) 的颜色,并写入相应的帧缓冲区位置。
{
    // old index: auto ind = point.y() + point.x() * width;
    if (point.x() < 0 || point.x() >= width ||
        point.y() < 0 || point.y() >= height)
        return;
    auto ind = (height - point.y()) * width + point.x();
    frame_buf[ind] = color;
}

Triangle.hpp, Triangle.cpp三角形数据 ,提供了数据设置的接口

class Triangle
{
  public:
    /*the original coordinates of the triangle, v0, v1, v2 in counter clockwise order*/
    /*Per vertex values*/
    /* 顶点,颜色,纹理坐标,法线 */
    Vector3f v[3]; 
    Vector3f color[3];      // color at each vertex;
    Vector2f tex_coords[3]; // texture u,v
    Vector3f normal[3];     // normal vector for each vertex

    // Texture *tex;
    Triangle();
    /* 返回三角形顶点坐标 */
    Eigen::Vector3f a() const { return v[0]; }
    Eigen::Vector3f b() const { return v[1]; }
    Eigen::Vector3f c() const { return v[2]; }

    void setVertex(int ind, Vector3f ver); /*set i-th vertex coordinates */
    void setNormal(int ind, Vector3f n);   /*set i-th vertex normal vector*/
    void setColor(int ind, float r, float g, float b); /*set i-th vertex color*/
    void setTexCoord(int ind, float s,
                     float t); /*set i-th vertex texture coordinate*/
    std::array<Vector4f, 3> toVector4() const;
};

#endif // RASTERIZER_TRIANGLE_H

//cpp

Triangle::Triangle()/* 初始值都为0 */
{
    v[0] << 0, 0, 0;
    v[1] << 0, 0, 0;
    v[2] << 0, 0, 0;

    color[0] << 0.0, 0.0, 0.0;
    color[1] << 0.0, 0.0, 0.0;
    color[2] << 0.0, 0.0, 0.0;

    tex_coords[0] << 0.0, 0.0;
    tex_coords[1] << 0.0, 0.0;
    tex_coords[2] << 0.0, 0.0;
}

void Triangle::setVertex(int ind, Eigen::Vector3f ver) { v[ind] = ver; }/* 设置指定索引的值 */

void Triangle::setNormal(int ind, Vector3f n) { normal[ind] = n; }

void Triangle::setColor(int ind, float r, float g, float b)/* 将颜色从0--255,转到0--1 */
{
    if ((r < 0.0) || (r > 255.) || (g < 0.0) || (g > 255.) || (b < 0.0) ||
        (b > 255.)) {
        throw std::runtime_error("Invalid color values");/* 超出范围抛出异常 */
    }

    color[ind] = Vector3f((float)r / 255., (float)g / 255., (float)b / 255.);
    return;
}
void Triangle::setTexCoord(int ind, float s, float t)
{
    tex_coords[ind] = Vector2f(s, t);
}

std::array<Vector4f, 3> Triangle::toVector4() const/* 三个顶点从 Vector3f 类型转换为 Vector4f 类型 */
{
    std::array<Vector4f, 3> res;
    std::transform(std::begin(v), std::end(v), res.begin(), [](auto& vec) {/* 遍历每个顶点 */
        return Vector4f(vec.x(), vec.y(), vec.z(), 1.f);
    });
    return res;
}

阅读复杂指针

如何阅读C/C++中的复杂的指针类型声明(源码中常遇到)_c++复杂阅读指针-CSDN博客

右左法则:从标识符开始,从右到左,优先级越高

括号法则:运算优先级更高

规律:普通变量(左边是本身类型),指针|引用(左边表示指向的类型),数组(左边表示元素类型),函数(左边表示返回类型)

int *  a  [10];a是一个包含10个数据的数组,每个元素是一个指向int的指针

int (*a) [3]; a是一个指针,指向3个元素的数组,每个元素是int类型

int *foo();foo是一个函数,返回指向int指针

int (*foo)();foo是一个指针,指向函数,函数返回int

int (*(*vtable)[])();vtable是一个指针,指向数组,每个元素是指针,并指向函数,函数返回类型为int

int name[] [n],name是一个数组,每个元素也是数组,包含n个int类型元素

const char** argv,argv是一个指针,指向常量字符的指针

const char* argv[]argv是一个数组,每个元素都是指向常量字符的指针

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

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

相关文章

Pandas DataFrame的多级列索引导出到Excel时,如何避免空白行和列

我想将multi-header数据框保存为Excel文件。以下是示例代码&#xff1a; import pandas as pd import numpy as npheader pd.MultiIndex.from_product([[location1,location2],[S1,S2,S3]],names[loc,S])df pd.DataFrame(np.random.randn(5, 6), index[a,b,c,d,e], columnsh…

Python 中的 11 种经典时间序列预测方法(备忘单)

摘要: 本文演示了 11 种不同的经典时间序列预测方法,这些方法包括: 自回归(AR) 移动平均线 (MA) 自回归移动平均线 (ARMA) 自回归综合移动平均线 (ARIMA) 季节性自回归综合移动平均线 (SARIMA) 季节性自回归综合移动平均线与外生回归量... 本文演示了 11 种不同的经典时间序…

sheng的学习笔记-AI-半监督聚类

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 半监督学习&#xff1a;sheng的学习笔记-AI-半监督学习-CSDN博客 聚类&#xff1a;sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 均值算法&#xff1a;sheng的学习笔记-AI-K均值算法_k均值算法怎么算迭代两次后的最大…

掌握Git分支管理策略:让团队协作更高效

在现代软件开发过程中&#xff0c;版本控制系统&#xff08;VCS&#xff09;是不可或缺的一部分。Git作为目前最流行的分布式版本控制系统之一&#xff0c;为开发者提供了强大的工具集来管理代码变更历史。然而&#xff0c;仅仅掌握Git的基本命令并不足以应对大型项目和团队协作…

当天审稿,当天上线,9月检索!

各领域CNKI知网普刊&#xff0c;最快一期预计下周送检&#xff0c;最快1天上线 领域广&#xff0c;计算机&#xff0c;社科&#xff0c;医学等各个方向都能收 包检索&#xff0c;可提供期刊部发票 知名出版社英文普刊 NO.1、Food Science and Nutrition Studies ISSN: 2573…

2024年全国大学生数学建模C题论文

C 题 农作物的种植策略 问题 1 &#xff1a;2024-2030 年农作物的最优种植方案 1.1 问题 1 的第一小问详细 该问题要求在假设未来农作物的预期销售量、种植成本、亩产量和销售价 格稳定的情况下&#xff0c;为乡村制定从 2024 年到 2030 年的农作物最优种植方案。特 别是要考虑…

骨传导耳机哪个牌子好用?精选五款黄金畅销骨传导机型测评

随着消费者对健康聆听方式的日益重视&#xff0c;骨传导耳机的市场需求持续高涨。众多耳机厂商在耳机的外观设计上倾注了大量心血&#xff0c;但在此过程中&#xff0c;部分品牌却忽视了产品的核心音质与佩戴舒适度&#xff0c;导致市场上涌现出一些外观时尚但内在品质不尽如人…

缓解父母焦虑!详细实测!这些免费AI可以成为孩子提高学习能力的得力助手!

近日&#xff0c;新版三年级英语教材冲上了热搜。家长纷纷表示&#xff0c;新版教材连26个英文字母都不教了&#xff0c;直接进入单词和文章教学。 ”娃都零基础&#xff0c;开学怎么跟得上&#xff1f;“ “这不是卷孩子&#xff0c;这是卷家长啊&#xff01;” 不仅是英语&…

【爱加密_云平台-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

[已更新问题二三matlab+python]2024数学建模国赛高教社杯C题:农作物的种植策略 思路代码文章助攻手把手保姆级

发布于9.6 10:00 有问题后续会修正!! 问题一代码展示: 问题二代码结果展示: 问题三代码展示: https://docs.qq.com/doc/DVVVlV0NmcnBDTlVJ问题一部分代码分享: #!/usr/bin/env python # coding: utf-8# In[15]:import pandas as pd# In[16]:# 读取Excel文件 file_path 附件2…

platform框架

platform框架 注册设备进入总线platform_device_register函数 注册驱动进入总线platform_driver_register函数 注册设备进入总线 platform_device_register函数 int platform_device_register(struct platform_device *pdev) struct platform_device {const char * name; 名…

《Rust避坑式入门》第2章:解决多线程并发数据竞争的不可变性

从第1章所讨论的出现数据竞争问题的多线程并发剧院订票系统的代码能够看出&#xff0c;虽然可变性能够方便地随时修改值&#xff0c;但滥用可变性&#xff0c;会在多线程并发编程时&#xff0c;带来数据竞争的难题。 共享可变状态所带来的多线程并发时的数据竞争难题&#xff…

维度不固定的多维数组形参笔记

在利用多维数组作为函数形参时遇到了点问题&#xff0c;如&#xff1a; void fun(char str[][10]); 这个函数可以传入多维数组&#xff0c;但元素个数必须是固定的&#xff0c;假如传入一个str[][20]&#xff0c;元素个数不一样的数组&#xff0c;那么这个函数就不适用了&…

6.2排序——选择排序与堆排序

本篇博客梳理选择排序&#xff0c;包括直接选择排序与堆排序 排序全部默认排成升序 一、直接选择排序 1&#xff0e;算法思想 每次遍历都选出最小的和最大的&#xff0c;放到序列最前面/最后面 2&#xff0e;具体操作 &#xff08;1&#xff09;单趟 每次遍历都选出最小的…

Opencv中的直方图(1)计算反向投影直方图函数calcBackProject()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算直方图的反向投影。 cv::calcBackProject 函数计算直方图的反向投影。也就是说&#xff0c;类似于 calcHist&#xff0c;在每个位置 (x, y)…

主流的3D模型格式有什么区别?

主流的3D模型格式在多个方面存在区别&#xff0c;这些区别主要体现在格式的特点、支持的功能、使用场景以及兼容性等方面。51建模网支持持obj、fbx、stl、glb、gltf、dae、3ds模型格式上传展示。以下是对几种主流3D模型格式的区别进行的详细分析&#xff1a; 1. OBJ格式 特点&…

初始JESD204B高速接口协议(JESD204B一)

本文参考 B B B站尤老师 J E S D 204 B JESD204B JESD204B视频&#xff0c;图片来自 J E S D JESD JESD手册或者 A D I / T I ADI/TI ADI/TI官方文档。 1、对比 L V D S LVDS LVDS与 J E S D 204 JESD204 JESD204 J E S D 204 B JESD204B JESD204B是逻辑器件和高速 A D C / D …

【YashanDB知识库】修改字段长度后,jdbc驱动接口报YAS-04007 Message:result set metadata changed异常

问题现象 yashandb修改表的字段长度后&#xff0c;客户的业务接口报YAS-04007异常&#xff0c;截图如下: 问题的风险及影响 客户的业务在访问yashandb时异常出错&#xff0c;影响使用 问题影响的版本 所有的yashandb版本 问题发生原因 使用jdbc接口获取PreparedStatement…

库存盘点频出错?试试这款专业软件的库存分析报表工具

在企业的日常运营中&#xff0c;库存管理的实际操作直接影响到我们的工作效率和企业的整体盈利情况。库存不仅是企业的物资储备&#xff0c;更是我们每天工作中必须处理的关键环节。如果库存管理不到位&#xff0c;可能会导致产品积压、资金占用&#xff0c;甚至影响到销售和客…

数据仓库技术选型方案文档

关联博客&#xff1a; 数据仓库技术选型方案文档 Flink CDC MySQL数据同步到Doris表同步配置生成工具类 新版报表系统&#xff08;明细报表、看板、数据大屏&#xff09;方案&介绍 文章目录 数据仓库技术选型背景现状现状架构目标架构业务反馈&痛点问题&#xff1a;原因…