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

项目实战:Qt+Opencv相机标定工具v1.3.0(支持打开摄像头、视频文件和网络地址,支持标定过程查看、删除和动态评价误差率,支持追加标定等等)

若该文为原创文章,转载请注明出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141334834

长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…

Qt开发专栏:项目实战(点击传送门)


需求

  1.打开摄像头,可设置帧率、分辨率(可设置);
  2.可打开usb、rtsp和本地文件(直接输入地址自动判断);
  3.opencv摄像头操作子线程处理;
  4.支持设置棋盘格的行列角点数;
  5.支持标定过程可控制;
  6.采集标定图、可对标定图进行查看、删除;
  7.可对已有的标定图查看评价像素误差率;
  8.标定完成后,可以追加标定,继续开始基于原来的标定采集图继续标定;
  9.支持定制配置文件的导出和导出(测试运行包不对外开放该功能);


相关博客

  《OpenCV开发笔记(〇):使用mingw530_32编译openCV3.4.1源码,搭建Qt5.9.3的openCV开发环境》
  《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》
  《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储》
  《OpenCV开发笔记(五):OpenCV读取与操作摄像头》
  《OpenCV开发笔记(六):OpenCV基础数据结构、颜色转换函数和颜色空间》
  《OpenCV开发笔记(七十六):相机标定(一):识别棋盘并绘制角点》
  《OpenCV开发笔记(七十七):相机标定(二):通过棋盘标定计算相机内参矩阵矫正畸变摄像头图像》


Demo:calibrateTool_v1.3.0 windows运行包

  广角摄像头标定过程
  请添加图片描述

  请添加图片描述

  鱼眼摄像头标定过程
  请添加图片描述

  请添加图片描述

  动态标定过程:查看、删除和评价
  请添加图片描述

  请添加图片描述

  CSDN粉丝0积分下载:https://download.csdn.net/download/qq21497936/89652658
  QQ群:博客首页扫码进入QQ技术群,点击“文件”搜索“calibrateTool”,群内与博文同步更新)


模块化部署

  在这里插入图片描述

关键源码

CalibrateManager.h

