A, install,

Maskrcnn-benchmark (Pytorch version)

First of all, read the environmental requirements of the official website, do not install directly, or the program is likely to report errors!!

  • PyTorch 1.0 from a nightly release. It will not work with 1.0 nor 1.0.1. Installation instructions can be found in Pytorch.org/get-started…
  • torchvision from master
  • cocoapi
  • yacs
  • matplotlib
  • GCC > = 4.9
  • OpenCV
# first, make sure that your conda is setup properly with the right environment
# for that, check that `which conda`, `which pip` and `which python` points to the
# right path. From a clean conda env, this is what you need to do

conda create --name maskrcnn_benchmark
conda activate maskrcnn_benchmark

# this installs the right pip and dependencies for the fresh python
conda install ipython

# maskrcnn_benchmark and coco api dependencies
pip install ninja yacs cython matplotlib tqdm opencv-python

# follow PyTorch installation in https://pytorch.org/get-started/locally/
# we give the instructions for CUDA 9.0Conda install -c PyTorch pyTorch -NIGHTLY TorchVision CUDatoolKit =9.0export INSTALL_DIR=$PWD

# install pycocotools
cd $INSTALL_DIR
git clone https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI
python setup.py build_ext install

# install apex
cd $INSTALL_DIR
git clone https://github.com/NVIDIA/apex.git
cd apex
python setup.py install --cuda_ext --cpp_ext

# install PyTorch Detection
cd $INSTALL_DIR
git clone https://github.com/facebookresearch/maskrcnn-benchmark.git
cd maskrcnn-benchmark

# the following will install the lib with
# symbolic links, so that you can modify
# the files if you want and won't need to
# re-build it
python setup.py build develop


unset INSTALL_DIR

# or if you are on macOS
# MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py build develop
Copy the code

Be sure to follow the above instructions step by step, do not omit, or the program is likely to report errors!!


2. Data preparation

The original data format I want to make is the training file in a file (train), the annotation file is CSV format, the content is as follows:

The first step

#! /usr/bin/env python
# coding=UTF-8
' '' @Description: @Author: HuangQinJian @LastEditors: HuangQinJian @Date: 2019-05-01 12:56:08 @LastEditTime: The 2019-05-01 13:11:38 '' '
import pandas as pd
import random
import os
import shutil

if not os.path.exists('trained/'):
    os.mkdir('trained/')

if not os.path.exists('val/'):
    os.mkdir('val/')

val_rate = 0.15

img_path = 'train/'
img_list = os.listdir(img_path)
train = pd.read_csv('train_label_fix.csv')
# print(img_list)
random.shuffle(img_list)

total_num = len(img_list)
val_num = int(total_num*val_rate)
train_num = total_num-val_num

for i in range(train_num):
    img_name = img_list[i]
    shutil.copy('train/' + img_name, 'trained/' + img_name)
for j in range(val_num):
    img_name = img_list[j+train_num]
    shutil.copy('train/' + img_name, 'val/' + img_name)
Copy the code

The second step is to convert the annotation file from CSV format to coco format. The code is as follows:

#! /usr/bin/env python
# coding=UTF-8
' '' @Description: @Author: HuangQinJian @LastEditors: HuangQinJian @Date: 2019-04-23 11:28:23 @LastEditTime: The 2019-05-01 13:15:57 '' 'import sys import os import json import cv2 import pandas as pd START_BOUNDING_BOX_ID = 1 PRE_DEFINE_CATEGORIES = {} def  convert(csv_path, img_path, json_file):"""Csv_path: CSV file path img_path: file path to store images json_file: file path to store generated JSON files"""
    json_dict = {"images": []."type": "instances"."annotations": []."categories": []}
    bnd_id = START_BOUNDING_BOX_ID
    categories = PRE_DEFINE_CATEGORIES
    csv = pd.read_csv(csv_path)
    img_nameList = os.listdir(img_path)
    img_num = len(img_nameList)
    print("Total number of pictures {0}".format(img_num))
    for i in range(img_num):
        # for i in range(30):
        image_id = i+1
        img_name = img_nameList[i]
        if img_name == '60f3ea2534804c9b806e7d5ae1e229cf.jpg' or img_name == '6b292bacb2024d9b9f2d0620f489b1e4.jpg':
            continue
        # Changes that may need to be made depending on the format
        lines = csv[csv.filename == img_name]
        img = cv2.imread(os.path.join(img_path, img_name))
        height, width, _ = img.shape
        image = {'file_name': img_name, 'height': height, 'width': width,
                 'id': image_id}
        print(image)
        json_dict['images'].append(image)
        for j in range(len(lines)):
            # Changes that may need to be made depending on the format
            category = str(lines.iloc[j]['type'])
            if category not in categories:
                new_id = len(categories)
                categories[category] = new_id
            category_id = categories[category]
            # Changes that may need to be made depending on the format
            xmin = int(lines.iloc[j]['X1'])
            ymin = int(lines.iloc[j]['Y1'])
            xmax = int(lines.iloc[j]['X3'])
            ymax = int(lines.iloc[j]['Y3'])
            # print(xmin, ymin, xmax, ymax)
            assert(xmax > xmin)
            assert(ymax > ymin)
            o_width = abs(xmax - xmin)
            o_height = abs(ymax - ymin)
            ann = {'area': o_width*o_height, 'iscrowd': 0.'image_id':
                   image_id, 'bbox': [xmin, ymin, o_width, o_height],
                   'category_id': category_id, 'id': bnd_id, 'ignore': 0.'segmentation': []}
            json_dict['annotations'].append(ann)
            bnd_id = bnd_id + 1
    for cate, cid in categories.items():
        cat = {'supercategory': 'none'.'id': cid, 'name': cate}
        json_dict['categories'].append(cat)

    json_fp = open(json_file, 'w')
    json_str = json.dumps(json_dict, indent=4)
    json_fp.write(json_str)
    json_fp.close()


if __name__ == '__main__':
    # csv_path = 'data/train_label_fix.csv'
    # img_path = 'data/train/'
    # json_file = 'train.json'
    csv_path = 'train_label_fix.csv'
    img_path = 'trained/'
    json_file = 'trained.json'
    convert(csv_path, img_path, json_file)
    csv_path = 'train_label_fix.csv'
    img_path = 'val/'
    json_file = 'val.json'
    convert(csv_path, img_path, json_file)
Copy the code

The third step is to visualize the format of the converted coco to ensure that the conversion is correct. The code is as follows:

Note: In this step, you need to download it firstcocoapiMay come upThe problem)

#! /usr/bin/env python
# coding=UTF-8
' '' @Description: @Author: HuangQinJian @LastEditors: HuangQinJian @Date: 2019-04-23 13:43:24 @LastEditTime: The 2019-04-30 21:29:26 '' 'from pycocotools.coco import COCO import skimage.io as io import matplotlib.pyplot as plt import pylab import cv2 import  os from skimage.io import imsave import numpy as np pylab.rcParams['figure.figsize'] = (8.0, 10.0)

img_path = 'data/train/'
annFile = 'train.json'

if not os.path.exists('anno_image_coco/'):
    os.makedirs('anno_image_coco/')


def draw_rectangle(coordinates, image, image_name):
    for coordinate in coordinates:
        left = np.rint(coordinate[0])
        right = np.rint(coordinate[1])
        top = np.rint(coordinate[2])
        bottom = np.rint(coordinate[3])
        # upper left coordinates, lower right coordinates
        cv2.rectangle(image,
                      (int(left), int(right)),
                      (int(top), int(bottom)),
                      (0, 255, 0),
                      2)
    imsave('anno_image_coco/'+image_name, image)


Initialize the COCO API for annotation data
coco = COCO(annFile)

# display COCO categories and supercategories
cats = coco.loadCats(coco.getCatIds())
nms = [cat['name'] for cat in cats]
# print('COCO categories: \n{}\n'.format(' '.join(nms)))

