【三维目标检测】SSN(二)

news2024/11/17 13:42:00

        SSN数据和源码配置调试过程请参考上一篇博文:【三维目标检测】SSN(一)_Coding的叶子的博客-CSDN博客。本文主要详细介绍SSN网络结构及其运行中间状态。

1 模型总体过程

        SSN主要结构如下图所示,其核心在于提出了shape-aware heads grouping和shape signature结构,前者针对不同类别目标设置不同Head,并得到不同尺度的特征图。相比于其他网络采用单一尺度的特征图,这种方法的可以有效提升精度,但是参数量也大大增加。从实现过程来看,这种结构实际上与增加anchor和FPN的作用相近似。另一方面,读者也可以类比以下yolov5的Head结构。shape signature结构主要是对目标轮廓进行编码,强调了目标轮廓形状的特点,从而最终进一步提升目标检测精度。

        需要注意的是,在接下来即将详细介绍的mmdetection3d SSN程序种仅仅使用了shape-aware heads grouping结构,并没有采用shape signature结构。

2 主要模块解析

2.1 体素化

        源码中用于实现体素化的入口函数为self.voxelize(points),具体实现函数为Voxelization(voxel_size=[0.25, 0.25, 8], point_cloud_range=[-50, -50, -5, 50, 50, 3], max_num_points=20, max_voxels=(30000, 40000), deterministic=True)。函数输入分别为:

        (1)points,Nx4,原始点云,N表示点云数量,4表示特征维度,特征为坐标x、y、z与反射强度r。

        (2)voxel_size:单位体素的尺寸,x、y、z方向上的尺度分别为0.25m、0.25m、8m。

        (3)point_cloud_range:x、y、z方向的距离范围,结合(2)中体素尺寸可以得到总的体素数量为400x400x1。

        (4)max_num_points:定义每个体素中取值点的最大数量,默认为20,在voxelnet中T=35。

        (5)max_voxels:表示含有点云的体素最大数量,训练时为30000,推理时为40000。训练时当数量超过30000时,仅保留30000,当数量不足40000时,则保留全部体素。

        (6)deterministic:取值为True时,表示每次体素化的结果是确定的,而不是随机的。

        体素化输出结果如下:

        (1)voxels:Mx20x4,体素中各个点的原始坐标和反射强度,M(M≤30000)个体素,每个体素最多20个点。

        (2)num_points:Mx1,每个体素中点的数量,最小数量为1,最大数量为20。

        (3)coors:体素自身坐标,坐标值为整数,表示体素的按照单位尺度得到的坐标,Mx4,[batch_id, x, y, z]

2.2 体素特征提取VFE(voxel_encoder)

        类似voxelnet和Pointpillars模型,体素特征通过SVFE层提取,即连续两层VFE,其中VFE层提取体素特征用的是PointNet网络。SVFW详细结构和计算过程请参考:【三维目标检测】VoxelNet(三):模型详解_Coding的叶子的博客-CSDN博客_voxelnet和【三维目标检测】Pointpillars(二)_Coding的叶子的博客-CSDN博客_voxels 点云。SVFW体素特征提取的入口函数为self.pts_voxel_encoder(voxels, num_points, coors, img_feats, img_metas)。SSN提取的体素特征voxel_features的维度为Mx64。

2.3 中间特征提取 middle_encoder

        SSN采用的中间特征提取网络为PointPillarsScatter。Pointpillars的中间特征提取层将voxel_features(Mx64)每一维特征投影到各个体素当中,类似于二维图像,Mx64->400x400x1,即Mx64->160000x64,没有取值的地方像素值取为0。Canvas,64x400x400。由于体素在Z轴方向上的长度仅仅为1,所以投影后得到的是一个平面信息,这样后续可以直接用二维卷积进行特征提取,而不需要采用三维卷积或三维稀疏卷积操作。这个操作实际上可以直接用三维稀疏卷积进行替换。中间特征提取层的入口函数为self.pts_middle_encoder(voxel_features, coors, batch_size),输出特征维度为64x400x400。

