国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

這篇具有很好參考價值的文章主要介紹了零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

  • 本圖文從介紹配置文件開始,逐步構(gòu)建一個新的配置文件,并依次構(gòu)建相關(guān)模型,最終使用一條點(diǎn)云數(shù)據(jù)簡單走了一下處理流程
  • 關(guān)于mmdetection3d的安裝,參考官方文檔安裝 — MMDetection3D 1.0.0rc4 文檔

1、讀取配置文件

1.1 mmdetection3d配置文件的組成

官方文檔:教程 1: 學(xué)習(xí)配置文件 — MMDetection3D 1.0.0rc4 文檔

在mmdetection3d中,主要思想是通過繼承默認(rèn)配置來實(shí)現(xiàn)自定義模型,當(dāng)然,也可以將模型的所有配置寫在一個文件里,按需使用。

配置文件存放于mmdetection3d/config目錄下,其中**_base_目錄為mmdetection3d自帶的基礎(chǔ)配置,即原始配置,從_base_**目錄的組成來看,mmdetection3d將配置文件分為四種,分別是:數(shù)據(jù)集 (dataset),模型 (model),訓(xùn)練策略 (schedule) 和運(yùn)行時的默認(rèn)設(shè)置 (default runtime)

下面基于一個配置文件的部分內(nèi)容,解釋一下該怎么看

# configs/centerpoint/centerpoint_01voxel_second_secfpn_4x8_cyclic_20e_nus.py
_base_ = [
    '../_base_/datasets/nus-3d.py',
    '../_base_/models/centerpoint_01voxel_second_secfpn_nus.py', # 繼承了這個模型的基礎(chǔ)文件
    '../_base_/schedules/cyclic_20e.py', '../_base_/default_runtime.py'
]
model = dict(
    pts_voxel_layer=dict(point_cloud_range=point_cloud_range),
    pts_bbox_head=dict(bbox_coder=dict(pc_range=point_cloud_range[:2])),
    # model training and testing settings
    train_cfg=dict(pts=dict(point_cloud_range=point_cloud_range)),
    test_cfg=dict(pts=dict(pc_range=point_cloud_range[:2])))

可以看出,在centerpoint_01voxel_second_secfpn_4x8_cyclic_20e_nus.py這個文件中,model部分只有一小段內(nèi)容,這是因?yàn)槔^承了centerpoint_01voxel_second_secfpn_nus.py,只是在繼承文件的基礎(chǔ)上來修改或添加某些特定字段

為了方便說明,來一份簡化版的配置文件

# configs/_base_/models/centerpoint_01voxel_second_secfpn_nus.py
model = dict(
    type='CenterPoint',
    pts_voxel_layer=dict( 
        max_num_points=10, voxel_size=voxel_size, max_voxels=(90000, 120000)),
    pts_voxel_encoder=dict(type='HardSimpleVFE', num_features=5),
    pts_middle_encoder=dict(),
    pts_backbone=dict(),
    pts_neck=dict(),
    pts_bbox_head=dict(),
    # model training and testing settings
    train_cfg=dict(),
    test_cfg=dict())

為了查看具體網(wǎng)絡(luò)是怎么實(shí)現(xiàn)的,我們首先從model最開始出發(fā),根據(jù)配置文件,第一個字段為type,上述例子中使用了CenterPoint,我們需要在mmdetection3d/mmdet3d/models/detectors/__init__.py中,找到CenterPoint,看一下是從哪里引入的,如下圖所示,這樣一來,我們找到了實(shí)現(xiàn)網(wǎng)絡(luò)的具體位置,路徑為:mmdetection3d/mmdet3d/models/detectors/centerpoint.py

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

再往下走,有一句:python pts_voxel_layer=dict( max_num_points=10, voxel_size=voxel_size, max_voxels=(90000, 120000)),

我們在mmdetection3d/mmdet3d/models/detectors/centerpoint.py中的__init__方法中,找到對應(yīng)初始化字段pts_voxel_layer

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

但是我們在此發(fā)現(xiàn),這里并沒有使用這個字段,這是因?yàn)镃enterPoint類繼承了MVXTwoStageDetector類,我們順藤摸瓜,查看MVXTwoStageDetector類,發(fā)現(xiàn)這個類使用了pts_voxel_layer字段,并且給出了使用過程。Voxelization(**pts_voxel_layer)為封裝好的一個體素化函數(shù),它返回一組能表示體素的參數(shù),這里我們不關(guān)心具體實(shí)現(xiàn)。另外,根據(jù)上圖可以看出,init方法里所有的字段與配置文件中的字段是對應(yīng)著順下來的,也就是說,我們可以從centerpoint類里順藤摸瓜,找到所有配置的具體實(shí)現(xiàn)

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

