当前位置: 首页 > news >正文

融媒体服务中PBO进行多重采样抗锯齿(MSAA)

如果不理解pbo 那先去了解概念,在此不再解释,这是我为了做融合服务器viewpointserver做的一部分工作,融合服务器的功能是将三维和流媒体,AI融合在一起,viewpointserver会直接读取三维工程的文件,同时融合rtsp视频流,将视频流作为纹理给材质,最后赋值给三维模型如fbx的表面。由于没有窗口,三维作为服务运行,里面有一项工作就是三维的抗锯齿采集。

PBO(Pixel Buffer Object)进行多重采样抗锯齿(MSAA)的一般步骤

1 初始化 OpenGL 和 MSAA 帧缓冲:

1.1开启 MSAA:

在初始化 OpenGL 时,通过设置相关参数开启多重采样抗锯齿。例如,使用 glEnable(GL_MULTISAMPLE) 函数来启用 OpenGL 的多重采样功能。

1.2 创建帧缓冲:

创建一个帧缓冲对象(FBO),用于存储多重采样后的图像数据。这可以通过 glGenFramebuffers 和 glBindFramebuffer 等函数来完成。

1.3 配置 FBO 的附件:

为 FBO 配置颜色附件和深度附件。对于颜色附件,创建一个纹理,并将其绑定到 FBO 上;对于深度附件,可以创建一个渲染缓冲对象(RBO)并绑定到 FBO。确保纹理和 RBO 的尺寸与渲染窗口的尺寸相匹配。

2 渲染到 MSAA 帧缓冲:

2.1 绑定 MSAA 帧缓冲:

在渲染场景之前,使用 glBindFramebuffer 函数将之前创建的 MSAA FBO 绑定为当前的渲染目标。这样,后续的渲染操作将把图像数据渲染到 MSAA FBO 中。

2.2 进行常规渲染:

按照正常的 OpenGL 渲染流程绘制场景中的物体。由于启用了 MSAA,OpenGL 会在每个像素内进行多个子采样,以实现抗锯齿效果。

3 使用 PBO 读取 MSAA 数据:

创建 PBO:使用 glGenBuffers 函数创建一个 PBO,并使用 glBindBuffer 函数将其绑定到 GL_PIXEL_PACK_BUFFER 目标上。然后,使用 glBufferData 函数为 PBO 分配足够的内存空间,以存储从 MSAA FBO 读取的像素数据。
读取像素数据到 PBO:在渲染完成后,使用 glReadPixels 函数将 MSAA FBO 中的像素数据读取到 PBO 中。由于 PBO 的存在,这个操作可以在后台异步进行,减少对 CPU 的阻塞。

4 处理和解析 PBO 中的数据:

4.1 映射 PBO:

使用 glMapBuffer 函数将 PBO 映射到 CPU 可访问的内存空间,以便读取和处理像素数据。这将返回一个指向 PBO 内存的指针,可以通过该指针访问像素数据。

4.2 解析像素数据:

根据需要,对 PBO 中的像素数据进行处理和解析。例如,可以将像素数据转换为图像格式,以便保存为文件或进行其他操作。在处理像素数据时,需要考虑 MSAA 的子采样信息,通常需要对多个子采样点的颜色值进行合并或平均,以得到最终的抗锯齿效果。

4.3 取消映射 PBO:

完成对 PBO 数据的处理后,使用 glUnmapBuffer 函数取消对 PBO 的映射,释放 CPU 对 PBO 内存的访问。

5 显示或使用抗锯齿后的图像:

5.1 将处理后的像素数据显示在屏幕上:

如果需要在屏幕上显示抗锯齿后的图像,可以使用 glDrawPixels 或其他相关的 OpenGL 函数将处理后的像素数据绘制到默认的帧缓冲中,然后通过交换缓冲区来显示在屏幕上。

5.2 保存为图像文件:

可以将处理后的像素数据保存为图像文件,以便后续使用。这可以通过使用图像库(如 stb_image 库)来实现,将像素数据写入图像文件中。