2.4 主干网络特征提取

        SSN主干网络采用了SECOND FPN结构,函数入口为self.pts_backbone(x),输出三种不同尺度的特征64x200x200、128x100x100、256x50x50。

        backbone:SECOND

        1、2.3中out 64x400x400经连续4个3x3卷积(第一个步长为2):64x200x200,out1

        2、out1 64x200x200经连续6个3x3卷积(第一个步长为2):128x100x100,out2

        3、out2 128x100x100经连续6个3x3卷积(第一个步长为2):256x50x50,out3

SECOND(
  (blocks): ModuleList(
    (0): Sequential(
      (0): Conv2d(64, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (1): NaiveSyncBatchNorm2d(64, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (2): ReLU(inplace=True)
      (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (4): NaiveSyncBatchNorm2d(64, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (5): ReLU(inplace=True)
      (6): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (7): NaiveSyncBatchNorm2d(64, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (8): ReLU(inplace=True)
      (9): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (10): NaiveSyncBatchNorm2d(64, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (11): ReLU(inplace=True)
    )
    (1): Sequential(
      (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (1): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (2): ReLU(inplace=True)
      (3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (4): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (5): ReLU(inplace=True)
      (6): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (7): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (8): ReLU(inplace=True)
      (9): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (10): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (11): ReLU(inplace=True)
      (12): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (13): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (14): ReLU(inplace=True)
      (15): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (16): NaiveSyncBatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (17): ReLU(inplace=True)
    )
    (2): Sequential(
      (0): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (1): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (2): ReLU(inplace=True)
      (3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (4): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (5): ReLU(inplace=True)
      (6): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (7): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (8): ReLU(inplace=True)
      (9): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (10): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (11): ReLU(inplace=True)
      (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (13): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (14): ReLU(inplace=True)
      (15): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (16): NaiveSyncBatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)
      (17): ReLU(inplace=True)
    )
  )
)

2.5 上采样拼接 self.neck

        Neck层分别对out1、out2、out3上采样后进行拼接,函数入口为self.pts_neck(x),拼接后输出特征pts_feats维度为384x200x200:

        out1:64x200x200 -> 128x200x200

        out2:128x100x100 -> 128x200x200

        out3:256x50x50 -> 128x200x200

       拼接out:128x200x200、128x200x200、128x200x200 ->384x200x200 (self.extract_feat)

2.6 检测头 bbox_head

        SSN的head结构入口函数为self.pts_bbox_head(pts_feats)。由于不同类别目标的点云自身在轮廓结构上有所差异,SSN设计针对不同类别设置了不同的Head。各个单独的Head与常规的RPN Head一致,主要包括分类head、位置head和方向head。另一方面,根据特征图越小视野越大这一卷积操作特征,我们知道小的特征图适合检测大目标。因而,针对车辆和卡车这种大目标,特征图尺度由200x200降为100x100。

        各个Head分支参数分别如下,将所有结果进行拼接可得到分类分数cls_score(500000x10)、位置bbox_pred(500000x9)和方向dir_cls_preds(500000x2),其中500000是anchor总数。位置的9个维度分别为中心偏移(dx、dy、dz)、尺寸对数(log(dw)、log(dl)、log(dz))、角度rz、速度(vx、vy)。

(1)2种anchor、2个类别(bicycle、motorcycle)、特征图200x200 ->160000
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 40) -> cls_score 40x200x200 -> 160000x10
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 36) ->bbox_pred 36x200x200 -> 160000x9
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 8) ->bbox_pred 8x200x200 -> 160000x2
(2)2种anchor、1个类别(pedestrian)、特征图200x200 ->80000
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 20) -> cls_score 20x200x200 -> 80000x10
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 18) ->bbox_pred 18x200x200 -> 80000x9
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 4) ->bbox_pred 4x200x200 -> 80000x2
(3)2种anchor、2个类别(traffic_cone、barrier)、特征图200x200 ->160000
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 40) -> cls_score 40x200x200 -> 160000x10
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 36) ->bbox_pred 36x200x200 -> 160000x9
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 8) ->bbox_pred 8x200x200 -> 160000x2
(4)2种anchor、1个类别(car)、特征图100x100 ->20000
pts_feats、Cls Conv2d(384, 64, 2)、Conv2d(64, 64)、Conv2d(64, 20) -> cls_score 20x100x100 -> 20000x10
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 18) ->bbox_pred 18x100x100 -> 20000x9
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 4) ->bbox_pred 4x100x100 -> 20000x2
(5)2种anchor、4个类别(truck、trailer、bus、construction_vehicle)、特征图100x100 -> 80000
pts_feats、Cls Conv2d(384, 64, 2)、Conv2d(64, 64)、Conv2d(64, 80) -> cls_score 80x100x100 -> 80000x10
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 72) ->bbox_pred 72x100x100 -> 80000x9
pts_feats、Cls Conv2d(384, 64)、Conv2d(64, 64)、Conv2d(64, 16) ->bbox_pred 16x100x100 -> 80000x2
Outs  outs = self.pts_bbox_head(pts_feats)
cls_score: 500000x10
bbox_pred:500000x9
dir_cls_preds:500000x2

