PointConv: Deep Convolutional Networks on 3D Point Clouds
    Wenxuan Wu     Zhongang Qi     Li Fuxin
    CORIS Institute     Oregon State University

论文地址:https://arxiv.org/abs/1811.07246

代码:https://github.com/DylanWusee/pointconv

摘要

  • PointConv是将动态滤波器扩展到点云上的一个新的卷积运算。可以应用于点云以构建深度卷积网络。
  • 卷积核被视为由权重函数和密度函数组成的三维局部坐标的非线性函数。权重函数通过MLP学习得到。
  • 提出了一个公式,改写权重函数的表达形式,可以有效地计算权重函数,从而能够大幅扩展网络并显着改善其性能。
  • 学习的卷积核可用于计算3D空间中任何点集上的平移不变和置换不变卷积。
  • PointConv可用作反卷积运算符,以将特征从子采样点云传播回其原始分辨率。
  • 在ModelNet40,ShapeNet和ScanNet上进行的实验表明,基于PointConv构建的深度卷积神经网络能够在3D点云上具有挑战性的语义分割基准上达到最新水平。
  • 将CIFAR-10转换为点云,在PointConv上构建的网络的性能可以与2D卷积网络相当。

一、前言

1.1直接获取3D数据的传感器

  室内传感器(例如激光扫描仪)

  飞行时间传感器(例如Kinect,RealSense或Google Tango)

  结构光传感器(例如iPhoneX上的传感器)

  室外传感器(例如LIDAR和MEMS传感器)

1.2为什么用3D数据

  深度信息 可以消除2D图像中的许多分割模糊性,并且表面法线 提供了场景几何的重要线索。

1.3目前遇到的困难

  3D数据通常以点云的形式出现,这是一组无序的3D点,每个点上有或没有附加功能(例如RGB)。

  点云是无序的,并且不符合2D图像中的规则网格。

  在这种无序输入上很难应用常规的CNN。

1.4现有的解决方法及存在的问题

  将3D空间转换为体素网格,但是在高分辨率体积上,体积将稀疏而CNN则难以计算。

二、本文idea

2.1 idea来源

  2D图像中,卷积神经网络(CNN)从根本上改变了计算机视觉的格局。

  CNN通过利用平移不变性获得成功,因此可以将同一组卷积滤波器应用于图像中的所有位置,从而减少参数数量并提高泛化能力。

  希望将这种成功转移到3D数据分析中。

2.2 初始思路

  本文提出了一种在非均匀采样下对3D点云进行卷积的新颖方法, 卷积运算可以看作是连续卷积算子的离散逼近。在3D空间中,我们可以把 卷积核的权重看作3D点相对于中心点的局部坐标的(Lipschitz)连续函数。该连续函数(即卷积核权重)可以用多层感知器(MLP)近似,如[33]和[16]所述。但是这些算法并没有考虑非均匀采样的问题,我们建议使用 反密度标度对MLP学习的连续函数(卷积核权重)进行加权,这与连续卷积的蒙特卡洛近似相对应,我们称这种操作为PointConv。

  PointConv涉及将点云的位置作为输入并学习MLP以近似权重函数,并对学习的权重应用反密度标度以补偿非均匀采样。

注:

  Lipschitz连续:

  对于函数f(x) ,如果存在一个常数K,使得对于任意在f(x)定义域上的两点x1,x2,满足:|f(x1)-f(x2)|<=|x1-x2|*K 。那么成函数f(x)满足Lipschitz连续条件,并称K为f(x)的Lipschitz常数。

Lipschitz连续是比一致连续性更强的连续性,它限制了函数在某个局部区间内的变化幅度不能超过某常量。

注:

  带有偏差样本的蒙特卡洛估计:

  点云通常是有偏差的样本,因为许多传感器很难测量平面边界附近的点,因此需要重新加权。

2.3 改进的思路

  当输出功能的通道大小非常大时,PointConv的简单实现会导致内存效率低下,因此难以训练和扩展到大型网络。为减少PointConv的内存消耗,通过使用 更改求和顺序 的重新构造来提高存储效率。

  这种新结构能够在3D点云上构建多层深度卷积网络,该网络具有与栅格图像上2D CNN相似的功能。

  可以实现与2D卷积网络中相同的平移不变性,以及点云中点的排列顺序的不变性。

