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

【Qt】图片绘制不清晰的问题

背景

实现一个图片浏览器,可以支持放大/缩小查看图片。主要组件如下:

// canvaswidget.h
#ifndef CANVASWIDGET_H
#define CANVASWIDGET_H#include <QWidget>class CanvasWidget : public QWidget
{Q_OBJECT
public:explicit CanvasWidget(QImage img, QWidget *parent = nullptr);void zoomIn();void zoomOut();signals:protected:QSize sizeHint();void paintEvent(QPaintEvent *event) override;void wheelEvent(QWheelEvent *event) override;private:qreal scale;QPixmap pixmap;
};#endif // CANVASWIDGET_H
// canvaswidget.cpp
#include "canvaswidget.h"
#include <QWheelEvent>
#include <QPainter>
#include <QPixmap>CanvasWidget::CanvasWidget(QImage img, QWidget *parent): QWidget{parent}, scale(1.0)
{pixmap = QPixmap::fromImage(img);
}void CanvasWidget::zoomIn() {scale = fmin(scale + 0.1, 10);update();
}void CanvasWidget::zoomOut() {scale = fmax(scale - 0.1, 0.1);update();
}void CanvasWidget::paintEvent(QPaintEvent *event) {if(!pixmap) {return QWidget::paintEvent(event);}QPainter p(this);p.setRenderHint(QPainter::Antialiasing);p.setRenderHint(QPainter::SmoothPixmapTransform);p.scale(scale, scale);p.drawPixmap(0,0,pixmap); // draw image
}void CanvasWidget::wheelEvent(QWheelEvent *event)
{if(event->modifiers() == Qt::ControlModifier) {QPointF delta = event->angleDelta();int v_delta = delta.y();if(v_delta > 0) {zoomIn();} else {zoomOut();}update();adjustSize();} else {QWidget::wheelEvent(event);}
}
QSize CanvasWidget::sizeHint()
{return QSize(800,800);
}

问题

在这种实现方式下,缩小图片时,图片会变得非常模糊,有非常明显的锯齿问题。
如下图所示,A是Windows自带图片查看器的效果,B是上述实现的效果。可以看出虽然B比A更大,但却更不清晰,有明显的锯齿。

在这里插入图片描述

尝试解决

为了解决这个不清晰的问题,尝试了很多种方案,方案及其实现方法如下:

不scale QPainter,而是在指定区域绘制Pixmap

p.drawPixmap(0,0,pixmap.size().width() * scale, pixmap.size().height * scale, pixmap);

使用QGraphicsView绘制图片

    QPixmap pixmap("/path/to/image.png");QGraphicsScene scene;QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);scene.addItem(item);QGraphicsView view;view.resize(800,600);view.setScene(&scene);// Optionally set view propertiesview.setRenderHint(QPainter::Antialiasing);   // Improve rendering qualityview.setDragMode(QGraphicsView::ScrollHandDrag); // Enable draggingview.setAlignment(Qt::AlignCenter);           // Center the imageview.fitInView(item, Qt::KeepAspectRatio);    // Scale to fit the view// Show the viewview.show();