2.7 损失函数

        losses = self.pts_bbox_head.loss(*loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore)

2.7.1 标签计算.

        根据Iou为每个anchor选择匹配的真实目标框

  1. 找到最大Iou的真实目标框和索引
  2. Iou小于指定阈值如0.4的anchor设置为负样本,对应gt_inds序号为0。
  3. Iou大于指定阈值如0.6的anchor设置为正样本,对应gt_inds需要设置为样本标签序号,从1开始。
  4. gt_inds取值为-1的点对应样本介于正负样本之间的情况。

        目标位置采用偏移回归的方式,如下所示。其中,a表示anchor,g表示真实标签,t表示模型预测标签。

za = za + ha / 2
zg = zg + hg / 2
diagonal = torch.sqrt(la**2 + wa**2)
xt = (xg - xa) / diagonal
yt = (yg - ya) / diagonal
zt = (zg - za) / ha
lt = torch.log(lg / la)
wt = torch.log(wg / wa)
ht = torch.log(hg / ha)
rt = rg - ra
limited_val = val - torch.floor(val / period + offset) * period

2.7.2 损失计算

        SSN总体损失包括目标类别损失、方向损失和位置偏移回归损失。目标类别和方向的损失函数分别为FocalLoss和CrossEntropyLoss。位置偏移回归的9个维度损失函数均为SmoothL1Loss,并且速度(最后两个维度)损失权重为0.2,其它权重均为1.0。在实验过程中,随机选择了两组样本,其负样本的点数量为999823,而正样本数量仅为91。针对这种正负样本不均衡的情况,目标类别损失函数采用了FocalLoss。

loss_cls = self.loss_cls(cls_score, labels, label_weights, avg_factor=num_total_samples)
loss_cls FocalLoss
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.2]
loss_bbox = self.loss_bbox(bbox_pred, bbox_targets, bbox_weights, avg_factor=num_total_samples)
SmoothL1Loss
loss_dir = self.loss_dir(dir_cls_preds, dir_targets, dir_weights, avg_factor=num_total_samples)
CrossEntropyLoss

2.8 顶层结构

        顶层结构主要包含以下三部分:

        (1)特征提取:self.extract_feat,通过PointPillars网路机构进行特征提取,输出结果见2.5节。

        (2)bbox Head:结果预测,见2.6节。

        (3)损失函数:见2.7节。

def forward_train(self, points=None, img_metas=None, gt_bboxes_3d=None, gt_labels_3d=None, gt_labels=None, gt_bboxes=None, img=None, proposals=None, gt_bboxes_ignore=None):
    img_feats, pts_feats = self.extract_feat(points, img=img, img_metas=img_metas)
    losses_pts = self.forward_pts_train(pts_feats, gt_bboxes_3d, gt_labels_3d,    img_metas, gt_bboxes_ignore)
    losses.update(losses_pts)
    return losses