2.4 进一步创新

  大多数最先进的算法pointnet,pointnet++无法执行反卷积,这限制了它们在分割任务上的性能。

  PointConv是卷积的完全近似,因此可以很自然地将PointConv扩展到PointDeconv,它可以完全利用粗层信息并传播到较细的层。

  通过使用PointConv和PointDeconv,可以提高语义分割任务的性能。

2.5 本文贡献

  • 提出PointConv,一种密度重加权卷积,可以完全模拟3D连续卷积,弥补不均匀采样带来的影响。(通过S的加权使得点云均匀,进而可视为是对3D连续卷积函数的近似);
  • 通过优化求和顺序,设计出一种PointConv的高效内存实现;即把权重计算分为两部分(MLP最后一层的输入M和权重H)来减少计算量,降低内存占有率,提升网络运行效率。
  • 将PointConv扩展到反卷积版本(PointDeconv),获得更好的分割结果,插值-skip connection-PointConv组成PointDeConv。

三、PointConv

3.1 2D图像与3D点云的区别

  对于d维向量x的函数f(x)和g(x),定义卷积如下:

  图像可以解释为2D离散函数,通常表示为网格状矩阵。在CNN中,每个滤波器都限于一个小的局部区域,例如3×3,5×5等。在每个局部区域内,不同像素之间的相对位置始终是固定的,如图1(a)所示。而且,对于局部区域内的每个位置,可以轻松地将滤波器离散化为具有实值权重的总和。

  点云表示为一组3D点{ pi∣i = 1,. . .,n },其中每个点都包含位置矢量(x,y,z)及其特征,例如颜色,表面法线等。与图像不同,点云具有更灵活的形状。点云中某个点的坐标p =(x,y,z)∈ R3不在固定网格上,而是可以采用任意连续值。因此, 每个局部区域中不同点的相对位置是不同的。栅格图像上的常规离散卷积滤波器无法直接应用于点云。图1显示了图像中的局部区域和点云之间的差异。

3.2 3D连续卷积 -> 点云卷积

3.2.1 原始PointConv

3D卷积的连续版本:

  其中W和F均为连续函数,F是以点p(x,y,z)为中心的局部区域G中点的特征。

3D卷积的离散版本:

  一组点云可以视为从一个连续空间R^3进行非均匀采样的结果。在每个局部区域中,(δx, δy, δz)可能是局部区域的任何可能的位置,上式可以离散化到一个离散的3D点云上:

  F 是每个点的特征,理解的是这里初始是把点云坐标xyz作为输入,也就是说,Cin是3。S(δx, δy, δz) 是点(δx, δy, δz)处的逆密度估计,可以理解为密度的相反数,一个点周围的密度越大,权重越小,因为有冗余。S(δx, δy, δz)是必须的,因为可以非常不均匀地对点云进行采样(涉及到蒙特卡洛估计)。然后使用逆密度估计对学到的权重进行加权,补偿不均匀采样。

  图2(a)是学习的连续权重函数;图(b)和(c)是二维点云中的不同局部区域。给定二维点,我们可以得到特定位置的权值。同样的道理也适用于3D点。在图2(c)中,点p3,p5,p6,p7,p8,p9,p10彼此非常接近,因此每个点的贡献会更小。常规的离散二维卷积可以看作是连续卷积权重函数的离散化,如(d)。

主要思想:

权重函数W(δx, δy, δz):

  • 通过MLP从三维坐标(δx, δy, δz)中近似
  • 权重函数高度依赖于输入点云的分布