使用深度缓冲的例子

以下使用qt来做,qt的优点是很多都是封装好的,比较容易实现,不用引入额外的库,当然我们也可以使用glfw来做,后面会给出例子

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QtWidgets/QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include "ui_MainWindow.h"QT_BEGIN_NAMESPACE
namespace Ui {class CMainWindow;
}
QT_END_NAMESPACEclass CMainWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{Q_OBJECTpublic:CMainWindow(QWidget *parent = Q_NULLPTR);~CMainWindow();void initFBO();protected:void initializeGL();void paintGL();void resizeGL(int w, int h);private:QImage m_img;GLsizei m_width = 0;GLsizei m_height = 0;GLsizeiptr m_dataSize = 0;GLuint m_VBO = 0;GLuint m_VAO = 0;GLuint m_EBO = 0;GLuint m_texture = 0;GLuint m_frameBuffer = 0;GLuint m_RBO = 0;GLuint m_fVBO = 0;GLuint m_fVAO = 0;GLuint m_textureFBO = 0;QOpenGLShaderProgram *m_programScreen = nullptr;QOpenGLShaderProgram *m_shaderProgram = nullptr;
private:Ui::CMainWindow *ui;
};
#endif //MAINWINDOW_H
#include "MainWindow.h"CMainWindow::CMainWindow(QWidget* parent): QOpenGLWidget(parent), ui(new Ui::CMainWindow)
{ui->setupUi(this);m_img = QImage("2.jpg");//picturem_width = m_img.width();m_height = m_img.height();m_dataSize = m_width * m_height * 3;
}CMainWindow::~CMainWindow()
{delete ui;glDeleteVertexArrays(1, &m_VAO);glDeleteBuffers(1, &m_VBO);glDeleteBuffers(1, &m_EBO);glDeleteVertexArrays(1, &m_fVAO);glDeleteBuffers(1, &m_fVBO);glDeleteBuffers(1, &m_frameBuffer);glDeleteBuffers(1, &m_RBO);
}
void CMainWindow::initFBO()
{glGenFramebuffers(1, &m_frameBuffer);glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);glGenTextures(1, &m_textureFBO);glBindTexture(GL_TEXTURE_2D, m_textureFBO);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);//TODOglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glBindTexture(GL_TEXTURE_2D, 0);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureFBO, 0);glGenRenderbuffers(1, &m_RBO);glBindRenderbuffer(GL_RENDERBUFFER, m_RBO);glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_width, m_height);glBindRenderbuffer(GL_RENDERBUFFER, 0);glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RBO);if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)qDebug() << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" ;glBindFramebuffer(GL_FRAMEBUFFER, 0);char vertexShaderSource[] ="#version 450 core\n""layout (location = 0) in vec2 aPos;\n""layout (location = 1) in vec2 aTexCoords;\n""out vec2 TexCoords;\n""void main()\n""{\n""   gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);\n""TexCoords = aTexCoords;\n""}\n";char fragmentShaderSource[] ="#version 450 core\n""out vec4 FragColor;\n""in vec2 TexCoords;\n""uniform sampler2D screenTexture;\n""void main()\n""{\n""   FragColor = texture(screenTexture, TexCoords);\n""}\n";m_programScreen = new QOpenGLShaderProgram;m_programScreen->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);m_programScreen->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);m_programScreen->link();m_programScreen->bind();m_programScreen->setUniformValue("screenTexture", 1);m_programScreen->release();float fb_Vertices[] = {// positions   // texCoords-1.0f,  1.0f,  0.0f, 1.0f,-1.0f, -1.0f,  0.0f, 0.0f,1.0f, -1.0f,  1.0f, 0.0f,-1.0f,  1.0f,  0.0f, 1.0f,1.0f, -1.0f,  1.0f, 0.0f,1.0f,  1.0f,  1.0f, 1.0f};glGenVertexArrays(1, &m_fVAO);glBindVertexArray(m_fVAO);glGenBuffers(1, &m_fVBO);glBindBuffer(GL_ARRAY_BUFFER, m_fVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(fb_Vertices), fb_Vertices, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(float)));glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);}void CMainWindow::initializeGL()
{this->initializeOpenGLFunctions();char vertexShaderSource[] ="#version 450 core\n""layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec3 aColor;\n""layout(location = 2) in vec2 aTexcood;\n""out vec3 vertexColor;\n""out vec2 m_tex;\n""void main()\n""{\n""   m_tex = aTexcood;\n""   vertexColor = aColor;\n""   gl_Position = vec4(aPos, 1.0);\n""}\n";char fragmentShaderSource[] ="#version 450 core\n""out vec4 FragColor;\n""in vec3 vertexColor;\n""in vec2 m_tex;\n""uniform sampler2D ourTexture;\n""void main()\n""{\n""   FragColor = texture2D(ourTexture, m_tex) * vec4(vertexColor, 1.0f);\n""}\n";m_shaderProgram = new QOpenGLShaderProgram;m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);m_shaderProgram->link();m_shaderProgram->bind();m_shaderProgram->setUniformValue("ourTexture", 0);m_shaderProgram->release();GLfloat vertices[] = {-1.0f, -1.0f,0.0f, 0.0f,0.0f,1.0f, 0.0f,0.0f,1.0f, -1.0f,0.0f, 0.0f,1.0f,0.0f, 1.0f,0.0f,1.0f,  1.0f,0.0f, 1.0f,0.0f,0.0f, 1.0f,1.0f,-1.0f,  1.0f,0.0f, 0.0f,1.0f,1.0f, 0.0f,1.0f,};GLuint indices[] = {0,1,2,0,2,3};glGenVertexArrays(1, &m_VAO);glBindVertexArray(m_VAO);glGenBuffers(1, &m_VBO);glBindBuffer(GL_ARRAY_BUFFER, m_VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glGenBuffers(1, &m_EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2);glBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);glGenTextures(1, &m_texture);glBindTexture(GL_TEXTURE_2D, m_texture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_img.bits());//TODOglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glGenerateMipmap(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, 0);//初始化FBOinitFBO();}void CMainWindow::paintGL()
{glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);glEnable(GL_DEPTH_TEST);glClearColor(0.5f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);m_shaderProgram->bind();glBindVertexArray(m_VAO);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_texture);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);glBindVertexArray(0);glBindTexture(GL_TEXTURE_2D, 0);m_shaderProgram->release();/********** 关键之处 ***********/GLuint fb = context()->defaultFramebufferObject();glBindFramebuffer(GL_FRAMEBUFFER, fb);glDisable(GL_DEPTH_TEST);glClearColor(1.0f, 1.0f, 1.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glViewport(0, 0, m_width, m_height);m_programScreen->bind();glBindVertexArray(m_fVAO);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, m_textureFBO);glDrawArrays(GL_TRIANGLES, 0, 6);glBindVertexArray(0);glBindTexture(GL_TEXTURE_2D, 0);m_programScreen->release();}void CMainWindow::resizeGL(int w, int h)
{glViewport(0, 0, w, h);
}

