opencv学习 特征提取
内容来源于《opencv4应用开发入门、进阶与工程化实践》
图像金字塔
略
拉普拉斯金字塔
对输入图像进行reduce操作会生成不同分辨率的图像,对这些图像进行expand操作,然后使用reduce减去expand之后的结果,就会得到拉普拉斯金字塔图像。
详情可查看https://zhuanlan.zhihu.com/p/80362140

图像金字塔融合
拉普拉斯金字塔通过源图像减去先缩小再放大的图像构成,保留的是残差,为图像还原做准备。
根据拉普拉斯金字塔的定义可以知道,拉普拉斯金字塔的每一层都是一个高斯差分图像。:
原图 = 拉普拉斯金字塔图L0层 + expand(高斯金字塔G1层),也就是说,可以基于低分辨率的图像与它的高斯差分图像,重建生成一个高分辨率的图像。
详情参考https://zhuanlan.zhihu.com/p/454085730的图像融合部分,讲的很好。
步骤:
- 生成苹果、橘子的高斯金字塔
和
- 求苹果、橘子的的拉普拉斯金字塔
和
- 求mask的高斯金字塔
- 在每个尺度(分辨率)下,用
拼接
和
,最终得到拼接的拉普拉斯金字塔
- 生成最低分辨率的起始图(都选取最低分辨率下的
和
根据同分辨率下
进行拼接,得到最低分辨率下的拼接结果
- 从
开始,利用
得到最高分辨率的拼接结果
示例代码:
int level = 3;
Mat smallestLevel;
Mat blend(Mat &a, Mat &b, Mat &m) {int width = a.cols;int height = a.rows;Mat dst = Mat::zeros(a.size(), a.type());Vec3b rgb1;Vec3b rgb2;int r1 = 0, g1 = 0, b1 = 0;int r2 = 0, g2 = 0, b2 = 0;int red = 0, green = 0, blue = 0;int w = 0;float w1 = 0, w2 = 0;for (int row = 0; row<height; row++) {for (int col = 0; col<width; col++) {rgb1 = a.at<Vec3b>(row, col);rgb2 = b.at<Vec3b>(row, col);w = m.at<uchar>(row, col);w2 = w / 255.0f;w1 = 1.0f - w2;b1 = rgb1[0] & 0xff;g1 = rgb1[1] & 0xff;r1 = rgb1[2] & 0xff;b2 = rgb2[0] & 0xff;g2 = rgb2[1] & 0xff;r2 = rgb2[2] & 0xff;red = (int)(r1*w1 + r2*w2);green = (int)(g1*w1 + g2*w2);blue = (int)(b1*w1 + b2*w2);// outputdst.at<Vec3b>(row, col)[0] = blue;dst.at<Vec3b>(row, col)[1] = green;dst.at<Vec3b>(row, col)[2] = red;}}return dst;
}vector<Mat> buildGaussianPyramid(Mat &image) {vector<Mat> pyramid;Mat copy = image.clone();pyramid.push_back(image.clone());Mat dst;for (int i = 0; i<level; i++) {pyrDown(copy, dst, Size(copy.cols / 2, copy.rows / 2));dst.copyTo(copy);pyramid.push_back(dst.clone());}smallestLevel = dst;return pyramid;
}vector<Mat> buildLapacianPyramid(Mat &image) {vector<Mat> lp;Mat temp;Mat copy = image.clone();Mat dst;for (int i = 0; i<level; i++) {pyrDown(copy, dst, Size(copy.cols / 2, copy.rows / 2));pyrUp(dst, temp, copy.size());Mat lapaian;subtract(copy, temp, lapaian);lp.push_back(lapaian);copy = dst.clone();}smallestLevel = dst;return lp;
}
void FeatureVectorOps::pyramid_blend_demo(Mat &apple, Mat &orange) {Mat mc = imread("D:/images/mask.png");if (apple.empty() || orange.empty()) {return;}imshow("苹果图像", apple);imshow("橘子图像", orange);vector<Mat> la = buildLapacianPyramid(apple);Mat leftsmallestLevel;smallestLevel.copyTo(leftsmallestLevel);vector<Mat> lb = buildLapacianPyramid(orange);Mat rightsmallestLevel;smallestLevel.copyTo(rightsmallestLevel);Mat mask;cvtColor(mc, mask, COLOR_BGR2GRAY);vector<Mat> maskPyramid = buildGaussianPyramid(mask);Mat samllmask;smallestLevel.copyTo(samllmask);Mat currentImage = blend(leftsmallestLevel, rightsmallestLevel, samllmask);imwrite("D:/samll.png", currentImage);// 重建拉普拉斯金字塔vector<Mat> ls;for (int i = 0; i<level; i++) {Mat a = la[i];Mat b = lb[i];Mat m = maskPyramid[i];ls.push_back(blend(a, b, m));}// 重建原图Mat temp;for (int i = level - 1; i >= 0; i--) {pyrUp(currentImage, temp, ls[i].size());add(temp, ls[i], currentImage);}imshow("高斯金子图像融合重建-图像", currentImage);
}
Harris角点检测
角点是图像中亮度变化最强的地方,反映了图像的本质特征。
图像的角点在各个方向上都有很强的梯度变化。
亚像素级别的角点检测
详细请参考https://www.cnblogs.com/qq21497936/p/13096048.html
大概理解是角点一般在边缘上,边缘的梯度与沿边缘方向的的向量正交,也就是内积为0,根据内积为零,角点周围能列出一个方程组,方程组的解就是角点坐标。
opencv亚像素级别定位函数API:
void cv::cornerSubPix(InputArray imageInputOutputArray corners //输入整数角点坐标,输出浮点数角点坐标Size winSize //搜索窗口Size zeroZone TermCriteria criteria //停止条件
)
示例代码
void FeatureVectorOps::corners_sub_pixels_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);int maxCorners = 400;double qualityLevel = 0.01;std::vector<Point2f> corners;goodFeaturesToTrack(gray, corners, maxCorners, qualityLevel, 5, Mat(), 3, false, 0.04);Size winSize = Size(5, 5);Size zeroZone = Size(-1, -1);//opencv迭代终止条件类TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.001);cornerSubPix(gray, corners, winSize, zeroZone, criteria);for (size_t t = 0; t < corners.size(); t++) {printf("refined Corner: %d, x:%.2f, y:%.2f\n", t, corners[t].x, corners[t].y);}
}
HOG特征描述子
详细请参考:https://baijiahao.baidu.com/s?id=1646997581304332534&wfr=spider&for=pc&searchword=HOG%E7%89%B9%E5%BE%81%E6%8F%8F%E8%BF%B0%E5%AD%90
讲的很好。
大概就是以一种特殊的直方图来表示图像特征,直方图存储的是梯度的方向和幅值(x轴是方向,y轴是幅值且加权)。
示例代码:
virtual void cv::HOGDescriptor::compute(InputArray imgstd::vector<float> & descriptorsSize winStride=Size()Size padding=Size()const std::vector<Point> &locations = std::vector<Point>()
)void FeatureVectorOps::hog_feature_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);HOGDescriptor hogDetector;std::vector<float> hog_descriptors;hogDetector.compute(gray, hog_descriptors, Size(8, 8), Size(0, 0));std::cout << hog_descriptors.size() << std::endl;for (size_t t = 0; t < hog_descriptors.size(); t++) {std::cout << hog_descriptors[t] << std::endl;}
}
HOG特征行人检测
opencv基于HOG行人特征描述子的检测函数:
void HOGDescriptor::detectMultiScale(InputArray img,vector<Rect>& foundLocations, double hitThreshold=0, Size winStride=Size(), Size padding=Size(),double scale=1.05,double finalThreshold=2.0,bool useMeanshiftGrouping=false
)
//示例代码
void FeatureVectorOps::hog_detect_demo(Mat &image) {HOGDescriptor *hog = new HOGDescriptor();hog->setSVMDetector(hog->getDefaultPeopleDetector());vector<Rect> objects;hog->detectMultiScale(image, objects, 0.0, Size(4, 4), Size(8, 8), 1.25);for (int i = 0; i < objects.size(); i++) {rectangle(image, objects[i], Scalar(0, 0, 255), 2, 8, 0);}imshow("HOG行人检测", image);
}
ORB特征描述子
没看懂。
描述子匹配
暴力匹配:
再使用暴力匹配之前先创建暴力匹配器:
static Ptr<BFMatcher> cv::BFMatcher::create(int normType=NORM_L2 //计算描述子暴力匹配时采用的计算方法bool crossCheck=false //是否使用交叉验证
)
调用暴力匹配的匹配方法,有两种,最佳匹配和KNN匹配
void cv::DescriptorMatch::match(InputArray queryDescriptorsInputArray trainDescriptorsstd::vector<DMatch> & matchesInputArray mask=noArray
)void cv::DescriptorMatch::knnMatch(InputArray queryDescriptorsInputArray trainDescriptorsstd::vector<DMatch> & matchesint kInputArray mask=noArraybool compactResult =false
)
FLANN匹配:
cv::FlannBasedMatcher::FlannBasedMatcher(const Ptr<flann::IndexParams> & indexParams=makePtr<flann::KDTreeIndexParams>()const Ptr<flann::SearchParams> & searchParams=makePtr<flann::SearchParams>()
)
示例代码:
void FeatureVectorOps::orb_match_demo(Mat &box, Mat &box_in_scene) {// ORB特征提取auto orb_detector = ORB::create();std::vector<KeyPoint> box_kpts;std::vector<KeyPoint> scene_kpts;Mat box_descriptors, scene_descriptors;orb_detector->detectAndCompute(box, Mat(), box_kpts, box_descriptors);orb_detector->detectAndCompute(box_in_scene, Mat(), scene_kpts, scene_descriptors);// 暴力匹配auto bfMatcher = BFMatcher::create(NORM_HAMMING, false);std::vector<DMatch> matches;bfMatcher->match(box_descriptors, scene_descriptors, matches);Mat img_orb_matches;drawMatches(box, box_kpts, box_in_scene, scene_kpts, matches, img_orb_matches);imshow("ORB暴力匹配演示", img_orb_matches);// FLANN匹配auto flannMatcher = FlannBasedMatcher(new flann::LshIndexParams(6, 12, 2));flannMatcher.match(box_descriptors, scene_descriptors, matches);Mat img_flann_matches;drawMatches(box, box_kpts, box_in_scene, scene_kpts, matches, img_flann_matches);namedWindow("FLANN匹配演示", WINDOW_FREERATIO);cv::namedWindow("FLANN匹配演示", cv::WINDOW_NORMAL);imshow("FLANN匹配演示", img_flann_matches);
}
基于特征的对象检测
特征描述子匹配之后,可以根据返回的各个DMatch中的索引得到关键点对,然后拟合生成从对象到场景的变换矩阵H。根据矩阵H可以求得对象在场景中的位置,从而完成基于特征的对象检测。
opencv中求得单应性矩阵的API:
Mat cv::findHomograph(InputArray srcPointsOutputArray dstPointsint method=0double ransacReprojThreshold=3OutputArray mask=noArray()const int maxIters=2000;const double confidence=0.995
)
有了变换矩阵H ,可以运用透视变换函数求得场景中对象的四个点坐标并绘制出来。
透视变换函数:
void cv::perspectiveTransform(InputArray srcOutputArray dstInputArray m
)
示例代码:
void FeatureVectorOps::find_known_object(Mat &book, Mat &book_on_desk) {// ORB特征提取auto orb_detector = ORB::create();std::vector<KeyPoint> box_kpts;std::vector<KeyPoint> scene_kpts;Mat box_descriptors, scene_descriptors;orb_detector->detectAndCompute(book, Mat(), box_kpts, box_descriptors);orb_detector->detectAndCompute(book_on_desk, Mat(), scene_kpts, scene_descriptors);// 暴力匹配auto bfMatcher = BFMatcher::create(NORM_HAMMING, false);std::vector<DMatch> matches;bfMatcher->match(box_descriptors, scene_descriptors, matches);// 好的匹配std::sort(matches.begin(), matches.end());const int numGoodMatches = matches.size() * 0.15;matches.erase(matches.begin() + numGoodMatches, matches.end());Mat img_bf_matches;drawMatches(book, box_kpts, book_on_desk, scene_kpts, matches, img_bf_matches);imshow("ORB暴力匹配演示", img_bf_matches);// 单应性求Hstd::vector<Point2f> obj_pts;std::vector<Point2f> scene_pts;for (size_t i = 0; i < matches.size(); i++){//-- Get the keypoints from the good matchesobj_pts.push_back(box_kpts[matches[i].queryIdx].pt);scene_pts.push_back(scene_kpts[matches[i].trainIdx].pt);}Mat H = findHomography(obj_pts, scene_pts, RANSAC);std::cout << "RANSAC estimation parameters: \n" << H << std::endl;std::cout << std::endl;H = findHomography(obj_pts, scene_pts, RHO);std::cout << "RHO estimation parameters: \n" << H << std::endl;std::cout << std::endl;H = findHomography(obj_pts, scene_pts, LMEDS);std::cout << "LMEDS estimation parameters: \n" << H << std::endl;// 变换矩阵得到目标点std::vector<Point2f> obj_corners(4);obj_corners[0] = Point(0, 0); obj_corners[1] = Point(book.cols, 0);obj_corners[2] = Point(book.cols, book.rows); obj_corners[3] = Point(0, book.rows);std::vector<Point2f> scene_corners(4);perspectiveTransform(obj_corners, scene_corners, H);// 绘制结果Mat dst;line(img_bf_matches, scene_corners[0] + Point2f(book.cols, 0), scene_corners[1] + Point2f(book.cols, 0), Scalar(0, 255, 0), 4);line(img_bf_matches, scene_corners[1] + Point2f(book.cols, 0), scene_corners[2] + Point2f(book.cols, 0), Scalar(0, 255, 0), 4);line(img_bf_matches, scene_corners[2] + Point2f(book.cols, 0), scene_corners[3] + Point2f(book.cols, 0), Scalar(0, 255, 0), 4);line(img_bf_matches, scene_corners[3] + Point2f(book.cols, 0), scene_corners[0] + Point2f(book.cols, 0), Scalar(0, 255, 0), 4);//-- Show detected matchesnamedWindow("基于特征的对象检测", cv::WINDOW_NORMAL);imshow("基于特征的对象检测", img_bf_matches);
}
相关文章:
opencv学习 特征提取
内容来源于《opencv4应用开发入门、进阶与工程化实践》 图像金字塔 略 拉普拉斯金字塔 对输入图像进行reduce操作会生成不同分辨率的图像,对这些图像进行expand操作,然后使用reduce减去expand之后的结果,就会得到拉普拉斯金字塔图像。 …...
关于maven项目构建的解释
在Idea中使用模块化构建项目 项目介绍: sky-take-out sky-common pom.xml sky-pojo pom.xml sky-server pom.xml pom.xml 说明 sky-server依赖sky-pojo和sky-common,继承sky-take-outsky-pojo继承sky-take-outsky-common继承sky-take-out 由于Idea编…...
IMU/捷联惯导常见的术语,以及性能评价标准(附Python解析代码)
0. 简介 现在的机器人领域在普遍使用IMU(惯性导航单元)。该系统有三个加速度传感器与三个角速度传感器(陀螺)组成,加速度计用来感受飞机相对于地垂线的加速度分量,陀螺仪用来感知飞机的角速率变化…...
Debezium发布历史98
原文地址: https://debezium.io/blog/2020/11/12/debezium-1-3-1-final-released/ 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. Debezium 1.3.1.Final 发布 十一月 12, 2020 作者: 克里…...
APUE学习之进程间通信(IPC)(下篇)
目录 一、进程间通信(IPC) 二、信号量(Semaphore) 1、基本概念 2、同步关系与互斥关系 3、临界区与临界资源 4、信号量的工作原理 5、信号量编程 6、实战演练 三、共享内存(Shared Memory) 1、…...
【Java 设计模式】行为型之中介者模式
文章目录 1. 定义2. 应用场景3. 代码实现结语 中介者模式(Mediator Pattern)是一种行为型设计模式,用于通过一个中介对象来集中管理多个对象之间的交互关系,从而降低对象之间的耦合度。中介者模式通过将对象之间的通信委托给中介者…...
MySql 慢SQL配置,查询,处理
一.慢SQL配置相关 1.查看慢SQL是否开启 执行下面命令查看是否开启慢SQL show variables like %slow_query_log; 复制代码 OFF: 未开启ON: 2.打开慢SQL配置 执行下面的命令开启慢查询日志 set global slow_query_logON; 复制代码 3.修改慢查询阈值 前面介绍了SQL执行到达了…...
算法:分界线
一、算法描述 电视剧《分界线》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字 剪切下来,剪拼成匿名信。 现在有一名举报人,希望借鉴这种手段,使用英文报刊完成举报操作。 但为…...
STM32单片机基本原理与应用(四)
直流电机驱动控制原理 1、电机正反转控制 在STM32中,直流电机的正反转控制主要通过改变电机输入电源的极性来实现。当电机的电压极性发生变化时,电机的旋转方向也会相应改变。在硬件电路中,可以通过继电器或晶体管等电子开关来切换电机的电源…...
elk之安装和简单配置
写在前面 本文看下elk的安装和简单配置,安装我们会尝试通过不同的方式来完成,也会介绍如何使用docker,docker-compose安装。 1:安装es 1.1:安装单实例 下载es安装包 在这里 下载,下载后解压到某个目录…...
springboot(ssm环保网站 绿色环保宣传系统Java系统
springboot(ssm环保网站 绿色环保宣传系统Java系统 开发语言:Java 框架:springboot(可改ssm) vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7࿰…...
【MBtiles数据索引和服务发布】GeoServer改造Springboot番外系列二
xyz地图服务访问示例:http://192.168.1.240:8081/gmserver/raster/xyz/firstWP:Imagery-raster/{z}/{x}/{y}.jpg 访问示例如下: mbtiles目录结构 根据z,x,y获取对应mbtiles文件路径的工具方法 说明:重点是使用getMb…...
Redis抓取数据到Logstash再推到Elasticsearch集群
一、安装Logstash 前面安装过Logstash了,不做解释直接跳过 参考:上一篇文章 二、配置Logstash 在logstash目录下,编辑我们之前的配置文件logstash.conf vim logstash.confinput、output字面意思,从redis去拿取数据,输出到Elasticsearch data_type:数据类型为list k…...
【代码随想录-链表】反转链表
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…...
32GPIO输入LED闪烁蜂鸣器
一.GPIO简介 所有的GPIO都挂载到APB2上,每个GPIO有16个引脚 内核可以通过APB2对寄存器进行读写,寄存器都是32位的,但每个引脚端口只有16位 驱动器用于增加信号的驱动能力 二.具体…...
Qt|QPushButton控件讲解
前提 按钮分为了四种状态:常态、聚焦、按下、禁用 前一段时间更新了MFC框架下CButton的自绘。因为MFC框架下的按钮限制性很高,所以只能由自绘实现各种风格,但是QT框架完美的解决了这个问题,我们只需要了解如何调用,就…...
再学webpack
1 优化 webpack 打包体积的思路 优化 webpack 打包体积的思路包括: 提取第三方库或通过引用外部文件的方式引入第三方库:将第三方库单独打包,并通过 CDN 引入,减少打包体积。使用代码压缩插件:例如 UglifyJsPlugin&a…...
systemd:service与target使用及相关命令
文章目录 一、 unit1.1 unit常用命令 二、 service系统服务2.1 unit service配置文件2.1.1 [Unit]区块2.1.2 [Service]区块2.1.3 [Install]区块2.1.4 示例介绍 2.2 service常用命令 三、target3.1 tartget有关命令 四、其他系统命令4.1 systemctl 相关系统管理命令4.2 journalc…...
FairGuard游戏加固入选《CCSIP 2023中国网络安全行业全景册(第六版)》
2024年1月24日, FreeBuf咨询正式发布《CCSIP 2023中国网络安全行业全景册(第六版)》。本次发布的全景图,共计展示20个一级分类、108个细分安全领域,旨在为广大企业提供网络安全产品选型参考,帮助企业了解中国网络安全技术与市场的…...
文心一言 VS ChatGPT :谁是更好的选择?
前言 目前各种大模型、人工智能相关内容覆盖了朋友圈已经各种媒体平台,对于Ai目前来看只能说各有千秋。GPT的算法迭代是最先进的,但是它毕竟属于国外产品,有着网络限制、注册限制、会员费高昂等弊端,难以让国内用户享受。文心一言…...
JMeter临界部分控制器正确用法与避坑指南
1. 为什么“临界部分控制器”是压测中真正卡住团队的隐形瓶颈很多人第一次在JMeter里看到临界部分控制器(Critical Section Controller),第一反应是:“这不就是个带锁的逻辑块?加个锁而已,能有多复杂&#…...
3分钟解锁QQ音乐加密文件:Mac用户必备的免费解密工具指南
3分钟解锁QQ音乐加密文件:Mac用户必备的免费解密工具指南 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默…...
多模态融合在死因推断中的应用:特征级与决策级融合策略对比
1. 项目概述:当AI遇见死因推断,多模态融合如何破局?在公共卫生和流行病学领域,准确推断死因(Cause of Death, COD)是评估疾病负担、制定卫生政策的基础。然而,在资源有限的地区,获取…...
如何快速搭建个人小说图书馆:番茄小说下载器完整实战指南
如何快速搭建个人小说图书馆:番茄小说下载器完整实战指南 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 你是否曾经遇到过这样的问题:想离线阅读喜欢的…...
iOS越狱终极指南:从A11到A17芯片的完整越狱解决方案
iOS越狱终极指南:从A11到A17芯片的完整越狱解决方案 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder 👇 项目地址: h…...
保姆级教程:用UE4/UE5的WebUI插件,把Web页面嵌入数字孪生项目
虚幻引擎WebUI插件实战:数字孪生项目中无缝嵌入Web页面的完整指南在数字孪生项目的开发过程中,将实时数据可视化的Web页面嵌入到虚幻引擎场景中已成为提升用户体验的关键技术。本文将以UE4/UE5的WebUI插件为核心工具,手把手演示如何将Web前端…...
Atlas-Learn:从点云构建流形图册的工程实践与黎曼优化应用
1. 项目概述:从点云到流形图册的工程实践在机器学习和数据科学领域,我们常常面对一个核心困境:数据点看似散落在高维的欧几里得空间中,但其内在的、有意义的规律却往往存在于一个低维的非线性结构上。想象一下,你有一堆…...
高能物理实时触发系统:HGQ与LGN算法在FPGA上的极致优化实践
1. 项目概述:当粒子对撞遇见实时AI在大型强子对撞机(LHC)每秒数千万次的质子对撞中,CMS探测器会捕获海量的高维数据。第一级触发系统(L1T)的任务,是在3.8微秒的极短时间内,将事件率从…...
不止于播放:用Unity Video Player的RenderTexture模式,轻松实现游戏内电视、监控屏效果
超越基础播放:用Unity VideoPlayer打造沉浸式动态屏幕效果在游戏开发中,环境细节往往是区分平庸与卓越作品的关键。想象一下:玩家走进一个废弃的安全屋,墙上的监控屏幕闪烁着模糊的画面;或是科幻基地中,数据…...
如何集成OpenClaw?2026年腾讯云部署及配置Token Plan保姆级步骤
如何集成OpenClaw?2026年腾讯云部署及配置Token Plan保姆级步骤。OpenClaw是开源的个人AI助手,Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主…...