逆密度函数S(δx, δy, δz):

  • 用一个核密度估计以及一个非线性变换(MLP实现)近似

  PointConv中的MLP的权重在所有点之间共享,以便保证置换不变性。为了计算反向密度尺度估计函数S(δx, δy, δz),我们首先使用核密度估计(KDE)离线估算点云中每个点周边的密度,然后将密度值输入到一个1D非线性变换的MLP中。使用非线性变换的原因是有必要让网络自适应地决定是否使用密度估计。

  PointConv学习一个网络用以近似卷积的连续权重。对于每个输入点,我们可以使用其相对坐标来计算MLP的权重。图2(a)展示了一个用于卷积的连续权重函数。不妨将点云输入视作对连续输入的离散化采样,一个离散卷积可以通过图2(b)所示的方式进行计算,用以提取局部特征,这对于不同的点云采样集合都有作用(可能具有不同的近似精度)(图2)(b-d)),其中的一个例子包括规则网格(图2(d))。注意,在栅格化图像中,局部区域中的相对位置是固定的。这时,PointConv(仅采用各点的相对位置作为权重函数的输入)将在整个图像上输出相同的权重和密度,此时它退化成为传统的离散化卷积。

  为了聚合整个点集中的特征,我们使用层次化的结构,该结构能够整合细粒度的小区域特征进而组合成覆盖更大空间范围的抽象特征。我们使用的层次结构由几个特征编码模块组成,类似于PointNet ++ [28]中使用的模块。每个模块大致相当于卷积CNN中的一个层。每个特征编码模块中的关键层是采样层,分组层和PointConv。

  这种方法的缺点是每个滤波器需要由一个网络近似,因此效率非常低。

3.2.2 高效的PointConv

  原始的PointConv实现内存消耗巨大和比较低效。我们提出了一种新的重构方法,这种方法通过将PointConv减少到两个标准操作来实现PointConv:矩阵乘法和2d卷积。这种新颖的技巧不仅利用了GPU的并行计算,而且可以使用主流深度学习框架轻松实现。因为反密度估计函数不存在内存问题,所以下面的讨论主要集中在权重函数上。

  将训练阶段的mini-batch size记为B,点云中的点的个数记为N,每个点的邻域中点的个数记为K,C_in为输入点的通道数,C_out为点的输出通道通道数。对一个点云而言,每部分局部区域都共享从MLP习得的相同的权重函数。但是对不同位置的不同点而言,运算得到的权重应当是不同的。由MLP生成的权重卷积核参数大小约为B × N × K × (C_in × C_out)。为此,本文提出高效版PointConv。

  假设B = 32, N = 512, K = 32, Cin = 64, Cout = 64,滤波器存储具有单点精度。然后,仅一层滤波器的内存大小只有8GB的。这样高的内存消耗会使网络难以训练。[33]使用非常小的网络和很少的过滤器,这大大降低了它的性能。为了解决这个问题,我们提出了一个基于以下引理的内存效率版本的PointConv:

  内存大小变为:B×N×C_mid×C_in,内存开销为原始PointConv的C_mid/(K*C_out)倍。

注:

(1)分类

  网络架构相当于PointNet++,只是用PointConv替换PointNet层。

  PointConvDensitySetAbstraction()层-全连接层。

(2)分割

  网络架构如图4所示。

  通过四层 编码-解码层-全连接层-1×1卷积层 组成。

3.2.3 PointDeConv

  对于分割任务,我们需要逐点预测。为了获得所有输入点的特征,需要一种将特征从子采样点云传播到更密集的点云的方法。 PointNet ++ [28]提议使用基于距离的插值来传播特征,由于局部区域内的局部相关性,这是合理的。但是,这并没有充分利用反卷积操作的优势,该反卷积操作从粗糙级别捕获传播信息的局部相关性。我们建议添加一个基于PointConv的PointDeconv层,作为反卷积操作来解决此问题。

  如图4所示,PointDeconv由两部分组成:插值和PointConv。首先,我们采用插值法传播来自上一层的粗略特征。继[28]之后,通过线性插值来自3个最近点的要素进行插值。然后,使用skip-links将内插特征与来自具有相同分辨率的卷积层中的特征连接起来。连接后,我们对连接的特征应用Point-Conv以获得最终的去卷积输出,类似于图像去卷积层[24]。我们应用此过程,直到所有输入点的特征都传播回原始分辨率为止。

四、实验

  三维数据集:ModelNet40,ShapeNet,ScanNet

  二维数据集:CIFAR-10

4.1 在ModelNet40上的分类

  使用PointNet的源代码对1,024个点进行均匀采样,并根据网格模型计算法向矢量。
  采用与PointNet相同的数据增强策略,即沿z轴随机旋转点云,并通过均值为零且标准偏差为0.02的高斯噪声使每个点抖动。