3 训练命令

python tools/train.py configs/ssn/hv_ssn_secfpn_sbn-all_2x16_2x_nus-3d.py

4 运行结果

【python三维深度学习】python三维点云从基础到深度学习_Coding的叶子的博客-CSDN博客_python点云目标检测从三维点云基础知识到深度学习,将按照以下目录持续进行更新。更新完成的部分可以在三维点云专栏中查看。含数据与python源码。https://blog.csdn.net/suiyingy/article/details/124017716

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

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

相关文章

认识分布式锁、使用分布式锁 Redission、实现秒杀案例

分布式锁 基本原理 分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行&…

[附源码]计算机毕业设计基于Vue的社区拼购商城Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

node.js-fs模块学习

目录 1.使用fs.readFile方法读取文件 2.使用fs.writeFile方法写入文件 3.fs小案例-整理成绩并写入到新文件中 4.fs模块-路径动态拼接的问题 1.使用fs.readFile方法读取文件 //导入fs模块 const fs require(fs)//调用fs读取文件 //参数1:读取文件的存放路径 //…

spring——Spring Bean属性注入——短命名空间注入——p 命名空间注入(setter注入)...

短命名空间注入 我们在通过构造函数或 setter 方法进行属性注入时&#xff0c;通常是在 <bean> 元素中嵌套 <property> 和 <constructor-arg> 元素来实现的。这种方式虽然结构清晰&#xff0c;但书写较繁琐。Spring 框架提供了 2 种短命名空间&#xff0c;可…

java基于Springboot的论坛管理系统-计算机毕业设计

项目介绍 在社会快速发展的影响下&#xff0c;论坛管理系统继续发展&#xff0c;使论坛管理系统的管理和运营比过去十年更加信息化。依照这一现实为基础&#xff0c;设计一个快捷而又方便的网上论坛管理系统是一项十分重要并且有价值的事情。对于传统的论坛管理系统控制模型来…

【大数据入门核心技术-Azkaban】(一)Azkaban介绍

目录 一、Azkaban 是什么 二、Azkaban 特点 三、Azkaban 与 Oozie 对比 一、Azkaban 是什么 Azkaban 是由 Linkedin 公司推出的一个批量工作流任务调度器&#xff0c;Azkaban 使用 job 文件建立任务之间的依赖关系&#xff0c;并提供 Web 界面供用户管理和调度工作流 官方网…

最新、最全面的Java面试题及答案(212道)

文章目录一. Java 基础1. JDK 和 JRE 有什么区别&#xff1f;2. 和 equals 的区别是什么&#xff1f;3. 两个对象的 hashCode() 相同&#xff0c;则equals() 也一定为true&#xff0c;对吗&#xff1f;4. final 在 Java 中有什么作用&#xff1f;5. Java 中的 Math. round(-1.…

服务器编译spark3.3.1源码支持CDH6.3.2

1、一定要注意编译环境的配置 mvn:3.6.3 scala:2.12.17 JDK:1.8 spark:3.3.1 服务器内存至少需要 8G 重点2、下载连接 wget https://dlcdn.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip wget https://downloads.lightbend.com/scala/2.12.17/scala-2…

大量域名数据下载地址收集整理

说明地址中文网站排行榜——网站排名大全http://www.alexa.cn/siterankAlexa排名(70万的数据)top-1m.csv.zipCisco Umbrellahttp://s3-us-west-1.amazonaws.com/umbrella-static/index.htmlMajestic Millionhttps://majestic.com/reports/majestic-millionTranco-List.euhttps:…

这回稳了,蓝桥杯才是yyds!