qt中采集场景如图
在这里插入图片描述

下面给出glfw的例子

glfw

首先初始化 OpenGL、GLFW 和 GLEW,也可以用glad,并创建了 MSAA FBO、颜色纹理、深度 RBO 和 PBO。然后,在渲染循环中,先将场景渲染到 MSAA FBO 中,再将 FBO 中的像素数据读取到 PBO 中,并对 PBO 中的像素数据进行处理。最后,清理资源并退出程序。当然实际应用中确实需要根据具体需求进行更多的错误处理和优化。

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdlib>// 窗口尺寸
const int WIDTH = 800;
const int HEIGHT = 600;// 创建 PBO
GLuint pbo;
// 创建 MSAA FBO
GLuint fbo;
// 颜色纹理
GLuint colorTexture;
// 深度 RBO
GLuint depthRBO;void init() {// 初始化 GLFWif (!glfwInit()) {std::cerr << "Failed to initialize GLFW" << std::endl;exit(EXIT_FAILURE);}// 创建窗口GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "MSAA with PBO", nullptr, nullptr);if (!window) {std::cerr << "Failed to create GLFW window" << std::endl;glfwTerminate();exit(EXIT_FAILURE);}// 将窗口设置为当前上下文glfwMakeContextCurrent(window);// 初始化 GLEWglewExperimental = GL_TRUE;if (glewInit()!= GLEW_OK) {std::cerr << "Failed to initialize GLEW" << std::endl;exit(EXIT_FAILURE);}// 开启多重采样抗锯齿glEnable(GL_MULTISAMPLE);// 创建 FBOglGenFramebuffers(1, &fbo);glBindFramebuffer(GL_FRAMEBUFFER, fbo);// 创建颜色纹理glGenTextures(1, &colorTexture);glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, colorTexture);glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, WIDTH, HEIGHT, GL_TRUE);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, colorTexture, 0);// 创建深度 RBOglGenRenderbuffers(1, &depthRBO);glBindRenderbuffer(GL_RENDERBUFFER, depthRBO);glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT);glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRBO);// 检查 FBO 是否完整if (glCheckFramebufferStatus(GL_FRAMEBUFFER)!= GL_FRAMEBUFFER_COMPLETE) {std::cerr << "Failed to create FBO" << std::endl;exit(EXIT_FAILURE);}// 创建 PBOglGenBuffers(1, &pbo);glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);glBufferData(GL_PIXEL_PACK_BUFFER, WIDTH * HEIGHT * 4, nullptr, GL_STREAM_READ);
}void renderScene() {// 绑定 MSAA FBO 并渲染场景glBindFramebuffer(GL_FRAMEBUFFER, fbo);glViewport(0, 0, WIDTH, HEIGHT);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 在这里进行场景的绘制操作// 解除绑定 FBOglBindFramebuffer(GL_FRAMEBUFFER, 0);
}void processPixels() {// 将 MSAA FBO 中的像素数据读取到 PBOglBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);// 映射 PBO 到 CPU 可访问的内存GLubyte* pixels = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);if (pixels) {// 在这里处理像素数据,例如保存为图像或进行其他操作// 为了简单起见,这里只是打印一些像素信息for (int i = 0; i < 10; i++) {std::cout << "Pixel " << i << ": ("<< (int)pixels[4 * i] << ", "<< (int)pixels[4 * i + 1] << ", "<< (int)pixels[4 * i + 2] << ", "<< (int)pixels[4 * i + 3] << ")" << std::endl;}// 取消映射 PBOglUnmapBuffer(GL_PIXEL_PACK_BUFFER);}
}int main() {init();// 渲染循环while (!glfwWindowShouldClose(glfwGetCurrentContext())) {renderScene();processPixels();// 交换缓冲区并处理事件glfwSwapBuffers(glfwGetCurrentContext());glfwPollEvents();}// 清理资源glDeleteBuffers(1, &pbo);glDeleteTextures(1, &colorTexture);glDeleteRenderbuffers(1, &depthRBO);glDeleteFramebuffers(1, &fbo);glfwTerminate();return 0;
}