4.2 在ShapeNet上的部件分割

  任务的输入是由点云表示的形状,目标是为点云中的每个点分配零件类别标签。 给出了每种形状的类别标签。 通常,通过使用已知的输入3D对象类别将可能的零件标签缩小到特定于给定对象类别的部分标签。并且还 **将每个点的法线方向计算为输入特征**,以更好地描述基础形状。

  我们使用点交叉点联合(IoU)来评估我们的PointConv网络,与PointNet ++ [28],SPLATNet [35]和其他一些部分分割算法[45、18、44、7]相同。结果显示在表2中。Point-Conv获得的类平均mIoU为82.8%,实例平均mIoU为85.7%,与仅将点云作为输入的最新算法相提并论。根据[35],SPLATNet2D-3D还采用了渲染的2D视图作为输入。由于我们的PointConv只接受3D点云作为输入,为了公平比较,我们只将我们的结果与[35]中的SPLATNet3D进行比较。

4.3 场景语义标注

  诸如ModelNet40 [43]和ShapeNet [2]之类的数据集是人造的合成数据集。正如我们在上一节中看到的那样,大多数最新算法都能在此类数据集上获得相对较好的结果。为了评估我们的方法处理包含大量噪声数据的现实点云的能力,我们使用ScanNet数据集评估了基于语义场景分割的PointConv。任务是在给定由点云表示的室内场景的情况下,预测每个3D点上的语义对象标签。 ScanNet的最新版本[5]包含所有1513个ScanNet扫描和100个新测试扫描的更新注释,其中所有语义标签均不公开,我们将结果提交给官方评估服务器以与其他方法进行比较。

  我们将算法与Tangent卷积[37],SPLAT Net [35],PointNet ++ [28]和ScanNet [5]进行了比较。所有提到的算法均在新的ScanNet数据集上将其结果报告给基准,并且仅输入算法使用3D坐标数据加上RGB。在我们的实验中, **我们通过从室内房间随机采样3m×1.5m×1.5m立方体来生成训练样本,并在整个扫描过程中使用滑动窗口进行评估。**我们将结合交会(IoU)报告为主要措施,这是与基准相同。我们在图7中可视化了一些示例性的语义分割结果。表3中列出了mIoU。mIoU是所有类别中IoU的平均值。我们的PointConv大大优于其他算法(表3)。 PointConv在一台GTX1080Ti上在Scan-Net上训练一个纪元的总运行时间约为170s,而8×8192点的评估时间约为0.5s。

4.4 在CIFAR-10上的分类

  在第3.1节中,我们声称PointConv可以与2D CNN等效。如果是这样,则基于PointConv的网络的性能应等同于光栅图像CNN的性能。为了验证这一点,我们使用CIFAR-10数据集作为比较基准。我们将CIFAR-10中的每个像素视为 具有xy坐标和RGB特征的2D点。在训练和测试之前, 将点云缩放到单位球上

  实验表明,CIFAR-10上的PointConv实际上具有与2D CNN相同的学习能力。 表4显示了图像卷积和Point-Conv的结果。 从表中可以看出,在CIFAR-10上PointCNN [21]的准确度仅为80.22%,远低于图像CNN。 但是,对于5层网络,使用PointConv的网络可以达到89.13%,与使用图像卷积的网络相似。而且,具有VGG19 [34]结构的PointConv与VGG19相比也可以达到同等精度。

五、消融实验和可视化

  在本节中,我们将进行其他实验以评估PointConv各个方面的有效性。 除了对PointConv的结构进行消融研究以外,我们还对ScanNet数据集上PointConv的性能进行了深入分析。 最后,我们提供了一些学习的过滤器用于可视化。

5.1 MLP结构

  在本节中,我们设计实验以评估PointConv中MLP参数的选择。为了快速评估,我们从ScanNet数据集中生成一个子集作为分类任务。 该子集中的每个示例均从原始场景扫描中随机抽取1,024个点进行采样.ScanNet数据集有20种不同的场景类型。根据经验,我们遍历了不同的Cmid选择和PointConv中不同数量的MLP层。每个实验进行了3次随机试验,结果可在补充中找到。 从结果可以看出, 较大的Cmid不一定提供更好的分类结果,而MLP中不同的层数在分类结果中并没有太大差异。由于Cmid与每个PointConv层的内存消耗呈线性关系,因此该结果表明,我们 可以选择一个较小的Cmid以提高内存效率