#ifndef CALIBRATEMANAGER_H
#define CALIBRATEMANAGER_H// opencv
#include "opencv/highgui.h"
#include "opencv/cxcore.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/xphoto.hpp"
#include "opencv2/dnn/dnn.hpp"
// opencv_contrib
#include <opencv2/xphoto.hpp>
#include <opencv2/ximgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>#include "cvui.h"
#include "calibrateCommon.h"
#include <QImage>
#include <QTimer>class CalibrateManager: public QObject
{Q_OBJECT
public:explicit CalibrateManager(QObject *parent = 0);~CalibrateManager();public slots:void testOpencvEnv();                       // 测试环境public:double  getBrightness()     const;          // 亮度double  getContrast()       const;          // 对比度double  getSaturation()     const;          // 饱和度double  getHue()            const;          // 色调double  getGain()           const;          // 增益double  getExposure()       const;          // 曝光度bool    getShowProperty()   const;          // 显示属性int     getCalibrateRegionX() const;        // 区域xint     getCalibrateRegionY() const;        // 区域yint     getCalibrateRegionWidth() const;    // 区域widthint     getCalibrateRegionHeight() const;   // 区域heightint     getChessboardColCornerCount() const;// 棋盘行角点数量int     getChessboardRowCornerCount() const;// 棋盘列角点数量QString getSerialize() const;               // 获取序列化参数public:void setBrightness  (double value);         // 亮度void setContrast    (double value);         // 对比度void setSaturation  (double value);         // 饱和度void setHue         (double value);         // 色调void setGain        (double value);         // 增益void setExposure    (double value);         // 曝光度void setShowProperty(bool value);           // 显示属性void setCalibrateRegionX(int x);            // 区域xvoid setCalibrateRegionY(int y);            // 区域yvoid setCalibrateRegionWidth(int width);    // 区域widthvoid setCalibrateRegionHeight(int height);  // 区域heightvoid setChessboardColCornerCount(int count);// 棋盘行角点数量void setChessboardRowCornerCount(int count);// 棋盘列角点数量bool setSerialize(QString str);             // 获取序列化参数signals:void signal_opened(bool result);            // 打开摄像头信号void signal_closed();                       // 关闭摄像头信号void signal_captureOneFrame(cv::Mat mat);   // 接收图像后抛出信号void signal_captureOneFrame(QImage image);  // 接收图像后抛出信号void signal_captureOneResultFrame(cv::Mat mat);   // 接收图像后抛出信号void signal_captureOneResultFrame(QImage image);  // 接收图像后抛出信号void signal_startedCalibrate(bool result);  // 开始标定结果void signal_regionChanged(int x, int y, int width, int height);void signal_fpsChanged(int fps);            // 帧率void signal_stopedCalibrate();              // 结束标定结果(这是强制中断,不是标定完成)void signal_finishedCalibrate();            // 标定完成void signal_cameraInfo(CameraInfo cameraInfo);  // 更新截图相机信息public slots:void slot_startCapture(int usb, int width = 0, int height = 0, int fps = 0);// 打开摄像头, 0...void slot_startCapture(QString url, int width = 0, int height = 0, int fps = 0);// 打开摄像头, 网络摄像头地址void slot_stopCapture();                    // 当正在采集中时(>>时),关闭摄像头会导致程序崩溃,所以采集与停止放一个线程中(消息循环)void slot_startCalibrate();                 // 开始标定void slot_addCalibrate();                   // 继续标定void slot_snapshot();                       // 快照void slot_deleteSnapshot(int index);        // 删除快照void slot_stopCalibrate();                  // 停止标定void slot_finishCalibrate();                // 完成标定public slots:void slot_start();                       // 开启线程void slot_stop();                        // 关闭线程protected slots:void slot_captrueFrame();           // 消息循环获取图像protected:void initControl();void updateCalibrateResult();       // 更新标定结果void calculateCalibrateErrors();    // 计算误差protected:bool findChessboard(int rowCornerCount, int colCornerCount, cv::Mat &mat, std::vector<cv::Point2f> &vectorPoint2fCorners);public:static QImage mat2Image(cv::Mat mat);      // cv::Mat 转 QImageprivate:bool _running;                      // 线程是否运行private:cv::VideoCapture *_pVideoCapture;   // 摄像头实例bool _showProperty;                 // 是否显示属性参数double _brightness;                 // 亮度double _contrast;                   // 对比度double _saturation;                 // 饱和度double _hue;                        // 色调double _gain;                       // 增益double _exposure;                   // 曝光度int _width;                         // 宽度int _height;                        // 高度int _fps;                           // 帧率bool _opened;                       // 摄像头是否打开bool _calibratingBefore;            // 标定前一个变化状态bool _calibrating;                  // 正在标定bool _calibratFinished;             // 校准完了(当前最近一个已经校准)int _calibrateRegionX;              // 标定region区域像素起始x坐标int _calibrateRegionY;              // 标定region区域像素起始y坐标int _calibrateRegionWidth;          // 标定region区域像素宽度int _calibrateRegionHeight;         // 标定region区域像素高度cv::Mat _mat;                       // 缓存一帧cv::Mat _resultMat;                 // 结果int _chessboardColCornerCount;      // 一列多少个角点int _chessboardRowCornerCount;      // 一行多少个角点std::vector<std::vector<cv::Point3f>> _vectorObjectPoint;    // 缓存点std::vector<std::vector<cv::Point2f>> _vectorImagePoint;bool _snapshot;                     // 拍照private:                                // 计算内参和畸变系数cv::Mat _cameraMatrix;              // 相机矩阵(接收输出)cv::Mat _distCoeffs;                // 畸变系数(接收输出)std::vector<cv::Mat> _rotate;       // 旋转量(接收输出)std::vector<cv::Mat> _translate;    // 偏移量(接收输出)private:CameraInfo _cameraInfo;
};#endif // CALIBRATEMANAGER_H

CalibrateManager.cpp

