[Halcon3D] 3D鞋点胶的点云边界提取

news2024/11/25 4:43:37
  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨

文章预览:

      • 一. 边界提取的常规思路
      • 二. 3D鞋点胶的点云边界提取具体步骤
        • 2.1、读取点云模型数据
        • 2.2、去噪(得到鞋子的点云数据集合)
        • 2.3、将鞋点云集合变换到原始坐标系下主轴-x y z(基准)
        • 2.5、求鞋点云最小外接box(选做)
        • 2.6、在Box中做切平面(切X轴),求与鞋子轮廓的交线


一. 边界提取的常规思路

3D鞋实物图如下所示:

在这里插入图片描述
鞋点胶的点云边界提取的常规思路:

(一) 法向量(很重要,本文基础内容暂时不做介绍,后面补充)

(二) 切平面(简单但适用性不强,本文使用该方式供初学者一个学习思路)

  1. 读取点云模型数据;
    read_object_model_3d(Operator)
  2. 分割出鞋子点云集合;
    connection_object_model_3d(Operator)
    select_object_model_3d(Operator)
  3. 仿射变换到长轴与X平行的位置(基准位置);
  4. 定义切平面,求鞋的3D点云集合跟切平面的点云交集
  5. 把交集的点云映射成2DXLD轮廓,求每段XLD轮廓的起点和终点坐标
  6. 把得到的每段XLD轮廓的起点和终点坐标映射转换成3D点云坐标
  7. 显示鞋的点云集合以及鞋的外边界点云集合;
  8. 若要配合机器人点胶的话,还需将外边界点云坐标排序、连接并指定机器人的运行轨迹,将外边界点云坐标转换成机器人坐标;

二. 3D鞋点胶的点云边界提取具体步骤

2.1、读取点云模型数据

如图所示:

在这里插入图片描述