存文件测试

static void saveImage(GLuint& pbo, const std::string& filename, int width, int height) {glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);// 将帧缓冲区内容读取到 PBOglReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);// 映射 PBO 获取数据指针GLubyte* pixels = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);if (pixels){stbi_write_png(filename.c_str(), width, height, 4, pixels, width * 4);glUnmapBuffer(GL_PIXEL_PACK_BUFFER);}else{std::cerr << "Failed to map." << std::endl;}glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

如下图所示,存的图像是倒立镜像的,实际上是正立的三角形,还没有将视频附上去,工作量有些大,等到下一个文章再写。
在这里插入图片描述

相关文章:

融媒体服务中PBO进行多重采样抗锯齿(MSAA)

如果不理解pbo 那先去了解概念&#xff0c;在此不再解释&#xff0c;这是我为了做融合服务器viewpointserver做的一部分工作&#xff0c;融合服务器的功能是将三维和流媒体&#xff0c;AI融合在一起&#xff0c;viewpointserver会直接读取三维工程的文件&#xff0c;同时融合rt…...

说说BPMN概念及应用

BPMN&#xff08;Business Process Modeling and Notation&#xff09;即业务流程建模与标注&#xff0c;是一种由OMG&#xff08;Object Management Group&#xff0c;对象管理组织&#xff09;制定的业务流程建模语言。以下是对BPMN标准的详细解释&#xff1a; 一、BPMN的起…...