至此,第一行分析完畢,再往下走,是一句pts_voxel_encoder=dict(type='HardSimpleVFE', num_features=5),分析方法與上面相同。

1.2 使用base配置文件構(gòu)建自己的配置文件

這部分我們繼承基礎(chǔ)配置文件,構(gòu)建一個簡單的配置文件,以便接下來使用

  1. 首先,我們在configs目錄下創(chuàng)建一個文件夾,用于保存自己的配置文件,并新建一個my_config.py文件

  2. 在新建的配置文件中,寫入以下內(nèi)容

    _base_ = [
        '../_base_/datasets/nus-3d-mini.py', # 這里我繼承了基礎(chǔ)文件中的nus-3d.py構(gòu)建了一個mini版本,主要就是修改了一下數(shù)據(jù)集路徑
        '../_base_/schedules/schedule_2x.py',
        '../_base_/default_runtime.py',
    ]
    voxel_size = [0.1, 0.1, 0.1]
    norm_cfg = None
    DOUBLE_FLIP = False
    # 為了簡單演示,這里只實(shí)現(xiàn)了體素構(gòu)造層和編碼層
    model = dict(
        type="MY_MODEL",
        voxel_layer=dict(
            max_num_points=32,
            point_cloud_range=[0, -39.68, -3, 69.12, 39.68, 1],
            voxel_size=voxel_size,
            max_voxels=(16000, 40000)),
        voxel_encoder=dict(
            type='VoxelFeatureExtractorV3',
            num_input_features=4
        ),
        train_cfg=dict(),
        test_cfg=dict())
    data = dict(
        samples_per_gpu=1,
        workers_per_gpu=4
    )
    

1.3 根據(jù)配置文件搭建網(wǎng)絡(luò)

接下來要做的,是根據(jù)我們配置文件中的model部分,開始搭建網(wǎng)絡(luò),具體步驟如下:

  • mmdet3d/models/detectors目錄下,創(chuàng)建一個py文件,這里取名為my_model.py

  • 構(gòu)造一個類,類名要和配置文件中的type一致,當(dāng)然也可以在注冊的時候用import … as …來替換:

    from ..builder import DETECTORS # 引入構(gòu)造器
    
    @DETECTORS.register_module() # 注冊,這一句必須要有
    class MY_MODEL():
        def __init__(self):
            pass
    
  • 在mmdet3d/models/detectors/_init_.py中注冊

    零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

  • 在此例中,便于理解,我們就不繼承任何文件了,僅寫出初始化方法

  • 接下來要做的,是要在init方法中定義相關(guān)參數(shù)并給出相應(yīng)實(shí)現(xiàn)

    from mmcv.ops import Voxelization # 引入mmcv中的體素化方法
    from .. import builder	# 引入構(gòu)造器
    from ..builder import DETECTORS
    
    @DETECTORS.register_module()
    class my_model():
        def __init__(self, voxel_layer, voxel_encoder, train_cfg, test_cfg):
            self.voxel_layer = Voxelization(**voxel_layer) # 這一層是mmcv自帶的,在3.4中會再介紹一下
            self.voxel_encoder = builder.build_voxel_encoder(voxel_encoder) # 這里表示這個層是需要我們自己構(gòu)造的
    
    
  • 再一步,是實(shí)現(xiàn)我們的voxel_encoder層,我們在mmdet3d/models/voxel_encoders目錄下,新建一個文件也好,直接寫在現(xiàn)有文件里也行,這里我寫在了voxel_encoder.py文件下

    @VOXEL_ENCODERS.register_module() # 注冊為體素編碼層
    class VoxelFeatureExtractorV3(nn.Module):
        def __init__(
                self, num_input_features=4, norm_cfg=None, name="VoxelFeatureExtractorV3"
        ):
            super(VoxelFeatureExtractorV3, self).__init__()
            self.name = name
            self.num_input_features = num_input_features
    
        def forward(self, features, num_voxels, coors=None):
            """
            	features: 輸入的體素
            	num_voxels: 體素數(shù)目
            """
            points_mean = features[:, :, : self.num_input_features].sum(
                dim=1, keepdim=False
            ) / num_voxels.type_as(features).view(-1, 1)
    
            return points_mean.contiguous()
    
  • 再一步,是在mmdet3d/models/voxel_encoders/__init__.py文件中,引入寫好的VoxelFeatureExtractorV3,這樣,我們就能在配置文件中,使用voxel_encoder=dict(type='VoxelFeatureExtractorV3', num_input_features=4)來調(diào)用我們的體素編碼模塊了
    零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

  • 關(guān)于根據(jù)配置文件的model部分搭建網(wǎng)絡(luò)就寫到這里,有時間的話我會補(bǔ)充更多細(xì)節(jié)