read_object_model_3d ('./2020-01-14-16832.om3', 'm', [], [], ObjectModel3D, Status)
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
visualize_object_model_3d (WindowHandle, ObjectModel3D, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

交互式显示函数 visualize_object_model_3d ,相比较于显示函数 disp_object_model_3d 的不同:

visualize_object_model_3d(Operator) — Interactively display 3D object models. 交互式显示,可以点击旋转,缩放。
disp_object_model_3d(Operator) — Display 3D object models. 只是展示。

2.2、去噪(得到鞋子的点云数据集合)

如图所示:

在这里插入图片描述

* ['distance_3d', 1]点云距离在1mm之内的算作一个点云连通域集合
connection_object_model_3d (ObjectModel3D, 'distance_3d', 1, ObjectModel3DConnected)
* 获取每个点云连通域集合包含的点个数(因为鞋子点云连通域包含的点云个数最多)
get_object_model_3d_params (ObjectModel3DConnected, 'num_points', GenParamValue)
* 筛选点数(获取点云最多的集合,即鞋子点云),2e7 = 2*10的七次方
select_object_model_3d (ObjectModel3DConnected, 'num_points', 'and', 20000, 2e7, ObjectModel3DSelected)
visualize_object_model_3d (WindowHandle, ObjectModel3DSelected, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut1)

Halcon例程中关于点云筛选的两种不同方式【select_points_object_model_3d_by_density.hdev】和【select_object_model_3d.hdev】:

在这里插入图片描述


2.3、将鞋点云集合变换到原始坐标系下主轴-x y z(基准)

所谓主轴:用最小外接长方体将点云囊括,获取其长轴、短轴以及高度。

而鞋点云的长轴、短轴和高度相对于坐标系X、Y、Z轴,会有一个姿态关系,这里称作 pose

姿态Pose7个参数,包括3个平移(x、y、z)+3个旋转(Rx、Ry、Rz)+1个旋转类型(旋转顺序)—— 常规有0(先绕X旋转,在绕Y旋转,最后绕Z旋转)和1(和0相反)。

我们目的就是将鞋点云变换到标准位置,让其长轴与X轴重合,短轴与Y轴重合,高度与Z轴重合,好处是切平面与鞋面垂直,与轴平行,沿轴切,不会乱。整齐。

鞋子点云在刚体/仿射变换后的姿态所图所示:

在这里插入图片描述

* 'principal_axes'代表求主轴,并输出当前主轴姿态Pose
moments_object_model_3d (ObjectModel3DSelected, 'principal_axes', Pose)
* 姿态翻转
pose_invert (Pose, PoseInvert)
* 点云模型刚体变换
rigid_trans_object_model_3d (ObjectModel3DSelected, PoseInvert, ObjectModel3DStandard)
visualize_object_model_3d (WindowHandle, ObjectModel3DStandard, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

moments_object_model_3d(Operator):确定主轴X轴方向,这样做的原因是为了方便沿着x轴做切平面的时候,方便分割。这就是确定长轴的原因。

标准位置的好处:做切平面与鞋面垂直。与轴平行,沿轴切,不会乱。整齐。

其参数二含义:

  • 'central_moment_2_points'计算点云模型的二阶矩(方差、即点云X、Y、Z的波动情况),输出X、Y、Z的方差,XY、XZ、YZ协方差(关联性)。
  • 'mean_points'计算点云模型的一阶矩(均值、即点云X、Y、Z的均值大小),输出X、Y、Z的均值。
  • 'principal_axes'计算点云模型的主轴,输出姿态Pose3个平移(x、y、z)+3个旋转(Rx、Ry、Rz)+`1个旋转类型)。

其中刚体变换等价于仿射变换的如下方式:

* 点云模型仿射变换
pose_to_hom_mat3d (PoseInvert, HomMat3D)
affine_trans_object_model_3d (ObjectModel3DSelected, HomMat3D, ObjectModel3DAffineTrans)

2.5、求鞋点云最小外接box(选做)

若觉得鞋点云主轴(长、宽和高轴)与坐标轴(X、Y和Z轴)基本重合,也可忽略这一步。

因为鞋长轴可能并不是直线,所以2.4得到的鞋点云长轴可能不一定和X轴重合,这时我们可以求鞋点云最小外接box继续调整转正鞋长轴和X轴之间的位置关系,使鞋点云转正。

1)三角曲面重建

在这里插入图片描述

求鞋点云的最小外接box之前可以做一个三角网格曲面重建(点集→曲面),使得点云更加圆滑。

1、三角曲面重建:将无序点云三角化。内部算子实际使用的是贪婪投影三角法:将有向点云投影到一个二维平面内,做平面内三角化,
   最后根据平面内的三角拓扑关系,生成一个三角网格曲面模型。此外,若使用膨胀腐蚀(参数3,本文默认[]),就会使网格变大变小。
2、优化项:三角曲面重建需要点时间。如果点数太多的话,可以简化点云(暂不做演示)。
3、局限性:三角曲面重建比较适用于表面连续比较光滑的曲面,或者点云密度比较均匀的情况,速度会比较快。否则会出现因点云不连续导致的奇形怪状,甚至悬空点等。
* 对鞋点云进行三角曲面重建(点数多会有点耗时)
triangulate_object_model_3d (ObjectModel3DStandard, 'greedy', [], [], TriangulatedObjectModel3D, Information)
visualize_object_model_3d (WindowHandle, TriangulatedObjectModel3D, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

2)求鞋点云最小外接box

在这里插入图片描述

* Pose0:box的主轴(长、宽和高轴)相对于坐标轴(X、Y和Z轴)的姿态
* Length1、Length2、Length3:box长宽高
smallest_bounding_box_object_model_3d (TriangulatedObjectModel3D, 'oriented', Pose0,Length1, Length2, Length3)
* 求出来的box主轴长轴并不一定和X轴完全重合,下面需要调整
pose_invert (Pose0, Pose1) //姿态翻转
rigid_trans_object_model_3d (TriangulatedObjectModel3D, Pose1, TransObjectModel3D)
visualize_object_model_3d (WindowHandle, TransObjectModel3D, [], [], ['lut','color_attrib','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

截止到这里,我们就算将第三步的【将鞋点云集合变换到原始坐标系下主轴-x y z(基准)】完成了,下面将鞋子和盒子一起显示一下:

在这里插入图片描述

smallest_bounding_box_object_model_3d (TransObjectModel3D, 'oriented', PoseBox,Length1, Length2, Length3)
gen_box_object_model_3d (PoseBox, Length1, Length2, Length3, PoseBoxOriented)
*['green','gray',0.5,'true'] 0.5代表盒子透明度,1表示不透明,0表示完全透明
visualize_object_model_3d (WindowHandle,[TransObjectModel3D,PoseBoxOriented], [],[], ['color_0','color_1','alpha_1','disp_pose'], ['green','gray',0.5,'true'],'RectBOX', [], [], Pose)

最小外接Box的计算可参考Halcon示例【smallest_bounding_box_object_model_3d.hdev】:

在这里插入图片描述


2.6、在Box中做切平面(切X轴),求与鞋子轮廓的交线

X轴,做切平面,每次沿X轴移动指定均匀长度。切平面与鞋子点云有一个点云交集,把点云交集映射到二维平面上形成一个XLD二维的轮廓交线,交线的两端(起点、终点)就是我们需要的轮廓点

切平面沿X轴方向一段段的对鞋子点云做切割,需要引入一个循环问题:

参考Halcon示例:inspect_3d_surface_intersections.hdev

在这里插入图片描述
本小结主要由几个步骤组成:

  1. 求出切平面与鞋点云的XLD轮廓;(知识点1intersect_plane_object_model_3d求交平面 )
  2. 做姿态转换以及内参1:1转换(图像尺寸和实际尺寸1:1,这样比较好转换),将XLD轮廓投影变换到二维XLD进行处理;(知识点2:三维到二维XLD轮廓转换)
  3. 对轮廓行方向点坐标进行排序,获得最大最小点(轮廓边缘);(知识点3:排序求出二维XLD轮廓的起点、终点坐标)
  4. 将所有的二维XLD轮廓起点、终点坐标再转换成三维点云坐标(行坐标对应Y坐标,列坐标对应Z坐标);(知识点4:二维XLD轮廓转换到三维点云,因为比例是1:1,姿态直接转就行)
  5. 显示;

在这里插入图片描述
代码如下:

* 5.在box中做切平面,求与轮廓的交线
objectsOut:=[]
Index_S:=[]
Index_E:=[]
color_S:=[]
color_E:=[]
colorsOut:=[]
colorvaluesOut:=[]
all_x:=[]
all_y:=[]
* 做切平面与鞋子的点云相交
for index1:=0 to 45 by 1
*  求交线点云(做切平面)
   CutPlanePose := PoseBox
   CutPlanePose[0]:=PoseBox[0]-Length1/2+(index1)*4+3  //pose中的第五个参数值x:第一个为沿着x轴的平移,保证循环时可以沿着x轴正方向重复以一个固定距离做切割
*                                                      //需要从Box最左边开始做切割,所以:PoseBox[0]-Length1/2,每次循环沿着x轴往右移动4个单位
   CutPlanePose[3]:=0
   CutPlanePose[4]:=90  //pose中的第五个参数值Ry:绕着y轴(绿色)旋转90度,让平面立起来做切割
   CutPlanePose[5]:=0
   gen_plane_object_model_3d (CutPlanePose, [-1,-1,1,1] * 90, [-1,1,1,-1] * 90, IntersectionPlane)
*  visualize_object_model_3d (WindowHandle, [TransObjectModel3D,IntersectionPlane], [], Pose, ['disp_pose'], ['true'], [], [], [], PoseOut1)
   intersect_plane_object_model_3d (TransObjectModel3D, CutPlanePose, ObjectModel3DIntersection)
*  visualize_object_model_3d (WindowHandle, ObjectModel3DIntersection, [], [], [], [], [], [], [], PoseOut2)
*  为了求交线轮廓的起点和终点,需要变换到二维XLD(跟相机标定将世界坐标系转换到图像像素坐标系一个原理,需要内外参)
*  图像中的点云都是物理点坐标,都是世界坐标系下的姿态(图像相对于世界坐标系下的姿态),所以需要翻转姿态,转换成图像坐标系下的姿态
   pose_invert (CutPlanePose, PoseInvert)
*  确定投影平面在前面
   get_object_model_3d_params (ObjectModel3DIntersection, 'diameter_axis_aligned_bounding_box', Diameter)
   PoseInvert[2] := PoseInvert[2] +Diameter
*  用平行于投影平面的相机(1:1的比例)
   Scale:=1
   CamParam := [0,0,1.0 / Scale,1.0 / Scale,0,0,500,500] //人为构建相机内参(焦距、畸变系数、图像中心点、宽高)
   project_object_model_3d (IntersectionXld, ObjectModel3DIntersection, CamParam, PoseInvert, 'data', 'lines')

*  转换过来之后就存二维图像处理XLD轮廓,将轮廓的所有上下起点和终点求出来就是我们需要的鞋子边界了
   count_obj (IntersectionXld, Number)
   Rows:=[]
   Columns:=[]
   Row:=[]
   Column:=[]
*  可能会有断开的轮廓,这里遍历一下获取所有轮廓点
   for I:=1 to  Number  by 1
     select_obj (IntersectionXld, EdgeContour, I)
     get_contour_xld(EdgeContour, Row,Column)
     Rows:=[Rows,Row]
     Columns:=[Columns,Column]
   endfor
*  点按照由上到下排序
   tuple_sort_index (Rows, Indices)
   tuple_length(Rows,Length)
   OrderRow:=[]
   OrderColumn:=[]
   if(Length>=1)
   for Row_Index:=0 to Length-1  by 1
      OrderRow:=[OrderRow,Rows[Indices[Row_Index]]]
      OrderColumn:=[OrderColumn,Columns[[Row_Index]]]
   endfor
   endif
   gen_contour_polygon_xld (Intersection, OrderRow, OrderColumn) 
*  求最大和最小点(行方向)
   tuple_sort_index (OrderRow, Indices)
   tuple_length(OrderRow,Length)
*  起点(xld)
   StartRow:=OrderRow[Indices[0]]
   StartColumn:=OrderColumn[Indices[0]]
*  终点(xld)
   EndRow:=OrderRow[Indices[Length-1]]
   EndColumn:=OrderColumn[Indices[Length-1]] 
   gen_cross_contour_xld(StartXP, StartRow, StartColumn, 6, 0.795296)
   gen_cross_contour_xld(EndXP, EndRow,EndColumn, 6, 0.795296)
   dev_display(Intersection)
   * 转成点云的坐标
   StartPose:=[CutPlanePose[0],StartRow,-StartColumn, 0,0,0,0]
   EndPose  :=[CutPlanePose[0],EndRow,-EndColumn, 0,0,0,0]
   gen_sphere_object_model_3d (StartPose, 2, StartPoint)
   gen_sphere_object_model_3d (EndPose  , 2, EndPoint  )  
*  visualize_object_model_3d (WindowHandle, [StartPoint,EndPoint], [], [], [], [], [], [], [], PoseOut4)
 * 所有对点的边界点集合
   objectsOut := [objectsOut,StartPoint]
   objectsOut := [objectsOut,EndPoint  ] 
*  显示时的颜色
   Index_S:= 0+index1*2
   Index_E:= 0+index1*2+1
   color_S:='color_'+Index_S
   color_E:='color_'+Index_E
   
   colorsOut := [colorsOut,color_S]
   colorsOut := [colorsOut,color_E]
   
   colorvaluesOut := [colorvaluesOut,'blue']
   colorvaluesOut := [colorvaluesOut,'blue']
     
   all_x:=[all_x,CutPlanePose[0]]
   all_y:=[all_y,StartRow]
   
   all_x:=[all_x,CutPlanePose[0]]
   all_y:=[all_y,EndRow]
   
endfor
*显示外边界模型点云
visualize_object_model_3d (WindowHandle,[objectsOut,TransObjectModel3D], [],[],[colorsOut],[colorvaluesOut], [], '', [], Pose)
*2二维显示
dev_open_window (0, 0, 512, 512, 'black', WindowHandle1)
dev_set_color('red')
gen_cross_contour_xld(Start,all_x,all_y, 3, 0.885398)

效果展示:

在这里插入图片描述
注意:当前的算法稳定性不好,而且有些边缘处理粗糙,本文仅供给初学者提供一个解决该问题的思路,最好的做法是基于法向量求解。

点云模型以及完整代码:https://pan.baidu.com/s/15nXvEC8HbzvGM3_DuyCEbg                                                              提取码:wznw


下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/648262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot整合Camunda工作流引擎实现审批流程实例

环境&#xff1a;Spingboot2.6.14 camunda-spring-boot-starter7.18.0 环境配置 依赖配置 <camunda.version>7.18.0</camunda.version> <dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boo…

OpenCV 项目开发实战--用 (C++ / Python)实现伪着色

文末附相关测试代码下载链接 在本教程中,我们将首先展示一种使用 OpenCV 的预定义颜色图对灰度图像进行伪彩色/伪彩色 的简单方法。如果您更愿意使用自己的颜色图,我们还将展示一种定义自定义颜色图的方法。 行星和太空中其他物体的灰度图像通常是伪彩色的,以显示细…

基于在线光度校准的混合稀疏单目视觉里程计

文章&#xff1a;Hybrid sparse monocular visual odometry with online photometric calibration 作者&#xff1a;Dongting Luo, Yan Zhuang and Sen Wang 编辑&#xff1a;点云PCL 代码&#xff1a;https://github.com/luodongting/HSO.git 欢迎各位加入知识星球&#xff0c…

小破站上线了!

作者 | 磊哥 来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09; 转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09; 为了给大家更好的阅读体验&#xff0c;磊哥搞了一个专业的技术网站&#xff0c;整理并总结了 Java 中比较经典的文章&…

管理类联考——英语——知识篇——作文题材说明

小作文题材 一、题材&#xff1a;小作文的内容&#xff08;写什么&#xff09; 1.疫情相关的主题&#xff1a;&#xff08;以信件方式出题可能性60%&#xff0c;对生活影响大&#xff09; (1)停学、复学&#xff1a;线上或线下停学和复学( go back to class/ school )&#x…

绕过激活锁 ,拯救一台旧手机iphone

一台旧的iphone忘了apple id账号和密码了&#xff0c;导致锁住了 某宝上解锁要花50&#xff0c; 不是舍不得花钱&#xff0c;作为一个搞技术的&#xff0c;实在觉得花钱有点丢人 经过一番探索 最终确定了有用的流程 并贴出来 亲测可用 最终实现了趟再床上就可以打卡 1、 刷机 …

拯救者2022款 y9000k 安装ubuntu20.04 休眠后无法唤醒(成功解决)

拯救者2022款 y9000k 安装ubuntu20.04 休眠后无法唤醒 一.建议在安装新的 NVIDIA 显卡驱动之前卸载原有的驱动程序。这样可以确保新驱动程序的安装过程更加干净和稳定。以下是卸载原有驱动的步骤&#xff1a;1.进入命令行界面&#xff1a; 按下 Ctrl Alt F3 进入文本模式的命…

IDEA Build Artifacts 功能使用总结

文章目录 创建Artifact步骤Build Artifact步骤 打开IDEA&#xff0c;在没有创建Artifact时&#xff0c;菜单"Build -> Build Artifacts…“是灰色的&#xff0c;不可用状态。 所以&#xff0c;第一步是进入"File -> Project Structure…”&#xff0c;创建Arti…

10. python从入门到精通——模块

目录 模块的概述 自定义模块 Python中的包 以主程序的形式执行 引用其他模块 模块的概述 什么是模块&#xff1a;在python中模块就是python程序&#xff0c;一个模块就是一个*.py的文件&#xff0c;通常情况下把能够实现某一特定功能的代码放置在一个文件中作为一个模块&…

基于Java实验室耗材管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

如何理解gic控制器中的originating PE Banked和target PE Banked

【问题】 如何理解originating PE Banked和target PE Banked&#xff0c;下面gicv2/gicv3的banked如何理解&#xff1f; 【回答】 GICv2 中&#xff0c;SGI 对于 originating PE&#xff08;即生成中断的处理器&#xff09;和 target PE&#xff08;即接收中断的处理器&#…

【JVM】命令行工具的基本使用--JVM常用指令

文章目录 背景一、Java 性能诊断工具简介二、简单命令行工具2.1、jps2.2、jinfo2.3、jstat2.4、jstack2.5、jmap2.6、jhat 三、图形化综合诊断工具3.1、JVisualvm3.2、JProfiler3.3、JConsole 背景 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题&#xff0c;在用…

few-shot / one shot / zero shot object counting论文汇总

文章目录 2021OBJECT COUNTING: YOU ONLY NEED TO LOOK AT ONE 2022Scale-Prior Deformable Convolution for Exemplar-Guided Class-Agnostic CountingCounTR: Transformer-based Generalised Visual CountingFew-shot Object Counting with Similarity-Aware Feature Enhance…

python+vue企业高校文档管理系统的设计与实现

开发语言&#xff1a;Python 框架&#xff1a;django/flask Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm 在这个推荐个性化的时代&#xff0c;采用新技术开发一个文档系统来分享和展示内容是一个…

编程语言/文件系统/网络协议存在的那些编码

前面的文章介绍了URL编码&#xff0c;UTF8编码&#xff0c;base64&#xff0c;gzip等多种编解码的方式&#xff0c;这里&#xff0c;本节对字符和编码一些杂项进行梳理&#xff0c;相信你会感兴趣。 Python 中的字符和编码 为什么要强调字符编号和字符编码分离这样⼀个概念呢…

A100 GPU服务器安装CUDA教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

02队列及代码实现

队列介绍 队列是一个有序列表&#xff0c;可以用数组或是链表来实现。、遵循先入先出的原则。 &#xff08;先存入队列的数据&#xff0c;要先取出。后存入的要后取出&#xff09; 数组模拟队列 队列本身是有序列表&#xff0c;若使用数组的结构来存储队列的数据&#xff0c;则…

【6月比赛合集】42场可报名的「创新应用」、「数据分析」和「程序设计」大奖赛,任君挑选!

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 创新应用赛&#xff08;39场比赛&#xff09;数据分析赛&…

MySQL—SQL优化详解(上)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

万物的算法日记|第三天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…