【微服务】初识(day1)

基础概念 集群 集群是将一个系统完整的部署到多个服务器&#xff0c;每个服务器提供系统的所有服务&#xff0c;多个服务器可以通过负载均衡完成任务&#xff0c;每个服务器都可以称为集群的节点。 分布式 分布式是将一个系统拆分为多个子系统&#xff0c;多个子系统部署在…...

15分钟学 Python 第40天:Python 爬虫入门(六)第一篇

Day40 &#xff1a;Python 爬取豆瓣网前一百的电影信息 1. 项目背景 在这个项目中&#xff0c;我们将学习如何利用 Python 爬虫技术从豆瓣网抓取前一百部电影的信息。通过这一练习&#xff0c;您将掌握网页抓取的基本流程&#xff0c;包括发送请求、解析HTML、存储数据等核心…...

分层解耦-05.IOCDI-DI详解

一.依赖注入的注解 在我们的项目中&#xff0c;EmpService的实现类有两个&#xff0c;分别是EmpServiceA和EmpServiceB。这两个实现类都加上Service注解。我们运行程序&#xff0c;就会报错。 这是因为我们依赖注入的注解Autowired默认是按照类型来寻找bean对象的进行依赖注入…...

HCIP-HarmonyOS Application Developer 习题(六)

&#xff08;多选&#xff09;1、Harmonyos多窗口交互能力提供了以下哪几种交互方式? A. 平行视界 B.全局消息通知 C.分屏 D.悬浮窗 答案&#xff1a;ACD 分析&#xff1a;系统提供了悬浮窗、分屏、平行视界三种多窗口交互&#xff0c;为用户在大屏幕设备上的多任务并行、便捷…...

【电路基础 · 3】实际电压源 实际电流源;两种电源的等效情况;戴维南模型 诺顿模型(自用)

总览 1.实际电源的两种模型和它们的等效变换 2.两种电源的等效情况 3.戴维南模型 && 诺顿模型 一、实际电源的两种模型和它们的等效变换 1.实际电压源 实际电压源不允许短路。因为它的内阻太小&#xff0c;如果短路&#xff0c;电流很大&#xff0c;可能会烧毁电源…...

案例-猜数字游戏

文章目录 效果展示初始画面演示视频 代码区 效果展示 初始画面 演示视频 猜数字游戏 代码区 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…...

POI数据的处理与分析

POI概念 POI&#xff08;Point of Interest&#xff0c;兴趣点&#xff09;数据指的是地理空间数据中的一类&#xff0c;表示某一具体地点或位置的信息。通常&#xff0c;这些数据包含位置坐标&#xff08;经纬度&#xff09;、名称、地址、类别和其他相关信息。POI 数据广泛应…...

ansible部分模块学习

ansible模块学习 copy模块 copy模块srcsource 源⽂件destdestination ⽬标backupbackupyes 则会在覆盖前进⾏备份mode修改权限owner修改为指定所有者group修改为指定⽤户组 案例1&#xff1a;传输/root/work/scripts/net-tools-install.sh⽂件到/opt/net-tools-install.sh …...

数据库(MySQL):使用命令从零开始在Navicat创建一个数据库及其数据表(二).设置主键自增等特点

