Qt——示波器/图表 QCustomPlot
一、介绍
QCustomPlot是一个用于绘图和数据可视化的Qt C++小部件。它没有进一步的依赖关系,提供友好的文档帮助。这个绘图库专注于制作好看的,出版质量的2D绘图,图形和图表,以及为实时可视化应用程序提供高性能。QCustomPlot可以导出各种格式,如矢量化的PDF文件和光栅化的图像,如PNG, JPG和BMP。QCustomPlot是用于在应用程序中显示实时数据以及为其他媒体生成高质量图的解决方案。
二、配置
1)下载
官方网站
http://www.qcustomplot.com/
从官网下载文件,选择2.1版本以上,因为这会开始支持Qt6了。可以选择源文件+实例+说明文档全部下载,或者选择下载单动态库或纯源码,文件不大建议全部下载。
2)QtCreator配置
新建一个Qt Widgets Application工程。
把下载好的qcustomplot.h和qcustomplot.cpp放到工程下,右击项目,添加现有文件。
对话框中选择选择qcustomplot.h和qcustomplot.cpp文件添加到项目中,并在pro文件中添加Qt += printsupport。
双击mainwindows.ui进入Designer界面,新建一个widget部件。
右击widget部件,选择提升为...。
在类名称里面输入QCustomPlot,选择“添加”,然后选择“提升”。这里要注意头文件路径,如果你是放在最外层(和pro文件同级),直接默认值就行。如果是放在某文件夹下,比如新建了一个custom文件夹并放置在里面,那么头文件这一栏应该是“custom/qcustomplot.h”。
提升之后,widget类已经被改成QCustomPlot。
在mianwindows.cpp构造函数添加如下demo代码。
// add two new graphs and set their look:
ui->widget->addGraph();
ui->widget->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph
ui->widget->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
ui->widget->addGraph();
ui->widget->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph
// generate some points of data (y0 for first, y1 for second graph):
QVector x(251), y0(251), y1(251);
for (int i=0; i<251; ++i)
{
x[i] = i;
y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosine
y1[i] = qExp(-i/150.0); // exponential envelope
}
// configure right and top axis to show ticks but no labels:
// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
ui->widget->xAxis2->setVisible(true);
ui->widget->xAxis2->setTickLabels(false);
ui->widget->yAxis2->setVisible(true);
ui->widget->yAxis2->setTickLabels(false);
// make left and bottom axes always transfer their ranges to right and top axes:
connect(ui->widget->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->widget->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->yAxis2, SLOT(setRange(QCPRange)));
// pass data points to graphs:
ui->widget->graph(0)->setData(x, y0);
ui->widget->graph(1)->setData(x, y1);
// let the ranges scale themselves so graph 0 fits perfectly in the visible area:
ui->widget->graph(0)->rescaleAxes();
// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
ui->widget->graph(1)->rescaleAxes(true);
// Note: we could have also just called ui->widget->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
编译构建项目成功后,执行即可看到demo图表。
3)添加说明文档
下载的文档可以直接添加到QtCreator的帮助里面。
把文件放到 D:\Qt\Qt5.9.6\Tools\QtCreator\share\doc\qtcreator底下
QtCreator选择工具-选项。
选择-文档-添加,在弹出的界面选择把qcustomplot.qch文件加进来。
如此,我们在帮助界面搜索qcustomplot就可以直接浏览帮助文档。 
三、常用功能详解
1)曲线
使用addGraph()方法新建曲线,返回一个QCPGraph对象指针,后续使用此指针或者根据索引获取指针对曲线动作。
建议使用保存对象指针方法操作曲线,因为索引容易误操作,比如当新建两条曲线的时候,删除第一条,第二条索引会从1变成0,高亮的时候索引也会有异常。
//初始化返回类指针
QCPGraph *graph1 = ui->plot->addGraph();
//根据索引获取类指针
QCPGraph *graph1 = ui->plot->graph(index)
如果你需要两条曲线在不同的坐标系,比如X轴相同,Y轴不同,那么就需要在初始化的时候指定坐标系,或者后续指定。
QCPGraph *graph1 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis);
QCPGraph *graph2 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis2);
//或者在addGraph之后使用
graph1->setKeyAxis(ui->plot->xAxis);
graph1->setValueAxis(ui->plot->yAxis);
graph2->setKeyAxis(ui->plot->xAxis2);
graph2->setValueAxis(ui->plot->yAxis2);
使用setData()方法设置曲线坐标数据,坐标数据使用QVector封装,使用此方法会覆盖原先的曲线。注意这里x和y的动态数组长度要一致,否则控制台会报错并失效。
QVector x0(251), y0(251);
for (int i=0; i<251; ++i)
{
x[i] = i;
y0[i] = qExp(-i/150.0)*qCos(i/10.0);
}
ui->plot->graph(0)->setData(x0,y0);//写入数据
使用addData()方法在原先基础上添加数据,适用于动态曲线,当然如果一直重新setData也是可以,不建议这么做。
ui->plot->graph(0)->addData(x0, y0)
使用clear()清空数据,但是曲线还保留着。
ui->plot->graph(0)->data()->clear();
使用setName()方法设置曲线名称,name方法返回曲线名称。
ui->plot->graph(0)->setName(QString(“graph1”));
qDebug()<Plot->graph(0)->name();
使用removeGraph()方法传入QCPGraph指针或者索引移除曲线。
ui->plot->removeGraph(0);
ui->plot->removeGraph(graph1);
设置曲线画笔颜色、宽度、样式。
ui->plot->graph(0)->setPen(QPen(QColor(120, 120, 120), 2));
设置曲线使用刷子。
ui->plot->graph(1)->setBrush(QColor(200, 200, 200, 20));
使用setChannelFillGraph()把通道2包含在1里面,这样刷子颜色就不会透视。
QCPGraph *graph2 = ui->widget->addGraph();
graph2->setData(x2, y2);
graph2->setPen(Qt::NoPen);
graph2->setBrush(QColor(200, 200, 200, 20));
graph2->setChannelFillGraph(graph1);
使用setScatterStyle()设置曲线散点的样式。
ui->plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 9));
2)柱状图
实例化QCPBars()。
QCPBars *bars1 = new QCPBars(ui->widget->xAxis, ui->widget->yAxis);
使用setWidth()设置柱状图宽度
bars1->setWidth(10);
使用setPen()设置画笔
bars1->setPen(QPen(QColor(120, 120, 120), 2));
使用setBrush()设置刷子颜色填充。
bars1->setBrush(QColor(10, 140, 70, 160));
使用moveAbove()设置栏2在1的上方。
bars2->moveAbove(bars1);
3)坐标轴
使用setVisible()方法设置是否显示。
ui->plot->xAxis2->setVisible(true);
ui->plot->yAxis2->setVisible(true);
使用setTickLabels()方法设置是否显示刻度。
ui->widget->xAxis2->setTickLabels(false);
ui->widget->yAxis2->setTickLabels(false);
使用rescaleAxes()方法设置自适应坐标轴,防止因为坐标轴范围过长而出现大量无数据地带
ui->Plot->graph(0)->rescaleAxes();
使用setRange()设置坐标轴范围,使用range()获取坐标轴范围数值。
ui->plot->xAxis->setRange(0, 100);
ui->plot->yAxis->setRange(0, 100);
QCPRange XAxis_Range=ui->plot->xAxis->range();
缩放、自适应等会触发rangeChanged()信号,同步使用setRange(),保证上下、左右坐标一致。
connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->yAxis2, SLOT(setRange(QCPRange)));
3)样式
使用setTickLabelColor()设置坐标轴标签的颜色。
ui->plot->xAxis->setTickLabelColor(Qt::red);
ui->plot->yAxis->setTickLabelColor(Qt::red);
使用setTickPen()设置含标签的刻度的画笔的颜色、线宽和样式。
ui->widget->xAxis->setTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setTickPen(QPen(Qt::red, 1));
使用setSubTickPen()设置不含标签的刻度的画笔的颜色、线宽和样式。
ui->widget->xAxis->setSubTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setSubTickPen(QPen(Qt::red, 1));
使用setBasePen()设置坐标轴画笔的颜色、线宽和样式。
ui->plot->xAxis->setBasePen(QPen(Qt::red, 1));
ui->plot->yAxis->setBasePen(QPen(Qt::red, 1));
使用setSubGridVisible()设置是否显示二级网格。
ui->plot->xAxis->grid()->setSubGridVisible(true);
ui->plot->yAxis->grid()->setSubGridVisible(true);
使用setPen()设置网格的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setSubGridPen()设置二级网格的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
使用setZeroLinePen()设置零线的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setZeroLinePen(Qt::NoPen);
ui->plot->yAxis->grid()->setZeroLinePen(Qt::NoPen);
使用setBackground()设置背景颜色,设置渐变色,也可以直接使用图片,纯色刷子来当背景。
QLinearGradient plotGradient;
plotGradient.setStart(0, 0);
plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
plotGradient.setColorAt(1, QColor(50, 50, 50));
ui->plot->setBackground(plotGradient);
QLinearGradient axisRectGradient;
axisRectGradient.setStart(0, 0);
axisRectGradient.setFinalStop(0, 350);
axisRectGradient.setColorAt(0, QColor(80, 80, 80));
axisRectGradient.setColorAt(1, QColor(30, 30, 30));
ui->widget->axisRect()->setBackground(axisRectGradient);
使用setUpperEnding()设置上轴结束的样式。
ui->plot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
ui->plot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
4)图例
使用setVisible()设置图例是否显示。
ui->plot->legend->setVisible(true);
使用setFillOrder()设置图例信息的水平方向。
ui->plot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst);
使用addElement()设置图例显示的坐标、位置和比例。
ui->plot->plotLayout()->addElement(1 , 0, ui->plot->legend);
使用setBorderPen()设置图例边框颜色、线宽、样式。
ui->plot->legend->setBorderPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setRowStretchFactor()设置显示比例,图例所在框的大小。
ui->plot->plotLayout()->setRowStretchFactor(1, 0.001);
5)其他
使用setInteractions()方法设置交互策略
ui->Plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
//放大拖拽选中等枚举
enum Interaction { iRangeDrag = 0x001 //左键点击可拖动
,iRangeZoom = 0x002 //范围可通过鼠标滚轮缩放
,iMultiSelect = 0x004 //可选中多条曲线
,iSelectPlottables = 0x008 //线条可选中
,iSelectAxes = 0x010 //坐标轴可选
,iSelectLegend = 0x020 //图例是可选择的
,iSelectItems = 0x040 //可选择项(矩形、箭头、文本项等
,iSelectOther = 0x080 //所有其他对象都是可选的
};
使用replot()重新启动绘制,当你需要一条动态曲线的时候,除了动态的addData(),还需要不断的使用replot()进行后续的绘制。
ui->plot->replot();
保存成Pdf、Png、Jpg、Bmp格式文件。
bool savePdf (const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())
bool savePng (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
bool saveJpg (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
bool saveBmp (const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
图例与曲线选中状态绑定。
//响应图例被选中信号
connect(ui->channelChart,&QCustomPlot::legendClick,
this,[=](QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event){
m_grap_A->setSelection(ui->channelChart->legend->item(0)->selected()?
QCPDataSelection(m_grap_A->data().data()->dataRange()):
QCPDataSelection());
}
//响应曲线被选中信号
connect(ui->channelChart,&QCustomPlot::plottableClick,
this,[=](QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event){
ui->channelChart->legend->item(0)->setSelected(m_grap_A->selected());
}
QPen样式
相关文章:

Qt——示波器/图表 QCustomPlot
一、介绍 QCustomPlot是一个用于绘图和数据可视化的Qt C小部件。它没有进一步的依赖关系,提供友好的文档帮助。这个绘图库专注于制作好看的,出版质量的2D绘图,图形和图表,以及为实时可视化应用程序提供高性能。QCustomPlot可以导出…...

《图解Vue3.0》- 调试
如何对vue3项目进行调试 调试是开发过程中必备的一项技能,掌握了这项技能,可以很好的定义bug所在。一般在开发vue3项目时,有三种方式。 代码中添加debugger;使用浏览器调试:sourcemap需启用vs code 调试:先开启node服…...

【PyQt5篇】和子线程进行通信
文章目录 🍔使用QtDesigner进行设计🛸和子线程进行通信🎈运行结果 🍔使用QtDesigner进行设计 我们首先使用QtDesigner设计界面 得到代码login.ui <?xml version"1.0" encoding"UTF-8"?> <ui …...
JavaScript数组操作方法全录
改变原数组的方法: push() - 将一个或多个元素添加到数组的末尾,并返回新数组的长度。 pop() - 从数组中移除最后一个元素,并返回该元素。 shift() - 从数组中移除第一个元素,并返回该元素。 unshift() - 将一个或多个元素添加到…...

8.排序(直接插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序)的模拟实现
1.排序的概念及其运用 1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录…...

(详解)python调用另一个.py文件中的类和函数或直接运行另一个.py文件
一、同一文件夹下的调用 1.调用函数 A.py文件如下: def add(x,y):print(和为:%d%(xy))在B.py文件中调用A.py的add函数如下: import A A.add(1,2)或 from A import add add(1,2)2.调用类 A.py文件如下: class Add:def __ini…...

每日一题:修改后的最大二进制字符串
给你一个二进制字符串 binary ,它仅有 0 或者 1 组成。你可以使用下面的操作任意次对它进行修改: 操作 1 :如果二进制串包含子字符串 "00" ,你可以用 "10" 将其替换。 比方说, "00010"…...

Redis 5种数据结构常用命令
文章目录 1 字符串2 哈希3 列表4 集合5 有序集合 1 字符串 命令描述set key value设置指定key的值为valueget key获取指定key的值del key [key …]删除一个或多个keymset key value [key value …]设置多个key的值mget key [key …]获取一个或多个key的值incr key将key中储存的…...

23、区间和
区间和 题目描述 假定有一个无限长的数轴,数轴上每个坐标上的数都是0。 现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。 接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间…...

Python零基础从小白打怪升级中~~~~~~~文件和文件夹的操作 (1)
第七节:文件和文件夹的操作 一、IO流(Stream) 通过“流”的形式允许计算机程序使用相同的方式来访问不同的输入/输出源。stream是从起源(source)到接收的(sink)的有序数据。我们这里把输入/输…...

Qt plugin 开发UI界面插件
目录 1.创建接口 2.创建插件 3.创建插件界面 4.插件实现 5.创建应用工程 6.应用插件 1.创建接口 打开QtCreater,点击左上角“文件”->新建文件或项目,在弹窗中选择C/CHeader File。 输入文件名,选好路径(可自行设置名称…...
Android查看SO库的依赖
➜ bin pwd /Users/xxx/Library/Android/sdk/ndk/21.1.6352462/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin ➜ bin ./aarch64-linux-android-readelf -d /Download/libxxx.so 0x0000000000000001 (NEEDED) Shared library: [liblog.so]0x…...

麒麟KOS删除鼠标右键新建菜单里不需要的选项
原文链接:麒麟KOS删除鼠标右键新建菜单里不需要的选项 Hello,大家好啊!在日常使用麒麟KOS操作系统时,我们可能会发现鼠标右键新建菜单里包含了一些不常用或者不需要的选项。这不仅影响我们的使用效率,也让菜单显得杂乱…...
DPDK系列之四十二DPDK应用网络编程UDP编程
一、UDP编程 UDP编程的应用和TCP编程的应用同样非常广泛,如果说真得想使用UDP编程,一般情况下还真得不至于运用DPDK这种重量级的框架。但一个框架的优秀与否,不仅仅在于自身的整体设计优秀,更重要的在于其对应用的支持更完善。 正…...

金三银四面试题(十九):MySQL中的锁
在MySQL中,锁是非常重要的,特别是在多用户并发访问数据库的环境中,因此也是面试中常问的话题。 请说说数据库的锁? 关于MySQL 的锁机制,可能会问很多问题,不过这也得看面试官在这方面的知识储备。 MySQL …...

【JavaScript】原型链/作用域/this指针/闭包
1.原型链 参考资料:Annotated ES5 ECMAScript起初并不支持如C、Smalltalk 或 Java 中“类”的形式创建对象,而是通过字面量表示法或者构造函数创建对象。每个构造函数都是一个具有名为“prototype”的属性的函数,该属性用于实现基于原型的继…...
Python的MATLAB使用
Python和MATLAB是两种不同的编程语言,它们各自拥有不同的生态系统和库。然而,你可以在Python中使用一些方法来实现与MATLAB类似的功能。以下是一些方法和库,可以帮助你在Python中实现MATLAB风格的编程: 1. NumPy: NumPy是Python中…...

文件输入/输出流(I/O)
文章目录 前言一、文件输入\输出流是什么?二、使用方法 1.FileInputStream与FileOutputStream类2.FileReader与FileWriter类总结 前言 对于文章I/O(输入/输出流的概述),有了下文。这篇文章将具体详细展述如何向磁盘文件中输入数据,或者读取磁…...
docker,schedule job和environment variables三者的含义与区别
这三个概念在软件开发和部署中扮演着不同的角色: Docker一般长这样:superlifestyle/sscp-api Schedule Job一般长这样:recorrect_ocr_receipt_status 、Sync2D365 Environment Variables一般长这样:D365_BATCH_OPERATION_SIZE ima…...
90天玩转Python—16—基础知识篇:面向对象知识详解
90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...

rm视觉学习1-自瞄部分
首先先感谢中南大学的开源,提供了很全面的思路,减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接:https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架: 代码框架结构:readme有…...