使用QWebEngineView绘制图片

    QWebEngineView web_view;QString htmlContent = R"(<!DOCTYPE html><html><head><style>body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; }img { max-width: 100%; max-height: 100%; }</style></head><body><img src="/path/to/image.png" alt="Image Not Found"></body></html>)";web_view.setHtml(htmlContent, QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/"));web_view.resize(800, 600);web_view.show();

将图片作为texture在QOpenGLWidget中绘制图片

#ifndef OPENGLIMAGE_H
#define OPENGLIMAGE_H#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <memory>class OpenGLImage : public QOpenGLWidget, protected QOpenGLFunctions
{Q_OBJECT
public:explicit OpenGLImage(QWidget *parent = nullptr);~OpenGLImage();QSize minimumSizeHint() const override;QSize sizeHint() const override;void loadImage(QString& path);QMatrix4x4 getViewMatrix() const;QMatrix4x4 getModelMatrix() const;protected:void initializeGL() override;void paintGL() override;void resizeGL(int width, int height) override;void wheelEvent(QWheelEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void keyPressEvent(QKeyEvent *event) override;void keyReleaseEvent(QKeyEvent* event) override;private:void setupDefaultShaderProgram();void setupDefaultTransform();void drawImage();void moveImage(const QPointF& cursorPos);void rotateImage(const QPointF& cursorPos);std::unique_ptr<QOpenGLShaderProgram> shaderProgram;std::unique_ptr<QOpenGLTexture> texture;std::unique_ptr<QImage> image;QOpenGLBuffer vbo;QOpenGLVertexArrayObject vao;QOpenGLBuffer ebo;bool isTextureSync;QColor clearColor;float norm_h;QSize viewSize;QVector3D cameraPos;QVector3D imagePos;QVector3D imageAngle;float viewAngle;float focalLength;QPointF lastClickPos;bool isRotMode;
};#endif // OPENGLIMAGE_H
#include "glimageview.h"
#include <vector>
#include <QtMath>
#include <iostream>
#include <QResizeEvent>#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1#define DEFAULT_CAMERA_POS_X (0.0f)
#define DEFAULT_CAMERA_POS_Y (0.0f)
#define DEFAULT_CAMERA_POS_Z (-2.0f)#define CLIP_NEAR (0.01f)
#define CLIP_FAR (100.0f)#define MIN_FOCAL 1.0f
#define MAX_FOCAL 150.0fOpenGLImage::OpenGLImage(QWidget *parent): QOpenGLWidget(parent),shaderProgram(nullptr),texture(nullptr),image(nullptr),isTextureSync(false),clearColor(Qt::gray),norm_h(-1.0f),viewSize(640,640),ebo(QOpenGLBuffer::Type::IndexBuffer),viewAngle(45.0f),isRotMode(false)
{focalLength = 1/qTan(qDegreesToRadians(viewAngle/2.0f));
}OpenGLImage::~OpenGLImage()
{
}void OpenGLImage::initializeGL()
{initializeOpenGLFunctions();setupDefaultShaderProgram();
}void OpenGLImage::paintGL()
{glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);drawImage();
}void OpenGLImage::resizeGL(int width, int height)
{viewSize = QSize(width, height);
}QSize OpenGLImage::minimumSizeHint() const
{int min_h = (int)(320.0f * norm_h);return QSize(320, min_h);
}QSize OpenGLImage::sizeHint() const
{return viewSize;
}void OpenGLImage::wheelEvent(QWheelEvent *event)
{QPoint numDegrees = event->angleDelta() / 8;float degree = (float)numDegrees.y() * -1.0f;degree /= 2.0f;if (viewAngle+degree > MIN_FOCAL && viewAngle+degree < MAX_FOCAL) {viewAngle += degree;focalLength = 1/qTan(qDegreesToRadians(viewAngle/2.0f));}event->accept();update();
}void OpenGLImage::drawImage() {if (image.get() == nullptr) return;glViewport(0, 0, viewSize.width(), viewSize.height());// qDebug() << viewSize.width() << ", " << viewSize.height() << "\n";// setup vertex array objectif (!vao.isCreated()){vao.create();}vao.bind();// setup vertex buffer objectstd::vector<GLfloat> coords;// bottom left;coords.push_back(-1.0f);coords.push_back(-1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(0.0f);coords.push_back(0.0f);// bottom rightcoords.push_back(1.0f);coords.push_back(-1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(1.0f);coords.push_back(0.0f);// top rightcoords.push_back(1.0f);coords.push_back(1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(1.0f);coords.push_back(1.0f);// top leftcoords.push_back(-1.0f);coords.push_back(1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(0.0f);coords.push_back(1.0f);if (!vbo.isCreated()){vbo.create();}vbo.bind();vbo.allocate(coords.data(), coords.size()*sizeof(GLfloat));// setup vertex element object// [bl, br, tr, tl]static const std::vector<GLuint> indices {0, 1, 2,2, 3, 0};if (!ebo.isCreated()){ebo.create();}ebo.bind();ebo.allocate(indices.data(), indices.size()*sizeof(GLuint));// associate vertex and buffershaderProgram->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);shaderProgram->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);shaderProgram->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 5 * sizeof(GLfloat));shaderProgram->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat));// assign transform matricesQMatrix4x4 projection; // projection matrxi must update everytime!float ratio = ((float)viewSize.width())/((float)viewSize.height());projection.perspective(viewAngle, ratio, CLIP_NEAR, CLIP_FAR);QMatrix4x4 model = getModelMatrix();model.rotate(imageAngle.x(), 0.0f, 1.0f, 0.0f);model.rotate(imageAngle.y()*-1.0f, 1.0f, 0.0f, 0.0f);shaderProgram->setUniformValue("model", model);QMatrix4x4 viewMat = getViewMatrix();shaderProgram->setUniformValue("view", viewMat);shaderProgram->setUniformValue("projection", projection);// setup textureif (texture.get() == nullptr || !isTextureSync) {QImage& img = *image.get();texture = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(img));isTextureSync = true;}texture->bind();glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
}void OpenGLImage::setupDefaultShaderProgram()
{QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);const char *vsrc ="attribute highp vec3 vertex;\n""uniform mediump mat4 model;\n""uniform mediump mat4 view;\n""uniform mediump mat4 projection;\n""\n""attribute mediump vec2 texCoord;\n""varying mediump vec2 texc;\n""void main(void)\n""{\n""    gl_Position = projection * view * model * vec4(vertex, 1.0f);\n""    texc = texCoord;\n""}\n";vshader->compileSourceCode(vsrc);QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);const char *fsrc ="uniform sampler2D texture;\n""varying mediump vec2 texc;\n""void main(void)\n""{\n""    gl_FragColor = texture2D(texture, texc);\n""}\n";fshader->compileSourceCode(fsrc);shaderProgram = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram(this));shaderProgram->addShader(vshader);shaderProgram->addShader(fshader);// assign locations of vertex and texture coordinatesshaderProgram->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);shaderProgram->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);shaderProgram->link();shaderProgram->bind();shaderProgram->setUniformValue("texture", 0);
}void OpenGLImage::setupDefaultTransform() {cameraPos = QVector3D(DEFAULT_CAMERA_POS_X, DEFAULT_CAMERA_POS_Y, DEFAULT_CAMERA_POS_Z);imagePos = QVector3D();imageAngle = QVector3D();
}void OpenGLImage::loadImage(QString& path) {QImage* p = new QImage(QImage(path).mirrored());image = std::unique_ptr<QImage>(p);isTextureSync = false;norm_h = (float)((float)image->height()/(float)image->width());int h = (int)((float)viewSize.width()*norm_h);viewSize = QSize(viewSize.width(), h);resize(viewSize);setupDefaultTransform();
}QMatrix4x4 OpenGLImage::getViewMatrix() const {QVector3D up(0.0f, 1.0f, 0.0f);QMatrix4x4 ret;ret.translate(cameraPos);QVector3D center(cameraPos.x(), cameraPos.y(), imagePos.z());ret.lookAt(QVector3D(), center, up);return ret;
}QMatrix4x4 OpenGLImage::getModelMatrix() const {QMatrix4x4 ret;ret.translate(imagePos);return ret;
}void OpenGLImage::mousePressEvent(QMouseEvent *event) {lastClickPos = event->localPos();qDebug() << lastClickPos;
}// movement is weird somehow...
void OpenGLImage::mouseMoveEvent(QMouseEvent *event) {if (isRotMode) {rotateImage(event->localPos());} else {moveImage(event->localPos());}lastClickPos = event->pos();event->accept();update();
}void OpenGLImage::moveImage(const QPointF &cursorPos) {QPointF delta = cursorPos-lastClickPos;float factor = qAbs(imagePos.z()-cameraPos.z()) / focalLength;factor /= (qMax(viewSize.width(), viewSize.height()));factor *= 3.5f;qDebug() << "dx=" << delta.x();qDebug() << "dy=" << delta.y();qDebug() << "L=" << (imagePos.z()-cameraPos.z());qDebug() << "focalLength=" << focalLength;qDebug() << "factor" << factor;delta *= factor;imagePos += QVector3D(delta.x(), -1.0f*delta.y(), 0.0f);
}void OpenGLImage::rotateImage(const QPointF &cursorPos) {QPointF delta = cursorPos-lastClickPos;delta.setX(delta.x() / (qreal)viewSize.width());delta.setX(delta.x() * 180.0f);delta.setY(delta.y() / (qreal)viewSize.height());delta.setY(delta.y() * -180.0f);qDebug() << delta;imageAngle += QVector3D(delta.x(), delta.y(), 0.0f);
}void OpenGLImage::mouseReleaseEvent(QMouseEvent *event) {
}void OpenGLImage::keyPressEvent(QKeyEvent *event) {if (event->key() == Qt::Key_Control) {qDebug() << "ctrl is pressed";isRotMode = true;} else {// call base class method as event is not handled.QOpenGLWidget::keyPressEvent(event);}
}void OpenGLImage::keyReleaseEvent(QKeyEvent *event) {if (event->key() == Qt::Key_Control) {qDebug() << "ctrl is released";isRotMode = false;} else {// call base class method as event is not handled.QOpenGLWidget::keyReleaseEvent(event);}
}

如下图所示,不同方案的效果略有不同,但所有方案都会出现缩小后图片变模糊的问题:
在这里插入图片描述

问题所在

最终在网友们的帮助下,发现了问题所在:这些实现方法在修改图片大小时都会对图片进行压缩。

比如void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source),在指定矩形区域内绘制图片,如果指定的矩形区域比图片本身尺寸小,绘制过程中就会对图片进行压缩,导致图片变得模糊。

如果想要将图片变小的同时,保持图片的清晰度,应该直接使用QPixmap的scaled函数:

p.drawPixmap(0,0,pixmap.scaled(pixmap.size() * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation));

效果如下,左边是新的实现方法的效果,右边是Windows自带的图片查看软件的效果:
在这里插入图片描述

其实我一开始的实现方法不算错,甚至是官方建议的,在QPixmap的文档中提到:

In some cases it can be more beneficial to draw the pixmap to a painter with a scale set rather than scaling the pixmap. This is the case when the painter is for instance based on OpenGL or when the scale factor changes rapidly.

图片查看器其实就会频繁改变scale按照建议就是应该采用修改QPainter的scale的方法,但这种方法确实会导致图片清晰度变低,出现模糊的问题。

相关文章:

【Qt】图片绘制不清晰的问题

背景 实现一个图片浏览器&#xff0c;可以支持放大/缩小查看图片。主要组件如下&#xff1a; // canvaswidget.h #ifndef CANVASWIDGET_H #define CANVASWIDGET_H#include <QWidget>class CanvasWidget : public QWidget {Q_OBJECT public:explicit CanvasWidget(QImag…...

2008年IMO几何预选题第3题

设有两个圆凸内接四边形 A B Q D ABQD ABQD 和 B P Q C BPQC BPQC, 在线段 P Q PQ PQ 上存在一点 E E E, 使得, ∠ E A P ∠ E D Q \angle EAP\angle EDQ ∠EAP∠EDQ, ∠ E B P ∠ E C Q \angle EBP\angle ECQ ∠EBP∠ECQ. 求证: A A A, B B B, C C C, D D D 四点共…...

NAT拓展

NAT ALG&#xff08;NAT应用级网&#xff09; 为某些应用层协议&#xff0c;因为其报文内容可能携带IP相关信息&#xff0c;而普通NAT转化无法将这些IP转化&#xff0c;从而导致协议无法正常运行 例如FTP&#xff0c;DHCP&#xff0c;RSTP&#xff0c;ICMP&#xff0c;IPSEC…...

Flink四大基石之State

State state 可以理解为-- 历史计算结果 有状态计算和无状态计算 无状态计算: 不需要考虑历史数据, 相同的输入,得到相同的输出!如:map, 将每个单词记为1, 进来一个hello, 得到(hello,1),再进来一个hello,得到的还是(hello,1) 有状态计算: 需要考虑历史数据, 相同的输入,可…...

Spacy小笔记:zh_core_web_trf、zh_core_web_lg、zh_core_web_md 和 zh_core_web_sm区别

Spacy小笔记 最近频繁用到spacy&#xff0c;就小记一下。 2024.11.29 zh_core_web_trf、zh_core_web_lg、zh_core_web_md 和 zh_core_web_sm区别 首先&#xff0c;它们都是预训练的中文模型&#xff1a; zh_core_web_trf:395M 架构: 基于 Transformer 架构&#xff08;bert…...

第六届智能控制、测量与信号处理国际学术会议 (ICMSP 2024)

重要信息 2024年11月29日-12月1日 中国陕西西安石油大学雁塔校区 大会官网&#xff1a;www.icmsp.net 大会简介 第六届智能控制、测量与信号处理国际学术会议&#xff08;ICMSP 2024&#xff09;由西安石油大学、中海油田服务股份有限公司、浙江水利水电学院与中国石油装备…...

docker服务容器化

docker服务容器化 1 引言2 多个容器间网络联通2.1 单独创建关联2.2 创建时关联 3 服务搭建3.1 镜像清单3.2 容器创建 4 联合实战4.2 flink_sql之kafka到starrocks4.2 flink_sql之mysql到starrocks 5 文献借鉴 1 引言 ​ 利用docker可以很效率地搭建服务&#xff0c;本文在win1…...

【QT】控件8

1.QDial 通过调节旋钮位置来控制窗口的不透明度&#xff1a; void Widget::on_dial_valueChanged(int value) {qDebug()<<value;this->setWindowOpacity((double)value/100); }效果演示&#xff1a; 2.Date/Time Edit 计算两个日期的差值 ui界面设计 计算按钮按下…...

漫谈推理谬误——错误因果

相关文章 漫谈推理谬误——错误假设-CSDN博客文章浏览阅读736次&#xff0c;点赞22次&#xff0c;收藏3次。在日常生活中&#xff0c;我们会面临各种逻辑推理&#xff0c;有些看起来一目了然&#xff0c;有些非常的科学严谨&#xff0c;但也有很多似是而非&#xff0c;隐藏了陷…...

【数据结构】队列实现剖析:掌握队列的底层实现

在计算机科学中&#xff0c;**队列&#xff08;Queue&#xff09;**是一种常见的数据结构&#xff0c;它遵循先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的原则。队列的应用非常广泛&#xff0c;例如任务调度、资源管理、进程通信等。本篇文章旨在为计…...

【C++】IO库(二):文件输入输出

8.2 文件输入输出 头文件 fstream 定义了三个类型来之支持文件IO&#xff0c;分别是&#xff1a; ifstream&#xff1a;从一个给定文件读取数据&#xff1b;ofstream&#xff1a;向一个给定文件写入数据&#xff1b;fstream&#xff1a;读写给定文件。 在 C 当中&#xff0c…...

105.【C语言】数据结构之二叉树求总节点和第K层节点的个数

目录 1.求二叉树总的节点的个数 1.容易想到的方法 代码 缺陷 思考:能否在TreeSize函数内定义静态变量解决size的问题呢? 其他写法 运行结果 2.最好的方法:分而治之 代码 运行结果 2.求二叉树第K层节点的个数 错误代码 运行结果 修正 运行结果 其他写法 1.求二…...

力扣637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。 提示&#xff1a; 树中节点数量在 [1, 104] 范围内-231 < Node.val < 231 - 1 代码&#xff1a; /*** Definition for a binary tree node.* stru…...

【前端】Next.js 服务器端渲染(SSR)与客户端渲染(CSR)的最佳实践

关于Next.js 服务器端渲染&#xff08;SSR&#xff09;与客户端渲染&#xff08;CSR&#xff09;的实践内容方面&#xff0c;我们按下面几点进行阐述。 1. 原理 服务器端渲染 (SSR): 在服务器上生成完整的HTML页面&#xff0c;然后发送给客户端。这使得用户在首次访问时能够…...

路径规划之启发式算法之一:A-Star(A*)算法

A*算法是一种启发式搜索算法&#xff0c;常用于解决路径规划问题。 一、A*算法的定义与原理 A*算法是一种用于在图形或网格中查找最短路径的算法。它在搜索过程中综合考虑了每个节点的实际距离&#xff08;g值&#xff09;和预估距离&#xff08;h值&#xff09;&#xff0c;以…...

Android复习代码1-4章

public class RudioButton extends AppCompatActivity {Overrideprotected void onCreate(Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_rudio_button);// 找到RadioGroup和TextView的实例RadioGroup radioGrou…...

【问题】webdriver.Chrome()设置参数executable_path报不存在

场景1: 标红报错unresolved reference executable_path 场景2: 执行报错TypeError: __init__() got an unexpected keyword argument executable_path 原因&#xff1a; 上述两种场景是因为selenium4开始不再支持某些初始化参数。比如executable_path 解决&#xff1a; 方案…...

win10系统安装docker-desktop

1、开启Hyper-v ———————————————— Hyper-V 是微软提供的一种虚拟化技术&#xff0c;它允许你在同一台物理计算机上运行多个独立的操作系统实例。这种技术主要用于开发、测试、以及服务器虚拟化等领域。 —————————————————————— &#…...

小程序-基于java+SpringBoot+Vue的乡村研学旅行平台设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…...

组件A底部栏(position: fixed )事件使用$emit更新内容失败bug解决

今天遇到一个很离奇的bug&#xff0c;记录一下 问题&#xff1a;在组件内底部栏使用$emit触发按钮事件但打印出来的值是初始化的值&#xff0c;更新的值被重置导致更新失败 原因&#xff1a;组件内底部使用了 position: fixed; 固定&#xff0c; 导致组件内插槽 this 与 保存按…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...