前言 在上一节中&#xff0c;主要介绍了 Navicat Premium 17 的使用以及创建一个基础的表格。当时只设置了给数据表补充字段&#xff0c;没有设置给数据表删除字段。现在补充一下。 ALTER TABLE student ADD test int(4); 给名为 student 的数据表添加 test 列&#xf…...

SQL第13课——创建高级联结

本课讲另外一些联结&#xff08;含义和使用方法&#xff09;&#xff0c;如何使用表别名&#xff0c;如何对被联结的表使用聚集函数。 13.1 使用表别名 第7课中使用别名引用被检索的表列&#xff0c;给列起别名的语法如下&#xff1a; SQL除了可以对列名和计算字段使用别名&a…...

订阅ROS2中相机的相关话题并保存RGB、深度和点云图

系统&#xff1a;Ubuntu22.04 ROS2版本&#xff1a;ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…...

Open WebUI | 自托管的类 ChatGPT 网站

Open WebUI 是一个扩展性强、功能丰富且用户友好的自托管 WebUI&#xff0c;旨在完全离线操作。它支持各种 LLM 服务&#xff0c;包括 Ollama 和 OpenAI 兼容的 API。该项目在 GitHub 上已有 38k 星&#xff0c;非常受欢迎。 功能介绍 废话不多说&#xff0c;上图&#xff01;…...

【Python】Python知识总结浅析

Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年首次发布。它以简洁的语法和强大的功能著称&#xff0c;适用于多种应用场景&#xff0c;包括Web开发、数据分析、人工智能、自动化脚本等。 易于学习和使用&#xff1a;Python的语法简洁明了&#xff0c;适合初…...

c#代码介绍23种设计模式_20策略者模式

目录 1、策略模式的定义 2、策略模式的结构 3、涉及到三个角色: 4、策略者模式在.NET中应用 5、策略者模式的适用场景 6、策略者模式的优缺点 7、实现思路 在现实生活中,策略模式的例子也非常常见,例如,中国的所得税,分为企业所得税、外商投资企业或外商企业所得税…...

FPGA-UART串口接收模块的理解

UART串口接收模块 背景 在之前就有写过关于串口模块的文章——《串口RS232的学习》。工作后很多项目都会用到串口模块&#xff0c;又来重新理解一下FPGA串口接收的代码思路。 关于串口相关的参数&#xff0c;以及在文章《串口RS232的学习》中已有详细的描述&#xff0c;这里就…...

复习HTML(基础)

目录 HTML含义 HTML作用 HTML的常用元素 元素的特点 元素的分类 1 是否嵌套关系 2 是否独占一行 块元素&#xff1a;独占一行 行内元素&#xff1a;共享一行 行内元素与块级元素的转换 3是否有结束标签 常用标签 1 标题标签&#xff1a;有六级 我们用h1 ~h6 表…...

Linux聊天集群开发之环境准备

一.windows下远程操作Linux 第一步&#xff1a;在Linux终端下配置openssh&#xff0c;输入netstate -tanp,查看ssh服务是否启动&#xff0c;默认端口22.。 注&#xff1a;如果openssh服务&#xff0c;则需下载。输入命令ps -e|grep ssh, 查看如否配有&#xff0c; ssh-agent …...

can 总线入门———can简介硬件电路

文章目录 0. 前言1. CAN简介2. 主流通讯协议对比3. CAN 硬件电路4. CAN 电平标准5. CAN 收发器 0. 前言 博客内容来自B站上CAN总线入门教程视频讲解&#xff0c;博客中的插图和内容均为视频中的内容。视频链接 CAN总线入门教程 1. CAN简介 先来看看一它名字的意思&#xff0c…...

从DAP-Link看USB虚拟串口设计:手把手教你给STM32F407添加双通道调试功能

从DAP-Link看USB虚拟串口设计&#xff1a;手把手教你给STM32F407添加双通道调试功能 在嵌入式开发中&#xff0c;调试工具的性能直接影响开发效率。传统调试器往往需要额外串口芯片&#xff0c;而现代方案如DAP-Link通过USB CDC类实现虚拟串口&#xff0c;既节省硬件成本又能提…...