...
void CalibrateManager::slot_captrueFrame()
{if(!_running){return;}if(_pVideoCapture->isOpened()){*_pVideoCapture >> _mat;if(_showProperty){cv::putText(_mat, QString("brightness: %1").arg(_brightness).toStdString(),cvPoint(0, 30), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("  contrast: %1").arg(_contrast  ).toStdString(),cvPoint(0, 60), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("saturation: %1").arg(_saturation).toStdString(),cvPoint(0, 90), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("       hue: %1").arg(_hue       ).toStdString(),cvPoint(0, 120), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("      gain: %1").arg(_gain      ).toStdString(),cvPoint(0, 150), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("  exposure: %1").arg(_exposure  ).toStdString(),cvPoint(0, 180), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));cv::putText(_mat, QString("press ESC out").toStdString(),cvPoint(0, 210), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255));}// 第一次进入标定if(!_calibratingBefore && _calibrating){_calibrateRegionX = 0;_calibrateRegionY = 0;_calibrateRegionWidth = _width;_calibrateRegionHeight = _height;_calibratingBefore = true;emit signal_regionChanged(_calibrateRegionX, _calibrateRegionY, _calibrateRegionWidth, _calibrateRegionHeight);QImage srcImage = mat2Image(_mat);emit signal_captureOneResultFrame(srcImage);}else if(_calibrating){QImage srcImage = mat2Image(_mat);// 获取std::vector<cv::Point2f> imagePoints;if(findChessboard(_chessboardRowCornerCount,_chessboardColCornerCount,_mat,imagePoints)){// 这是拍照截图if(_snapshot){// 三维世界坐标系std::vector<cv::Point3f> objectPoints;for(int i = 0; i < _chessboardRowCornerCount; i++){for(int j = 0; j < _chessboardColCornerCount; j++){objectPoints.push_back(cv::Point3f(j, i, 0));}}// 图像识别出来的角点(一张图一组)_vectorObjectPoint.push_back(objectPoints);_vectorImagePoint.push_back(imagePoints);_snapshot = false;{SnapShot snapShot;snapShot.dateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz");snapShot.srcImage = srcImage;snapShot.drawChessboardImage = mat2Image(_mat);snapShot.imagePoints = imagePoints;snapShot.objectPoints = objectPoints;_cameraInfo.listSnapShot.append(snapShot);// 更新标定结果updateCalibrateResult();// 计算误差率calculateCalibrateErrors();// 抛出更新emit signal_cameraInfo(_cameraInfo);}}}
//            if(_cameraInfo.listSnapShot.size() == 0)
//            {
//                QImage srcImage = mat2Image(_mat);
//                emit signal_captureOneResultFrame(srcImage);
//            }else{
//                cv::undistort(_mat, _resultMat, _cameraMatrix, _distCoeffs);
//                QImage image = mat2Image(_resultMat);
//                emit signal_captureOneResultFrame(image);
//            }}else if(_calibratFinished){
//            if(_cameraInfo.listSnapShot.size() == 0)
//            {
//                QImage srcImage = mat2Image(_mat);
//                emit signal_captureOneResultFrame(srcImage);
//            }else{
//                cv::undistort(_mat, _resultMat, _cameraMatrix, _distCoeffs);
//                QImage image = mat2Image(_resultMat);
//                emit signal_captureOneResultFrame(image);
//            }}// 抛出原图QImage image = mat2Image(_mat);emit signal_captureOneFrame(image);// 抛出校正图if(_cameraMatrix.empty()){emit signal_captureOneResultFrame(image);}else{LOG;cv::undistort(_mat, _resultMat, _cameraMatrix, _distCoeffs);QImage dstImage = mat2Image(_resultMat);emit signal_captureOneResultFrame(dstImage);}QTimer::singleShot(5, this, SLOT(slot_captrueFrame()));}
}
...

入坑

  算法的研究优化过程中,受到摄像头光学、标定板、标定板所占视口大小,图像处理过程原本的流程优化、标定过程中动态的处理等多方面因素,坑多暂时未记录。


本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141334834

相关文章:

项目实战:Qt+Opencv相机标定工具v1.3.0(支持打开摄像头、视频文件和网络地址,支持标定过程查看、删除和动态评价误差率,支持追加标定等等)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/141334834 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…...

【数据结构】汇总八、排序算法