2、構(gòu)建模型

此部分,我們使用jupyter notebook逐步、分解的從數(shù)據(jù)抓取開始,演示一下數(shù)據(jù)在我們搭建的網(wǎng)絡(luò)中的運(yùn)行流程

2.1 讀取配置文件

在真正的訓(xùn)練過程中,是通過傳入的參數(shù),根據(jù)配置文件路徑導(dǎo)入整個參數(shù)的,相關(guān)代碼位于tools/train.py。這里為簡便期間,我們直接使用路徑讀取配置文件

# 讀取配置文件
from mmcv import Config

config_file = "/home/wistful/work/mmdetection3d/configs/my_config/my_config.py"
cfg = Config.fromfile(config_file)
print("cfg type:",type(cfg))
print("cfg.model type:",type(cfg.model))
cfg.model  # 打印模型部分

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

可以看出,打印出來的模型結(jié)構(gòu),與我們配置文件中的一樣。其中,cfg和cfg.model等等的數(shù)據(jù)類型在此就不介紹了

2.2 讀取數(shù)據(jù)

# 取數(shù)據(jù)
from mmdet3d.datasets import build_dataset

datasets = [build_dataset(cfg.data.train)]

print("datastes type:", type(datasets))
print("datastes[0] type", type(datasets[0]))
print("datastes[0][0] type", type(datasets[0][0]))

datasets[0][0].keys()

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

這里,就不再解釋相關(guān)內(nèi)容了,只需要明白datasets為一個長度1的列表,datasets[0]為一個nuscenes數(shù)據(jù)集類型,datasets[0][i]是nuscenes數(shù)據(jù)集的所有內(nèi)容,每一項(xiàng)包含了四部分內(nèi)容:‘img_metas’, ‘points’, ‘gt_bboxes_3d’, ‘gt_labels_3d’

實(shí)際上,在真正訓(xùn)練或測試過程中,還需要一個data_loader迭代器,方便我們?nèi)?strong>多線程地讀取數(shù)據(jù),并且可以實(shí)現(xiàn)batch以及shuffle的讀取等,mmdet已經(jīng)幫我們實(shí)現(xiàn)了,這里我們由于只需要一條數(shù)據(jù)模擬一下流程,就不構(gòu)造data_loader了

2.3 構(gòu)造模型

# 構(gòu)建模型
from mmdet3d.models import build_model
model = build_model(
    cfg.model,
    train_cfg=cfg.get('train_cfg'),
    test_cfg=cfg.get('test_cfg')
)
model

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

3、運(yùn)行流程

3.1 voxel_layer:點(diǎn)云 -> 體素

# 示例文件配置中,第一步是voxel_layer層,將點(diǎn)云編碼為體素

voxel_layer = model.voxel_layer
# 取點(diǎn)云數(shù)據(jù)
points = datasets[0][0].get('points').data
# 將點(diǎn)云數(shù)據(jù)送入 voxel_layer
voxels_out, coors_out, num_points_per_voxel_out = voxel_layer(points)

上述代碼中,voxel_layer(points)執(zhí)行的是self.voxel_layer = Voxelization(**voxel_layer),Voxelization的輸入輸出大家可以去具體看一下

我們再使用voxel_layer.parameters打印一下參數(shù),得到下面輸出:

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

現(xiàn)在再來回想一下我們自定義的配置文件,這里再放一下:

voxel_size = [0.1, 0.1, 0.1]
model = dict(
    type="MY_MODEL",
    voxel_layer=dict(
        max_num_points=32,
        point_cloud_range=[0, -39.68, -3, 69.12, 39.68, 1],
        voxel_size=voxel_size,
        max_voxels=(16000, 40000)),
    voxel_encoder=dict(
        type='VoxelFeatureExtractorV3',
        num_input_features=4
    ),
    train_cfg=dict(),
    test_cfg=dict())

可以看出,voxel_layer層傳入的參數(shù)是我們配置文件中的內(nèi)容,根據(jù)前面提到過的Voxelization的輸入輸出,可以看到,forward部分只缺一個points input,即點(diǎn)云。在本節(jié)剛開始的代碼塊中,voxels_out, coors_out, num_points_per_voxel_out = voxel_layer(points)執(zhí)行的便是將點(diǎn)云轉(zhuǎn)換為體素操作,我們輸出前后形狀來看一下:

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

