【mmdetection系列】mmdetection之backbone讲解

news2024/11/15 17:26:04

如果是自己来写这部分代码的话,真的是很容易,如果这个框架中有自带的backbone结构的话,那可以从其他地方找到对应的pytorch版本实现,或者自己写。

配置部分在configs/_base_/models目录下,具体实现在mmdet/models/backbone目录下。

1.configs

 

我们看下yolox的backbone吧。https://github.com/open-mmlab/mmdetection/blob/master/configs/yolox/yolox_s_8x8_300e_coco.py

    backbone=dict(type='CSPDarknet', deepen_factor=0.33, widen_factor=0.5),

2.具体实现

 

具体实现,去找CSPDarknet这个类:

https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/backbones/csp_darknet.py#L124

@BACKBONES.register_module()
class CSPDarknet(BaseModule):
    """CSP-Darknet backbone used in YOLOv5 and YOLOX.
    Args:
        arch (str): Architecture of CSP-Darknet, from {P5, P6}.
            Default: P5.
        deepen_factor (float): Depth multiplier, multiply number of
            blocks in CSP layer by this amount. Default: 1.0.
        widen_factor (float): Width multiplier, multiply number of
            channels in each layer by this amount. Default: 1.0.
        out_indices (Sequence[int]): Output from which stages.
            Default: (2, 3, 4).
        frozen_stages (int): Stages to be frozen (stop grad and set eval
            mode). -1 means not freezing any parameters. Default: -1.
        use_depthwise (bool): Whether to use depthwise separable convolution.
            Default: False.
        arch_ovewrite(list): Overwrite default arch settings. Default: None.
        spp_kernal_sizes: (tuple[int]): Sequential of kernel sizes of SPP
            layers. Default: (5, 9, 13).
        conv_cfg (dict): Config dict for convolution layer. Default: None.
        norm_cfg (dict): Dictionary to construct and config norm layer.
            Default: dict(type='BN', requires_grad=True).
        act_cfg (dict): Config dict for activation layer.
            Default: dict(type='LeakyReLU', negative_slope=0.1).
        norm_eval (bool): Whether to set norm layers to eval mode, namely,
            freeze running stats (mean and var). Note: Effect on Batch Norm
            and its variants only.
        init_cfg (dict or list[dict], optional): Initialization config dict.
            Default: None.
    Example:
        >>> from mmdet.models import CSPDarknet
        >>> import torch
        >>> self = CSPDarknet(depth=53)
        >>> self.eval()
        >>> inputs = torch.rand(1, 3, 416, 416)
        >>> level_outputs = self.forward(inputs)
        >>> for level_out in level_outputs:
        ...     print(tuple(level_out.shape))
        ...
        (1, 256, 52, 52)
        (1, 512, 26, 26)
        (1, 1024, 13, 13)
    """
    # From left to right:
    # in_channels, out_channels, num_blocks, add_identity, use_spp
    arch_settings = {
        'P5': [[64, 128, 3, True, False], [128, 256, 9, True, False],
               [256, 512, 9, True, False], [512, 1024, 3, False, True]],
        'P6': [[64, 128, 3, True, False], [128, 256, 9, True, False],
               [256, 512, 9, True, False], [512, 768, 3, True, False],
               [768, 1024, 3, False, True]]
    }

    def __init__(self,
                 arch='P5',
                 deepen_factor=1.0,
                 widen_factor=1.0,
                 out_indices=(2, 3, 4),
                 frozen_stages=-1,
                 use_depthwise=False,
                 arch_ovewrite=None,
                 spp_kernal_sizes=(5, 9, 13),
                 conv_cfg=None,
                 norm_cfg=dict(type='BN', momentum=0.03, eps=0.001),
                 act_cfg=dict(type='Swish'),
                 norm_eval=False,
                 init_cfg=dict(
                     type='Kaiming',
                     layer='Conv2d',
                     a=math.sqrt(5),
                     distribution='uniform',
                     mode='fan_in',
                     nonlinearity='leaky_relu')):
        super().__init__(init_cfg)
        arch_setting = self.arch_settings[arch]
        if arch_ovewrite:
            arch_setting = arch_ovewrite
        assert set(out_indices).issubset(
            i for i in range(len(arch_setting) + 1))
        if frozen_stages not in range(-1, len(arch_setting) + 1):
            raise ValueError('frozen_stages must be in range(-1, '
                             'len(arch_setting) + 1). But received '
                             f'{frozen_stages}')

        self.out_indices = out_indices
        self.frozen_stages = frozen_stages
        self.use_depthwise = use_depthwise
        self.norm_eval = norm_eval
        conv = DepthwiseSeparableConvModule if use_depthwise else ConvModule

        self.stem = Focus(
            3,
            int(arch_setting[0][0] * widen_factor),
            kernel_size=3,
            conv_cfg=conv_cfg,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.layers = ['stem']

        for i, (in_channels, out_channels, num_blocks, add_identity,
                use_spp) in enumerate(arch_setting):
            in_channels = int(in_channels * widen_factor)
            out_channels = int(out_channels * widen_factor)
            num_blocks = max(round(num_blocks * deepen_factor), 1)
            stage = []
            conv_layer = conv(
                in_channels,
                out_channels,
                3,
                stride=2,
                padding=1,
                conv_cfg=conv_cfg,
                norm_cfg=norm_cfg,
                act_cfg=act_cfg)
            stage.append(conv_layer)
            if use_spp:
                spp = SPPBottleneck(
                    out_channels,
                    out_channels,
                    kernel_sizes=spp_kernal_sizes,
                    conv_cfg=conv_cfg,
                    norm_cfg=norm_cfg,
                    act_cfg=act_cfg)
                stage.append(spp)
            csp_layer = CSPLayer(
                out_channels,
                out_channels,
                num_blocks=num_blocks,
                add_identity=add_identity,
                use_depthwise=use_depthwise,
                conv_cfg=conv_cfg,
                norm_cfg=norm_cfg,
                act_cfg=act_cfg)
            stage.append(csp_layer)
            self.add_module(f'stage{i + 1}', nn.Sequential(*stage))
            self.layers.append(f'stage{i + 1}')

    def _freeze_stages(self):
        if self.frozen_stages >= 0:
            for i in range(self.frozen_stages + 1):
                m = getattr(self, self.layers[i])
                m.eval()
                for param in m.parameters():
                    param.requires_grad = False

    def train(self, mode=True):
        super(CSPDarknet, self).train(mode)
        self._freeze_stages()
        if mode and self.norm_eval:
            for m in self.modules():
                if isinstance(m, _BatchNorm):
                    m.eval()

    def forward(self, x):
        outs = []
        for i, layer_name in enumerate(self.layers):
            layer = getattr(self, layer_name)
            x = layer(x)
            if i in self.out_indices:
                outs.append(x)
        return tuple(outs)

3.如何调用的?

3.1 注册

注册创建类名字典。

@BACKBONES.register_module()

3.2 调用

即以字典中的类名,进行类的实例化。

由于backbone是包在models里面的,所以去看YOLOX这个类。

https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/detectors/yolox.py#L15

@DETECTORS.register_module()
class YOLOX(SingleStageDetector):
    r"""Implementation of `YOLOX: Exceeding YOLO Series in 2021
    <https://arxiv.org/abs/2107.08430>`_
    Note: Considering the trade-off between training speed and accuracy,
    multi-scale training is temporarily kept. More elegant implementation
    will be adopted in the future.
    Args:
        backbone (nn.Module): The backbone module.
        neck (nn.Module): The neck module.
        bbox_head (nn.Module): The bbox head module.
        train_cfg (obj:`ConfigDict`, optional): The training config
            of YOLOX. Default: None.
        test_cfg (obj:`ConfigDict`, optional): The testing config
            of YOLOX. Default: None.
        pretrained (str, optional): model pretrained path.
            Default: None.
        input_size (tuple): The model default input image size. The shape
            order should be (height, width). Default: (640, 640).
        size_multiplier (int): Image size multiplication factor.
            Default: 32.
        random_size_range (tuple): The multi-scale random range during
            multi-scale training. The real training image size will
            be multiplied by size_multiplier. Default: (15, 25).
        random_size_interval (int): The iter interval of change
            image size. Default: 10.
        init_cfg (dict, optional): Initialization config dict.
            Default: None.
    """

    def __init__(self,
                 backbone,
                 neck,
                 bbox_head,
                 train_cfg=None,
                 test_cfg=None,
                 pretrained=None,
                 input_size=(640, 640),
                 size_multiplier=32,
                 random_size_range=(15, 25),
                 random_size_interval=10,
                 init_cfg=None):
        super(YOLOX, self).__init__(backbone, neck, bbox_head, train_cfg,
                                    test_cfg, pretrained, init_cfg)
        log_img_scale(input_size, skip_square=True)
        self.rank, self.world_size = get_dist_info()
        self._default_input_size = input_size
        self._input_size = input_size
        self._random_size_range = random_size_range
        self._random_size_interval = random_size_interval
        self._size_multiplier = size_multiplier
        self._progress_in_iter = 0

    def forward_train(self,
                      img,
                      img_metas,
                      gt_bboxes,
                      gt_labels,
                      gt_bboxes_ignore=None):
        """
        Args:
            img (Tensor): Input images of shape (N, C, H, W).
                Typically these should be mean centered and std scaled.
            img_metas (list[dict]): A List of image info dict where each dict
                has: 'img_shape', 'scale_factor', 'flip', and may also contain
                'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'.
                For details on the values of these keys see
                :class:`mmdet.datasets.pipelines.Collect`.
            gt_bboxes (list[Tensor]): Each item are the truth boxes for each
                image in [tl_x, tl_y, br_x, br_y] format.
            gt_labels (list[Tensor]): Class indices corresponding to each box
            gt_bboxes_ignore (None | list[Tensor]): Specify which bounding
                boxes can be ignored when computing the loss.
        Returns:
            dict[str, Tensor]: A dictionary of loss components.
        """
        # Multi-scale training
        img, gt_bboxes = self._preprocess(img, gt_bboxes)

        losses = super(YOLOX, self).forward_train(img, img_metas, gt_bboxes,
                                                  gt_labels, gt_bboxes_ignore)

        # random resizing
        if (self._progress_in_iter + 1) % self._random_size_interval == 0:
            self._input_size = self._random_resize(device=img.device)
        self._progress_in_iter += 1

        return losses

    def _preprocess(self, img, gt_bboxes):
        scale_y = self._input_size[0] / self._default_input_size[0]
        scale_x = self._input_size[1] / self._default_input_size[1]
        if scale_x != 1 or scale_y != 1:
            img = F.interpolate(
                img,
                size=self._input_size,
                mode='bilinear',
                align_corners=False)
            for gt_bbox in gt_bboxes:
                gt_bbox[..., 0::2] = gt_bbox[..., 0::2] * scale_x
                gt_bbox[..., 1::2] = gt_bbox[..., 1::2] * scale_y
        return img, gt_bboxes

    def _random_resize(self, device):
        tensor = torch.LongTensor(2).to(device)

        if self.rank == 0:
            size = random.randint(*self._random_size_range)
            aspect_ratio = float(
                self._default_input_size[1]) / self._default_input_size[0]
            size = (self._size_multiplier * size,
                    self._size_multiplier * int(aspect_ratio * size))
            tensor[0] = size[0]
            tensor[1] = size[1]

        if self.world_size > 1:
            dist.barrier()
            dist.broadcast(tensor, 0)

        input_size = (tensor[0].item(), tensor[1].item())
        return input_size

 发现并不容易看出backbone的部分,然后去找其基类SingleStageDetector中的代码段,通过获取注册字典中的CSPDarknet:

self.backbone = build_backbone(backbone)

https://github.com/open-mmlab/mmdetection/blob/31c84958f54287a8be2b99cbf87a6dcf12e57753/mmdet/models/detectors/single_stage.py#L12

class SingleStageDetector(BaseDetector):
    """Base class for single-stage detectors.
    Single-stage detectors directly and densely predict bounding boxes on the
    output features of the backbone+neck.
    """

    def __init__(self,
                 backbone,
                 neck=None,
                 bbox_head=None,
                 train_cfg=None,
                 test_cfg=None,
                 pretrained=None,
                 init_cfg=None):
        super(SingleStageDetector, self).__init__(init_cfg)
        if pretrained:
            warnings.warn('DeprecationWarning: pretrained is deprecated, '
                          'please use "init_cfg" instead')
            backbone.pretrained = pretrained
        self.backbone = build_backbone(backbone)
        if neck is not None:
            self.neck = build_neck(neck)
        bbox_head.update(train_cfg=train_cfg)
        bbox_head.update(test_cfg=test_cfg)
        self.bbox_head = build_head(bbox_head)
        self.train_cfg = train_cfg
        self.test_cfg = test_cfg

    def extract_feat(self, img):
        """Directly extract features from the backbone+neck."""
        x = self.backbone(img)
        if self.with_neck:
            x = self.neck(x)
        return x

    def forward_dummy(self, img):
        """Used for computing network flops.
        See `mmdetection/tools/analysis_tools/get_flops.py`
        """
        x = self.extract_feat(img)
        outs = self.bbox_head(x)
        return outs

    def forward_train(self,
                      img,
                      img_metas,
                      gt_bboxes,
                      gt_labels,
                      gt_bboxes_ignore=None):
        """
        Args:
            img (Tensor): Input images of shape (N, C, H, W).
                Typically these should be mean centered and std scaled.
            img_metas (list[dict]): A List of image info dict where each dict
                has: 'img_shape', 'scale_factor', 'flip', and may also contain
                'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'.
                For details on the values of these keys see
                :class:`mmdet.datasets.pipelines.Collect`.
            gt_bboxes (list[Tensor]): Each item are the truth boxes for each
                image in [tl_x, tl_y, br_x, br_y] format.
            gt_labels (list[Tensor]): Class indices corresponding to each box
            gt_bboxes_ignore (None | list[Tensor]): Specify which bounding
                boxes can be ignored when computing the loss.
        Returns:
            dict[str, Tensor]: A dictionary of loss components.
        """
        super(SingleStageDetector, self).forward_train(img, img_metas)
        x = self.extract_feat(img)
        losses = self.bbox_head.forward_train(x, img_metas, gt_bboxes,
                                              gt_labels, gt_bboxes_ignore)
        return losses

    def simple_test(self, img, img_metas, rescale=False):
        """Test function without test-time augmentation.
        Args:
            img (torch.Tensor): Images with shape (N, C, H, W).
            img_metas (list[dict]): List of image information.
            rescale (bool, optional): Whether to rescale the results.
                Defaults to False.
        Returns:
            list[list[np.ndarray]]: BBox results of each image and classes.
                The outer list corresponds to each image. The inner list
                corresponds to each class.
        """
        feat = self.extract_feat(img)
        results_list = self.bbox_head.simple_test(
            feat, img_metas, rescale=rescale)
        bbox_results = [
            bbox2result(det_bboxes, det_labels, self.bbox_head.num_classes)
            for det_bboxes, det_labels in results_list
        ]
        return bbox_results

    def aug_test(self, imgs, img_metas, rescale=False):
        """Test function with test time augmentation.
        Args:
            imgs (list[Tensor]): the outer list indicates test-time
                augmentations and inner Tensor should have a shape NxCxHxW,
                which contains all images in the batch.
            img_metas (list[list[dict]]): the outer list indicates test-time
                augs (multiscale, flip, etc.) and the inner list indicates
                images in a batch. each dict has image information.
            rescale (bool, optional): Whether to rescale the results.
                Defaults to False.
        Returns:
            list[list[np.ndarray]]: BBox results of each image and classes.
                The outer list corresponds to each image. The inner list
                corresponds to each class.
        """
        assert hasattr(self.bbox_head, 'aug_test'), \
            f'{self.bbox_head.__class__.__name__}' \
            ' does not support test-time augmentation'

        feats = self.extract_feats(imgs)
        results_list = self.bbox_head.aug_test(
            feats, img_metas, rescale=rescale)
        bbox_results = [
            bbox2result(det_bboxes, det_labels, self.bbox_head.num_classes)
            for det_bboxes, det_labels in results_list
        ]
        return bbox_results

    def onnx_export(self, img, img_metas, with_nms=True):
        """Test function without test time augmentation.
        Args:
            img (torch.Tensor): input images.
            img_metas (list[dict]): List of image information.
        Returns:
            tuple[Tensor, Tensor]: dets of shape [N, num_det, 5]
                and class labels of shape [N, num_det].
        """
        x = self.extract_feat(img)
        outs = self.bbox_head(x)
        # get origin input shape to support onnx dynamic shape

        # get shape as tensor
        img_shape = torch._shape_as_tensor(img)[2:]
        img_metas[0]['img_shape_for_onnx'] = img_shape
        # get pad input shape to support onnx dynamic shape for exporting
        # `CornerNet` and `CentripetalNet`, which 'pad_shape' is used
        # for inference
        img_metas[0]['pad_shape_for_onnx'] = img_shape

        if len(outs) == 2:
            # add dummy score_factor
            outs = (*outs, None)
        # TODO Can we change to `get_bboxes` when `onnx_export` fail
        det_bboxes, det_labels = self.bbox_head.onnx_export(
            *outs, img_metas, with_nms=with_nms)

        return det_bboxes, det_labels

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

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

相关文章

微信小程序——云音乐界面

文章目录第一章 开发前的准备一、项目展示二、项目分析三、项目初始化第二章 标签页切换一、任务分析二、常用组件介绍三、编写页面结构和样式第三章 音乐推荐一、任务分析二、组件介绍三、编写音乐推荐页面结构和样式第一章 开发前的准备 一、项目展示 音乐小程序项目效果展…

.net开发安卓入门 - Notification(通知)

.net开发安卓入门 - Notification&#xff08;通知&#xff09;通知的布局创建通知通道创建和发布通知我的样例效果图代码资源文件常见问题一切代码都准备就绪了&#xff0c;为什么就是不提示消息内容呢&#xff1f;为什么我的通知不是弹出式的同系列文章推荐通知的布局 创建通…

yolov7运行自己的VOC格式数据集

yolov7运行VOC格式数据集测试开发环境使用自己的VOC格式数据集训练修改配置文件yolov7.yaml修改配置文件voc.yamlVOC格式数据集转换COCO格式开始训练重头开始fine-trainBUG常见报错1常见报错2成功训练网络评价指标可视化测试开发环境 去官网下载yolov7的权重文件&#xff0c;放…

async/await

理解async函数就要先理解generator (生成器)函数,因为async是generator函数的语法糖。 Generator函数 Generator 函数是 ES6 提供的一种异步编程解决方案&#xff0c;可以先理解为一个状态机&#xff0c;封装了多个内部状态&#xff0c;执行Generator函数返回一个遍历器对象&…

【ChatGPT 中文版插件】无需注册体验 ChatGPT 的攻略

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

假设检验介绍

数据科学是一个不断发展的领域&#xff0c;近年来越来越受欢迎。数据科学的一个重要组成部分是假设检验的使用&#xff0c;它可用于从数据中得出结论并做出明智的决策。 什么是假设检验&#xff1f; 假设检验是数据科学中常用的方法&#xff0c;用于评估关于总体参数的假设的有…

前端超级实用的Visual Studio Code插件

前端超级实用的Visual Studio Code插件1、Bracket Pair Colorizer&#xff1a;可以把不同嵌套层级的各种类型的括号&#xff0c;用不同的颜色标注出来2、Auto Close Tag:自动闭合HTML标签3、Auto Rename Tag:自动关闭标签&#xff0c;在开始标记的结束括号中键入后&#xff0c;…

2022年浙大城市学院新生程序设计竞赛(同步赛)D. Cutting with Lines Ⅰ(线段分割 离散化+并查集 补写法)

题目 二维平面&#xff0c;左下角(0,0)右上角(n,m)(1<n,m<1e6)的一块矩形&#xff0c; q(q<2e3)次线段切割操作&#xff0c;操作分四种&#xff1a; ai 1 x&#xff0c;表示切割(x,m)到(x,m-ai)这条竖直线段(0<x<n,1<ai<1e6) ai 2 x&#xff0c;表示切…

【车载开发系列】UDS诊断---诊断设备在线($0x3E)

【车载开发系列】UDS诊断—诊断设备在线&#xff08;$0x3E&#xff09; 一.概念定义 此服务用于向ECU指示诊断工具在线。当其他UDS服务不存在时&#xff0c;为防止ECU自动转入默认会话模式并停止通信&#xff0c;必须使用此服务。建议以功能寻址的方式发送该指令它唯一的功能…

解决编译 Visual Studio 工程时报 NuGet Package Restore Failed

背景 域渗透的过程中会用到很多 .Net 工具。但是官方仓库没有直接发布的二进制包&#xff0c;那么就需要我们自己手动编译。这些工具又有很多会选择做 NuGet 依赖。如果本地配置不对&#xff0c;就会导致编译失败。 接下来我们就讨论一下怎么解决这个问题。 现象 我们以 AD…

【Vue 快速入门系列】ref、props、mixin、插件使用、样式混合解决方案合集

文章目录前言一、ref属性的使用二、props配置三、mixin混合语法1.简介2.使用方法3.注意点4.结合实例使用①全局混入②局部混入四、插件的使用1.插件语法①定义插件②引入插件并使用2.上手插件五、样式混合问题前言 在前面介绍到了Vue的一些基本概念与如何使用Vue&#xff0c;并…

ARM64(M1版)Mac运行MAA以及AzurLaneAutoScript自动化打明日方舟和碧蓝航线

前言 首先感谢Github上面MAA以及AzurLaneAutoScript的开发组&#xff0c;让我们有工具可用。 再感谢吕明珠LmeSzinc 和binss 大佬&#xff0c;他们的教程让我受益良多。 能看到这篇教程的&#xff0c;想必都拥有M1或者M2芯片的Mac电脑&#xff0c;因为新芯片不能安装双系统所…

RabbitMQ:安装配置

一般来说&#xff0c;安装分为两种方式&#xff1a;1. 下载 RabbitMQ 源文件&#xff0c;解压源文件之后进行安装。2. 通过 brew 命令安装。在这里&#xff0c;推荐使用 brew 来安装&#xff0c;非常强大的 Mac 端包管理工具。 ~ 本篇内容包括&#xff1a;Mac 安装 RabbitMQ、M…

SSM网上在线水果店商城超市网站平台

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 该项目为前后台项目&#xff0c;分为普通用户与管理员两种角色&#xff0c;前台普通用户登录&#xff0c;后台管理员登录&#xff1b; 管理员角…

【数电实验】组合逻辑电路

实验三 触发器及其应用 一 实验目的 1 了解触发器的触发方式&#xff08;上升沿触发、下降沿出发&#xff09;及其触发特点&#xff1b; 2 测试常用触发器的逻辑功能&#xff1b; 3 掌握用触发器设计同步时序逻辑电路的方法。 二 实验内容 1 测试双D触发器74HC74的逻辑功能…

cmu 445 poject 1笔记

文章目录cmu 445 poject 1笔记Extendible hashingLRU-KBufferPool Managercmu 445 poject 1笔记 2022年的任务 https://15445.courses.cs.cmu.edu/fall2022/project1/ extendible hashinglru-kbufferpool manger 本文不写代码&#xff0c;只记录遇到的一些思维盲点 Extendible …

SpringCloud02:微服务架构rest模拟环境搭建

微服务架构rest模拟环境搭建Rest环境搭建&#xff1a;服务提供者springcloud主模块pom.xmlspringcloud-api模块springcloud-provider-dept-8001服务提供模块配置相关Rest环境服务消费者Java编写Rest环境搭建&#xff1a;服务提供者 springcloud主模块pom.xml <?xml versi…

让我们看看xargs做了什么事情?

说到xargs,不得不提到 find 和 grep ,当然了少不了管道 | find 和 grep我经常会搞混掉这两个功能很相似的命令的用法,总是会记不太住怎么用,也借此文章加深一下记忆。 find ./xx/xx/ -name abc.v grep -r abc ./* // -r 表示整个目录查找 一般我们会使用find…

[附源码]计算机毕业设计基于Java酒店管理系统Springboot程序

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

Python Open3D点云配准点对点,点对面ICP(Iterative Closest Point)

Python Open3D点云配准 ICP(Iterative Closest Point&#xff09; 这篇博客将介绍 迭代最近点配准算法(Iterative Closest Point, ICP) 。多年来&#xff0c;它一直是研究和工业中几何注册的支柱。输入是两个点云和一个初始变换&#xff0c;该变换大致将源点云与目标点云对齐。…