竞技编程新利器:IQuest-Coder-V1-40B在算法解题中的实际应用

竞技编程新利器&#xff1a;IQuest-Coder-V1-40B在算法解题中的实际应用 1. 模型概述与核心能力 1.1 IQuest-Coder-V1-40B技术背景 IQuest-Coder-V1-40B-Instruct是专为软件工程和竞技编程设计的新一代代码大语言模型。该模型基于创新的代码流多阶段训练范式构建&#xff0c…...

能耗监控系统:OpenClaw+GLM-4-7-Flash分析家庭用电报告

能耗监控系统&#xff1a;OpenClawGLM-4-7-Flash分析家庭用电报告 1. 为什么需要本地化的能耗监控系统 去年夏天&#xff0c;我家电费账单突然比平时高出40%。当我尝试用市面上的智能电表分析工具时&#xff0c;发现需要将用电数据上传到第三方平台才能生成报告——这意味着我…...

寻音捉影·侠客行企业应用:制药企业GMP培训录音中自动核查‘无菌操作’等SOP术语

寻音捉影侠客行企业应用&#xff1a;制药企业GMP培训录音中自动核查‘无菌操作’等SOP术语 1. 引言&#xff1a;制药企业的音频管理痛点 在制药企业的日常运营中&#xff0c;GMP&#xff08;良好生产规范&#xff09;培训是确保药品质量和生产安全的关键环节。每次培训都会产…...

Day | 11 【苍穹外卖统计业务的实现:含详细思路分析】

&#x1f525;个人主页&#xff1a;北极的代码&#xff08;欢迎来访&#xff09; &#x1f3ac;作者简介&#xff1a;java后端学习者 ❄️个人专栏&#xff1a;苍穹外卖日记&#xff0c;SSM框架深入&#xff0c;JavaWeb ✨命运的结局尽可永在&#xff0c;不屈的挑战却不可须臾或…...

claude code 使用

1&#xff0c;模型更换进入C盘目录 C:\Users\****\.claude 找到 settings.json这个是通义千问模型{"env": {"ANTHROPIC_AUTH_TOKEN": "sk-3db74945b4a****","ANTHROPIC_BASE_URL": "https://dashscope.aliyuncs.com/apps/anthro…...

终极指南:如何快速导出并永久保存微信聊天记录

终极指南&#xff1a;如何快速导出并永久保存微信聊天记录 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾担心更换手机后丢失宝贵的微信聊天记录&#xff1f;工…...

Phi-3-mini-128k-instruct与STM32开发:生成嵌入式C代码与调试逻辑

Phi-3-mini-128k-instruct与STM32开发&#xff1a;生成嵌入式C代码与调试逻辑 1. 引言 如果你玩过STM32&#xff0c;尤其是像STM32F103C8T6这种经典的“蓝色药丸”最小系统板&#xff0c;肯定对下面这些场景不陌生&#xff1a;为了点亮一个LED&#xff0c;翻遍数据手册&#…...

水墨江南模型软件测试实践:生成结果的稳定性与一致性验证

水墨江南模型软件测试实践&#xff1a;生成结果的稳定性与一致性验证 最近在项目里用上了水墨江南这个AI绘画模型&#xff0c;效果确实惊艳&#xff0c;那种烟雨朦胧、小桥流水的意境拿捏得很准。但问题也来了&#xff0c;当我们想把它集成到产品里&#xff0c;给用户稳定提供…...

三维点云到二维图像投影的实战指南:从原理到代码实现

1. 三维点云投影二维图像的核心原理 第一次接触三维点云投影时&#xff0c;我也被各种坐标系转换绕得头晕。后来发现只要抓住一个核心&#xff1a;三维到二维的投影本质上是坐标系转换的接力赛。想象你拿着手机拍照&#xff0c;物体从现实世界到手机屏幕的旅程&#xff0c;就是…...