即將自定范圍內(nèi)的點(diǎn)云,按照自定體素大小[0.1,0.1,0.1],每塊體素最多保留32個點(diǎn),最終將32242個點(diǎn),轉(zhuǎn)換為了6051個體素,每個體素包含的點(diǎn)不一樣,但都記錄下來了。

3.2 voxel_encoder:體素編碼

這一層,主要是將上一層(voxel_layer)的輸出進(jìn)行encoder,往上翻到1.3,我們給出了相應(yīng)實(shí)現(xiàn),這里實(shí)現(xiàn)較為簡單,即求每個體素中的平均點(diǎn)。我們現(xiàn)在這里記一下實(shí)現(xiàn)中的forward函數(shù):def forward(self, features, num_voxels, coors=None)

我們先打印一下這一層的參數(shù)

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

發(fā)現(xiàn)沒有輸出,這是因?yàn)槲覀儧]有定義相關(guān)方法,我們在VoxelFeatureExtractorV3類中加一個方法:

    def __repr__(self):
        s = self.__class__.__name__ + '('
        s += 'num_input_features=' + str(self.num_input_features)
        s += ')'
        return s

再次執(zhí)行就有輸出了,參數(shù)也是與配置文件相同。下面代碼將上一層的輸出傳遞到這一層

import torch

voxel_encoder = model.voxel_encoder
print(voxel_encoder.parameters)
voxel_encoder_inputs = voxels_out  # 將上一層的輸出作為輸入
num_voxels = torch.tensor(voxels_out.shape[0])  # 這里只用一條數(shù)據(jù)作為演示,所以要轉(zhuǎn)一下tensor
voxel_encoder_result = voxel_encoder(voxel_encoder_inputs, num_voxels)
print("voxel_encoder output shape:", voxel_encoder_result.shape)

零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程

我們的配置文件和網(wǎng)絡(luò)只給出了兩個基礎(chǔ)層的定義和實(shí)現(xiàn),剩下的幾層(neck、backbone…)都大同小異,都是這么個流程,完整的流程還會有損失函數(shù)的計算、反向更新等等,這一步是寫在模型的forward里,此篇就不再詳解了文章來源地址http://www.zghlxwxcb.cn/news/detail-449985.html