排序Sort 【注意】本章是 排序 的知识点汇总&#xff0c;全文1万多字&#xff0c;含有大量代码和图片&#xff0c;建议点赞收藏&#xff08;doge.png&#xff09;&#xff01;&#xff01; 【注意】在这一章&#xff0c;记录就是数据的意思。 排序可视化网站&#xff1a; D…...

Java-分割list并执行多线程任务的工具类

要创建一个用于分割列表并执行多线程任务的工具类,你可以使用 Java 的 ExecutorService 和 ThreadPoolExecutor 来实现。下面是一个详细的示例,展示了如何创建这样一个工具类。 步骤 1: 创建线程池 首先,创建一个线程池来执行任务。 步骤 2: 分割列表 接着,定义一个方…...

Springboot-从服务器获取一个输入流,转成视频文件存到oss

要在Spring Boot应用中从服务器获取一个输入流,然后将该流转换为视频文件并存储到阿里云 OSS中,你可以遵循以下步骤: 设置阿里云OSS客户端:首先,你需要配置阿里云OSS客户端,以便能够上传文件到OSS。 获取输入流:使用HTTP客户端(如RestTemplate或WebClient)从服务器…...

[Meachines] [Easy] Bastion SMB未授权访问+VHD虚拟硬盘挂载+注册表获取NTLM哈希+mRemoteNG远程管理工具权限提升

信息收集 IP AddressOpening Ports10.10.10.134TCP:22, 135, 139, 445, 5985, 47001, 49664, 49665, 49666, 49667, 49668, 49669, 49670 $ nmap -p- 10.10.10.134 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH fo…...

STM32标准库学习笔记-9.DMA 直接存储器存取

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 DMA&#xff08;Direct Memory Access&#xff09; DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预…...

ubuntu VCS+verdi安装遇到的一些问题

主体流程&#xff1a;https://blog.51cto.com/u_15346322/4995147 我的是Ubuntu22.4 安装目录问题 执行 ./installer -gui 只能安装到home 或者 sudo ./setup.sh -install_as_root 能安装到/usr/ 目录 运行 vcs 出现 bin/sh: Illegal option -h sudo rm -f /bin/sh sudo…...

使用Poi-tl对word模板生成动态报告

一、pom依赖问题&#xff1a; <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.12.2</version> </dependency> 使用 poi-tl 的 1.12.2版本&#xff0c;如果使用了poi依赖&#x…...

day45-dynamic programming-part12-8.16

tasks for today: 1. 115.不同的子序列 2. 583.两个字符串选的删除操作 3. 72.编辑距离 4. 总结编辑两个序列关系的问题 ------------------------------------------------------------------- 1. 115.不同的子序列 In this practice, it is necessary to compare with t…...

C# String的方法

目录 #region 知识点九 字符串切割 #region 知识点一 字符串指定位置获取 #region 知识点二 字符串拼接 #region 知识点三 正向查找字符位置 #region 知识点四 反向查找指定字符串位置 #region 知识点五 移除指定位置后的字符 #region 知识点六 替换指定字符串 #region 知识点七…...

Oracle RAC vs Clusterware vs ASM

Oracle RAC vs Clusterware vs ASM Oracle RACCache FusionRAC后台进程自动负载管理DBA管理工具Oracle ClusterwareCRS组件HAS组件管理工具Oracle ASMASM实例ASM磁盘组镜像和故障组ASM磁盘ASM文件Oracle RAC RAC即Real Application Clusters,是一种Oracle高可用部署架构。Orac…...

“华为杯”第十五届中国研究生数学建模竞赛-F题:机场新增卫星厅对中转旅客影响的研究

目录 摘 要: 一、 问题重述 1.1 研究背景 1.2 已知信息 1.3 需要解决的问题 二、 模型假设 三、 符号说明 四、 问题一模型的建立与求解 4.1 问题描述与分析 4.2 模型的求解 4.3 求解结果与分析 五、 问题二模型的建立与求解 5.1 问题描述与分析 5.2 模型的求解 5.3 求解结果与…...

正点原子linux开发板 qt程序交叉编译执行