为了提高自己的编程能力&#xff0c;很多人会选择参加比赛。而这些比赛中&#xff0c;连续三年入选“全国普通高校学科竞赛排行榜”的蓝桥杯大赛&#xff0c;可以综合测评加分&#xff0c;优先奖学金评定、升学考研加分&#xff0c;yyds !! 蓝桥杯大赛报名截止至12月16日&…

Win 11 安装pycolmap

1.vcpkg安装 1.1 下载vcpkg源码 >> git clone gitgithub.com:microsoft/vcpkg.git1.2 编译生成vcpkg工具 >> .\vcpkg\bootstrap-vcpkg.bat这样在vcpkg文件夹下就会生成vcpkg.exe文件 2.colmap安装 2.1 命令安装colmap的gpu版本 >> .\vcpkg install col…

矩阵 行列式的计算

行列式要求 要计算行列式&#xff0c;那么这个矩阵一定是一个方阵 行列式性质 行列式转置后值不变互换行列式中两行&#xff0c;值变为相反数行列式中两行成比例&#xff0c;行列式为0行列式中一行所有元素乘以一个数后加到另一行&#xff0c;行列式值不变 行列式的计算有很…

【编译原理】第二章部分课后题答案

《编译原理&#xff08;第三版&#xff09;》陈意云著 第 二 章 课 后 习 题 T 2.3 叙述由下列正规式描述的语言 0(0∣1)∗0\space\space0\space\space(\space\space 0\space\space |\space\space 1\space\space)^{\space*\space\space}00 ( 0 ∣ 1 ) ∗ 0 正规式规定开…

Java搭建宝塔部署实战毕设项目springboot销售培训考评系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕业设计项目springboot销售培训考评系统源码。 技术架构 技术框架&#xff1a;jQuery MySQL5.7 mybatis shiro Layui HTML CSS JS jpa运行环境&#xff1a;jdk8 IntelliJ…

【Linux】四、Linux 进程概念(三)|进程优先级|环境变量

目录 七、进程优先级 7.1 基本概念 7.1.1 什么是优先级 7.1.2 为什么存在优先级 7.1.3 Linux 优先级特点 7.2 查看系统进程 7.3 PRI 和 IN 7.4 查看进程优先级和更改进程优先级 7.5 其它概念 7.6 进程切换 八、环境变量 8.1 环境变量基本概念 8.2 常见环境变量 8…

windows下node.js通过N-API调用c++函数

环境准备 vscode安装&#xff08;以下均在vscode中操作&#xff09;node.js安装&#xff0c;版本不要太老c工具链安装&#xff0c;安装Visual Studio2019社区版即可&#xff0c;或者执行 npm install --global windows-build-tools&#xff08;这个我没试过&#xff0c;window…

ARM SDRAM

前言 涉及到的文档&#xff1a; S5PV210_UM_REV1.1 x210cv3.pdf K4T1G164QE.pdf 一、SDRAM 引入 1、简介 SDRAM&#xff1a;Syncronized Dynamic Ramdam Access Memory&#xff0c;同步动态随机存储器; DDR&#xff1a;DDR 就是 DDR SDRAM&#xff0c;是 SDRAM 的升级版。…

[论文分享] DnD: A Cross-Architecture Deep Neural Network Decompiler

DnD: A Cross-Architecture Deep Neural Network Decompiler [USENIX 2022] Ruoyu Wu Purdue University Taegyu Kim The Pennsylvania State University Dave (Jing) Tian Purdue University Antonio Bianchi Purdue University Dongyan Xu Purdue University 深度神经网络(…

web前端期末大作业:婚纱网页主题网站设计——唯一旅拍婚纱公司网站HTML+CSS+JavaScript

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

代码随想录训练营day59, 下一个更大元素II, 接雨水

下一个更大元素II 给定一个循环数组, 输出每个元素的下一个更大元素, 没有则-1 所以在遍历的过程中, 模拟走了两遍nums class Solution {public int[] nextGreaterElements(int[] nums) {int len nums.length;//先进行边界判断if(nums null || len < 1){return new int…