到了這里,關(guān)于零基礎(chǔ)熟悉mmdetection3d數(shù)據(jù)提取、模型搭建過程的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • MMDetection3D簡單學(xué)習(xí)

    我們通常把模型的各個組成成分分成 6 種類型: 編碼器(encoder):包括 voxel encoder 和 middle encoder 等進(jìn)入 backbone 前所使用的基于體素的方法,如? HardVFE ?和? PointPillarsScatter 。 骨干網(wǎng)絡(luò)(backbone):通常采用 FCN 網(wǎng)絡(luò)來提取特征圖,如? ResNet ?和? SECOND 。 頸部網(wǎng)絡(luò)(neck):

    2024年02月13日
    瀏覽(23)
  • 【MMDetection3D】環(huán)境搭建,使用PointPillers訓(xùn)練&測試&可視化KITTI數(shù)據(jù)集

    【MMDetection3D】環(huán)境搭建,使用PointPillers訓(xùn)練&測試&可視化KITTI數(shù)據(jù)集

    2D卷不動了,來卷3D,之后更多地工作會放到3D檢測上 本文將簡單介紹什么是3D目標(biāo)檢測、KITTI數(shù)據(jù)集以及MMDetection3D算法庫,重點(diǎn)介紹如何在MMDetection3D中,使用PointPillars算法訓(xùn)練KITTI數(shù)據(jù)集,并對結(jié)果進(jìn)行測試和可視化。 ? 對于一張輸入圖像,2D目標(biāo)檢測旨在給出物體類別并標(biāo)

    2024年02月03日
    瀏覽(38)
  • MMDetection3D框架環(huán)境配置

    MMDetection3D框架環(huán)境配置

    MMDetection3D是一個基于PyTorch的開源3D目標(biāo)檢測框架。下面是MMDetection3D的環(huán)境配置步驟: 安裝Anaconda,教程很多不在說明。 1.創(chuàng)建Python環(huán)境 使用以下命令創(chuàng)建一個Python 3.8環(huán)境: 使用以下命令激活Python環(huán)境:? 2.安裝gpu版本的torch、torchvision 2.1 下載對應(yīng)的torch、torchvision安裝包:

    2024年02月09日
    瀏覽(25)
  • mmdetection3d-之(一)--FCOS3d訓(xùn)練nuscenes-mini數(shù)據(jù)集

    參考網(wǎng)上的博客,出現(xiàn)各種錯誤,最大的是: AssertionError: Samples in split doesn\\\'t match samples in predictions. 給了解決方案,也不知道那個數(shù)字是怎么來的。索性自己來一遍,參考了github issue。? ?第一步,下載數(shù)據(jù)集并解壓: 第二步,修改代碼 tools/create_data.py? ?第三步,制作數(shù)據(jù)

    2024年02月15日
    瀏覽(26)
  • mmdetection3d nuScenes (持續(xù)更新)

    本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 本文為專欄《python三維點(diǎn)云從基礎(chǔ)到深度學(xué)習(xí)》系列文章,地址為“https://blog.csdn.net/suiyingy/article/details/124017716”。 ????????Mmdetection3d集成了大量3D深度學(xué)習(xí)算法,其中很大一部分可以在智能駕駛nuScenes數(shù)據(jù)集上運(yùn)行。在算法

    2023年04月15日
    瀏覽(19)
  • win10 mmdetection3d環(huán)境搭建

    win10 mmdetection3d環(huán)境搭建

    官網(wǎng):mmdetection3d/README_zh-CN.md at master · open-mmlab/mmdetection3d · GitHub 安裝過程參照:win10 mmdetection3d 訓(xùn)練KITTI_樹和貓的博客-CSDN博客_pointnet訓(xùn)練kitti 官網(wǎng)安裝過程 3D目標(biāo)檢測框架綜述-知乎中描述了當(dāng)前3D目標(biāo)檢測的數(shù)據(jù)和模型狀況,為了能將數(shù)據(jù)和評價標(biāo)準(zhǔn)等統(tǒng)一,介紹了4個比

    2023年04月18日
    瀏覽(22)
  • 【MMDetection3D】MVXNet踩坑筆記

    【MMDetection3D】MVXNet踩坑筆記

    原文 代碼 MVXNet(CVPR2019) 最近許多關(guān)于3D target detection的工作都集中在設(shè)計能夠使用點(diǎn)云數(shù)據(jù)的神經(jīng)網(wǎng)絡(luò)架構(gòu)上。雖然這些方法表現(xiàn)出令人鼓舞的性能,但它們通?;趩我荒B(tài),無法利用其他模態(tài)(如攝像頭和激光雷達(dá))的信息。盡管一些方法融合了來自不同模式的數(shù)據(jù),這些方

    2024年01月18日
    瀏覽(44)
  • 新版mmdetection3d將3D bbox繪制到圖像

    新版mmdetection3d將3D bbox繪制到圖像

    使用 python mmdet3d/utils/collect_env.py 收集環(huán)境信息 以前寫過mmdetection3d中的可視化,但mmdetection3d更新后代碼已經(jīng)不適用了,正好我把我的工作全轉(zhuǎn)移到新版mmdetection3d上來了,因此重新寫了一下推理結(jié)果可視化。整體思路還是構(gòu)建模型、構(gòu)建數(shù)據(jù)、推理、繪制,下面分步講解 我用

    2024年04月15日
    瀏覽(25)
  • mmdetection3d系列--(1)安裝步驟(無坑版)

    mmdetection3d系列--(1)安裝步驟(無坑版)

    ? 最近在看一些基于點(diǎn)云3d目標(biāo)檢測的文章,需要復(fù)現(xiàn)甚至修改一些算法,就找到了mmlab開源的mmdetection3d目標(biāo)檢測框架,方便后續(xù)學(xué)習(xí)。 ??? 在安裝的時候遇到一點(diǎn)坑,比如環(huán)境問題,安裝完能跑demo但是不能跑訓(xùn)練測試問題等。在解決問題后還是完成了安裝。在這里記錄一

    2024年02月02日
    瀏覽(15)
  • MMDetection3D庫中的一些模塊介紹

    MMDetection3D庫中的一些模塊介紹

    本文目前僅包含2個體素編碼器、2個中間編碼器、1個主干網(wǎng)絡(luò)、1個頸部網(wǎng)絡(luò)和1個檢測頭。如果有機(jī)會,會繼續(xù)補(bǔ)充更多模型。 若發(fā)現(xiàn)內(nèi)容有誤,歡迎指出。 ??MMDetection3D的點(diǎn)云數(shù)據(jù)一般會經(jīng)歷如下步驟/模塊: ??下面分別介紹每個部分的一些典型模型。 ??在介紹體素

    2023年04月17日
    瀏覽(16)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包