1.开发板光盘 A-基础资料->5、开发工具->1、交叉编译器->fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh 拷贝到 Ubuntu 虚拟机 用文件传输系统或者共享文件夹传输到linux虚拟机 用ls -l查看权限&#xff0c;如果是白色的使…...

聚星文社和虹猫哪个好

聚星文社和虹猫是两个不同的公司&#xff0c;各有各的特点。下面是它们各自的优点&#xff1a; 聚星文社&#xff1a;Docshttps://docs.qq.com/doc/DRU1vcUZlanBKR2xy 聚星文社是一家传媒公司&#xff0c;专注于出版漫画、动画、小说等内容&#xff0c;拥有丰富的IP资源和创作…...

三十八、【人工智能】【机器学习】【监督贝叶斯网络(Bayesian Networks)学习】- 算法模型

系列文章目录 第一章 【机器学习】初识机器学习 第二章 【机器学习】【监督学习】- 逻辑回归算法 (Logistic Regression) 第三章 【机器学习】【监督学习】- 支持向量机 (SVM) 第四章【机器学习】【监督学习】- K-近邻算法 (K-NN) 第五章【机器学习】【监督学习】- 决策树…...

[书生大模型实战营][L0][Task1] Linux 远程连接 InternStudio

[书生大模型实战营][Task1] Linux 远程连接 InterStudio 1. 申请 InterStudio 账号 https://studio.intern-ai.org.cn/console/dashboard 2. ssh 生成公匙与密匙 使用 ssh-gen 生成公匙与密匙 # 1. ssh-gen ssh-gen# 2. 查看生成的文件 ls ~/.ssh# 3. 打开生成的公匙&#…...

【vue教程】六. Vue 的状态管理

目录 往期列表本章涵盖知识点回顾Vuex 的基本概念什么是 Vuex&#xff1f;为什么需要 Vuex&#xff1f; Vuex 的核心概念stategettersmutationsactionsmodules Vuex 的安装和基本使用安装 Vuex创建 store在 Vue 应用中使用 store在组件中访问和修改状态 Vuex 的模块化模块化的好…...

无人机电子调速器详解!!!

电子调速器是无人机动力系统中的关键组件&#xff0c;主要负责将电池提供的直流电转换为交流电&#xff0c;并精确控制电机的转速&#xff0c;从而实现对无人机飞行状态的精确控制。以下是对无人机电子调速器的详细解析&#xff1a; 一、基本功能与原理 功能&#xff1a; 直…...

Clichouse数据导出导入(数据迁移)

背景&#xff1a;因为clickhouse数据持续增加&#xff0c;导致服务器磁盘不够使用&#xff0c;云服务器的系统盘不能扩容&#xff0c;所以只能进行迁移 连接clickhouse查看要迁移那些数据库 rootjcdata:~/buckup/clickhouse# clickhouse-client -udefault --password 123456…...

Java基础——IService.class 中查询数据方法list() 源码剖析及使用

下面详细介绍Mybatis-plus 的默认服务IService.class 中的查询数据的方法及使用。 方法定义及其详细介绍 default List<T> list(Wrapper<T> queryWrapper) default List<T> list(Wrapper<T> queryWrapper) {return this.getBaseMapper().selectList(q…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...

路由基础-路由表

本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中&#xff0c;往往存在多个不同的IP网段&#xff0c;数据在不同的IP网段之间交互是需要借助三层设备的&#xff0c;这些设备具备路由能力&#xff0c;能够实现数据的跨网段转发。 路由是数据通信网络中最基…...

无需布线的革命:电力载波技术赋能楼宇自控系统-亚川科技

无需布线的革命&#xff1a;电力载波技术赋能楼宇自控系统 在楼宇自动化领域&#xff0c;传统控制系统依赖复杂的专用通信线路&#xff0c;不仅施工成本高昂&#xff0c;后期维护和扩展也极为不便。电力载波技术&#xff08;PLC&#xff09;的突破性应用&#xff0c;彻底改变了…...

Ray框架:分布式AI训练与调参实践

Ray框架&#xff1a;分布式AI训练与调参实践 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 Ray框架&#xff1a;分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...