5.2 逆密度尺度

  在本节中,我们研究密度反比S的有效性。我们选择ScanNet作为评估任务,因为ScanNet中的点云是从真实的室内场景生成的。我们遵循作者提供的标准训练/验证拆分。我们分别在Sec3.1中描述了在有和没有逆密度标度的情况下训练网络。表5示出了结果。如我们所见,具有逆密度标度的PointConv的性能比不具有逆密度标度的PointConv的性能好大约1%,这证明了逆密度标度的有效性。在我们的实验中,我们观察到反密度标度在靠近输入的层中趋于更有效。在深层,MLP倾向于学会减少密度标度的影响。 一个可能的原因是,使用最远的点采样算法作为我们的子采样算法,更深层的点云倾向于更均匀地分布。如表5所示,与ScanNet数据集上没有密度的方法相比,不使用非线性变换直接应用密度的结果较差,这表明非线性变换能够学习数据集中的逆密度标度。

5.3 在ScanNet上的消融研究

  可以看到,我们的PointConv大大优于其他方法。由于我们只允许将算法的一个最终结果提交给ScanNet的基准服务器,因此我们使用[5]提供的公共验证集对PointConv进行了更多消融研究。对于分割任务,我们用从3m×1.5m×1.5m中随机采样的8,192个点训练PointConv,并通过滑动窗口的方式详尽地选择3m×1.5m×1.5m立方体中的所有点来评估模型。具有不同步幅大小的xy平面。为了鲁棒性,我们在所有实验中均使用5个窗口的多数票。从表5中,我们可以看到 较小的步幅可以改善分割结果,而ScanNet上的RGB信息似乎并不能显着改善分割结果。即使没有这些额外的改进,PointConv仍大大超过基准。

5.4 可视化

  图8展示了我们PointConv中从MLP中学到的过滤器。 为了更好地可视化过滤器,我们通过平面z = 0对学习的函数进行采样。从图8中,我们可以看到学习的连续过滤器中的一些模式。

六、结论

  在这项工作中,我们提出了一种在3D点云上执行卷积运算的新颖方法,称为PointConv。 PointConv在局部点坐标上训练多层感知器,以在卷积滤波器中近似连续的权重和密度函数,这使其自然地具有排列不变和平移不变的特性,这允许直接在3D点云上构建深度卷积网络。 我们提出了一种有效的实现方式,极大地提高了其可伸缩性。 我们在多个具有挑战性的基准上展示了其强大的性能,并具有与2D图像中基于网格的卷积网络的性能相匹配的功能。 在以后的工作中,我们希望使用PointConv(例如ResNet和DenseNet)将更多主流图像卷积网络体系结构引入点云数据中。可以在这里找到代码:https://github.com/DylanWusee/pointconv

总结:

  • 目前所有的基于点云上的算法,第一步做的都是 最远点采样(FPS) ,从宏观上来看,最远点采样的方法在 减少点云样本数量的同时也极大的 保留点云的原始的空间结构。但是从微观上看,最远点采样的算法属于 非均匀采样,这样就会导致某些局部区域点大量聚集,而某些区域的的点的数量只有寥寥无几。而PointConv正是发现这一问题,尝试着通过 核密度估计方法来解决这个问题,所以博主认为这也是PointConv提出的最大的一个贡献。
  • 传统的或者可以说是常用的方法一般是通过 三个点进行线性插值的方法来进行特征传播,但PointConv的作者认为这并不能够很好的做到点云的特征的传播。所以作者重新设计了一个更好的特征传播层。 作者将Pointconv的部分加入了线性插值之后,这使得网络能更好的特征的传播。

参考:https://blog.csdn.net/Dujing2019/article/details/107016494

https://blog.csdn.net/john_bh/article/details/103959200

https://yongqi.blog.csdn.net/article/details/103175381

https://blog.csdn.net/sinat_37532065/article/details/101061465

https://blog.csdn.net/weixin_42956785/article/details/91880225

https://blog.csdn.net/weixin_43026096/article/details/103527901

https://blog.csdn.net/weixin_43026096/article/details/103282320