nms = set([cat['supercategory'] for cat in cats])
# print('COCO supercategories: \n{}'.format(' '.join(nms)))

img_path = 'data/train/'
img_list = os.listdir(img_path)
# for i in range(len(img_list)):
for i in range(7):
    imgIds = i+1
    img = coco.loadImgs(imgIds)[0]
    image_name = img['file_name']
    # print(img)

    Load and display images
    # I = io.imread('%s/%s' % (img_path, img['file_name']))
    # plt.axis('off')
    # plt.imshow(I)
    # plt.show()

    # catIds=[] specifies a box that displays all categories. You can also specify categories
    annIds = coco.getAnnIds(imgIds=img['id'], catIds=[], iscrowd=None)
    anns = coco.loadAnns(annIds)
    # print(anns)
    coordinates = []
    img_raw = cv2.imread(os.path.join(img_path, image_name))
    for j in range(len(anns)):
        coordinate = []
        coordinate.append(anns[j]['bbox'][0])
        coordinate.append(anns[j]['bbox'][1]+anns[j]['bbox'][3])
        coordinate.append(anns[j]['bbox'][0]+anns[j]['bbox'][2])
        coordinate.append(anns[j]['bbox'] [1])# print(coordinate)
        coordinates.append(coordinate)
    # print(coordinates)
    draw_rectangle(coordinates, img_raw, image_name)
Copy the code

3. File configuration

There are a lot of things that need to be changed during training your own data set, so here are a few that are commonly used:

  • Modify themaskrcnn_benchmark/config/paths_catalog.pyData set path:
class DatasetCatalog(object):
    # Modify the path according to your actual situation!!
    # Modify the path according to your actual situation!!
    # Modify the path according to your actual situation!!
    DATA_DIR = ""
    DATASETS = {
        "coco_2017_train": {
            "img_dir": "coco/train2017"."ann_file": "coco/annotations/instances_train2017.json"
        },
        "coco_2017_val": {
            "img_dir": "coco/val2017"."ann_file": "coco/annotations/instances_val2017.json"
        },
        # change the path of training set!!
        # change the path of training set!!
        # change the path of training set!!
        "coco_2014_train": {
            "img_dir": "/data1/hqj/traffic-sign-identification/trained"."ann_file": "/data1/hqj/traffic-sign-identification/trained.json"
        },
        # change the path of validation set!!
        # change the path of validation set!!
        # change the path of validation set!!
        "coco_2014_val": {
            "img_dir": "/data1/hqj/traffic-sign-identification/val"."ann_file": "/data1/hqj/traffic-sign-identification/val.json"
        },
        # change the path of the test set!!
        # change the path of the test set!!
        # change the path of the test set!!
        "coco_2014_test": {
            "img_dir": "/data1/hqj/traffic-sign-identification/test".Copy the code
  • Configuration file under config:

Since there are a lot of parameters in this file that need to be changed according to my specific needs, I listed my own configuration (using e2e_faster_rCNn_X_101_32x8d_fpn_1x.yaml, where I have comments that must be changed, such as NUM_CLASSES) :

INPUT:
  MIN_SIZE_TRAIN: (1000,)
  MAX_SIZE_TRAIN: 1667
  MIN_SIZE_TEST: 1000
  MAX_SIZE_TEST: 1667
MODEL:
  META_ARCHITECTURE: "GeneralizedRCNN"
  WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d"
  BACKBONE:
    CONV_BODY: "R-101-FPN"RPN: USE_FPN: True BATCH_SIZE_PER_IMAGE: 128 ANCHOR_SIZES: (16, 32, 64, 128, 256) ANCHOR_STRIDE: (4, 8, 16, 32, 64) PRE_NMS_TOP_N_TRAIN: 2000 PRE_NMS_TOP_N_TEST: 1000 POST_NMS_TOP_N_TEST: 1000 FPN_POST_NMS_TOP_N_TEST: 1000 FPN_POST_NMS_TOP_N_TRAIN: 1000 ASPECT_RATIOS: (1.0,) FPN: USE_GN: True ROI_HEADS:# Whether to use FPN
    USE_FPN: True
  ROI_BOX_HEAD:
    USE_GN: True
    POOLER_RESOLUTION: 7
    POOLER_SCALES: (0.25, 0.125, 0.0625, 0.03125)
    POOLER_SAMPLING_RATIO: 2
    FEATURE_EXTRACTOR: "FPN2MLPFeatureExtractor"
    PREDICTOR: "FPNPredictor"
    # change to the number of categories you need to check +1
    NUM_CLASSES: 22
  RESNETS:
    BACKBONE_OUT_CHANNELS: 256
    STRIDE_IN_1X1: False
    NUM_GROUPS: 32
    WIDTH_PER_GROUP: 8
DATASETS:
  In # paths_catalog.py, don't forget the comma if you specify only one dataset (e.g. :("coco_2014_val",))
  TRAIN: ("coco_2014_train",)
  TEST: ("coco_2014_val",)
DATALOADER:
  SIZE_DIVISIBILITY: 32
SOLVER:
  BASE_LR: 0.001
  WEIGHT_DECAY: 0.0001
  STEPS: (240000, 320000)
  MAX_ITER: 360000
  # important Settings, specific can see's official website: https://github.com/facebookresearch/maskrcnn-benchmark/blob/master/README.md
  IMS_PER_BATCH: 1
  Save the model interval
  CHECKPOINT_PERIOD: 18000
Output file path
OUTPUT_DIR: "./weight/"
Copy the code
  • If only detection tasks are performed, delete themmaskrcnn-benchmark/maskrcnn_benchmark/data/datasets/coco.pyLines 82 to 84 are more safe.
  • maskrcnn_benchmark/engine/trainer.pyIn line 90, you can set the log output interval (default 20, I feel output too frequently, see yourself).

4. Model training

  • Single GPU

According to the official website:

python /path_to_maskrcnn_benchmark/tools/train_net.py --config-file "/path/to/config/file.yaml"
Copy the code

However, this will use the first GPU by default. If you want to specify a GPU, you can use the following command:

# 3 is the ID of the GPU to use
CUDA_VISIBLE_DEVICES=3 python /path_to_maskrcnn_benchmark/tools/train_net.py --config-file "/path/to/config/file.yaml"
Copy the code

If memory overflow occurs, you need to adjust parameters. For details, see the official website: Troubleshooting Memory Overflow

  • Many GPU

According to the official website:

export NGPUS=8
python -m torch.distributed.launch --nproc_per_node=$NGPUS /path_to_maskrcnn_benchmark/tools/train_net.py --config-file "path/to/config/file.yaml" MODEL.RPN.FPN_POST_NMS_TOP_N_TRAIN images_per_gpu x 1000
Copy the code

But this defaults to using a random GPU. If you want to specify a GPU, you can use the following command:

# --nproc_per_node=4 --nproc_per_node=4CUDA_VISIBLE_DEVICES=0,1,2,3 python -m torch.distributed. Launch --nproc_per_node=4 /path_to_maskrcnn_benchmark/tools/train_net.py --config-file"path/to/config/file.yaml"
Copy the code

Unfortunately, the multi-GPU has not been running successfully on my server, please help to solve it!!

Multi-gpu training error


5. Model verification

  • Modify the config configuration fileWEIGHT: ".. /weight/model_final.pth"(Here should be the weight saved after training)
  • Run the command:
CUDA_VISIBLE_DEVICES=5 python tools/test_net.py --config-file "/path/to/config/file.yaml" TEST.IMS_PER_BATCH 8
Copy the code

Test. IMS_PER_BATCH 8 can also be directly configured in the config file:

TEST:
  IMS_PER_BATCH: 8
Copy the code

6. Model prediction

  • Modify the config configuration fileWEIGHT: ".. /weight/model_final.pth"(Here should be the weight saved after training)
  • Modify thedemo/predictor.pyIn CATEGORIES, replace the object category of your data (if you want to visualize the result, there is no change, you can refer to itdemo/Examples below) :
class COCODemo(object):
    # COCO categories for pretty print
    CATEGORIES = [
        "__background". ]Copy the code
  • Create a new filedemo/predict.py(Notes have been made where modifications are needed)
#! /usr/bin/env python
# coding=UTF-8
' '' @Description: @Author: HuangQinJian @LastEditors: HuangQinJian @Date: 2019-05-01 12:36:04 @LastEditTime: The 2019-05-03 17:29:23 '' '
import os

import matplotlib.pylab as pylab
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from PIL import Image

from maskrcnn_benchmark.config import cfg
from predictor import COCODemo
from tqdm import tqdm

# this makes our figures bigger
pylab.rcParams['figure.figsize'] = 20, 12

# Replace with your own configuration file
# Replace with your own configuration file
# Replace with your own configuration file
config_file = ".. /configs/e2e_faster_rcnn_R_50_FPN_1x.yaml"

# update the config options with the config file
cfg.merge_from_file(config_file)
# manual override some options
cfg.merge_from_list(["MODEL.DEVICE"."cuda"])


def load(img_path):
    pil_image = Image.open(img_path).convert("RGB")
    # convert to BGR format
    image = np.array(pil_image)[:, :, [2, 1, 0]]
    return image

# Adapt to your needs
# Adapt to your needs
# Adapt to your needsCoco_demo = COCODemo(CFG, min_image_size=1600, confidence_threshold=0.7,)# Test the path of the image
# Test the path of the image
# Test the path of the image
imgs_dir = '/data1/hqj/traffic-sign-identification/test'
img_names = os.listdir(imgs_dir)

submit_v4 = pd.DataFrame()
empty_v4 = pd.DataFrame()

filenameList = []

X1List = []
X2List = []
X3List = []
X4List = []

Y1List = []
Y2List = []
Y3List = []
Y4List = []

TypeList = []

empty_img_name = []

# for img_name in img_names:
for i, img_name in enumerate(tqdm(img_names)):
    path = os.path.join(imgs_dir, img_name)
    image = load(path)
    # compute predictions
    predictions = coco_demo.compute_prediction(image)
    try:
        scores = predictions.get_field("scores").numpy()
        bbox = predictions.bbox[np.argmax(scores)].numpy()
        labelList = predictions.get_field("labels").numpy()
        label = labelList[np.argmax(scores)]

        filenameList.append(img_name)
        X1List.append(round(bbox[0]))
        Y1List.append(round(bbox[1]))
        X2List.append(round(bbox[2]))
        Y2List.append(round(bbox[1]))
        X3List.append(round(bbox[2]))
        Y3List.append(round(bbox[3]))
        X4List.append(round(bbox[0]))
        Y4List.append(round(bbox[3]))
        TypeList.append(label)
        # print(filenameList, X1List, X2List, X3List, X4List, Y1List,
        # Y2List, Y3List, Y4List, TypeList)
        print(label)
    except:
        empty_img_name.append(img_name)
        print(empty_img_name)

submit_v4['filename'] = filenameList
submit_v4['X1'] = X1List
submit_v4['Y1'] = Y1List
submit_v4['X2'] = X2List
submit_v4['Y2'] = Y2List
submit_v4['X3'] = X3List
submit_v4['Y3'] = Y3List
submit_v4['X4'] = X4List
submit_v4['Y4'] = Y4List
submit_v4['type'] = TypeList

empty_v4['filename'] = empty_img_name

submit_v4.to_csv('submit_v4.csv', index=None)
empty_v4.to_csv('empty_v4.csv', index=None)
Copy the code
  • Run the command:
CUDA_VISIBLE_DEVICES=5  python demo/predict.py
Copy the code

Vii. Concluding remarks

  1. If you have modifiedmaskrcnn-benchmarkFolder code, be sure to recompile! Be sure to recompile! Be sure to recompile!

2. For more exciting content, welcome to myCSDN