全網首發!超詳細的SparseR-CNN實戰

      網友投稿 1090 2022-05-30

      1、簡介

      目前,目標檢測領域中主流的兩大類方法。

      第一大類是 從非Deep時代就被廣泛應用的dense detector ,例如DPM,YOLO,RetinaNet,FCOS。在dense detector中,大量的object candidates例如sliding-windows,anchor-boxes, reference-points等被提前預設在圖像網格或者特征圖網格上,然后直接預測這些candidates到gt的scaling/offest和物體類別。

      第二大類是 dense-to-sparse detector ,例如R-CNN家族。這類方法的特點是對一組sparse的candidates預測回歸和分類,而這組sparse的candidates來自于dense detector。

      但是,dense屬性的一些固有局限總讓人難以滿意,比如:

      NMS 后處理

      many-to-one 正負樣本分配

      prior candidates的設計

      Sparse R-CNN拋棄了anchor boxes或者reference point等dense概念,直接從a sparse set of learnable proposals出發,沒有NMS后處理,整個網絡異常干凈和簡潔,可以看做是在dense(單階段),dense2sparse(二階段)之外的一個全新的檢測范式。

      2、Detectron2介紹

      Detectron2 是Facebook第二代檢測工具箱,支持目標檢測、實例分割、姿態估計、語義分割和全景分割等任務。

      我們使用Detectron2很方便的實現模型的訓練、測試以及模型轉換。所以現在很多的新模型都是在Detectron2開發。

      3、搭建Sparse R-CNN測試環境

      我本地環境:

      操作系統:win10、Cuda11.0。

      3.1 創建虛擬環境

      創建虛擬環境,并激活環境。

      conda create --name sparsercnn python=3.7 activate sparsercnn conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cudatoolkit=11.0 -c pytorch

      1

      2

      3

      3.2 安裝apex庫

      APEX是英偉達開源的,完美支持PyTorch框架,用于改變數據格式來減小模型顯存占用的工具。其中最有價值的是amp(Automatic Mixed Precision),將模型的大部分操作都用Float16數據類型測試,一些特別操作仍然使用Float32。并且用戶僅僅通過三行代碼即可完美將自己的訓練代碼遷移到該模型。實驗證明,使用Float16作為大部分操作的數據類型,并沒有降低參數,在一些實驗中,反而由于可以增大Batch size,帶來精度上的提升,以及訓練速度上的提升。

      3.2.1 下載apex庫

      網址 https://github.com/NVIDIA/apex,下載到本地文件夾。解壓后進入到apex的目錄安裝依賴。在執行命令;

      cd C:\Users\WH\Downloads\apex-master #進入apex目錄 pip install -r requirements.txt

      1

      2

      3.2.2 安裝apex庫

      依賴安裝完后,打開cmd,cd進入到剛剛下載完的apex-master路徑下,運行:

      python setup.py install

      1

      然后跑了一堆東西,最后是這樣的:

      安裝完成!

      3.3 安裝fvcore庫

      fvcore庫的簡介

      fvcore是一個輕量級的核心庫,它提供了在各種計算機視覺框架(如Detectron2)中共享的最常見和最基本的功能。這個庫基于Python 3.6+和PyTorch。這個庫中的所有組件都經過了類型注釋、測試和基準測試。Facebook 的人工智能實驗室即FAIR的計算機視覺組負責維護這個庫。

      github地址:https://github.com/facebookresearch/fvcore

      執行命令

      conda install -c fvcore -c iopath -c conda-forge fvcore

      1

      3.4 安裝Detectron2環境需要其他庫

      安裝pycocotools

      pip install pycocotools

      1

      安裝cv2

      pip install opencv-python

      1

      安裝 antlr4

      pip install antlr4-python3-runtime

      1

      安裝future

      pip install future

      1

      安裝protobuf

      pip install protobuf

      1

      安裝absl

      pip install absl-py

      1

      安裝tensorboard

      pip install tensorboard

      1

      安裝pydot

      pip install pydot

      1

      安裝scipy

      pip install scipy -i https://pypi.tuna.tsinghua.edu.cn/simple

      1

      3.5 編譯Sparse R-CNN

      進入Sparse R-CNN目錄,目錄根據自己的實際情況更改。

      cd D:\SparseR-CNN-main

      1

      編譯Detectron2和Sparse R-CNN

      python setup.py build develop

      1

      看到如下信息,則表明安裝完成,如果缺少庫的情況,則需要安裝庫,再編譯,直到編譯成功!

      4、測試環境

      新建input_img和output_img文件夾,imgs文件夾存放待測試的圖片。

      圖片如下:

      下載模型“r50_100pro_3x_model.pth”(注:如果不能下載,關注我的公眾號獲取連接。),將其放到“projects/SparseRCNN”目錄下面。

      執行命令:

      python demo/demo.py --config-file projects/SparseRCNN/configs/sparsercnn.res50.100pro.3x.yaml --input imgs/*.jpg --output imgout --opts MODEL.WEIGHTS projects/SparseRCNN/r50_100pro_3x_model.pth

      1

      運行結果:

      能夠運行demo說明環境已經沒有問題了。

      5、制作數據集

      本次采用的數據集是Labelme標注的數據集,地址:鏈接:https://pan.baidu.com/s/1nxo9-NpNWKK4PwDZqwKxGQ 提取碼:kp4e,需要將其轉為COCO格式的數據集。轉換代碼如下:

      新建labelme2coco.py

      import argparse import json import matplotlib.pyplot as plt import skimage.io as io import cv2 from labelme import utils import numpy as np import glob import PIL.Image REQUIRE_MASK = False labels = {'aircraft': 1, 'oiltank': 2} class labelme2coco(object): def __init__(self, labelme_json=[], save_json_path='./new.json'): ''' :param labelme_json: the list of all labelme json file paths :param save_json_path: the path to save new json ''' self.labelme_json = labelme_json self.save_json_path = save_json_path self.images = [] self.categories = [] self.annotations = [] # self.data_coco = {} self.label = [] self.annID = 1 self.height = 0 self.width = 0 self.require_mask = REQUIRE_MASK self.save_json() def data_transfer(self): for num, json_file in enumerate(self.labelme_json): if not json_file == self.save_json_path: with open(json_file, 'r') as fp: data = json.load(fp) self.images.append(self.image(data, num)) for shapes in data['shapes']: print("label is ") print(shapes['label']) label = shapes['label'] # if label[1] not in self.label: if label not in self.label: print("find new category: ") self.categories.append(self.categorie(label)) print(self.categories) # self.label.append(label[1]) self.label.append(label) points = shapes['points'] self.annotations.append(self.annotation(points, label, num)) self.annID += 1 def image(self, data, num): image = {} img = utils.img_b64_to_arr(data['imageData']) height, width = img.shape[:2] img = None image['height'] = height image['width'] = width image['id'] = num + 1 image['file_name'] = data['imagePath'].split('/')[-1] self.height = height self.width = width return image def categorie(self, label): categorie = {} categorie['supercategory'] = label # categorie['supercategory'] = label categorie['id'] = labels[label] # 0 默認為背景 categorie['name'] = label return categorie def annotation(self, points, label, num): annotation = {} print(points) x1 = points[0][0] y1 = points[0][1] x2 = points[1][0] y2 = points[1][1] contour = np.array([[x1, y1], [x2, y1], [x2, y2], [x1, y2]]) # points = [[x1, y1], [x2, y2]] for rectangle contour = contour.astype(int) area = cv2.contourArea(contour) print("contour is ", contour, " area = ", area) annotation['segmentation'] = [list(np.asarray([[x1, y1], [x2, y1], [x2, y2], [x1, y2]]).flatten())] # [list(np.asarray(contour).flatten())] annotation['iscrowd'] = 0 annotation['area'] = area annotation['image_id'] = num + 1 if self.require_mask: annotation['bbox'] = list(map(float, self.getbbox(points))) else: x1 = points[0][0] y1 = points[0][1] width = points[1][0] - x1 height = points[1][1] - y1 annotation['bbox'] = list(np.asarray([x1, y1, width, height]).flatten()) annotation['category_id'] = self.getcatid(label) annotation['id'] = self.annID return annotation def getcatid(self, label): for categorie in self.categories: # if label[1]==categorie['name']: if label == categorie['name']: return categorie['id'] return -1 def getbbox(self, points): polygons = points mask = self.polygons_to_mask([self.height, self.width], polygons) return self.mask2box(mask) def mask2box(self, mask): # np.where(mask==1) index = np.argwhere(mask == 1) rows = index[:, 0] clos = index[:, 1] left_top_r = np.min(rows) # y left_top_c = np.min(clos) # x right_bottom_r = np.max(rows) right_bottom_c = np.max(clos) return [left_top_c, left_top_r, right_bottom_c - left_top_c, right_bottom_r - left_top_r] def polygons_to_mask(self, img_shape, polygons): mask = np.zeros(img_shape, dtype=np.uint8) mask = PIL.Image.fromarray(mask) xy = list(map(tuple, polygons)) PIL.ImageDraw.Draw(mask).polygon(xy=xy, outline=1, fill=1) mask = np.array(mask, dtype=bool) return mask def data2coco(self): data_coco = {} data_coco['images'] = self.images data_coco['categories'] = self.categories data_coco['annotations'] = self.annotations return data_coco def save_json(self): print("in save_json") self.data_transfer() self.data_coco = self.data2coco() print(self.save_json_path) json.dump(self.data_coco, open(self.save_json_path, 'w'), indent=4) labelme_json = glob.glob('LabelmeData/*.json') from sklearn.model_selection import train_test_split trainval_files, test_files = train_test_split(labelme_json, test_size=0.2, random_state=55) import os if not os.path.exists("projects/SparseRCNN/datasets/coco/annotations"): os.makedirs("projects/SparseRCNN/datasets/coco/annotations/") if not os.path.exists("projects/SparseRCNN/datasets/coco/train2017"): os.makedirs("projects/SparseRCNN/datasets/coco/train2017") if not os.path.exists("projects/SparseRCNN/datasets/coco/val2017"): os.makedirs("projects/SparseRCNN/datasets/coco/val2017") labelme2coco(trainval_files, 'projects/SparseRCNN/datasets/coco/annotations/instances_train2017.json') labelme2coco(test_files, 'projects/SparseRCNN/datasets/coco/annotations/instances_val2017.json') import shutil for file in trainval_files: shutil.copy(os.path.splitext(file)[0] + ".jpg", "projects/SparseRCNN/datasets/coco/train2017/") for file in test_files: shutil.copy(os.path.splitext(file)[0] + ".jpg", "projects/SparseRCNN/datasets/coco/val2017/")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      112

      113

      114

      115

      116

      117

      118

      119

      120

      121

      122

      123

      124

      125

      126

      127

      128

      129

      130

      131

      132

      133

      134

      135

      136

      137

      138

      139

      140

      141

      142

      143

      144

      145

      146

      147

      148

      149

      150

      151

      152

      153

      154

      155

      156

      157

      158

      159

      160

      161

      162

      163

      164

      165

      166

      167

      168

      169

      170

      171

      172

      173

      174

      175

      6、配置訓練環境

      6.1 更改預訓練模型的size

      在projects/SparseRCNN目錄,新建change_model_size.py文件

      import torch import numpy as np import pickle num_class = 2 pretrained_weights = torch.load('r50_100pro_3x_model.pth') pretrained_weights["head.head_series.0.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.0.class_logits.bias"].resize_(num_class) pretrained_weights["head.head_series.1.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.1.class_logits.bias"].resize_(num_class) pretrained_weights["head.head_series.2.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.2.class_logits.bias"].resize_(num_class) pretrained_weights["head.head_series.3.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.3.class_logits.bias"].resize_(num_class) pretrained_weights["head.head_series.4.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.4.class_logits.bias"].resize_(num_class) pretrained_weights["head.head_series.5.class_logits.weight"].resize_(num_class,256) pretrained_weights["head.head_series.5.class_logits.bias"].resize_(num_class) torch.save(pretrained_weights, "model_%d.pth"%num_class)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      全網首發!超詳細的SparseR-CNN實戰

      14

      15

      16

      17

      18

      19

      這個文件的目的是修改模型輸出的size,numclass按照本次打算訓練的數據集的類別設置。

      6.2 修改config參數

      路徑:“detectron2/engine/defaults.py”

      –config-file:模型的配置文件,SparseRCNN的模型配置文件放在“projects/SparseRCNN/configs”下面。名字和預訓練模型對應。

      parser.add_argument("--config-file", default="./configs/sparsercnn.res50.100pro.3x.yaml", metavar="FILE", help="path to config file")

      1

      resume 是否再次,訓練,如果設置為true,則接著上次訓練的結果訓練。所以第一次訓練不用設置。

      parser.add_argument( "--resume", action="store_true", help="Whether to attempt to resume from the checkpoint directory. " "See documentation of `DefaultTrainer.resume_or_load()` for what it means.", )

      1

      2

      3

      4

      5

      6

      –num-gpus,gpu的個數,如果只有一個設置為1,如果有多個,可以自己設置想用的個數。

      parser.add_argument("--num-gpus", type=int, default=1, help="number of gpus *per machine*")

      1

      opts指的是yaml文件的參數。

      上面的參數可以設置,也可以不設置,設置之后可以直接運行不用再考慮設置參數,如果不設置每次訓練的時候配置一次參數。

      修改類別,文件路徑“projects/SparseRCNN/config.py”,

      cfg.MODEL.SparseRCNN.NUM_CLASSES = 2

      1

      修改yaml文件參數

      sparsercnn.res50.100pro.3x.yaml中修改預訓練模型的路徑。

      WEIGHTS: "model_2.pth"

      1

      BASE_LR:設置學習率。

      STEPS:設置訓練多少步之后調整學習率。

      MAX_ITER:最大迭代次數。

      CHECKPOINT_PERIOD:設置迭代多少次保存一次模型

      IMS_PER_BATCH:batchsize的大小,根據顯存大小設置。

      NUM_CLASSES:數據集中物體類別的種類。

      NUM_PROPOSALS:提議框的個數。

      BASE_LR: 0.00025 #在Base-SparseRCNN.yaml中 IMS_PER_BATCH: 2#在Base-SparseRCNN.yaml中 NUM_CLASSES:2 STEPS: (21000, 25000) MAX_ITER: 54000 CHECKPOINT_PERIOD: 5000

      1

      2

      3

      4

      5

      6

      6.3 修改train_net.py

      主要修改該setup函數,增加數據集注冊。

      NUM_CLASSES=2 def setup(args): """ Create configs and perform basic setups. """ register_coco_instances("train", {}, "datasets/coco/annotations/instances_train2017.json", "datasets/coco/train2017") register_coco_instances("test", {}, "datasets/coco/annotations/instances_val2017.json", "datasets/coco/val2017") cfg = get_cfg() add_sparsercnn_config(cfg) cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) cfg.DATASETS.TRAIN = ("train",) cfg.DATASETS.TEST = ("test",) cfg.MODEL.SparseRCNN.NUM_CLASSES = NUM_CLASSES cfg.MODEL.ROI_HEADS.NUM_CLASSES=NUM_CLASSES cfg.freeze() default_setup(cfg, args) return cfg

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      還要修改detectron2/engine/launch.py,在launch函數下面增加一句

      dist.init_process_group('gloo', init_method='file://tmp/somefile', rank=0, world_size=1)

      1

      如下圖:

      這句話的作用是初始化分布式訓練,因為我們沒有使用分布式,所以沒有初始化,但是不初始化就會報錯,所以加上這句。

      7、訓練

      兩種啟動方式:

      第一種,命令行:進入“projects/SparseRCNN/”目錄下,執行:

      python train_net.py

      1

      第二種,直接在pycharm 直接運行train_net.py.

      訓練結果:

      從訓練結果上看,效果確實不錯,和CenterNet2的結果相差不大,不過模型很大,大約有1.2G,比CenterNet2的模型大了一倍多。

      8、測試

      修改demo/demo.py

      8.1 修改setup_cfg函數

      在紅框的位置增加代碼,詳細如下面的代碼。

      NUM_CLASSES=2 def setup_cfg(args): # load config from file and command-line arguments cfg = get_cfg() from projects.SparseRCNN.sparsercnn import add_sparsercnn_config add_sparsercnn_config(cfg) cfg.MODEL.SparseRCNN.NUM_CLASSES = NUM_CLASSES cfg.MODEL.ROI_HEADS.NUM_CLASSES = NUM_CLASSES cfg.merge_from_file(args.config_file) cfg.merge_from_list(args.opts) # Set score_threshold for builtin models cfg.MODEL.RETINANET.SCORE_THRESH_TEST = args.confidence_threshold cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = args.confidence_threshold cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = args.confidence_threshold cfg.freeze() return cfg

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      8.2 修改顯示類別

      在demo/predictor.py

      代碼:

      visualizer.metadata.thing_classes[:10] = ["aircraft", "oiltank"]

      1

      然后進入SparseR-CNN-main目錄,執行如下命令:

      python demo/demo.py --config-file projects/SparseRCNN/configs/sparsercnn.res50.100pro.3x.yaml --input img/*jpg --output out --opts MODEL.WEIGHTS projects/Spa rseRCNN/output/model_final.pth

      1

      2

      3

      運行結果:

      機器學習 深度學習 神經網絡

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:一文搞懂HUB75接口(附帶LED單元板驅動介紹)
      下一篇:Python語言課程設計名片管理系統
      相關文章
      亚洲综合熟女久久久30p| 免费观看亚洲人成网站| 亚洲av成本人无码网站| 亚洲视频在线观看网站| 亚洲国产精品特色大片观看完整版 | 亚洲中文字幕人成乱码| 久久亚洲一区二区| 亚洲狠狠婷婷综合久久久久| 国产AV无码专区亚洲AV毛网站| 亚洲电影日韩精品| mm1313亚洲精品国产| 亚洲不卡无码av中文字幕| 国产成人久久精品亚洲小说| WWW亚洲色大成网络.COM| 日韩精品成人亚洲专区| 亚洲国产成人VA在线观看| 亚洲高清偷拍一区二区三区 | 亚洲精品高清无码视频| 亚洲国产精品无码久久久秋霞2 | 亚洲一区二区三区日本久久九| 亚洲av日韩av不卡在线观看| 亚洲AV无码码潮喷在线观看| 亚洲成人在线电影| 亚洲黄色免费在线观看| 亚洲精品网站在线观看你懂的| 亚洲福利一区二区三区| 亚洲成a人片在线观看精品| 亚洲另类无码专区首页| 在线观看亚洲视频| 亚洲一级片内射网站在线观看| 在线观看亚洲天天一三视| 国产成人综合亚洲AV第一页 | 欧洲 亚洲 国产图片综合| 亚洲av色香蕉一区二区三区 | 亚洲毛片不卡av在线播放一区 | 亚洲熟妇丰满xxxxx| 国产精品亚洲一区二区三区久久 | 亚洲午夜精品久久久久久浪潮| 亚洲人精品午夜射精日韩| 久久久久亚洲Av片无码v| 亚洲第一香蕉视频|