论文笔记:(2019CVPR)PointConv: Deep Convolutional Networks on 3D Point Clouds的更多相关文章

  1. 阅读笔记:Very Deep Convolutional Networks for Large-Scale Image Recognition

    摘要: 在这篇论文我们主要研究卷积神级网络的深度对大范围图像识别效果的影响,我们发现增加神经网络层数增加到16-19层时我们的实验结果有很大的提高.这使得我们在2014年的ImageNet Chall ...

  2. 《DSLR-Quality Photos on Mobile Devices with Deep Convolutional Networks》研读笔记

    <DSLR-Quality Photos on Mobile Devices with Deep Convolutional Networks>研读笔记 论文标题:DSLR-Quality ...

  3. VGGNet论文翻译-Very Deep Convolutional Networks for Large-Scale Image Recognition

    Very Deep Convolutional Networks for Large-Scale Image Recognition Karen Simonyan[‡] & Andrew Zi ...

  4. SPPNet论文翻译-空间金字塔池化Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    http://www.dengfanxin.cn/?p=403 原文地址 我对物体检测的一篇重要著作SPPNet的论文的主要部分进行了翻译工作.SPPNet的初衷非常明晰,就是希望网络对输入的尺寸更加 ...

  5. 深度学习论文翻译解析(九):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    论文标题:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition 标题翻译:用于视觉识别的深度卷积神 ...

  6. 论文笔记之:Deep Generative Image Models using a Laplacian Pyramid of Adversarial Networks

    Deep Generative Image Models using a Laplacian Pyramid of Adversarial Networks NIPS 2015  摘要:本文提出一种 ...

  7. Very Deep Convolutional Networks for Large-Scale Image Recognition

    Very Deep Convolutional Networks for Large-Scale Image Recognition 转载请注明:http://blog.csdn.net/stdcou ...

  8. 目标检测--Spatial pyramid pooling in deep convolutional networks for visual recognition(PAMI, 2015)

    Spatial pyramid pooling in deep convolutional networks for visual recognition 作者: Kaiming He, Xiangy ...

  9. 论文笔记(1):Deep Learning.

    论文笔记1:Deep Learning         2015年,深度学习三位大牛(Yann LeCun,Yoshua Bengio & Geoffrey Hinton),合作在Nature ...

随机推荐

  1. Linux命令大全之挂载命令

    理解:Linux挂载相当于Windows分配盘符 1.查询系统中已挂载的设备 mount 2.设置自动挂载 编辑文件/etc/fstab,把文件写入就可以启动自动挂载了, 注:一般不把光盘写入,如果写 ...

  2. DBA入门相关知识介绍

    DBA(database administrator):数据库管理员                           DBMS(database management system):数据库管理系 ...

  3. 微信sdk上传图片大小1k,损坏的问题以及微信上传图片需要的配置

    微信公众号的appid和appsecret有问题,会导致上传图片大小为1k这个问题 微信上传图片需要设置公众号的'JS接口安全域名'

  4. 聊聊IOC中依赖注入那些事 (Dependency inject)

    What is Dependency injection 依赖注入定义为组件之间依赖关系由容器在运行期决定,形象的说即由容器动态的将某个依赖关系注入到组件之中在面向对象编程中,我们经常处理的问题就是解 ...

  5. javascript之强制类型转换

    在javascript中,常会发生强制类型转换的情况有以下几种 字符串拼接 var a = 1; var b = a + '1'; console.log(b); //11 ==运算符 var a = ...

  6. Kubernetes网络的iptables模式和ipvs模式支持ping分析

    1.iptables模式无法ping通原因分析 iptables模式下,无法ping通任何svc,包括clusterip.所有ns下,下面来分析原因: 查看kubernetes的网络模式 curl 1 ...

  7. 4、mysql登录密码修改和找回

    操作适合5.1-5.5:当前的环境是5.5的环境: 4.1.mysql启动的原理: mysqld_safe -> my.cnf ->mysql.sock http://blog.51cto ...

  8. 解决git同步每次都需要输入用户名、密码

    打开 git bash 执行命令: git config --global credential.helper store

  9. AD设计中地铜突然消失且无法选中删除的解决办法

    作者:struct_mooc 博客地址: https://www.cnblogs.com/structmooc/p/14984466.html   前几天在设计一块电路板的时候,已经全部设计完了!但是 ...

  10. python导入模块--案例

    1 导入模块 1.1 问题 本案例要求先编写一个star模块,主要要求如下: 建立工作目录 ~/bin/ 创建模块文件 ~/bin/star.py 模块中创建pstar函数,实现打印50个星号的功能 ...