├── .gitignore ├── MobileNetV1.py ├── README.md ├── __init__.py ├── config.py ├── data_loader ├── GETTING_STARTED.md ├── coviar_data_loader.c ├── install.sh └── setup.py ├── dataloader.py ├── datasets └── cityscapes │ └── list │ ├── cityscapes_train_list.txt │ └── cityscapes_val_list.txt ├── decode.py ├── demo_offline.py ├── demo_online.py ├── furnace ├── __init__.py ├── base_model │ ├── __init__.py │ ├── resnet.py │ └── xception.py ├── datasets │ ├── BaseDataset.py │ ├── __init__.py │ ├── ade │ │ ├── __init__.py │ │ ├── ade.py │ │ └── color150.mat │ ├── cityscapes │ │ ├── __init__.py │ │ └── cityscapes.py │ └── voc │ │ ├── __init__.py │ │ └── voc.py ├── engine │ ├── .ipynb_checkpoints │ │ └── engine-checkpoint.py │ ├── __init__.py │ ├── dist_test.py │ ├── engine.py │ ├── evaluator.py │ ├── logger.py │ ├── lr_policy.py │ └── version.py ├── legacy │ ├── __init__.py │ ├── eval_methods.py │ ├── parallel │ │ └── parallel_apply.py │ └── sync_bn │ │ ├── __init__.py │ │ ├── comm.py │ │ ├── functions.py │ │ ├── parallel.py │ │ ├── parallel_apply.py │ │ ├── src │ │ ├── __init__.py │ │ ├── cpu │ │ │ ├── __init__.py │ │ │ ├── operator.cpp │ │ │ ├── operator.h │ │ │ ├── setup.py │ │ │ └── syncbn_cpu.cpp │ │ └── gpu │ │ │ ├── __init__.py │ │ │ ├── common.h │ │ │ ├── device_tensor.h │ │ │ ├── operator.cpp │ │ │ ├── operator.h │ │ │ ├── setup.py │ │ │ └── syncbn_kernel.cu │ │ └── syncbn.py ├── seg_opr │ ├── __init__.py │ ├── loss_opr.py │ ├── metric.py │ ├── seg_oprs.py │ ├── sgd.py │ └── sigmoid_focal_loss │ │ ├── __init__.py │ │ ├── functions │ │ ├── __init__.py │ │ └── sigmoid_focal_loss.py │ │ ├── modules │ │ ├── __init__.py │ │ └── sigmoid_focal_loss.py │ │ ├── setup.py │ │ └── src │ │ ├── sigmoid_focal_loss.cpp │ │ └── sigmoid_focal_loss_cuda.cu ├── tools │ ├── __init__.py │ ├── benchmark │ │ ├── __init__.py │ │ ├── compute_flops.py │ │ ├── compute_madd.py │ │ ├── compute_memory.py │ │ ├── compute_speed.py │ │ ├── model_hook.py │ │ ├── reporter.py │ │ ├── stat_tree.py │ │ └── statistics.py │ └── gluon2pytorch.py └── utils │ ├── __init__.py │ ├── img_utils.py │ ├── init_func.py │ ├── pyt_utils.py │ └── visualize.py ├── image2video_12.py ├── infer_ffw_rgc_rgfs.py ├── infer_perframe.py ├── mobile_light_fpn.py ├── model ├── bisenet │ ├── cityscapes.bisenet.R101 │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ ├── cityscapes.bisenet.R18.speed │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ ├── cityscapes.bisenet.R18 │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ ├── cityscapes.bisenet.X39.speed │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ └── cityscapes.bisenet.X39 │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py ├── dfn │ ├── cityscapes.dfn.R101_v1c │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ └── voc.dfn.R101_v1c │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py ├── fcn │ └── voc.fcn32s.R101_v1c │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py ├── psanet │ ├── ade.psanet.R101_v1c │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py │ └── ade.psanet.R50_v1c │ │ ├── config.py │ │ ├── dataloader.py │ │ ├── eval.py │ │ ├── network.py │ │ └── train.py └── pspnet │ ├── ade.pspnet.R101_v1c │ ├── config.py │ ├── dataloader.py │ ├── eval.py │ ├── network.py │ └── train.py │ └── ade.pspnet.R50_v1c │ ├── config.py │ ├── dataloader.py │ ├── eval.py │ ├── network.py │ └── train.py ├── network.py ├── stuttgart_00.avi ├── train.py └── val_sequence ├── l └── lindau_000000_000019_leftImg8bit │ ├── mv_cont │ ├── frame0.png │ ├── frame1.png │ ├── frame10.png │ ├── frame11.png │ ├── frame2.png │ ├── frame3.png │ ├── frame4.png │ ├── frame5.png │ ├── frame6.png │ ├── frame7.png │ ├── frame8.png │ └── frame9.png │ └── res_cont │ ├── frame0.png │ ├── frame1.png │ ├── frame10.png │ ├── frame11.png │ ├── frame2.png │ ├── frame3.png │ ├── frame4.png │ ├── frame5.png │ ├── frame6.png │ ├── frame7.png │ ├── frame8.png │ └── frame9.png └── lindau ├── lindau_000000_000000_leftImg8bit.png ├── lindau_000000_000001_leftImg8bit.png ├── lindau_000000_000002_leftImg8bit.png ├── lindau_000000_000003_leftImg8bit.png ├── lindau_000000_000004_leftImg8bit.png ├── lindau_000000_000005_leftImg8bit.png ├── lindau_000000_000006_leftImg8bit.png ├── lindau_000000_000007_leftImg8bit.png ├── lindau_000000_000008_leftImg8bit.png ├── lindau_000000_000009_leftImg8bit.png ├── lindau_000000_000010_leftImg8bit.png ├── lindau_000000_000011_leftImg8bit.png ├── lindau_000000_000012_leftImg8bit.png ├── lindau_000000_000013_leftImg8bit.png ├── lindau_000000_000014_leftImg8bit.png ├── lindau_000000_000015_leftImg8bit.png ├── lindau_000000_000016_leftImg8bit.png ├── lindau_000000_000017_leftImg8bit.png ├── lindau_000000_000018_leftImg8bit.png ├── lindau_000000_000019_leftImg8bit.png ├── lindau_000000_000020_leftImg8bit.png ├── lindau_000000_000021_leftImg8bit.png ├── lindau_000000_000022_leftImg8bit.png ├── lindau_000000_000023_leftImg8bit.png ├── lindau_000000_000024_leftImg8bit.png ├── lindau_000000_000025_leftImg8bit.png ├── lindau_000000_000026_leftImg8bit.png ├── lindau_000000_000027_leftImg8bit.png ├── lindau_000000_000028_leftImg8bit.png └── lindau_000000_000029_leftImg8bit.png /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | datasets/cityscapes/input/ 3 | logs 4 | *__pycache__ 5 | pretrained/* 6 | visualize 7 | *.pth 8 | *.log 9 | mobilenet.py 10 | Test* 11 | val_12 12 | *.sh 13 | stuttgart_00 -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | from .furnace import * -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TapLab' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "datasets/cityscapes/input/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "../list/cityscapes_train_list.txt") 42 | C.eval_source = osp.join(C.dataset_path, "../list/cityscapes_val_list.txt") 43 | C.test_source = osp.join(C.dataset_path, "../list/cityscapes_val_list.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 19 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 1024 64 | C.image_height = 1024 65 | C.image_width = 1024 66 | C.num_train_imgs = 2975 67 | C.num_eval_imgs = 500 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "pretrained/resnet18_v1.pth" 76 | 77 | """Train Config""" 78 | C.lr = 1e-2 79 | C.lr_power = 0.9 80 | C.momentum = 0.9 81 | C.weight_decay = 5e-4 82 | C.batch_size = 5 # 5 * C.num_gpu 83 | C.nepochs = 100 * 5 # * 5(scales) 84 | C.niters_per_epoch = 3000 // C.batch_size # 2975 85 | C.num_workers = 8 86 | C.train_scale_array = [0.75, 1, 1.25, 1.5, 1.75, 2.0] 87 | 88 | #C.ngpus = 3 89 | 90 | """Eval Config""" 91 | C.eval_iter = 30 92 | C.eval_stride_rate = 5 / 6 93 | C.eval_scale_array = [1, ] # multi scales: 0.5, 0.75, 1, 1.25, 1.5, 1.75 94 | C.eval_flip = False # True if use the ms_flip strategy 95 | C.eval_base_size = 1024 96 | C.eval_crop_size = 1024 97 | 98 | """Display Config""" 99 | C.snapshot_iter = 50 100 | C.record_info_iter = 20 101 | C.display_iter = 50 102 | 103 | 104 | def open_tensorboard(): 105 | pass 106 | 107 | 108 | if __name__ == '__main__': 109 | print(config.epoch_num) 110 | parser = argparse.ArgumentParser() 111 | parser.add_argument( 112 | '-tb', '--tensorboard', default=False, action='store_true') 113 | args = parser.parse_args() 114 | 115 | if args.tensorboard: 116 | open_tensorboard() 117 | -------------------------------------------------------------------------------- /data_loader/GETTING_STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | This document briefly describes how to install and use the code. 3 | 4 | ## Environment 5 | We conducted experiments in the following environment: 6 | - Linux 7 | - Python 3.6 8 | - FFmpeg 9 | 10 | Similar environments (e.g. with OSX, Python 2) might work with small modification, but not tested. 11 | 12 | ## Data loader 13 | 14 | This data loader that directly takes a compressed video and returns compressed representation (I-frame, motion vectors, or residual) as a numpy array. 15 | 16 | #### Supported video format 17 | Currently we only support mpeg4 raw videos. Other codecs, e.g. H.264, coming soon. The mpeg4 raw videos can be obtained using FFmpeg: 18 | 19 | `ffmpeg -i input.mp4 -c:v -c:v mpeg4 -f rawvideo output.mp4` 20 | 21 | #### Install 22 | - Download FFmpeg (`git clone https://github.com/FFmpeg/FFmpeg.git`). 23 | - Go to FFmpeg home, and `git checkout 74c6a6d3735f79671b177a0e0c6f2db696c2a6d2`. 24 | - `make clean` 25 | - `./configure --prefix=${FFMPEG_INSTALL_PATH} --enable-pic --disable-yasm --enable-shared` 26 | - `make` 27 | - `make install` 28 | - If needed, add `${FFMPEG_INSTALL_PATH}/lib/` to `$LD_LIBRARY_PATH`. 29 | - Go to `data_loader` folder. 30 | - Modify `setup.py` to use your FFmpeg path (`${FFMPEG_INSTALL_PATH}`). 31 | - `./install.sh` 32 | 33 | #### Usage 34 | The data loader has two functions: `load` for loading a representation and `get_num_frames` for 35 | counting the number of frames in a video. 36 | 37 | The following call returns one frame (specified by `frame_index=0,1,...`) of one GOP 38 | (specified by `gop_index=0,1,...`). 39 | ```python 40 | from coviar import load 41 | load([input], [gop_index], [frame_index], [representation_type], [accumulate]) 42 | ``` 43 | - input: path to video (.mp4). 44 | - representation_type: `0`, `1`, or `2`. `0` for I-frames, `1` for motion vectors, `2` for residuals. 45 | - accumulate: `True` or `False`. `True` returns the accumulated representation. `False` returns the original compressed representations. (See paper for details. ) 46 | 47 | For example, 48 | ``` 49 | load(input.mp4, 3, 8, 1, True) 50 | ``` 51 | returns the accumulated motion vectors of the 9th frame of the 4th GOP. 52 | 53 | ## Citation 54 | 55 | ``` 56 | @misc{coviar-torch, 57 | author = {Wu, Chao-Yuan}, 58 | title = {pytorch-coviar}, 59 | howpublished = {\url{https://github.com/chaoyuaw/pytorch-coviar}}, 60 | year = {2018} 61 | } 62 | ``` -------------------------------------------------------------------------------- /data_loader/install.sh: -------------------------------------------------------------------------------- 1 | rm -rf build 2 | python setup.py build_ext 3 | python setup.py install --user 4 | -------------------------------------------------------------------------------- /data_loader/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | import numpy as np 3 | 4 | coviar_utils_module = Extension('coviar', 5 | sources = ['coviar_data_loader.c'], 6 | include_dirs=[np.get_include(), '${FFMPEG_INSTALL_PATH}/include/'], 7 | extra_compile_args=['-DNDEBUG', '-O3'], 8 | extra_link_args=['-lavutil', '-lavcodec', '-lavformat', '-lswscale', '-L${FFMPEG_INSTALL_PATH}/lib/'] 9 | ) 10 | 11 | setup ( name = 'coviar', 12 | version = '0.1', 13 | description = 'Utils for coviar training.', 14 | ext_modules = [ coviar_utils_module ] 15 | ) 16 | -------------------------------------------------------------------------------- /dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | 16 | def __call__(self, img, gt): 17 | img, gt = random_mirror(img, gt) 18 | if config.train_scale_array is not None: 19 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 20 | 21 | img = normalize(img, self.img_mean, self.img_std) 22 | 23 | crop_size = (config.image_height, config.image_width) 24 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 25 | 26 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 27 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 28 | 29 | p_img = p_img.transpose(2, 0, 1) 30 | 31 | extra_dict = None 32 | 33 | return p_img, p_gt, extra_dict 34 | 35 | 36 | def get_train_loader(engine, dataset, config=config): 37 | data_setting = {'img_root': config.img_root_folder, 38 | 'gt_root': config.gt_root_folder, 39 | 'train_source': config.train_source, 40 | 'eval_source': config.eval_source} 41 | train_preprocess = TrainPre(config.image_mean, config.image_std) 42 | 43 | train_dataset = dataset(data_setting, "train", train_preprocess, 44 | config.batch_size * config.niters_per_epoch) 45 | 46 | train_sampler = None 47 | is_shuffle = True 48 | batch_size = config.batch_size 49 | 50 | if engine and engine.distributed: 51 | train_sampler = torch.utils.data.distributed.DistributedSampler( 52 | train_dataset) 53 | batch_size = config.batch_size // engine.world_size 54 | is_shuffle = False 55 | 56 | train_loader = data.DataLoader(train_dataset, 57 | batch_size=batch_size, 58 | num_workers=config.num_workers, 59 | drop_last=True, 60 | shuffle=is_shuffle, 61 | pin_memory=True, 62 | sampler=train_sampler) 63 | 64 | return train_loader, train_sampler 65 | 66 | 67 | class EvalPre(object): 68 | def __init__(self, img_mean, img_std): 69 | self.img_mean = img_mean 70 | self.img_std = img_std 71 | 72 | def __call__(self, img, gt): 73 | img, gt = random_mirror(img, gt) 74 | 75 | img = normalize(img, self.img_mean, self.img_std) 76 | # h,w,c -> c,h,w 77 | img = img.transpose(2, 0, 1) 78 | 79 | extra_dict = None 80 | 81 | return img, gt, extra_dict 82 | 83 | 84 | def get_eval_loader(engine, dataset, batch_size=4): 85 | data_setting = {'img_root': config.img_root_folder, 86 | 'gt_root': config.gt_root_folder, 87 | 'train_source': config.train_source, 88 | 'eval_source': config.eval_source} 89 | # train_preprocess = TrainPre(config.image_mean, config.image_std) 90 | eval_preprocess = EvalPre(config.image_mean, config.image_std) 91 | 92 | eval_dataset = dataset(data_setting, "val", eval_preprocess) 93 | 94 | eval_sampler = None 95 | is_shuffle = False 96 | # batch_size = 4 97 | 98 | if engine and engine.distributed: 99 | eval_sampler = torch.utils.data.distributed.DistributedSampler( 100 | eval_dataset) 101 | batch_size = config.batch_size // engine.world_size 102 | is_shuffle = False 103 | 104 | eval_loader = data.DataLoader(eval_dataset, 105 | batch_size=batch_size, 106 | num_workers=config.num_workers, 107 | drop_last=True, 108 | shuffle=is_shuffle, 109 | pin_memory=True, 110 | sampler=eval_sampler) 111 | 112 | return eval_loader, eval_sampler -------------------------------------------------------------------------------- /decode.py: -------------------------------------------------------------------------------- 1 | # The script aims to obtain the compressed information 2 | # Visualization the motion vectors and residual graph 3 | 4 | import numpy as np 5 | import cv2 6 | import os, glob 7 | import time 8 | from skimage.io import imread, imsave 9 | 10 | from coviar import load 11 | from coviar import get_num_frames 12 | 13 | GOP_FRAMES_NUM = 12 14 | 15 | # The dir for RGB frames 16 | PATH_RGB_FRAMES = 'rgb_cont' 17 | 18 | # The dir for continuous MV 19 | PATH_MV_CONT = 'mv_cont/' 20 | # The dir for Residual map 21 | PATH_RES_CONT = 'res_cont/' 22 | 23 | 24 | video_names = glob.glob('./*.avi') 25 | video_names.sort() 26 | 27 | 28 | def main(): 29 | #for video_name in video_names[:2]: 30 | for video_name in video_names: 31 | fold_path = video_name.split('.avi')[0].split('/')[-1] 32 | path_img = os.path.join(fold_path, PATH_RGB_FRAMES) 33 | path_mv = os.path.join(fold_path, PATH_MV_CONT) 34 | path_res = os.path.join(fold_path, PATH_RES_CONT) 35 | if not os.path.exists(path_img): 36 | os.makedirs(path_img) 37 | if not os.path.exists(path_mv): 38 | os.makedirs(path_mv) 39 | if not os.path.exists(path_res): 40 | os.makedirs(path_res) 41 | NUM_FRAMES = get_num_frames(video_name) 42 | print(NUM_FRAMES) 43 | # The index of GOP 44 | curGopIdx = 0 45 | for curGopIdx in range(max(NUM_FRAMES // GOP_FRAMES_NUM, 1)): 46 | for innerGopIdx in range(GOP_FRAMES_NUM): 47 | curFrameIdx = curGopIdx * GOP_FRAMES_NUM + innerGopIdx 48 | print(video_name, curGopIdx, innerGopIdx) 49 | 50 | # start = time.time() 51 | rgbFrame = load(video_name, curGopIdx, innerGopIdx, 0, True) 52 | # print("rgb time: ", time.time()-start) 53 | cv2.imwrite(path_img+'/frame'+str(curFrameIdx)+'.png', rgbFrame) 54 | 55 | # start = time.time() 56 | mvCont_origin = load(video_name, curGopIdx, innerGopIdx, 1, False) 57 | # print("mv time: ", time.time()-start) 58 | 59 | # start = time.time() 60 | resCont = load(video_name, curGopIdx, innerGopIdx, 2, False) 61 | # print("res time: ", time.time()-start) 62 | 63 | if mvCont_origin is None: 64 | mvCont_origin = np.zeros([1024,2048,2], dtype=np.uint8) 65 | 66 | mvCont = mvCont_origin + 2048 67 | # (high_h, low_h, high_w, low_w) 68 | mvPng = np.array([((mvCont[:,:,0] >> 8) & 0xff) , (mvCont[:,:,0] & 0xff), ((mvCont[:,:,1] >> 8) & 0xff), (mvCont[:,:,1] & 0xff)], dtype = np.uint8) 69 | mvPng = np.transpose(mvPng, [1,2,0]) 70 | 71 | imsave(path_mv+'/frame'+str(curFrameIdx)+'.png', mvPng) 72 | 73 | if resCont is None: 74 | resCont = np.zeros([1024,2048,3], dtype=np.uint8) 75 | 76 | resCont = np.round((resCont + 256)/2).astype(np.uint8) 77 | imsave(path_res+'/frame'+str(curFrameIdx)+'.png', resCont) 78 | 79 | 80 | if __name__ == "__main__": 81 | main() -------------------------------------------------------------------------------- /furnace/__init__.py: -------------------------------------------------------------------------------- 1 | from .base_model import * 2 | from .datasets import * 3 | from .engine import * 4 | from .legacy import * 5 | from .seg_opr import * 6 | from .tools import * 7 | from .utils import * -------------------------------------------------------------------------------- /furnace/base_model/__init__.py: -------------------------------------------------------------------------------- 1 | from .resnet import ResNet, resnet18, resnet34, resnet50, resnet101, resnet152 2 | from .xception import Xception, xception39 3 | -------------------------------------------------------------------------------- /furnace/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .ade import ADE 2 | from .voc import VOC 3 | from .cityscapes import Cityscapes 4 | 5 | __all__ = ['ADE', 'VOC', 'Cityscapes'] -------------------------------------------------------------------------------- /furnace/datasets/ade/__init__.py: -------------------------------------------------------------------------------- 1 | from .ade import ADE 2 | 3 | __all__ = ['ADE'] -------------------------------------------------------------------------------- /furnace/datasets/ade/color150.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/datasets/ade/color150.mat -------------------------------------------------------------------------------- /furnace/datasets/cityscapes/__init__.py: -------------------------------------------------------------------------------- 1 | from .cityscapes import Cityscapes 2 | from .cityscapes import colors 3 | from .cityscapes import class_names 4 | 5 | __all__ = ['Cityscapes'] -------------------------------------------------------------------------------- /furnace/datasets/cityscapes/cityscapes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2017/12/16 下午8:41 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : cityscapes.py 7 | import numpy as np 8 | 9 | from datasets.BaseDataset import BaseDataset 10 | 11 | colors = [[128, 64, 128], [244, 35, 232], [70, 70, 70], 12 | [102, 102, 156], [190, 153, 153], [153, 153, 153], 13 | [250, 170, 30], [220, 220, 0], [107, 142, 35], 14 | [152, 251, 152], [70, 130, 180], [220, 20, 60], [255, 0, 0], 15 | [0, 0, 142], [0, 0, 70], [0, 60, 100], [0, 80, 100], 16 | [0, 0, 230], [119, 11, 32]] 17 | 18 | ids = [7, 8, 11, 12, 13, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 19 | 28, 31, 32, 33] 20 | 21 | class_names = ['road', 'sidewalk', 'building', 'wall', 'fence', 'pole', 22 | 'traffic light', 'traffic sign', 23 | 'vegetation', 'terrain', 'sky', 'person', 'rider', 'car', 24 | 'truck', 'bus', 'train', 'motorcycle', 'bicycle'] 25 | 26 | 27 | class Cityscapes(BaseDataset): 28 | trans_labels = [7, 8, 11, 12, 13, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29 | 28, 31, 32, 33] 30 | 31 | @classmethod 32 | def get_class_colors(*args): 33 | return [[128, 64, 128], [244, 35, 232], [70, 70, 70], 34 | [102, 102, 156], [190, 153, 153], [153, 153, 153], 35 | [250, 170, 30], [220, 220, 0], [107, 142, 35], 36 | [152, 251, 152], [70, 130, 180], [220, 20, 60], [255, 0, 0], 37 | [0, 0, 142], [0, 0, 70], [0, 60, 100], [0, 80, 100], 38 | [0, 0, 230], [119, 11, 32]] 39 | 40 | @classmethod 41 | def get_class_names(*args): 42 | # class counting(gtFine) 43 | # 2953 2811 2934 970 1296 2949 1658 2808 2891 1654 2686 2343 1023 2832 44 | # 359 274 142 513 1646 45 | return ['road', 'sidewalk', 'building', 'wall', 'fence', 'pole', 46 | 'traffic light', 'traffic sign', 47 | 'vegetation', 'terrain', 'sky', 'person', 'rider', 'car', 48 | 'truck', 'bus', 'train', 'motorcycle', 'bicycle'] 49 | 50 | @classmethod 51 | def transform_label(cls, pred, name): 52 | label = np.zeros(pred.shape) 53 | ids = np.unique(pred) 54 | for id in ids: 55 | label[np.where(pred == id)] = cls.trans_labels[id] 56 | 57 | new_name = (name.split('.')[0]).split('_')[:-1] 58 | new_name = '_'.join(new_name) + '.png' 59 | 60 | print('Trans', name, 'to', new_name, ' ', 61 | np.unique(np.array(pred, np.uint8)), ' ---------> ', 62 | np.unique(np.array(label, np.uint8))) 63 | return label, new_name -------------------------------------------------------------------------------- /furnace/datasets/voc/__init__.py: -------------------------------------------------------------------------------- 1 | from .voc import VOC 2 | 3 | __all__ = ['VOC'] -------------------------------------------------------------------------------- /furnace/datasets/voc/voc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2017/12/16 下午8:41 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : mclane.py 7 | 8 | from datasets.BaseDataset import BaseDataset 9 | 10 | 11 | class VOC(BaseDataset): 12 | @classmethod 13 | def get_class_colors(*args): 14 | return [[0, 0, 0], [0, 0, 128], [0, 128, 0], [0, 128, 128], 15 | [128, 0, 0], [128, 0, 128], [128, 128, 0], 16 | [128, 128, 128], 17 | [0, 0, 64], [0, 0, 192], [0, 128, 64], 18 | [0, 128, 192], 19 | [128, 0, 64], [128, 0, 192], [128, 128, 64], 20 | [128, 128, 192], [0, 64, 0], [0, 64, 128], 21 | [0, 192, 0], 22 | [0, 192, 128], [128, 64, 0], ] 23 | 24 | @classmethod 25 | def get_class_names(*args): 26 | return ['background', 'aeroplane', 'bicycle', 'bird', 27 | 'boat', 28 | 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 29 | 'diningtable', 30 | 'dog', 'horse', 'motorbike', 'person', 31 | 'pottedplant', 32 | 'sheep', 'sofa', 'train', 'tv/monitor'] 33 | 34 | 35 | if __name__ == "__main__": 36 | data_setting = {'img_root': '/unsullied/sharefs/g:research_detection/GeneralDetection/VOC/VOC/VOC2012_AUG/', 37 | 'gt_root': '/unsullied/sharefs/g:research_detection/GeneralDetection/VOC/VOC/VOC2012_AUG', 38 | 'train_source': '/unsullied/sharefs/g:research_detection/GeneralDetection/VOC/VOC/VOC2012_AUG/config/train.txt', 39 | 'eval_source': '/unsullied/sharefs/g:research_detection/GeneralDetection/VOC/VOC/VOC2012_AUG/config/val.txt'} 40 | voc = VOC(data_setting, 'train', None) 41 | print(voc.get_class_names()) 42 | print(voc.get_length()) 43 | print(next(iter(voc))) 44 | -------------------------------------------------------------------------------- /furnace/engine/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/engine/__init__.py -------------------------------------------------------------------------------- /furnace/engine/logger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/8/2 上午11:48 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : logger.py 7 | import os 8 | import sys 9 | import logging 10 | 11 | from utils import pyt_utils 12 | # from utils.pyt_utils import ensure_dir 13 | 14 | _default_level_name = os.getenv('ENGINE_LOGGING_LEVEL', 'INFO') 15 | _default_level = logging.getLevelName(_default_level_name.upper()) 16 | 17 | 18 | class LogFormatter(logging.Formatter): 19 | log_fout = None 20 | date_full = '[%(asctime)s %(lineno)d@%(filename)s:%(name)s] ' 21 | date = '%(asctime)s ' 22 | msg = '%(message)s' 23 | 24 | def format(self, record): 25 | if record.levelno == logging.DEBUG: 26 | mcl, mtxt = self._color_dbg, 'DBG' 27 | elif record.levelno == logging.WARNING: 28 | mcl, mtxt = self._color_warn, 'WRN' 29 | elif record.levelno == logging.ERROR: 30 | mcl, mtxt = self._color_err, 'ERR' 31 | else: 32 | mcl, mtxt = self._color_normal, '' 33 | 34 | if mtxt: 35 | mtxt += ' ' 36 | 37 | if self.log_fout: 38 | self.__set_fmt(self.date_full + mtxt + self.msg) 39 | formatted = super(LogFormatter, self).format(record) 40 | # self.log_fout.write(formatted) 41 | # self.log_fout.write('\n') 42 | # self.log_fout.flush() 43 | return formatted 44 | 45 | self.__set_fmt(self._color_date(self.date) + mcl(mtxt + self.msg)) 46 | formatted = super(LogFormatter, self).format(record) 47 | 48 | return formatted 49 | 50 | if sys.version_info.major < 3: 51 | def __set_fmt(self, fmt): 52 | self._fmt = fmt 53 | else: 54 | def __set_fmt(self, fmt): 55 | self._style._fmt = fmt 56 | 57 | @staticmethod 58 | def _color_dbg(msg): 59 | return '\x1b[36m{}\x1b[0m'.format(msg) 60 | 61 | @staticmethod 62 | def _color_warn(msg): 63 | return '\x1b[1;31m{}\x1b[0m'.format(msg) 64 | 65 | @staticmethod 66 | def _color_err(msg): 67 | return '\x1b[1;4;31m{}\x1b[0m'.format(msg) 68 | 69 | @staticmethod 70 | def _color_omitted(msg): 71 | return '\x1b[35m{}\x1b[0m'.format(msg) 72 | 73 | @staticmethod 74 | def _color_normal(msg): 75 | return msg 76 | 77 | @staticmethod 78 | def _color_date(msg): 79 | return '\x1b[32m{}\x1b[0m'.format(msg) 80 | 81 | 82 | def get_logger(log_dir=None, log_file=None, formatter=LogFormatter): 83 | logger = logging.getLogger() 84 | logger.setLevel(_default_level) 85 | del logger.handlers[:] 86 | 87 | if log_dir and log_file: 88 | pyt_utils.ensure_dir(log_dir) 89 | LogFormatter.log_fout = True 90 | file_handler = logging.FileHandler(log_file, mode='a') 91 | file_handler.setLevel(logging.INFO) 92 | file_handler.setFormatter(formatter) 93 | logger.addHandler(file_handler) 94 | 95 | stream_handler = logging.StreamHandler() 96 | stream_handler.setFormatter(formatter(datefmt='%d %H:%M:%S')) 97 | stream_handler.setLevel(0) 98 | logger.addHandler(stream_handler) 99 | return logger 100 | -------------------------------------------------------------------------------- /furnace/engine/lr_policy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/8/1 上午1:50 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : lr_policy.py.py 7 | 8 | from abc import ABCMeta, abstractmethod 9 | 10 | 11 | class BaseLR(): 12 | __metaclass__ = ABCMeta 13 | 14 | @abstractmethod 15 | def get_lr(self, cur_iter): pass 16 | 17 | 18 | class PolyLR(BaseLR): 19 | def __init__(self, start_lr, lr_power, total_iters): 20 | self.start_lr = start_lr 21 | self.lr_power = lr_power 22 | self.total_iters = total_iters + 0.0 23 | 24 | def get_lr(self, cur_iter): 25 | return self.start_lr * ( 26 | (1 - float(cur_iter) / self.total_iters) ** self.lr_power) 27 | 28 | 29 | class MultiStageLR(BaseLR): 30 | def __init__(self, lr_stages): 31 | assert type(lr_stages) in [list, tuple] and len(lr_stages[0]) == 2, \ 32 | 'lr_stages must be list or tuple, with [iters, lr] format' 33 | self._lr_stagess = lr_stages 34 | 35 | def get_lr(self, epoch): 36 | for it_lr in self._lr_stagess: 37 | if epoch < it_lr[0]: 38 | return it_lr[1] 39 | 40 | 41 | class LinearIncreaseLR(BaseLR): 42 | def __init__(self, start_lr, end_lr, warm_iters): 43 | self._start_lr = start_lr 44 | self._end_lr = end_lr 45 | self._warm_iters = warm_iters 46 | self._delta_lr = (end_lr - start_lr) / warm_iters 47 | 48 | def get_lr(self, cur_epoch): 49 | return self._start_lr + cur_epoch * self._delta_lr 50 | -------------------------------------------------------------------------------- /furnace/engine/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/8/3 下午2:59 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : version.py 7 | 8 | __version__ = '0.1.1' -------------------------------------------------------------------------------- /furnace/legacy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/legacy/__init__.py -------------------------------------------------------------------------------- /furnace/legacy/parallel/parallel_apply.py: -------------------------------------------------------------------------------- 1 | # import threading 2 | import torch 3 | import torch.multiprocessing as mp 4 | from torch.cuda._utils import _get_device_index 5 | 6 | 7 | def get_a_var(obj): 8 | if isinstance(obj, torch.Tensor): 9 | return obj 10 | 11 | if isinstance(obj, list) or isinstance(obj, tuple): 12 | for result in map(get_a_var, obj): 13 | if isinstance(result, torch.Tensor): 14 | return result 15 | if isinstance(obj, dict): 16 | for result in map(get_a_var, obj.items()): 17 | if isinstance(result, torch.Tensor): 18 | return result 19 | return None 20 | 21 | 22 | def parallel_apply(modules, inputs, kwargs_tup=None, devices=None): 23 | r"""Applies each `module` in :attr:`modules` in parallel on arguments 24 | contained in :attr:`inputs` (positional) and :attr:`kwargs_tup` (keyword) 25 | on each of :attr:`devices`. 26 | Args: 27 | modules (Module): modules to be parallelized 28 | inputs (tensor): inputs to the modules 29 | devices (list of int or torch.device): CUDA devices 30 | :attr:`modules`, :attr:`inputs`, :attr:`kwargs_tup` (if given), and 31 | :attr:`devices` (if given) should all have same length. Moreover, each 32 | element of :attr:`inputs` can either be a single object as the only argument 33 | to a module, or a collection of positional arguments. 34 | """ 35 | assert len(modules) == len(inputs) 36 | if kwargs_tup is not None: 37 | assert len(modules) == len(kwargs_tup) 38 | else: 39 | kwargs_tup = ({},) * len(modules) 40 | if devices is not None: 41 | assert len(modules) == len(devices) 42 | else: 43 | devices = [None] * len(modules) 44 | devices = list(map(lambda x: _get_device_index(x, True), devices)) 45 | context = mp.get_context('spawn') 46 | # lock = threading.Lock() 47 | # results = {} 48 | # results = [] 49 | results_queue = context.Queue(len(devices)) 50 | grad_enabled = torch.is_grad_enabled() 51 | 52 | def _worker(i, module, input, kwargs, device=None): 53 | torch.set_grad_enabled(grad_enabled) 54 | if device is None: 55 | device = get_a_var(input).get_device() 56 | try: 57 | with torch.cuda.device(device): 58 | # this also avoids accidental slicing of `input` if it is a Tensor 59 | if not isinstance(input, (list, tuple)): 60 | input = (input,) 61 | output = module(*input, **kwargs) 62 | results_queue.put(output) 63 | # with lock: 64 | # results[i] = output 65 | except Exception as e: 66 | results_queue.put(e) 67 | # with lock: 68 | # results[i] = e 69 | 70 | if len(modules) > 1: 71 | processes = [context.Process(target=_worker, 72 | args=(i, module, input, kwargs, device)) 73 | for i, (module, input, kwargs, device) in 74 | enumerate(zip(modules, inputs, kwargs_tup, devices))] 75 | 76 | for process in processes: 77 | process.start() 78 | for process in processes: 79 | process.join() 80 | else: 81 | _worker(0, modules[0], inputs[0], kwargs_tup[0], devices[0]) 82 | 83 | outputs = [] 84 | for i in range(len(inputs)): 85 | output = results_queue.get() 86 | if isinstance(output, Exception): 87 | raise output 88 | outputs.append(output) 89 | return outputs 90 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/10/3 下午2:10 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : __init__.py 7 | 8 | from .syncbn import * 9 | from .parallel import * -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/functions.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Hang Zhang 3 | ## Email: zhanghang0704@gmail.com 4 | ## Copyright (c) 2018 5 | ## 6 | ## This source code is licensed under the MIT-style license found in the 7 | ## LICENSE file in the root directory of this source tree 8 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 | 10 | """Synchronized Cross-GPU Batch Normalization functions""" 11 | import torch 12 | from torch.autograd import Variable, Function 13 | from .src import * 14 | 15 | __all__ = ['sum_square', 'batchnormtrain'] 16 | 17 | def sum_square(input): 18 | r"""Calculate sum of elements and sum of squares for Batch Normalization""" 19 | return _sum_square.apply(input) 20 | 21 | 22 | class _sum_square(Function): 23 | @staticmethod 24 | def forward(ctx, input): 25 | ctx.save_for_backward(input) 26 | if input.is_cuda: 27 | xsum, xsqusum = gpu.sumsquare_forward(input) 28 | else: 29 | xsum, xsqusum = cpu.sumsquare_forward(input) 30 | return xsum, xsqusum 31 | 32 | @staticmethod 33 | def backward(ctx, gradSum, gradSquare): 34 | input, = ctx.saved_variables 35 | if input.is_cuda: 36 | gradInput = gpu.sumsquare_backward(input, gradSum, gradSquare) 37 | else: 38 | raise NotImplemented 39 | return gradInput 40 | 41 | 42 | class _batchnormtrain(Function): 43 | @staticmethod 44 | def forward(ctx, input, mean, std, gamma, beta): 45 | ctx.save_for_backward(input, mean, std, gamma, beta) 46 | if input.is_cuda: 47 | output = gpu.batchnorm_forward(input, mean, std, gamma, beta) 48 | else: 49 | output = cpu.batchnorm_forward(input, mean, std, gamma, beta) 50 | return output 51 | 52 | @staticmethod 53 | def backward(ctx, gradOutput): 54 | input, mean, std, gamma, beta = ctx.saved_variables 55 | if gradOutput.is_cuda: 56 | gradInput, gradMean, gradStd, gradGamma, gradBeta = \ 57 | gpu.batchnorm_backward(gradOutput, input, mean, 58 | std, gamma, beta, True) 59 | else: 60 | raise NotImplemented 61 | return gradInput, gradMean, gradStd, gradGamma, gradBeta 62 | 63 | 64 | def batchnormtrain(input, mean, std, gamma, beta): 65 | r"""Applies Batch Normalization over a 3d input that is seen as a 66 | mini-batch. 67 | 68 | .. _encoding.batchnormtrain: 69 | 70 | .. math:: 71 | 72 | y = \frac{x - \mu[x]}{ \sqrt{var[x] + \epsilon}} * \gamma + \beta 73 | 74 | Shape: 75 | - Input: :math:`(N, C)` or :math:`(N, C, L)` 76 | - Output: :math:`(N, C)` or :math:`(N, C, L)` (same shape as input) 77 | 78 | """ 79 | return _batchnormtrain.apply(input, mean, std, gamma, beta) 80 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/parallel_apply.py: -------------------------------------------------------------------------------- 1 | # import threading 2 | import queue 3 | import torch 4 | import torch.multiprocessing as mp 5 | # from pathos.multiprocessing import ProcessPool as Pool 6 | from torch.cuda._utils import _get_device_index 7 | 8 | 9 | def get_a_var(obj): 10 | if isinstance(obj, torch.Tensor): 11 | return obj 12 | 13 | if isinstance(obj, list) or isinstance(obj, tuple): 14 | for result in map(get_a_var, obj): 15 | if isinstance(result, torch.Tensor): 16 | return result 17 | if isinstance(obj, dict): 18 | for result in map(get_a_var, obj.items()): 19 | if isinstance(result, torch.Tensor): 20 | return result 21 | return None 22 | 23 | 24 | def parallel_apply(modules, inputs, kwargs_tup=None, devices=None): 25 | r"""Applies each `module` in :attr:`modules` in parallel on arguments 26 | contained in :attr:`inputs` (positional) and :attr:`kwargs_tup` (keyword) 27 | on each of :attr:`devices`. 28 | Args: 29 | modules (Module): modules to be parallelized 30 | inputs (tensor): inputs to the modules 31 | devices (list of int or torch.device): CUDA devices 32 | :attr:`modules`, :attr:`inputs`, :attr:`kwargs_tup` (if given), and 33 | :attr:`devices` (if given) should all have same length. Moreover, each 34 | element of :attr:`inputs` can either be a single object as the only argument 35 | to a module, or a collection of positional arguments. 36 | """ 37 | assert len(modules) == len(inputs) 38 | if kwargs_tup is not None: 39 | assert len(modules) == len(kwargs_tup) 40 | else: 41 | kwargs_tup = ({},) * len(modules) 42 | if devices is not None: 43 | assert len(modules) == len(devices) 44 | else: 45 | devices = [None] * len(modules) 46 | devices = list(map(lambda x: _get_device_index(x, True), devices)) 47 | context = mp.get_context('spawn') 48 | # lock = threading.Lock() 49 | # results = {} 50 | # results = [] 51 | # pool = context.Pool(len(devices)) 52 | results_queue = queue.Queue(len(devices)) 53 | grad_enabled = torch.is_grad_enabled() 54 | 55 | def _worker(module, input, kwargs, device=None): 56 | torch.set_grad_enabled(grad_enabled) 57 | if device is None: 58 | device = get_a_var(input).get_device() 59 | try: 60 | with torch.cuda.device(device): 61 | # this also avoids accidental slicing of `input` if it is a Tensor 62 | if not isinstance(input, (list, tuple)): 63 | input = (input,) 64 | output = module(*input, **kwargs) 65 | results_queue.put(output) 66 | # with lock: 67 | # results[i] = output 68 | except Exception as e: 69 | results_queue.put(e) 70 | # with lock: 71 | # results[i] = e 72 | 73 | if len(modules) > 1: 74 | # pool.map(_worker, [modules, inputs, kwargs_tup, devices]) 75 | processes = [context.Process(target=_worker, 76 | args=(i, module, input, kwargs, device)) 77 | for i, (module, input, kwargs, device) in 78 | enumerate(zip(modules, inputs, kwargs_tup, devices))] 79 | 80 | for process in processes: 81 | process.start() 82 | for process in processes: 83 | process.join() 84 | else: 85 | _worker(0, modules[0], inputs[0], kwargs_tup[0], devices[0]) 86 | 87 | outputs = [] 88 | for i in range(len(inputs)): 89 | output = results_queue.get() 90 | if isinstance(output, Exception): 91 | raise output 92 | outputs.append(output) 93 | return outputs 94 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | from torch.utils.cpp_extension import load 4 | 5 | cwd = os.path.dirname(os.path.realpath(__file__)) 6 | cpu_path = os.path.join(cwd, 'cpu') 7 | gpu_path = os.path.join(cwd, 'gpu') 8 | 9 | cpu = load('syncbn_cpu', [ 10 | os.path.join(cpu_path, 'operator.cpp'), 11 | os.path.join(cpu_path, 'syncbn_cpu.cpp'), 12 | ], build_directory=cpu_path, verbose=False) 13 | 14 | if torch.cuda.is_available(): 15 | gpu = load('syncbn_gpu', [ 16 | os.path.join(gpu_path, 'operator.cpp'), 17 | os.path.join(gpu_path, 'syncbn_kernel.cu'), 18 | ], build_directory=gpu_path, verbose=False) 19 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/cpu/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/legacy/sync_bn/src/cpu/__init__.py -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/cpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("batchnorm_forward", &BatchNorm_Forward_CPU, "BatchNorm forward (CPU)"); 5 | m.def("batchnorm_backward", &BatchNorm_Backward_CPU, "BatchNorm backward (CPU)"); 6 | m.def("sumsquare_forward", &Sum_Square_Forward_CPU, "SumSqu forward (CPU)"); 7 | m.def("sumsquare_backward", &Sum_Square_Backward_CPU, "SumSqu backward (CPU)"); 8 | } 9 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/cpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | at::Tensor BatchNorm_Forward_CPU( 5 | const at::Tensor input_, 6 | const at::Tensor mean_, 7 | const at::Tensor std_, 8 | const at::Tensor gamma_, 9 | const at::Tensor beta_); 10 | 11 | std::vector BatchNorm_Backward_CPU( 12 | const at::Tensor gradoutput_, 13 | const at::Tensor input_, 14 | const at::Tensor mean_, 15 | const at::Tensor std_, 16 | const at::Tensor gamma_, 17 | const at::Tensor beta_, 18 | bool train); 19 | 20 | std::vector Sum_Square_Forward_CPU( 21 | const at::Tensor input_); 22 | 23 | at::Tensor Sum_Square_Backward_CPU( 24 | const at::Tensor input_, 25 | const at::Tensor gradSum_, 26 | const at::Tensor gradSquare_); -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/cpu/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from torch.utils.cpp_extension import BuildExtension, CppExtension 3 | 4 | setup( 5 | name='syncbn_cpu', 6 | ext_modules=[ 7 | CppExtension('syncbn_cpu', [ 8 | 'operator.cpp', 9 | 'syncbn_cpu.cpp', 10 | ]), 11 | ], 12 | cmdclass={ 13 | 'build_ext': BuildExtension 14 | }) 15 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/cpu/syncbn_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 6 | if (x.ndimension() == 2) { 7 | return v; 8 | } else { 9 | std::vector broadcast_size = {1, -1}; 10 | for (int64_t i = 2; i < x.ndimension(); ++i) 11 | broadcast_size.push_back(1); 12 | 13 | return v.view(broadcast_size); 14 | } 15 | } 16 | 17 | at::Tensor BatchNorm_Forward_CPU( 18 | const at::Tensor input, 19 | const at::Tensor mean, 20 | const at::Tensor std, 21 | const at::Tensor gamma, 22 | const at::Tensor beta) { 23 | auto output = (input - broadcast_to(mean, input)) / broadcast_to(std, input); 24 | output = output * broadcast_to(gamma, input) + broadcast_to(beta, input); 25 | return output; 26 | } 27 | 28 | // Not implementing CPU backward for now 29 | std::vector BatchNorm_Backward_CPU( 30 | const at::Tensor gradoutput, 31 | const at::Tensor input, 32 | const at::Tensor mean, 33 | const at::Tensor std, 34 | const at::Tensor gamma, 35 | const at::Tensor beta, 36 | bool train) { 37 | /* outputs*/ 38 | at::Tensor gradinput = at::zeros_like(input); 39 | at::Tensor gradgamma = at::zeros_like(gamma); 40 | at::Tensor gradbeta = at::zeros_like(beta); 41 | at::Tensor gradMean = at::zeros_like(mean); 42 | at::Tensor gradStd = at::zeros_like(std); 43 | return {gradinput, gradMean, gradStd, gradgamma, gradbeta}; 44 | } 45 | 46 | std::vector Sum_Square_Forward_CPU( 47 | const at::Tensor input) { 48 | /* outputs */ 49 | at::Tensor sum = torch::zeros({input.size(1)}, input.options()); 50 | at::Tensor square = torch::zeros({input.size(1)}, input.options()); 51 | return {sum, square}; 52 | } 53 | 54 | at::Tensor Sum_Square_Backward_CPU( 55 | const at::Tensor input, 56 | const at::Tensor gradSum, 57 | const at::Tensor gradSquare) { 58 | /* outputs */ 59 | at::Tensor gradInput = at::zeros_like(input); 60 | return gradInput; 61 | } 62 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/gpu/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/legacy/sync_bn/src/gpu/__init__.py -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/gpu/device_tensor.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct DeviceTensor { 5 | public: 6 | inline __device__ __host__ DeviceTensor(DType *p, const int *size) 7 | : dptr_(p) { 8 | for (int i = 0; i < Dim; ++i) { 9 | size_[i] = size ? size[i] : 0; 10 | } 11 | } 12 | 13 | inline __device__ __host__ unsigned getSize(const int i) const { 14 | assert(i < Dim); 15 | return size_[i]; 16 | } 17 | 18 | inline __device__ __host__ int numElements() const { 19 | int n = 1; 20 | for (int i = 0; i < Dim; ++i) { 21 | n *= size_[i]; 22 | } 23 | return n; 24 | } 25 | 26 | inline __device__ __host__ DeviceTensor select(const size_t x) const { 27 | assert(Dim > 1); 28 | int offset = x; 29 | for (int i = 1; i < Dim; ++i) { 30 | offset *= size_[i]; 31 | } 32 | DeviceTensor tensor(dptr_ + offset, nullptr); 33 | for (int i = 0; i < Dim - 1; ++i) { 34 | tensor.size_[i] = this->size_[i+1]; 35 | } 36 | return tensor; 37 | } 38 | 39 | inline __device__ __host__ DeviceTensor operator[](const size_t x) const { 40 | assert(Dim > 1); 41 | int offset = x; 42 | for (int i = 1; i < Dim; ++i) { 43 | offset *= size_[i]; 44 | } 45 | DeviceTensor tensor(dptr_ + offset, nullptr); 46 | for (int i = 0; i < Dim - 1; ++i) { 47 | tensor.size_[i] = this->size_[i+1]; 48 | } 49 | return tensor; 50 | } 51 | 52 | inline __device__ __host__ size_t InnerSize() const { 53 | assert(Dim >= 3); 54 | size_t sz = 1; 55 | for (size_t i = 2; i < Dim; ++i) { 56 | sz *= size_[i]; 57 | } 58 | return sz; 59 | } 60 | 61 | inline __device__ __host__ size_t ChannelCount() const { 62 | assert(Dim >= 3); 63 | return size_[1]; 64 | } 65 | 66 | inline __device__ __host__ DType* data_ptr() const { 67 | return dptr_; 68 | } 69 | 70 | DType *dptr_; 71 | int size_[Dim]; 72 | }; 73 | 74 | template 75 | struct DeviceTensor { 76 | inline __device__ __host__ DeviceTensor(DType *p, const int *size) 77 | : dptr_(p) { 78 | size_[0] = size ? size[0] : 0; 79 | } 80 | 81 | inline __device__ __host__ unsigned getSize(const int i) const { 82 | assert(i == 0); 83 | return size_[0]; 84 | } 85 | 86 | inline __device__ __host__ int numElements() const { 87 | return size_[0]; 88 | } 89 | 90 | inline __device__ __host__ DType &operator[](const size_t x) const { 91 | return *(dptr_ + x); 92 | } 93 | 94 | inline __device__ __host__ DType* data_ptr() const { 95 | return dptr_; 96 | } 97 | 98 | DType *dptr_; 99 | int size_[1]; 100 | }; 101 | 102 | template 103 | static DeviceTensor devicetensor(const at::Tensor &blob) { 104 | DType *data = blob.data(); 105 | DeviceTensor tensor(data, nullptr); 106 | for (int i = 0; i < Dim; ++i) { 107 | tensor.size_[i] = blob.size(i); 108 | } 109 | return tensor; 110 | } 111 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/gpu/operator.cpp: -------------------------------------------------------------------------------- 1 | #include "operator.h" 2 | 3 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 4 | m.def("batchnorm_forward", &BatchNorm_Forward_CUDA, "BatchNorm forward (CUDA)"); 5 | m.def("batchnorm_backward", &BatchNorm_Backward_CUDA, "BatchNorm backward (CUDA)"); 6 | m.def("sumsquare_forward", &Sum_Square_Forward_CUDA, "SumSqu forward (CUDA)"); 7 | m.def("sumsquare_backward", &Sum_Square_Backward_CUDA, "SumSqu backward (CUDA)"); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/gpu/operator.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | at::Tensor BatchNorm_Forward_CUDA( 6 | const at::Tensor input_, 7 | const at::Tensor mean_, 8 | const at::Tensor std_, 9 | const at::Tensor gamma_, 10 | const at::Tensor beta_); 11 | 12 | std::vector BatchNorm_Backward_CUDA( 13 | const at::Tensor gradoutput_, 14 | const at::Tensor input_, 15 | const at::Tensor mean_, 16 | const at::Tensor std_, 17 | const at::Tensor gamma_, 18 | const at::Tensor beta_, 19 | bool train); 20 | 21 | std::vector Sum_Square_Forward_CUDA( 22 | const at::Tensor input_); 23 | 24 | at::Tensor Sum_Square_Backward_CUDA( 25 | const at::Tensor input_, 26 | const at::Tensor gradSum_, 27 | const at::Tensor gradSquare_); 28 | -------------------------------------------------------------------------------- /furnace/legacy/sync_bn/src/gpu/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension 3 | 4 | setup( 5 | name='syncbn_gpu', 6 | ext_modules=[ 7 | CUDAExtension('syncbn_gpu', [ 8 | 'operator.cpp', 9 | 'syncbn_kernel.cu', 10 | ]), 11 | ], 12 | cmdclass={ 13 | 'build_ext': BuildExtension 14 | }) 15 | -------------------------------------------------------------------------------- /furnace/seg_opr/__init__.py: -------------------------------------------------------------------------------- 1 | from .seg_oprs import * 2 | -------------------------------------------------------------------------------- /furnace/seg_opr/loss_opr.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.ndimage as nd 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | 8 | from engine.logger import get_logger 9 | from seg_opr.seg_oprs import one_hot 10 | 11 | logger = get_logger() 12 | 13 | 14 | class SigmoidFocalLoss(nn.Module): 15 | def __init__(self, ignore_label, gamma=2.0, alpha=0.25, 16 | reduction='mean'): 17 | super(SigmoidFocalLoss, self).__init__() 18 | self.ignore_label = ignore_label 19 | self.gamma = gamma 20 | self.alpha = alpha 21 | self.reduction = reduction 22 | 23 | def forward(self, pred, target): 24 | b, h, w = target.size() 25 | pred = pred.view(b, -1, 1) 26 | pred_sigmoid = pred.sigmoid() 27 | target = target.view(b, -1).float() 28 | mask = (target.ne(self.ignore_label)).float() 29 | target = mask * target 30 | onehot = target.view(b, -1, 1) 31 | 32 | # TODO: use the pred instead of pred_sigmoid 33 | max_val = (-pred_sigmoid).clamp(min=0) 34 | 35 | pos_part = (1 - pred_sigmoid) ** self.gamma * ( 36 | pred_sigmoid - pred_sigmoid * onehot) 37 | neg_part = pred_sigmoid ** self.gamma * (max_val + ( 38 | (-max_val).exp() + (-pred_sigmoid - max_val).exp()).log()) 39 | 40 | loss = -(self.alpha * pos_part + (1 - self.alpha) * neg_part).sum( 41 | dim=-1) * mask 42 | if self.reduction == 'mean': 43 | loss = loss.mean() 44 | 45 | return loss 46 | 47 | 48 | class ProbOhemCrossEntropy2d(nn.Module): 49 | def __init__(self, ignore_label, reduction='mean', thresh=0.6, min_kept=256, 50 | down_ratio=1, use_weight=False): 51 | super(ProbOhemCrossEntropy2d, self).__init__() 52 | self.ignore_label = ignore_label 53 | self.thresh = float(thresh) 54 | self.min_kept = int(min_kept) 55 | self.down_ratio = down_ratio 56 | if use_weight: 57 | weight = torch.FloatTensor( 58 | [1.4297, 1.4805, 1.4363, 3.365, 2.6635, 1.4311, 2.1943, 1.4817, 59 | 1.4513, 2.1984, 1.5295, 1.6892, 3.2224, 1.4727, 7.5978, 9.4117, 60 | 15.2588, 5.6818, 2.2067]) 61 | self.criterion = torch.nn.CrossEntropyLoss(reduction=reduction, 62 | weight=weight, 63 | ignore_index=ignore_label) 64 | else: 65 | self.criterion = torch.nn.CrossEntropyLoss(reduction=reduction, 66 | ignore_index=ignore_label) 67 | 68 | def forward(self, pred, target): 69 | b, c, h, w = pred.size() 70 | target = target.view(-1) 71 | valid_mask = target.ne(self.ignore_label) 72 | target = target * valid_mask.long() 73 | num_valid = valid_mask.sum() 74 | 75 | prob = F.softmax(pred, dim=1) 76 | prob = (prob.transpose(0, 1)).reshape(c, -1) 77 | 78 | if self.min_kept > num_valid: 79 | logger.info('Labels: {}'.format(num_valid)) 80 | elif num_valid > 0: 81 | prob = prob.masked_fill_(~valid_mask, 1) 82 | mask_prob = prob[ 83 | target, torch.arange(len(target), dtype=torch.long)] 84 | threshold = self.thresh 85 | if self.min_kept > 0: 86 | _, index = torch.sort(mask_prob) 87 | threshold_index = index[min(len(index), self.min_kept) - 1] 88 | if mask_prob[threshold_index] > self.thresh: 89 | threshold = mask_prob[threshold_index] 90 | kept_mask = mask_prob.le(threshold) 91 | target = target * kept_mask.long() 92 | valid_mask = valid_mask * kept_mask 93 | # logger.info('Valid Mask: {}'.format(valid_mask.sum())) 94 | 95 | target = target.masked_fill_(~valid_mask, self.ignore_label) 96 | target = target.view(b, h, w) 97 | 98 | return self.criterion(pred, target) -------------------------------------------------------------------------------- /furnace/seg_opr/metric.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | import numpy as np 4 | 5 | np.seterr(divide='ignore', invalid='ignore') 6 | 7 | 8 | # voc cityscapes metric 9 | def hist_info(n_cl, pred, gt): 10 | assert (pred.shape == gt.shape) 11 | k = (gt >= 0) & (gt < n_cl) 12 | labeled = np.sum(k) 13 | correct = np.sum((pred[k] == gt[k])) 14 | 15 | return np.bincount(n_cl * gt[k].astype(int) + pred[k].astype(int), 16 | minlength=n_cl ** 2).reshape(n_cl, 17 | n_cl), labeled, correct 18 | 19 | 20 | def compute_score(hist, correct, labeled): 21 | iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist)) 22 | mean_IU = np.nanmean(iu) 23 | mean_IU_no_back = np.nanmean(iu[1:]) 24 | freq = hist.sum(1) / hist.sum() 25 | freq_IU = (iu[freq > 0] * freq[freq > 0]).sum() 26 | mean_pixel_acc = correct / labeled 27 | 28 | return iu, mean_IU, mean_IU_no_back, mean_pixel_acc 29 | 30 | 31 | # ade metric 32 | def meanIoU(area_intersection, area_union): 33 | iou = 1.0 * np.sum(area_intersection, axis=1) / np.sum(area_union, axis=1) 34 | meaniou = np.nanmean(iou) 35 | meaniou_no_back = np.nanmean(iou[1:]) 36 | 37 | return iou, meaniou, meaniou_no_back 38 | 39 | 40 | def intersectionAndUnion(imPred, imLab, numClass): 41 | # Remove classes from unlabeled pixels in gt image. 42 | # We should not penalize detections in unlabeled portions of the image. 43 | imPred = np.asarray(imPred).copy() 44 | imLab = np.asarray(imLab).copy() 45 | 46 | imPred += 1 47 | imLab += 1 48 | # Remove classes from unlabeled pixels in gt image. 49 | # We should not penalize detections in unlabeled portions of the image. 50 | imPred = imPred * (imLab > 0) 51 | 52 | # imPred = imPred * (imLab >= 0) 53 | 54 | # Compute area intersection: 55 | intersection = imPred * (imPred == imLab) 56 | (area_intersection, _) = np.histogram(intersection, bins=numClass, 57 | range=(1, numClass)) 58 | 59 | # Compute area union: 60 | (area_pred, _) = np.histogram(imPred, bins=numClass, range=(1, numClass)) 61 | (area_lab, _) = np.histogram(imLab, bins=numClass, range=(1, numClass)) 62 | area_union = area_pred + area_lab - area_intersection 63 | 64 | return area_intersection, area_union 65 | 66 | 67 | def mean_pixel_accuracy(pixel_correct, pixel_labeled): 68 | mean_pixel_accuracy = 1.0 * np.sum(pixel_correct) / ( 69 | np.spacing(1) + np.sum(pixel_labeled)) 70 | 71 | return mean_pixel_accuracy 72 | 73 | 74 | def pixelAccuracy(imPred, imLab): 75 | # Remove classes from unlabeled pixels in gt image. 76 | # We should not penalize detections in unlabeled portions of the image. 77 | pixel_labeled = np.sum(imLab >= 0) 78 | pixel_correct = np.sum((imPred == imLab) * (imLab >= 0)) 79 | pixel_accuracy = 1.0 * pixel_correct / pixel_labeled 80 | 81 | return pixel_accuracy, pixel_correct, pixel_labeled 82 | 83 | 84 | def accuracy(preds, label): 85 | valid = (label >= 0) 86 | acc_sum = (valid * (preds == label)).sum() 87 | valid_sum = valid.sum() 88 | acc = float(acc_sum) / (valid_sum + 1e-10) 89 | return acc, valid_sum 90 | -------------------------------------------------------------------------------- /furnace/seg_opr/sgd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/9/12 下午3:03 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : sgd.py 7 | 8 | import torch 9 | from torch.optim.sgd import SGD 10 | 11 | 12 | class StandardSGD(SGD): 13 | def step(self, closure=None): 14 | """Performs a single optimization step. 15 | Arguments: 16 | closure (callable, optional): A closure that reevaluates the model 17 | and returns the loss. 18 | """ 19 | loss = None 20 | if closure is not None: 21 | loss = closure() 22 | 23 | for group in self.param_groups: 24 | weight_decay = group['weight_decay'] 25 | momentum = group['momentum'] 26 | dampening = group['dampening'] 27 | nesterov = group['nesterov'] 28 | 29 | for p in group['params']: 30 | if p.grad is None: 31 | continue 32 | d_p = p.grad.data 33 | if weight_decay != 0: 34 | d_p.add_(weight_decay, p.data) 35 | d_p.mul_(group['lr']) 36 | if momentum != 0: 37 | param_state = self.state[p] 38 | if 'momentum_buffer' not in param_state: 39 | buf = param_state['momentum_buffer'] = torch.zeros_like( 40 | p.data) 41 | buf.mul_(momentum).add_(d_p) 42 | else: 43 | buf = param_state['momentum_buffer'] 44 | buf.mul_(momentum).add_(1 - dampening, d_p) 45 | if nesterov: 46 | d_p = d_p.add(momentum, buf) 47 | else: 48 | d_p = buf 49 | 50 | p.data.add_(-1, d_p) 51 | 52 | return loss -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/__init__.py: -------------------------------------------------------------------------------- 1 | from .modules.sigmoid_focal_loss import SigmoidFocalLoss, sigmoid_focal_loss 2 | 3 | __all__ = ['SigmoidFocalLoss', 'sigmoid_focal_loss'] 4 | -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/functions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/seg_opr/sigmoid_focal_loss/functions/__init__.py -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/functions/sigmoid_focal_loss.py: -------------------------------------------------------------------------------- 1 | import torch.nn.functional as F 2 | from torch.autograd import Function 3 | from torch.autograd.function import once_differentiable 4 | 5 | from .. import sigmoid_focal_loss_cuda 6 | 7 | 8 | class SigmoidFocalLossFunction(Function): 9 | 10 | @staticmethod 11 | def forward(ctx, input, target, gamma=2.0, alpha=0.25, reduction='mean'): 12 | ctx.save_for_backward(input, target) 13 | num_classes = input.shape[1] 14 | ctx.num_classes = num_classes 15 | ctx.gamma = gamma 16 | ctx.alpha = alpha 17 | 18 | loss = sigmoid_focal_loss_cuda.forward(input, target, num_classes, 19 | gamma, alpha) 20 | reduction_enum = F._Reduction.get_enum(reduction) 21 | # none: 0, mean:1, sum: 2 22 | if reduction_enum == 0: 23 | return loss 24 | elif reduction_enum == 1: 25 | return loss.mean() 26 | elif reduction_enum == 2: 27 | return loss.sum() 28 | 29 | @staticmethod 30 | @once_differentiable 31 | def backward(ctx, d_loss): 32 | input, target = ctx.saved_tensors 33 | num_classes = ctx.num_classes 34 | gamma = ctx.gamma 35 | alpha = ctx.alpha 36 | d_loss = d_loss.contiguous() 37 | d_input = sigmoid_focal_loss_cuda.backward(input, target, d_loss, 38 | num_classes, gamma, alpha) 39 | return d_input, None, None, None, None 40 | 41 | 42 | sigmoid_focal_loss = SigmoidFocalLossFunction.apply 43 | -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/furnace/seg_opr/sigmoid_focal_loss/modules/__init__.py -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/modules/sigmoid_focal_loss.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | 3 | from ..functions.sigmoid_focal_loss import sigmoid_focal_loss 4 | 5 | 6 | class SigmoidFocalLoss(nn.Module): 7 | 8 | def __init__(self, ignore_label, gamma, alpha): 9 | super(SigmoidFocalLoss, self).__init__() 10 | self.ignore_label = ignore_label 11 | self.gamma = gamma 12 | self.alpha = alpha 13 | 14 | def forward(self, logits, targets): 15 | assert logits.is_cuda 16 | b, h, w = targets.size() 17 | logits = logits.view(b, -1) 18 | targets = targets.view(b, -1) 19 | mask = (targets.ne(self.ignore_label)) 20 | targets = mask.long() * targets 21 | target_mask = (targets > 0) 22 | 23 | loss = sigmoid_focal_loss(logits, targets, self.gamma, self.alpha, 24 | 'none') 25 | loss = loss * mask.float() 26 | return loss.sum() / target_mask.sum() 27 | 28 | def __repr__(self): 29 | tmpstr = self.__class__.__name__ + "(" 30 | tmpstr += "gamma=" + str(self.gamma) 31 | tmpstr += ", alpha=" + str(self.alpha) 32 | tmpstr += ")" 33 | return tmpstr 34 | -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension 3 | 4 | setup( 5 | name='SigmoidFocalLoss', 6 | ext_modules=[ 7 | CUDAExtension('sigmoid_focal_loss_cuda', [ 8 | 'src/sigmoid_focal_loss.cpp', 9 | 'src/sigmoid_focal_loss_cuda.cu', 10 | ]), 11 | ], 12 | cmdclass={'build_ext': BuildExtension}) 13 | -------------------------------------------------------------------------------- /furnace/seg_opr/sigmoid_focal_loss/src/sigmoid_focal_loss.cpp: -------------------------------------------------------------------------------- 1 | // modify from 2 | // https://github.com/facebookresearch/maskrcnn-benchmark/blob/master/maskrcnn_benchmark/csrc/SigmoidFocalLoss.h 3 | #include 4 | 5 | at::Tensor SigmoidFocalLoss_forward_cuda(const at::Tensor &logits, 6 | const at::Tensor &targets, 7 | const int num_classes, 8 | const float gamma, const float alpha); 9 | 10 | at::Tensor SigmoidFocalLoss_backward_cuda(const at::Tensor &logits, 11 | const at::Tensor &targets, 12 | const at::Tensor &d_losses, 13 | const int num_classes, 14 | const float gamma, const float alpha); 15 | 16 | // Interface for Python 17 | at::Tensor SigmoidFocalLoss_forward(const at::Tensor &logits, 18 | const at::Tensor &targets, 19 | const int num_classes, const float gamma, 20 | const float alpha) { 21 | if (logits.type().is_cuda()) { 22 | return SigmoidFocalLoss_forward_cuda(logits, targets, num_classes, gamma, 23 | alpha); 24 | } 25 | } 26 | 27 | at::Tensor SigmoidFocalLoss_backward(const at::Tensor &logits, 28 | const at::Tensor &targets, 29 | const at::Tensor &d_losses, 30 | const int num_classes, const float gamma, 31 | const float alpha) { 32 | if (logits.type().is_cuda()) { 33 | return SigmoidFocalLoss_backward_cuda(logits, targets, d_losses, 34 | num_classes, gamma, alpha); 35 | } 36 | } 37 | 38 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 39 | m.def("forward", &SigmoidFocalLoss_forward, 40 | "SigmoidFocalLoss forward (CUDA)"); 41 | m.def("backward", &SigmoidFocalLoss_backward, 42 | "SigmoidFocalLoss backward (CUDA)"); 43 | } 44 | -------------------------------------------------------------------------------- /furnace/tools/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/8/20 下午12:53 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : __init__.py.py 7 | -------------------------------------------------------------------------------- /furnace/tools/benchmark/__init__.py: -------------------------------------------------------------------------------- 1 | from .compute_speed import compute_speed 2 | from .compute_memory import compute_memory 3 | from .compute_madd import compute_madd 4 | from .compute_flops import compute_flops 5 | from .stat_tree import StatTree, StatNode 6 | from .model_hook import ModelHook 7 | from .reporter import report_format 8 | from .statistics import stat, ModelStat 9 | 10 | __all__ = ['report_format', 'StatTree', 'StatNode', 'compute_speed', 11 | 'compute_madd', 'compute_flops', 'ModelHook', 'stat', 'ModelStat', 12 | '__main__', 13 | 'compute_memory'] -------------------------------------------------------------------------------- /furnace/tools/benchmark/compute_flops.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import numpy as np 4 | 5 | 6 | def compute_flops(module, inp, out): 7 | if isinstance(module, nn.Conv2d): 8 | return compute_Conv2d_flops(module, inp, out), 'Conv2d' 9 | elif isinstance(module, nn.BatchNorm2d): 10 | return compute_BatchNorm2d_flops(module, inp, out), 'BatchNorm2d' 11 | elif isinstance(module, ( 12 | nn.AvgPool2d, nn.MaxPool2d, nn.AdaptiveAvgPool2d, 13 | nn.AdaptiveMaxPool2d)): 14 | return compute_Pool2d_flops(module, inp, out), 'Pool2d' 15 | elif isinstance(module, 16 | (nn.ReLU, nn.ReLU6, nn.PReLU, nn.ELU, nn.LeakyReLU, 17 | nn.Sigmoid)): 18 | return compute_ReLU_flops(module, inp, out), 'Activation' 19 | elif isinstance(module, nn.Upsample): 20 | return compute_Upsample_flops(module, inp, out), 'Upsample' 21 | elif isinstance(module, nn.Linear): 22 | return compute_Linear_flops(module, inp, out), 'Linear' 23 | else: 24 | print("[Flops]: {} is not supported!".format(type(module).__name__)) 25 | return 0, -1 26 | pass 27 | 28 | 29 | def compute_Conv2d_flops(module, inp, out): 30 | # Can have multiple inputs, getting the first one 31 | assert isinstance(module, nn.Conv2d) 32 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 33 | 34 | batch_size = inp.size()[0] 35 | in_c = inp.size()[1] 36 | k_h, k_w = module.kernel_size 37 | out_c, out_h, out_w = out.size()[1:] 38 | groups = module.groups 39 | 40 | filters_per_channel = out_c // groups 41 | conv_per_position_flops = k_h * k_w * in_c * filters_per_channel 42 | active_elements_count = batch_size * out_h * out_w 43 | 44 | total_conv_flops = conv_per_position_flops * active_elements_count 45 | 46 | bias_flops = 0 47 | if module.bias is not None: 48 | bias_flops = out_c * active_elements_count 49 | 50 | total_flops = total_conv_flops + bias_flops 51 | return total_flops 52 | 53 | 54 | def compute_BatchNorm2d_flops(module, inp, out): 55 | assert isinstance(module, nn.BatchNorm2d) 56 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 57 | in_c, in_h, in_w = inp.size()[1:] 58 | batch_flops = np.prod(inp.shape) 59 | if module.affine: 60 | batch_flops *= 2 61 | return batch_flops 62 | 63 | 64 | def compute_ReLU_flops(module, inp, out): 65 | assert isinstance(module, 66 | (nn.ReLU, nn.ReLU6, nn.PReLU, nn.ELU, nn.LeakyReLU, 67 | nn.Sigmoid)) 68 | batch_size = inp.size()[0] 69 | active_elements_count = batch_size 70 | 71 | for s in inp.size()[1:]: 72 | active_elements_count *= s 73 | 74 | return active_elements_count 75 | 76 | 77 | def compute_Pool2d_flops(module, inp, out): 78 | assert isinstance(module, ( 79 | nn.MaxPool2d, nn.AvgPool2d, nn.AdaptiveAvgPool2d, nn.AdaptiveMaxPool2d)) 80 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 81 | return np.prod(inp.shape) 82 | 83 | 84 | def compute_Linear_flops(module, inp, out): 85 | assert isinstance(module, nn.Linear) 86 | assert len(inp.size()) == 2 and len(out.size()) == 2 87 | batch_size = inp.size()[0] 88 | return batch_size * inp.size()[1] * out.size()[1] 89 | 90 | 91 | def compute_Upsample_flops(module, inp, out): 92 | assert isinstance(module, nn.Upsample) 93 | output_size = out[0] 94 | batch_size = inp.size()[0] 95 | output_elements_count = batch_size 96 | for s in output_size.shape[1:]: 97 | output_elements_count *= s 98 | 99 | return output_elements_count 100 | -------------------------------------------------------------------------------- /furnace/tools/benchmark/compute_memory.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import numpy as np 4 | 5 | 6 | def compute_memory(module, inp, out): 7 | if isinstance(module, (nn.ReLU, nn.ReLU6, nn.ELU, nn.LeakyReLU)): 8 | return compute_ReLU_memory(module, inp, out) 9 | elif isinstance(module, nn.PReLU): 10 | return compute_PReLU_memory(module, inp, out) 11 | elif isinstance(module, nn.Conv2d): 12 | return compute_Conv2d_memory(module, inp, out) 13 | elif isinstance(module, nn.BatchNorm2d): 14 | return compute_BatchNorm2d_memory(module, inp, out) 15 | elif isinstance(module, nn.Linear): 16 | return compute_Linear_memory(module, inp, out) 17 | elif isinstance(module, ( 18 | nn.AvgPool2d, nn.MaxPool2d, nn.AdaptiveAvgPool2d, 19 | nn.AdaptiveMaxPool2d)): 20 | return compute_Pool2d_memory(module, inp, out) 21 | else: 22 | print("[Memory]: {} is not supported!".format(type(module).__name__)) 23 | return 0, 0 24 | pass 25 | 26 | 27 | def num_params(module): 28 | return sum(p.numel() for p in module.parameters() if p.requires_grad) 29 | 30 | 31 | def compute_ReLU_memory(module, inp, out): 32 | assert isinstance(module, (nn.ReLU, nn.ReLU6, nn.ELU, nn.LeakyReLU)) 33 | batch_size = inp.size()[0] 34 | mread = batch_size * inp.size()[1:].numel() 35 | mwrite = batch_size * inp.size()[1:].numel() 36 | 37 | return (mread, mwrite) 38 | 39 | 40 | def compute_PReLU_memory(module, inp, out): 41 | assert isinstance(module, (nn.PReLU)) 42 | batch_size = inp.size()[0] 43 | mread = batch_size * (inp.size()[1:].numel() + num_params(module)) 44 | mwrite = batch_size * inp.size()[1:].numel() 45 | 46 | return (mread, mwrite) 47 | 48 | 49 | def compute_Conv2d_memory(module, inp, out): 50 | # Can have multiple inputs, getting the first one 51 | assert isinstance(module, nn.Conv2d) 52 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 53 | 54 | batch_size = inp.size()[0] 55 | in_c = inp.size()[1] 56 | out_c, out_h, out_w = out.size()[1:] 57 | 58 | # This includes weighs with bias if the module contains it. 59 | mread = batch_size * (inp.size()[1:].numel() + num_params(module)) 60 | mwrite = batch_size * out_c * out_h * out_w 61 | return (mread, mwrite) 62 | 63 | 64 | def compute_BatchNorm2d_memory(module, inp, out): 65 | assert isinstance(module, nn.BatchNorm2d) 66 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 67 | batch_size, in_c, in_h, in_w = inp.size() 68 | 69 | mread = batch_size * (inp.size()[1:].numel() + 2 * in_c) 70 | mwrite = inp.size().numel() 71 | return (mread, mwrite) 72 | 73 | 74 | def compute_Linear_memory(module, inp, out): 75 | assert isinstance(module, nn.Linear) 76 | assert len(inp.size()) == 2 and len(out.size()) == 2 77 | batch_size = inp.size()[0] 78 | mread = batch_size * (inp.size()[1:].numel() + num_params(module)) 79 | mwrite = out.size().numel() 80 | 81 | return (mread, mwrite) 82 | 83 | 84 | def compute_Pool2d_memory(module, inp, out): 85 | assert isinstance(module, ( 86 | nn.MaxPool2d, nn.AvgPool2d, nn.AdaptiveAvgPool2d, nn.AdaptiveMaxPool2d)) 87 | assert len(inp.size()) == 4 and len(inp.size()) == len(out.size()) 88 | batch_size = inp.size()[0] 89 | mread = batch_size * inp.size()[1:].numel() 90 | mwrite = batch_size * out.size()[1:].numel() 91 | return (mread, mwrite) 92 | -------------------------------------------------------------------------------- /furnace/tools/benchmark/compute_speed.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding=utf8 3 | 4 | import time 5 | import cv2 6 | import numpy as np 7 | 8 | import torch 9 | import torch.nn.functional as F 10 | import torchprof 11 | 12 | from engine.logger import get_logger 13 | 14 | logger = get_logger() 15 | 16 | 17 | def compute_speed(model, input_size, device, iteration): 18 | torch.cuda.set_device(device) 19 | torch.backends.cudnn.benchmark = True 20 | 21 | model.eval() 22 | model = model.cuda() 23 | 24 | input = torch.randn(*input_size, device=device) 25 | 26 | torch.cuda.synchronize() 27 | for _ in range(50): 28 | model(input) 29 | torch.cuda.synchronize() 30 | 31 | logger.info('=========Speed Testing=========') 32 | time_spent = [] 33 | for _ in range(iteration): 34 | torch.cuda.synchronize() 35 | t_start = time.perf_counter() 36 | with torch.no_grad(): 37 | model(input) 38 | torch.cuda.synchronize() 39 | time_spent.append(time.perf_counter() - t_start) 40 | torch.cuda.synchronize() 41 | elapsed_time = np.sum(time_spent) 42 | with torchprof.Profile(model, use_cuda=True) as prof: 43 | model(input) 44 | print(prof.display(show_events=False)) 45 | logger.info( 46 | 'Elapsed time: [%.2f s / %d iter]' % (elapsed_time, iteration)) 47 | logger.info('Speed Time: %.2f ms / iter FPS: %.2f' % ( 48 | elapsed_time / iteration * 1000, iteration / elapsed_time)) -------------------------------------------------------------------------------- /furnace/tools/benchmark/reporter.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | pd.set_option('display.width', 1000) 4 | pd.set_option('display.max_rows', 10000) 5 | pd.set_option('display.max_columns', 10000) 6 | 7 | 8 | def round_value(value, binary=False): 9 | divisor = 1024. if binary else 1000. 10 | 11 | if value // divisor ** 4 > 0: 12 | return str(round(value / divisor ** 4, 2)) + 'T' 13 | elif value // divisor ** 3 > 0: 14 | return str(round(value / divisor ** 3, 2)) + 'G' 15 | elif value // divisor ** 2 > 0: 16 | return str(round(value / divisor ** 2, 2)) + 'M' 17 | elif value // divisor > 0: 18 | return str(round(value / divisor, 2)) + 'K' 19 | return str(value) 20 | 21 | 22 | def report_format(collected_nodes): 23 | data = list() 24 | for node in collected_nodes: 25 | name = node.name 26 | input_shape = ' '.join(['{:>3d}'] * len(node.input_shape)).format( 27 | *[e for e in node.input_shape]) 28 | output_shape = ' '.join(['{:>3d}'] * len(node.output_shape)).format( 29 | *[e for e in node.output_shape]) 30 | parameter_quantity = node.parameter_quantity 31 | inference_memory = node.inference_memory 32 | MAdd = node.MAdd 33 | Flops = node.Flops 34 | ConvFlops = node.ConvFlops 35 | mread, mwrite = [i for i in node.Memory] 36 | duration = node.duration 37 | data.append([name, input_shape, output_shape, parameter_quantity, 38 | inference_memory, MAdd, duration, Flops, ConvFlops, mread, 39 | mwrite]) 40 | df = pd.DataFrame(data) 41 | df.columns = ['module name', 'input shape', 'output shape', 42 | 'params', 'memory(MB)', 'MAdd', 'duration', 'Flops', 43 | 'ConvFlops', 'MemRead(B)', 'MemWrite(B)'] 44 | df['duration[%]'] = df['duration'] / (df['duration'].sum() + 1e-7) 45 | df['MemR+W(B)'] = df['MemRead(B)'] + df['MemWrite(B)'] 46 | total_parameters_quantity = df['params'].sum() 47 | total_memory = df['memory(MB)'].sum() 48 | total_operation_quantity = df['MAdd'].sum() 49 | total_flops = df['Flops'].sum() 50 | total_conv_flops = df['ConvFlops'].sum() 51 | total_duration = df['duration[%]'].sum() 52 | total_mread = df['MemRead(B)'].sum() 53 | total_mwrite = df['MemWrite(B)'].sum() 54 | total_memrw = df['MemR+W(B)'].sum() 55 | del df['duration'] 56 | 57 | # Add Total row 58 | total_df = pd.Series([total_parameters_quantity, total_memory, 59 | total_operation_quantity, total_flops, 60 | total_conv_flops, total_duration, 61 | mread, mwrite, total_memrw], 62 | index=['params', 'memory(MB)', 'MAdd', 'Flops', 63 | 'ConvFlops', 'duration[%]', 64 | 'MemRead(B)', 'MemWrite(B)', 'MemR+W(B)'], 65 | name='total') 66 | df = df.append(total_df) 67 | 68 | df = df.fillna(' ') 69 | # df['params'] = df['params'].apply( 70 | # lambda x: '{}'.format(x)) 71 | df['memory(MB)'] = df['memory(MB)'].apply( 72 | lambda x: '{:.2f}'.format(x)) 73 | df['duration[%]'] = df['duration[%]'].apply(lambda x: '{:.2%}'.format(x)) 74 | df['MAdd'] = df['MAdd'].apply(lambda x: '{:,}'.format(x)) 75 | df['Flops'] = df['Flops'].apply(lambda x: '{:,}'.format(x)) 76 | df['ConvFlops'] = df['ConvFlops'].apply(lambda x: '{:,}'.format(x)) 77 | 78 | summary = str(df) + '\n' 79 | summary += "=" * len(str(df).split('\n')[0]) 80 | summary += '\n' 81 | summary += "Total params: {}B\n".format( 82 | round_value(total_parameters_quantity)) 83 | 84 | summary += "-" * len(str(df).split('\n')[0]) 85 | summary += '\n' 86 | summary += "Total memory: {:.2f}MB\n".format(total_memory) 87 | summary += "Total MAdd: {}MAdd\n".format( 88 | round_value(total_operation_quantity)) 89 | summary += "Total Flops: {}Flops\n".format(round_value(total_flops)) 90 | summary += "Total Flops(Conv Only): {}Flops\n".format( 91 | round_value(total_conv_flops)) 92 | summary += "Total MemR+W: {}B\n".format(round_value(total_memrw, True)) 93 | return summary 94 | -------------------------------------------------------------------------------- /furnace/tools/benchmark/statistics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from collections import OrderedDict 4 | 5 | from .model_hook import ModelHook 6 | from .stat_tree import StatTree, StatNode 7 | from .reporter import report_format 8 | 9 | 10 | def get_parent_node(root_node, stat_node_name): 11 | assert isinstance(root_node, StatNode) 12 | 13 | node = root_node 14 | names = stat_node_name.split('.') 15 | for i in range(len(names) - 1): 16 | node_name = '.'.join(names[0:i+1]) 17 | child_index = node.find_child_index(node_name) 18 | assert child_index != -1 19 | node = node.children[child_index] 20 | return node 21 | 22 | 23 | def convert_leaf_modules_to_stat_tree(leaf_modules): 24 | assert isinstance(leaf_modules, OrderedDict) 25 | 26 | create_index = 1 27 | root_node = StatNode(name='root', parent=None) 28 | for leaf_module_name, leaf_module in leaf_modules.items(): 29 | names = leaf_module_name.split('.') 30 | for i in range(len(names)): 31 | create_index += 1 32 | stat_node_name = '.'.join(names[0:i+1]) 33 | parent_node = get_parent_node(root_node, stat_node_name) 34 | node = StatNode(name=stat_node_name, parent=parent_node) 35 | parent_node.add_child(node) 36 | if i == len(names) - 1: # leaf module itself 37 | input_shape = leaf_module.input_shape.numpy().tolist() 38 | output_shape = leaf_module.output_shape.numpy().tolist() 39 | node.input_shape = input_shape 40 | node.output_shape = output_shape 41 | node.parameter_quantity = leaf_module.parameter_quantity.numpy()[0] 42 | node.inference_memory = leaf_module.inference_memory.numpy()[0] 43 | node.MAdd = leaf_module.MAdd.numpy()[0] 44 | node.Flops = leaf_module.Flops.numpy()[0] 45 | node.ConvFlops = leaf_module.ConvFlops.numpy()[0] 46 | node.duration = leaf_module.duration.numpy()[0] 47 | node.Memory = leaf_module.Memory.numpy().tolist() 48 | return StatTree(root_node) 49 | 50 | 51 | class ModelStat(object): 52 | def __init__(self, model, input_size, query_granularity=1): 53 | assert isinstance(model, nn.Module) 54 | assert isinstance(input_size, (tuple, list)) and len(input_size) == 4 55 | self._model = model 56 | self._input_size = input_size 57 | self._query_granularity = query_granularity 58 | 59 | def _analyze_model(self): 60 | model_hook = ModelHook(self._model, self._input_size) 61 | leaf_modules = model_hook.retrieve_leaf_modules() 62 | stat_tree = convert_leaf_modules_to_stat_tree(leaf_modules) 63 | collected_nodes = stat_tree.get_collected_stat_nodes(self._query_granularity) 64 | return collected_nodes 65 | 66 | def show_report(self): 67 | collected_nodes = self._analyze_model() 68 | report = report_format(collected_nodes) 69 | print(report) 70 | 71 | 72 | def stat(model, input_size, query_granularity=1): 73 | ms = ModelStat(model, input_size, query_granularity) 74 | ms.show_report() 75 | -------------------------------------------------------------------------------- /furnace/tools/gluon2pytorch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/8/4 下午11:32 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : gluon2pytorch.py 7 | 8 | import os 9 | import mxnet as mx 10 | from gluoncv.model_zoo import get_model 11 | import torch 12 | 13 | import argparse 14 | 15 | parser = argparse.ArgumentParser() 16 | parser.add_argument('-m', '--model', type=str) 17 | parser.add_argument('-p', '--model_path', default='/unsullied/sharefs/yuchangqian/Storage/model_zoo', type=str) 18 | 19 | args = parser.parse_args() 20 | gluon_model_path = os.path.join(args.model_path, 'gluon_model') 21 | gluon_model_file = os.path.join(gluon_model_path, args.model+'.params') 22 | if not os.path.exists(gluon_model_file): 23 | gluon_model = get_model(args.model, pretrained=True, root=gluon_model_path) 24 | gluon_model_files = os.listdir(gluon_model_path) 25 | for file in gluon_model_files: 26 | if '-' in file: 27 | new_name = file.split('-')[0] + '.params' 28 | os.rename(os.path.join(gluon_model_path, file), os.path.join(gluon_model_path, new_name)) 29 | gluon_model_params = mx.nd.load(gluon_model_file) 30 | 31 | pytorch_model_params = {} 32 | 33 | print('Convert Gluon Model to PyTorch Model ...') 34 | for key, value in gluon_model_params.items(): 35 | if 'gamma' in key: 36 | key = key.replace('gamma', 'weight') 37 | elif 'beta' in key: 38 | key = key.replace('beta', 'bias') 39 | 40 | tensor = torch.from_numpy(value.asnumpy()) 41 | tensor.require_grad = True 42 | pytorch_model_params[key] = tensor 43 | 44 | pytorch_model_path = os.path.join(args.model_path, 'pytorch_model') 45 | torch.save(pytorch_model_params, os.path.join(pytorch_model_path, args.model+'.pth')) 46 | print('Finished!') 47 | -------------------------------------------------------------------------------- /furnace/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .img_utils import * 2 | from .init_func import * 3 | from .pyt_utils import * 4 | from .visualize import * -------------------------------------------------------------------------------- /furnace/utils/init_func.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | # @Time : 2018/9/28 下午12:13 4 | # @Author : yuchangqian 5 | # @Contact : changqian_yu@163.com 6 | # @File : init_func.py.py 7 | import torch 8 | import torch.nn as nn 9 | 10 | 11 | def __init_weight(feature, conv_init, norm_layer, bn_eps, bn_momentum, 12 | **kwargs): 13 | for name, m in feature.named_modules(): 14 | if isinstance(m, (nn.Conv2d, nn.Conv3d, nn.ConvTranspose2d)): 15 | conv_init(m.weight, **kwargs) 16 | elif isinstance(m, norm_layer): 17 | m.eps = bn_eps 18 | m.momentum = bn_momentum 19 | nn.init.constant_(m.weight, 1) 20 | nn.init.constant_(m.bias, 0) 21 | 22 | 23 | def init_weight(module_list, conv_init, norm_layer, bn_eps, bn_momentum, 24 | **kwargs): 25 | if isinstance(module_list, list): 26 | for feature in module_list: 27 | __init_weight(feature, conv_init, norm_layer, bn_eps, bn_momentum, 28 | **kwargs) 29 | else: 30 | __init_weight(module_list, conv_init, norm_layer, bn_eps, bn_momentum, 31 | **kwargs) 32 | 33 | 34 | def group_weight(weight_group, module, norm_layer, lr, no_decay_lr=None): 35 | group_decay = [] 36 | group_no_decay = [] 37 | for m in module.modules(): 38 | if isinstance(m, nn.Linear): 39 | group_decay.append(m.weight) 40 | if m.bias is not None: 41 | group_no_decay.append(m.bias) 42 | elif isinstance(m, (nn.Conv2d, nn.Conv3d, nn.ConvTranspose2d)): 43 | group_decay.append(m.weight) 44 | if m.bias is not None: 45 | group_no_decay.append(m.bias) 46 | elif isinstance(m, norm_layer) or isinstance(m, ( 47 | nn.GroupNorm, nn.InstanceNorm2d, nn.LayerNorm)): 48 | if m.weight is not None: 49 | group_no_decay.append(m.weight) 50 | if m.bias is not None: 51 | group_no_decay.append(m.bias) 52 | assert len(list(module.parameters())) == len(group_decay) + len( 53 | group_no_decay) 54 | weight_group.append(dict(params=group_decay, lr=lr)) 55 | lr = lr if no_decay_lr is None else no_decay_lr 56 | weight_group.append(dict(params=group_no_decay, weight_decay=.0, lr=lr)) 57 | return weight_group 58 | -------------------------------------------------------------------------------- /image2video_12.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import cv2 3 | import os 4 | import numpy as np 5 | from PIL import Image, ImageDraw,ImageFont 6 | 7 | # ---------------------------------- Test ----------------------------------------- 8 | 9 | # PATH_FOLDERS= ['aachen', 'bochum', 'bremen', 'cologne', 'darmstadt',\ 10 | # 'dusseldorf', 'erfurt', 'hamburg', 'hanover', 'jena', 'krefeld',\ 11 | # 'monchengladbach', 'strasbourg', 'stuttgart', 'tubingen', 'ulm', 'weimar', 'zurich'] 12 | 13 | # ---------------------------------- Val ------------------------------------------ 14 | PATH_FOLDERS= ['frankfurt', 'lindau', 'munster'] 15 | 16 | output_shape = (2048,1024) 17 | 18 | 19 | clip_size = 30 20 | #fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') 21 | fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X') 22 | 23 | 24 | for PATH_IMGS in PATH_FOLDERS: 25 | jpgNames = os.listdir(PATH_IMGS) 26 | 27 | i = 0 28 | while(i < len(jpgNames)): 29 | if(i % clip_size == 0): 30 | video_writer = cv2.VideoWriter(filename=jpgNames[i+19].split('.png')[0]+ '.avi', fourcc=fourcc, fps=17, frameSize=output_shape) 31 | # from 9 -> 20, 12 frames 32 | i += 8 33 | curImgName = jpgNames[i] 34 | curImgPath = os.path.join(PATH_IMGS, curImgName) 35 | 36 | img = cv2.imread(filename=curImgPath) 37 | img = cv2.resize(img, output_shape, interpolation = cv2.INTER_LINEAR) 38 | cv2.waitKey(100) 39 | video_writer.write(img) 40 | 41 | if(i % 30 == 20): 42 | print(curImgName + ' done!') 43 | video_writer.release() 44 | i += 9 45 | i += 1 46 | 47 | 48 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R101/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 42 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 43 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 19 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 1024 64 | C.image_height = 1024 65 | C.image_width = 1024 66 | C.num_train_imgs = 2975 67 | C.num_eval_imgs = 500 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet101_v1c.pth" 76 | 77 | """Train Config""" 78 | C.lr = 1e-2 79 | C.lr_power = 0.9 80 | C.momentum = 0.9 81 | C.weight_decay = 5e-4 82 | C.batch_size = 16 #4 * C.num_gpu 83 | C.nepochs = 80 84 | C.niters_per_epoch = 1000 85 | C.num_workers = 24 86 | C.train_scale_array = [0.75, 1, 1.25, 1.5, 1.75, 2.0] 87 | 88 | """Eval Config""" 89 | C.eval_iter = 30 90 | C.eval_stride_rate = 5 / 6 91 | C.eval_scale_array = [1, ] # multi scales: 0.5, 0.75, 1, 1.25, 1.5, 1.75 92 | C.eval_flip = False 93 | C.eval_base_size = 1024 94 | C.eval_crop_size = 1024 95 | 96 | """Display Config""" 97 | C.snapshot_iter = 50 98 | C.record_info_iter = 20 99 | C.display_iter = 50 100 | 101 | 102 | def open_tensorboard(): 103 | pass 104 | 105 | 106 | if __name__ == '__main__': 107 | print(config.epoch_num) 108 | parser = argparse.ArgumentParser() 109 | parser.add_argument( 110 | '-tb', '--tensorboard', default=False, action='store_true') 111 | args = parser.parse_args() 112 | 113 | if args.tensorboard: 114 | open_tensorboard() 115 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R101/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | 16 | def __call__(self, img, gt): 17 | img, gt = random_mirror(img, gt) 18 | if config.train_scale_array is not None: 19 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 20 | 21 | img = normalize(img, self.img_mean, self.img_std) 22 | 23 | crop_size = (config.image_height, config.image_width) 24 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 25 | 26 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 27 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 28 | 29 | p_img = p_img.transpose(2, 0, 1) 30 | 31 | extra_dict = None 32 | 33 | return p_img, p_gt, extra_dict 34 | 35 | 36 | def get_train_loader(engine, dataset): 37 | data_setting = {'img_root': config.img_root_folder, 38 | 'gt_root': config.gt_root_folder, 39 | 'train_source': config.train_source, 40 | 'eval_source': config.eval_source} 41 | train_preprocess = TrainPre(config.image_mean, config.image_std) 42 | 43 | train_dataset = dataset(data_setting, "train", train_preprocess, 44 | config.batch_size * config.niters_per_epoch) 45 | 46 | train_sampler = None 47 | is_shuffle = True 48 | batch_size = config.batch_size 49 | 50 | if engine.distributed: 51 | train_sampler = torch.utils.data.distributed.DistributedSampler( 52 | train_dataset) 53 | batch_size = config.batch_size // engine.world_size 54 | is_shuffle = False 55 | 56 | train_loader = data.DataLoader(train_dataset, 57 | batch_size=batch_size, 58 | num_workers=config.num_workers, 59 | drop_last=True, 60 | shuffle=is_shuffle, 61 | pin_memory=True, 62 | sampler=train_sampler) 63 | 64 | return train_loader, train_sampler 65 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R101/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.cityscapes import Cityscapes 18 | from network import BiSeNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | 29 | pred = self.sliding_eval(img, config.eval_crop_size, 30 | config.eval_stride_rate, device=device) 31 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 32 | pred, 33 | label) 34 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 35 | 'correct': correct_tmp} 36 | 37 | if self.save_path is not None: 38 | fn = name + '.png' 39 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 40 | logger.info('Save the image ' + fn) 41 | 42 | if self.show_image: 43 | colors = self.dataset.get_class_colors 44 | image = img 45 | clean = np.zeros(label.shape) 46 | comp_img = show_img(colors, config.background, image, clean, 47 | label, 48 | pred) 49 | cv2.imshow('comp_image', comp_img) 50 | cv2.waitKey(0) 51 | 52 | return results_dict 53 | 54 | def compute_metric(self, results): 55 | hist = np.zeros((config.num_classes, config.num_classes)) 56 | correct = 0 57 | labeled = 0 58 | count = 0 59 | for d in results: 60 | hist += d['hist'] 61 | correct += d['correct'] 62 | labeled += d['labeled'] 63 | count += 1 64 | 65 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 66 | labeled) 67 | result_line = print_iou(iu, mean_pixel_acc, 68 | dataset.get_class_names(), True) 69 | return result_line 70 | 71 | 72 | if __name__ == "__main__": 73 | parser = argparse.ArgumentParser() 74 | parser.add_argument('-e', '--epochs', default='last', type=str) 75 | parser.add_argument('-d', '--devices', default='1', type=str) 76 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 77 | parser.add_argument('--show_image', '-s', default=False, 78 | action='store_true') 79 | parser.add_argument('--save_path', '-p', default=None) 80 | 81 | args = parser.parse_args() 82 | all_dev = parse_devices(args.devices) 83 | 84 | network = BiSeNet(config.num_classes, is_training=False, 85 | criterion=None) 86 | data_setting = {'img_root': config.img_root_folder, 87 | 'gt_root': config.gt_root_folder, 88 | 'train_source': config.train_source, 89 | 'eval_source': config.eval_source} 90 | dataset = Cityscapes(data_setting, 'val', None) 91 | 92 | with torch.no_grad(): 93 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 94 | config.image_std, network, 95 | config.eval_scale_array, config.eval_flip, 96 | all_dev, args.verbose, args.save_path, 97 | args.show_image) 98 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 99 | config.link_val_log_file) 100 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R18.speed/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 42 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 43 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 19 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 1024 64 | C.image_height = 768 65 | C.image_width = 768 * 2 66 | C.gt_down_sampling = 8 67 | C.num_train_imgs = 2975 68 | C.num_eval_imgs = 500 69 | 70 | """ Settings for network, this would be different for each kind of model""" 71 | C.fix_bias = True 72 | C.fix_bn = False 73 | C.sync_bn = True 74 | C.bn_eps = 1e-5 75 | C.bn_momentum = 0.1 76 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet18_v1.pth" 77 | 78 | """Train Config""" 79 | C.lr = 1e-2 80 | C.lr_power = 0.9 81 | C.momentum = 0.9 82 | C.weight_decay = 5e-4 83 | C.batch_size = 16 #4 * C.num_gpu 84 | C.nepochs = 80 85 | C.niters_per_epoch = 1000 86 | C.num_workers = 24 87 | C.train_scale_array = [0.75, 1, 1.25, 1.5, 1.75, 2.0] 88 | 89 | """Eval Config""" 90 | C.eval_iter = 30 91 | C.eval_stride_rate = 2 / 3 92 | C.eval_scale_array = [1, ] 93 | C.eval_flip = False 94 | C.eval_height = 768 95 | C.eval_width = 768 * 2 96 | 97 | """Display Config""" 98 | C.snapshot_iter = 50 99 | C.record_info_iter = 20 100 | C.display_iter = 50 101 | 102 | 103 | def open_tensorboard(): 104 | pass 105 | 106 | 107 | if __name__ == '__main__': 108 | print(config.epoch_num) 109 | parser = argparse.ArgumentParser() 110 | parser.add_argument( 111 | '-tb', '--tensorboard', default=False, action='store_true') 112 | args = parser.parse_args() 113 | 114 | if args.tensorboard: 115 | open_tensorboard() 116 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R18.speed/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | 16 | def __call__(self, img, gt): 17 | img, gt = random_mirror(img, gt) 18 | if config.train_scale_array is not None: 19 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 20 | 21 | img = normalize(img, self.img_mean, self.img_std) 22 | 23 | crop_size = (config.image_height, config.image_width) 24 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 25 | 26 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 27 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 28 | p_gt = cv2.resize(p_gt, (config.image_width // config.gt_down_sampling, 29 | config.image_height // config.gt_down_sampling), 30 | interpolation=cv2.INTER_NEAREST) 31 | 32 | p_img = p_img.transpose(2, 0, 1) 33 | 34 | extra_dict = None 35 | 36 | return p_img, p_gt, extra_dict 37 | 38 | 39 | def get_train_loader(engine, dataset): 40 | data_setting = {'img_root': config.img_root_folder, 41 | 'gt_root': config.gt_root_folder, 42 | 'train_source': config.train_source, 43 | 'eval_source': config.eval_source} 44 | train_preprocess = TrainPre(config.image_mean, config.image_std) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.batch_size * config.niters_per_epoch) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=True, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R18/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 42 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 43 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 19 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 1024 64 | C.image_height = 1024 65 | C.image_width = 1024 66 | C.num_train_imgs = 2975 67 | C.num_eval_imgs = 500 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet18_v1.pth" 76 | 77 | """Train Config""" 78 | C.lr = 1e-2 79 | C.lr_power = 0.9 80 | C.momentum = 0.9 81 | C.weight_decay = 5e-4 82 | C.batch_size = 16 # 4 * C.num_gpu 83 | C.nepochs = 80 84 | C.niters_per_epoch = 1000 85 | C.num_workers = 24 86 | C.train_scale_array = [0.75, 1, 1.25, 1.5, 1.75, 2.0] 87 | 88 | """Eval Config""" 89 | C.eval_iter = 30 90 | C.eval_stride_rate = 5 / 6 91 | C.eval_scale_array = [1, ] # multi scales: 0.5, 0.75, 1, 1.25, 1.5, 1.75 92 | C.eval_flip = False # True if use the ms_flip strategy 93 | C.eval_base_size = 1024 94 | C.eval_crop_size = 1024 95 | 96 | """Display Config""" 97 | C.snapshot_iter = 50 98 | C.record_info_iter = 20 99 | C.display_iter = 50 100 | 101 | 102 | def open_tensorboard(): 103 | pass 104 | 105 | 106 | if __name__ == '__main__': 107 | print(config.epoch_num) 108 | parser = argparse.ArgumentParser() 109 | parser.add_argument( 110 | '-tb', '--tensorboard', default=False, action='store_true') 111 | args = parser.parse_args() 112 | 113 | if args.tensorboard: 114 | open_tensorboard() 115 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R18/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | 16 | def __call__(self, img, gt): 17 | img, gt = random_mirror(img, gt) 18 | if config.train_scale_array is not None: 19 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 20 | 21 | img = normalize(img, self.img_mean, self.img_std) 22 | 23 | crop_size = (config.image_height, config.image_width) 24 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 25 | 26 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 27 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 28 | 29 | p_img = p_img.transpose(2, 0, 1) 30 | 31 | extra_dict = None 32 | 33 | return p_img, p_gt, extra_dict 34 | 35 | 36 | def get_train_loader(engine, dataset): 37 | data_setting = {'img_root': config.img_root_folder, 38 | 'gt_root': config.gt_root_folder, 39 | 'train_source': config.train_source, 40 | 'eval_source': config.eval_source} 41 | train_preprocess = TrainPre(config.image_mean, config.image_std) 42 | 43 | train_dataset = dataset(data_setting, "train", train_preprocess, 44 | config.batch_size * config.niters_per_epoch) 45 | 46 | train_sampler = None 47 | is_shuffle = True 48 | batch_size = config.batch_size 49 | 50 | if engine.distributed: 51 | train_sampler = torch.utils.data.distributed.DistributedSampler( 52 | train_dataset) 53 | batch_size = config.batch_size // engine.world_size 54 | is_shuffle = False 55 | 56 | train_loader = data.DataLoader(train_dataset, 57 | batch_size=batch_size, 58 | num_workers=config.num_workers, 59 | drop_last=True, 60 | shuffle=is_shuffle, 61 | pin_memory=True, 62 | sampler=train_sampler) 63 | 64 | return train_loader, train_sampler 65 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.R18/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.cityscapes import Cityscapes 18 | from network import BiSeNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | 29 | pred = self.sliding_eval(img, config.eval_crop_size, 30 | config.eval_stride_rate, device=device) 31 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 32 | pred, 33 | label) 34 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 35 | 'correct': correct_tmp} 36 | 37 | if self.save_path is not None: 38 | fn = name + '.png' 39 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 40 | logger.info('Save the image ' + fn) 41 | 42 | if self.show_image: 43 | colors = self.dataset.get_class_colors 44 | image = img 45 | clean = np.zeros(label.shape) 46 | comp_img = show_img(colors, config.background, image, clean, 47 | label, 48 | pred) 49 | cv2.imshow('comp_image', comp_img) 50 | cv2.waitKey(0) 51 | 52 | return results_dict 53 | 54 | def compute_metric(self, results): 55 | hist = np.zeros((config.num_classes, config.num_classes)) 56 | correct = 0 57 | labeled = 0 58 | count = 0 59 | for d in results: 60 | hist += d['hist'] 61 | correct += d['correct'] 62 | labeled += d['labeled'] 63 | count += 1 64 | 65 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 66 | labeled) 67 | result_line = print_iou(iu, mean_pixel_acc, 68 | dataset.get_class_names(), True) 69 | return result_line 70 | 71 | 72 | if __name__ == "__main__": 73 | parser = argparse.ArgumentParser() 74 | parser.add_argument('-e', '--epochs', default='last', type=str) 75 | parser.add_argument('-d', '--devices', default='1', type=str) 76 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 77 | parser.add_argument('--show_image', '-s', default=False, 78 | action='store_true') 79 | parser.add_argument('--save_path', '-p', default=None) 80 | 81 | args = parser.parse_args() 82 | all_dev = parse_devices(args.devices) 83 | 84 | network = BiSeNet(config.num_classes, is_training=False, 85 | criterion=None) 86 | data_setting = {'img_root': config.img_root_folder, 87 | 'gt_root': config.gt_root_folder, 88 | 'train_source': config.train_source, 89 | 'eval_source': config.eval_source} 90 | dataset = Cityscapes(data_setting, 'val', None) 91 | 92 | with torch.no_grad(): 93 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 94 | config.image_std, network, 95 | config.eval_scale_array, config.eval_flip, 96 | all_dev, args.verbose, args.save_path, 97 | args.show_image) 98 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 99 | config.link_val_log_file) 100 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.X39.speed/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 42 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 43 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | add_path(osp.join(C.root_dir, 'furnace')) 54 | 55 | """Image Config""" 56 | C.num_classes = 19 57 | C.background = -1 58 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 59 | C.image_std = np.array([0.229, 0.224, 0.225]) 60 | C.target_size = 1024 61 | C.base_size = 832 62 | C.image_height = 768 63 | C.image_width = 1536 64 | C.gt_down_sampling = 8 65 | C.num_train_imgs = 2975 66 | C.num_eval_imgs = 500 67 | 68 | """ Settings for network, this would be different for each kind of model""" 69 | C.fix_bias = True 70 | C.fix_bn = False 71 | C.sync_bn = True 72 | C.bn_eps = 1e-5 73 | C.bn_momentum = 0.1 74 | C.pretrained_model = None 75 | 76 | """Train Config""" 77 | C.lr = 1e-2 78 | C.lr_power = 0.9 79 | C.momentum = 0.9 80 | C.weight_decay = 5e-4 81 | C.batch_size = 16 #4 * C.num_gpu 82 | C.nepochs = 140 83 | C.niters_per_epoch = 1000 84 | C.num_workers = 24 85 | C.train_scale_array = [0.5, 0.75, 1, 1.25, 1.5, 1.75] 86 | 87 | """Eval Config""" 88 | C.eval_iter = 30 89 | C.eval_stride_rate = 2 / 3 90 | C.eval_scale_array = [1, ] 91 | C.eval_flip = False 92 | C.eval_height = 768 93 | C.eval_width = 1536 94 | 95 | """Display Config""" 96 | C.snapshot_iter = 50 97 | C.record_info_iter = 20 98 | C.display_iter = 50 99 | 100 | 101 | def open_tensorboard(): 102 | pass 103 | 104 | 105 | if __name__ == '__main__': 106 | print(config.epoch_num) 107 | parser = argparse.ArgumentParser() 108 | parser.add_argument( 109 | '-tb', '--tensorboard', default=False, action='store_true') 110 | args = parser.parse_args() 111 | 112 | if args.tensorboard: 113 | open_tensorboard() 114 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.X39.speed/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import random 4 | import numpy as np 5 | from torch.utils import data 6 | 7 | from config import config 8 | from utils.img_utils import random_scale, random_mirror, normalize, \ 9 | generate_random_crop_pos, random_crop_pad_to_shape 10 | 11 | 12 | class TrainPre(object): 13 | def __init__(self, img_mean, img_std): 14 | self.img_mean = img_mean 15 | self.img_std = img_std 16 | 17 | def __call__(self, img, gt): 18 | img, gt = random_mirror(img, gt) 19 | if config.train_scale_array is not None: 20 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 21 | 22 | img = normalize(img, self.img_mean, self.img_std) 23 | 24 | crop_size = (config.image_height, config.image_width) 25 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 26 | 27 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 28 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 29 | p_gt = cv2.resize(p_gt, (config.image_width // config.gt_down_sampling, 30 | config.image_height // config.gt_down_sampling), 31 | interpolation=cv2.INTER_NEAREST) 32 | 33 | p_img = p_img.transpose(2, 0, 1) 34 | 35 | extra_dict = None 36 | 37 | return p_img, p_gt, extra_dict 38 | 39 | 40 | def get_train_loader(engine, dataset): 41 | data_setting = {'img_root': config.img_root_folder, 42 | 'gt_root': config.gt_root_folder, 43 | 'train_source': config.train_source, 44 | 'eval_source': config.eval_source} 45 | train_preprocess = TrainPre(config.image_mean, config.image_std) 46 | 47 | train_dataset = dataset(data_setting, "train", train_preprocess, 48 | config.batch_size * config.niters_per_epoch) 49 | 50 | train_sampler = None 51 | is_shuffle = True 52 | batch_size = config.batch_size 53 | 54 | if engine.distributed: 55 | train_sampler = torch.utils.data.distributed.DistributedSampler( 56 | train_dataset) 57 | batch_size = config.batch_size // engine.world_size 58 | is_shuffle = False 59 | 60 | train_loader = data.DataLoader(train_dataset, 61 | batch_size=batch_size, 62 | num_workers=config.num_workers, 63 | drop_last=True, 64 | shuffle=is_shuffle, 65 | pin_memory=True, 66 | sampler=train_sampler) 67 | 68 | return train_loader, train_sampler 69 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.X39/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 39 | C.img_root_folder = C.dataset_path 40 | C.gt_root_folder = C.dataset_path 41 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 42 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 43 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 19 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 1024 64 | C.image_height = 1024 65 | C.image_width = 1024 66 | C.num_train_imgs = 2975 67 | C.num_eval_imgs = 500 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = None 76 | 77 | """Train Config""" 78 | C.lr = 1e-2 79 | C.lr_power = 0.9 80 | C.momentum = 0.9 81 | C.weight_decay = 5e-4 82 | C.batch_size = 16 #4 * C.num_gpu 83 | C.nepochs = 140 84 | C.niters_per_epoch = 1000 85 | C.num_workers = 24 86 | C.train_scale_array = [0.75, 1, 1.25, 1.5, 1.75, 2.0] 87 | 88 | """Eval Config""" 89 | C.eval_iter = 30 90 | C.eval_stride_rate = 5 / 6 91 | C.eval_scale_array = [1, ] # multi scales: 0.5, 0.75, 1, 1.25, 1.5, 1.75 92 | C.eval_flip = False # True if use multi-flip strategy 93 | C.eval_base_size = 1024 94 | C.eval_crop_size = 1024 95 | 96 | """Display Config""" 97 | C.snapshot_iter = 50 98 | C.record_info_iter = 20 99 | C.display_iter = 50 100 | 101 | 102 | def open_tensorboard(): 103 | pass 104 | 105 | 106 | if __name__ == '__main__': 107 | print(config.epoch_num) 108 | parser = argparse.ArgumentParser() 109 | parser.add_argument( 110 | '-tb', '--tensorboard', default=False, action='store_true') 111 | args = parser.parse_args() 112 | 113 | if args.tensorboard: 114 | open_tensorboard() 115 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.X39/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | 16 | def __call__(self, img, gt): 17 | img, gt = random_mirror(img, gt) 18 | if config.train_scale_array is not None: 19 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 20 | 21 | img = normalize(img, self.img_mean, self.img_std) 22 | 23 | crop_size = (config.image_height, config.image_width) 24 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 25 | 26 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 27 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 28 | 29 | p_img = p_img.transpose(2, 0, 1) 30 | 31 | extra_dict = None 32 | 33 | return p_img, p_gt, extra_dict 34 | 35 | 36 | def get_train_loader(engine, dataset): 37 | data_setting = {'img_root': config.img_root_folder, 38 | 'gt_root': config.gt_root_folder, 39 | 'train_source': config.train_source, 40 | 'eval_source': config.eval_source} 41 | train_preprocess = TrainPre(config.image_mean, config.image_std) 42 | 43 | train_dataset = dataset(data_setting, "train", train_preprocess, 44 | config.batch_size * config.niters_per_epoch) 45 | 46 | train_sampler = None 47 | is_shuffle = True 48 | batch_size = config.batch_size 49 | 50 | if engine.distributed: 51 | train_sampler = torch.utils.data.distributed.DistributedSampler( 52 | train_dataset) 53 | batch_size = config.batch_size // engine.world_size 54 | is_shuffle = False 55 | 56 | train_loader = data.DataLoader(train_dataset, 57 | batch_size=batch_size, 58 | num_workers=config.num_workers, 59 | drop_last=True, 60 | shuffle=is_shuffle, 61 | pin_memory=True, 62 | sampler=train_sampler) 63 | 64 | return train_loader, train_sampler 65 | -------------------------------------------------------------------------------- /model/bisenet/cityscapes.bisenet.X39/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.cityscapes import Cityscapes 18 | from network import BiSeNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | 29 | pred = self.sliding_eval(img, config.eval_crop_size, 30 | config.eval_stride_rate, device=device) 31 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 32 | pred, 33 | label) 34 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 35 | 'correct': correct_tmp} 36 | 37 | if self.save_path is not None: 38 | fn = name + '.png' 39 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 40 | logger.info('Save the image ' + fn) 41 | 42 | if self.show_image: 43 | colors = self.dataset.get_class_colors 44 | image = img 45 | clean = np.zeros(label.shape) 46 | comp_img = show_img(colors, config.background, image, clean, 47 | label, 48 | pred) 49 | cv2.imshow('comp_image', comp_img) 50 | cv2.waitKey(0) 51 | 52 | return results_dict 53 | 54 | def compute_metric(self, results): 55 | hist = np.zeros((config.num_classes, config.num_classes)) 56 | correct = 0 57 | labeled = 0 58 | count = 0 59 | for d in results: 60 | hist += d['hist'] 61 | correct += d['correct'] 62 | labeled += d['labeled'] 63 | count += 1 64 | 65 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 66 | labeled) 67 | result_line = print_iou(iu, mean_pixel_acc, 68 | dataset.get_class_names(), True) 69 | return result_line 70 | 71 | 72 | if __name__ == "__main__": 73 | parser = argparse.ArgumentParser() 74 | parser.add_argument('-e', '--epochs', default='last', type=str) 75 | parser.add_argument('-d', '--devices', default='1', type=str) 76 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 77 | parser.add_argument('--show_image', '-s', default=False, 78 | action='store_true') 79 | parser.add_argument('--save_path', '-p', default=None) 80 | 81 | args = parser.parse_args() 82 | all_dev = parse_devices(args.devices) 83 | 84 | network = BiSeNet(config.num_classes, is_training=False, 85 | criterion=None, ohem_criterion=None) 86 | data_setting = {'img_root': config.img_root_folder, 87 | 'gt_root': config.gt_root_folder, 88 | 'train_source': config.train_source, 89 | 'eval_source': config.eval_source} 90 | dataset = Cityscapes(data_setting, 'val', None) 91 | 92 | with torch.no_grad(): 93 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 94 | config.image_std, network, 95 | config.eval_scale_array, config.eval_flip, 96 | all_dev, args.verbose, args.save_path, 97 | args.show_image) 98 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 99 | config.link_val_log_file) 100 | -------------------------------------------------------------------------------- /model/dfn/cityscapes.dfn.R101_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 12345 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | # C.dataset_path = "/unsullied/sharefs/yuchangqian/Storage/Datasets/Cityscapes/" 39 | C.dataset_path = "/root/Source/Datasets/Segmentation/Cityscapes/" 40 | C.img_root_folder = C.dataset_path 41 | C.gt_root_folder = C.dataset_path 42 | C.train_source = osp.join(C.dataset_path, "config_new/train.txt") 43 | C.eval_source = osp.join(C.dataset_path, "config_new/val.txt") 44 | C.test_source = osp.join(C.dataset_path, "config_new/test.txt") 45 | C.demo_source = osp.join(C.dataset_path, "config_new/demo.txt") 46 | C.is_test = False 47 | 48 | """Path Config""" 49 | 50 | 51 | def add_path(path): 52 | if path not in sys.path: 53 | sys.path.insert(0, path) 54 | 55 | 56 | add_path(osp.join(C.root_dir, 'furnace')) 57 | 58 | from utils.pyt_utils import model_urls 59 | 60 | """Image Config""" 61 | C.num_classes = 19 62 | C.background = -1 63 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 64 | C.image_std = np.array([0.229, 0.224, 0.225]) 65 | C.image_height = 800 66 | C.image_width = 800 67 | C.num_train_imgs = 2975 68 | C.num_eval_imgs = 500 69 | 70 | """ Settings for network, this would be different for each kind of model""" 71 | C.fix_bias = True 72 | C.bn_eps = 1e-5 73 | C.bn_momentum = 0.1 74 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet101_v1c.pth" 75 | # C.pretrained_model = "/unsullied/sharefs/yuchangqian/Storage/model_zoo/pytorch_model/resnet101_v1c.pth" 76 | C.aux_loss_alpha = 0.1 77 | 78 | """Train Config""" 79 | C.lr = 7e-4 80 | C.lr_power = 0.9 81 | C.momentum = 0.9 82 | C.weight_decay = 1e-4 83 | C.batch_size = 16 # 4 * C.num_gpu 84 | C.nepochs = 80 85 | C.niters_per_epoch = 1000 86 | C.num_workers = 24 87 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2.0] 88 | 89 | """Eval Config""" 90 | C.eval_iter = 30 91 | C.eval_stride_rate = 2 / 3 92 | C.eval_scale_array = [1, ] # 0.5, 0.75, 1, 1.5, 1.75 93 | C.eval_flip = False # True if use the ms_flip stragey 94 | C.eval_base_size = 800 95 | C.eval_crop_size = 800 96 | 97 | """Display Config""" 98 | C.snapshot_iter = 10 99 | C.record_info_iter = 20 100 | C.display_iter = 50 101 | 102 | 103 | def open_tensorboard(): 104 | pass 105 | 106 | if __name__ == '__main__': 107 | print(config.epoch_num) 108 | parser = argparse.ArgumentParser() 109 | parser.add_argument( 110 | '-tb', '--tensorboard', default=False, action='store_true') 111 | args = parser.parse_args() 112 | 113 | if args.tensorboard: 114 | open_tensorboard() 115 | -------------------------------------------------------------------------------- /model/dfn/cityscapes.dfn.R101_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | edge_radius = 7 16 | self.edge_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, 17 | (edge_radius, edge_radius)) 18 | 19 | def __call__(self, img, gt): 20 | img, gt = random_mirror(img, gt) 21 | if config.train_scale_array is not None: 22 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 23 | 24 | id255 = np.where(gt == 255) 25 | no255_gt = np.array(gt) 26 | no255_gt[id255] = 0 27 | cgt = cv2.Canny(no255_gt, 5, 5, apertureSize=7) 28 | cgt = cv2.dilate(cgt, self.edge_kernel) 29 | cgt[cgt == 255] = 1 30 | 31 | img = normalize(img, self.img_mean, self.img_std) 32 | 33 | crop_size = (config.image_height, config.image_width) 34 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 35 | 36 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 37 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 38 | p_cgt, _ = random_crop_pad_to_shape(cgt, crop_pos, crop_size, 255) 39 | 40 | p_img = p_img.transpose(2, 0, 1) 41 | 42 | extra_dict = {'aux_label': p_cgt} 43 | 44 | return p_img, p_gt, extra_dict 45 | 46 | 47 | def get_train_loader(engine, dataset): 48 | data_setting = {'img_root': config.img_root_folder, 49 | 'gt_root': config.gt_root_folder, 50 | 'train_source': config.train_source, 51 | 'eval_source': config.eval_source} 52 | train_preprocess = TrainPre(config.image_mean, config.image_std) 53 | 54 | train_dataset = dataset(data_setting, "train", train_preprocess, 55 | config.batch_size * config.niters_per_epoch) 56 | 57 | train_sampler = None 58 | is_shuffle = True 59 | batch_size = config.batch_size 60 | 61 | if engine.distributed: 62 | train_sampler = torch.utils.data.distributed.DistributedSampler( 63 | train_dataset) 64 | batch_size = config.batch_size // engine.world_size 65 | is_shuffle = False 66 | 67 | train_loader = data.DataLoader(train_dataset, 68 | batch_size=batch_size, 69 | num_workers=config.num_workers, 70 | drop_last=True, 71 | shuffle=is_shuffle, 72 | pin_memory=True, 73 | sampler=train_sampler) 74 | 75 | return train_loader, train_sampler 76 | -------------------------------------------------------------------------------- /model/dfn/cityscapes.dfn.R101_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.cityscapes import Cityscapes 18 | from network import DFN 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | 29 | pred = self.sliding_eval(img, config.eval_crop_size, 30 | config.eval_stride_rate, device) 31 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 32 | pred, 33 | label) 34 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 35 | 'correct': correct_tmp} 36 | 37 | if self.save_path is not None: 38 | fn = name + '.png' 39 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 40 | logger.info('Save the image ' + fn) 41 | 42 | if self.show_image: 43 | colors = self.dataset.get_class_colors 44 | image = img 45 | clean = np.zeros(label.shape) 46 | comp_img = show_img(colors, config.background, image, clean, 47 | label, 48 | pred) 49 | cv2.imshow('comp_image', comp_img) 50 | cv2.waitKey(0) 51 | 52 | return results_dict 53 | 54 | def compute_metric(self, results): 55 | hist = np.zeros((config.num_classes, config.num_classes)) 56 | correct = 0 57 | labeled = 0 58 | count = 0 59 | for d in results: 60 | hist += d['hist'] 61 | correct += d['correct'] 62 | labeled += d['labeled'] 63 | count += 1 64 | 65 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 66 | labeled) 67 | result_line = print_iou(iu, mean_pixel_acc, 68 | dataset.get_class_names(), True) 69 | return result_line 70 | 71 | 72 | if __name__ == "__main__": 73 | parser = argparse.ArgumentParser() 74 | parser.add_argument('-e', '--epochs', default='last', type=str) 75 | parser.add_argument('-d', '--devices', default='1', type=str) 76 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 77 | parser.add_argument('--show_image', '-s', default=False, 78 | action='store_true') 79 | parser.add_argument('--save_path', '-p', default=None) 80 | 81 | args = parser.parse_args() 82 | all_dev = parse_devices(args.devices) 83 | 84 | network = DFN(config.num_classes, criterion=None, aux_criterion=None, 85 | alpha=config.aux_loss_alpha) 86 | data_setting = {'img_root': config.img_root_folder, 87 | 'gt_root': config.gt_root_folder, 88 | 'train_source': config.train_source, 89 | 'eval_source': config.eval_source} 90 | dataset = Cityscapes(data_setting, 'val', None) 91 | 92 | with torch.no_grad(): 93 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 94 | config.image_std, network, 95 | config.eval_scale_array, config.eval_flip, 96 | all_dev, args.verbose, args.save_path, 97 | args.show_image) 98 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 99 | config.link_val_log_file) 100 | -------------------------------------------------------------------------------- /model/dfn/voc.dfn.R101_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import math 11 | import numpy as np 12 | from easydict import EasyDict as edict 13 | import argparse 14 | 15 | import torch.utils.model_zoo as model_zoo 16 | 17 | C = edict() 18 | config = C 19 | cfg = C 20 | 21 | C.seed = 12345 22 | 23 | """please config ROOT_dir and user when u first using""" 24 | C.repo_name = 'TorchSeg' 25 | C.abs_dir = osp.realpath(".") 26 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 27 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 28 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 29 | C.log_dir_link = osp.join(C.abs_dir, 'log') 30 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 31 | 32 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 33 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 34 | C.link_log_file = C.log_file + '/log_last.log' 35 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 36 | C.link_val_log_file = C.log_dir + '/val_last.log' 37 | 38 | """Data Dir and Weight Dir""" 39 | C.dataset_path = "/root/Source/Datasets/Segmentation/VOC2012_AUG" 40 | C.img_root_folder = C.dataset_path 41 | C.gt_root_folder = C.dataset_path 42 | C.train_source = osp.join(C.dataset_path, "config/train.txt") 43 | C.eval_source = osp.join(C.dataset_path, "config/val.txt") 44 | C.test_source = osp.join(C.dataset_path, "config/voc12_test.txt") 45 | C.is_test = False 46 | 47 | """Path Config""" 48 | 49 | 50 | def add_path(path): 51 | if path not in sys.path: 52 | sys.path.insert(0, path) 53 | 54 | 55 | add_path(osp.join(C.root_dir, 'furnace')) 56 | 57 | """Image Config""" 58 | C.num_classes = 21 59 | C.background = 0 60 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 61 | C.image_std = np.array([0.229, 0.224, 0.225]) 62 | C.target_size = 512 63 | C.image_height = 512 64 | C.image_width = 512 65 | C.num_train_imgs = 10582 66 | C.num_eval_imgs = 1449 67 | 68 | """ Settings for network, this would be different for each kind of model""" 69 | C.fix_bias = True 70 | C.fix_bn = False 71 | C.sync_bn = True 72 | C.bn_eps = 1e-5 73 | C.bn_momentum = 0.1 74 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet101_v1c.pth" 75 | C.aux_loss_alpha = 0.1 76 | 77 | """Train Config""" 78 | C.lr = 8e-4 79 | C.lr_power = 0.9 80 | C.momentum = 0.9 81 | C.weight_decay = 1e-5 82 | C.batch_size = 32 #4 * C.num_gpu 83 | C.nepochs = 120 84 | C.niters_per_epoch = int(math.ceil(C.num_train_imgs * 1.0 // C.batch_size)) 85 | C.num_workers = 24 86 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2.0] 87 | 88 | """Eval Config""" 89 | C.eval_iter = 30 90 | C.eval_stride_rate = 2 / 3 91 | C.eval_scale_array = [1, ] # multi_scale: 0.5, 0.75, 1, 1.5, 1.75 92 | C.eval_flip = False 93 | C.eval_base_size = 512 94 | C.eval_crop_size = 512 95 | 96 | """Display Config""" 97 | C.snapshot_iter = 10 98 | C.record_info_iter = 20 99 | C.display_iter = 50 100 | 101 | 102 | def open_tensorboard(): 103 | pass 104 | 105 | 106 | if __name__ == '__main__': 107 | parser = argparse.ArgumentParser() 108 | parser.add_argument( 109 | '-tb', '--tensorboard', default=False, action='store_true') 110 | args = parser.parse_args() 111 | 112 | if args.tensorboard: 113 | open_tensorboard() 114 | -------------------------------------------------------------------------------- /model/dfn/voc.dfn.R101_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | edge_radius = 7 16 | self.edge_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, 17 | (edge_radius, edge_radius)) 18 | 19 | def __call__(self, img, gt): 20 | img, gt = random_mirror(img, gt) 21 | if config.train_scale_array is not None: 22 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 23 | 24 | id255 = np.where(gt == 255) 25 | no255_gt = np.array(gt) 26 | no255_gt[id255] = 0 27 | cgt = cv2.Canny(no255_gt, 5, 5, apertureSize=7) 28 | cgt = cv2.dilate(cgt, self.edge_kernel) 29 | cgt[cgt == 255] = 1 30 | 31 | img = normalize(img, self.img_mean, self.img_std) 32 | 33 | crop_size = (config.image_height, config.image_width) 34 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 35 | 36 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 37 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 38 | p_cgt, _ = random_crop_pad_to_shape(cgt, crop_pos, crop_size, 255) 39 | 40 | p_img = p_img.transpose(2, 0, 1) 41 | 42 | extra_dict = {'aux_label': p_cgt} 43 | 44 | return p_img, p_gt, extra_dict 45 | 46 | 47 | def get_train_loader(engine, dataset): 48 | data_setting = {'img_root': config.img_root_folder, 49 | 'gt_root': config.gt_root_folder, 50 | 'train_source': config.train_source, 51 | 'eval_source': config.eval_source} 52 | train_preprocess = TrainPre(config.image_mean, config.image_std) 53 | 54 | train_dataset = dataset(data_setting, "train", train_preprocess, 55 | config.batch_size * config.niters_per_epoch) 56 | 57 | train_sampler = None 58 | is_shuffle = True 59 | batch_size = config.batch_size 60 | 61 | if engine.distributed: 62 | train_sampler = torch.utils.data.distributed.DistributedSampler( 63 | train_dataset) 64 | batch_size = config.batch_size // engine.world_size 65 | is_shuffle = False 66 | 67 | train_loader = data.DataLoader(train_dataset, 68 | batch_size=batch_size, 69 | num_workers=config.num_workers, 70 | drop_last=True, 71 | shuffle=is_shuffle, 72 | pin_memory=True, 73 | sampler=train_sampler) 74 | 75 | return train_loader, train_sampler 76 | -------------------------------------------------------------------------------- /model/dfn/voc.dfn.R101_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from network import DFN 13 | 14 | from utils.pyt_utils import ensure_dir, link_file, load_model, \ 15 | parse_devices 16 | from utils.visualize import print_iou, show_img 17 | from engine.evaluator import Evaluator 18 | from engine.logger import get_logger 19 | from seg_opr.metric import hist_info, compute_score 20 | from datasets import VOC 21 | 22 | logger = get_logger() 23 | 24 | 25 | class SegEvaluator(Evaluator): 26 | def func_per_iteration(self, data, device): 27 | img = data['data'] 28 | label = data['label'] 29 | name = data['fn'] 30 | 31 | pred = self.sliding_eval(img, config.eval_crop_size, 32 | config.eval_stride_rate, device) 33 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 34 | pred, 35 | label) 36 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 37 | 'correct': correct_tmp} 38 | 39 | if self.save_path is not None: 40 | fn = name + '.png' 41 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 42 | logger.info('Save the image ' + fn) 43 | 44 | if self.show_image: 45 | colors = self.dataset.get_class_colors 46 | image = img 47 | clean = np.zeros(label.shape) 48 | comp_img = show_img(colors, config.background, image, clean, 49 | label, 50 | pred) 51 | cv2.imshow('comp_image', comp_img) 52 | cv2.waitKey(0) 53 | 54 | return results_dict 55 | 56 | def compute_metric(self, results): 57 | hist = np.zeros((config.num_classes, config.num_classes)) 58 | correct = 0 59 | labeled = 0 60 | count = 0 61 | for d in results: 62 | hist += d['hist'] 63 | correct += d['correct'] 64 | labeled += d['labeled'] 65 | count += 1 66 | 67 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 68 | labeled) 69 | result_line = print_iou(iu, mean_pixel_acc, 70 | dataset.get_class_names(), True) 71 | return result_line 72 | 73 | 74 | if __name__ == "__main__": 75 | parser = argparse.ArgumentParser() 76 | parser.add_argument('-e', '--epochs', default='last', type=str) 77 | parser.add_argument('-d', '--devices', default='1', type=str) 78 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 79 | parser.add_argument('--show_image', '-s', default=False, 80 | action='store_true') 81 | parser.add_argument('--save_path', '-p', default=None) 82 | 83 | args = parser.parse_args() 84 | all_dev = parse_devices(args.devices) 85 | 86 | mp_ctx = mp.get_context('spawn') 87 | network = DFN(config.num_classes, criterion=None, aux_criterion=None, 88 | alpha=config.aux_loss_alpha) 89 | data_setting = {'img_root': config.img_root_folder, 90 | 'gt_root': config.gt_root_folder, 91 | 'train_source': config.train_source, 92 | 'eval_source': config.eval_source} 93 | dataset = VOC(data_setting, 'val', None) 94 | 95 | with torch.no_grad(): 96 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 97 | config.image_std, network, 98 | config.eval_scale_array, config.eval_flip, 99 | all_dev, args.verbose, args.save_path, 100 | args.show_image) 101 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 102 | config.link_val_log_file) 103 | -------------------------------------------------------------------------------- /model/fcn/voc.fcn32s.R101_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | C = edict() 15 | config = C 16 | cfg = C 17 | 18 | C.seed = 304 19 | 20 | """please config ROOT_dir and user when u first using""" 21 | C.repo_name = 'TorchSeg' 22 | C.abs_dir = osp.realpath(".") 23 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 24 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 25 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 26 | C.log_dir_link = osp.join(C.abs_dir, 'log') 27 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 28 | 29 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 30 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 31 | C.link_log_file = C.log_file + '/log_last.log' 32 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 33 | C.link_val_log_file = C.log_dir + '/val_last.log' 34 | 35 | """Data Dir and Weight Dir""" 36 | C.img_root_folder = "/unsullied/sharefs/yuchangqian/Storage/Datasets/VOC2012_AUG/" 37 | C.gt_root_folder = "/unsullied/sharefs/yuchangqian/Storage/Datasets/VOC2012_AUG/" 38 | C.train_source = "/unsullied/sharefs/yuchangqian/Storage/Datasets/VOC2012_AUG/config/train.txt" 39 | C.eval_source = "/unsullied/sharefs/yuchangqian/Storage/Datasets/VOC2012_AUG/config/val.txt" 40 | C.test_source = "/unsullied/sharefs/yuchangqian/Storage/Datasets/VOC2012_AUG/config/voc12_test.txt" 41 | C.is_test = False 42 | 43 | """Path Config""" 44 | 45 | 46 | def add_path(path): 47 | if path not in sys.path: 48 | sys.path.insert(0, path) 49 | 50 | 51 | add_path(osp.join(C.root_dir, 'furnace')) 52 | 53 | from utils.pyt_utils import model_urls 54 | 55 | """Image Config""" 56 | C.num_classes = 21 57 | C.background = 0 58 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 59 | C.image_std = np.array([0.229, 0.224, 0.224]) 60 | C.target_size = 512 61 | C.image_height = 512 62 | C.image_width = 512 63 | C.num_train_imgs = 10582 64 | C.num_eval_imgs = 1449 65 | 66 | """ Settings for network, this would be different for each kind of model""" 67 | C.fix_bias = True 68 | C.fix_bn = False 69 | C.bn_eps = 1e-5 70 | C.bn_momentum = 0.1 71 | C.loss_weight = None 72 | C.pretrained_model = "/unsullied/sharefs/yuchangqian/Storage/model_zoo/pytorch_model/resnet101_v1c.pth" 73 | 74 | """Train Config""" 75 | C.lr = 1e-2 76 | C.lr_power = 0.9 77 | C.momentum = 0.9 78 | C.weight_decay = 1e-4 79 | C.batch_size = 32 # 4 * C.num_gpu 80 | C.nepochs = 60 81 | C.niters_per_epoch = int(np.ceil(C.num_train_imgs // C.batch_size)) 82 | C.num_workers = 32 83 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2] 84 | C.aux_loss_ratio = 0.5 85 | 86 | """Eval Config""" 87 | C.eval_iter = 30 88 | C.eval_stride_rate = 2 / 3 89 | C.eval_scale_array = [1, ] 90 | C.eval_flip = False 91 | C.eval_base_size = 512 92 | C.eval_crop_size = 512 93 | 94 | """Display Config""" 95 | C.snapshot_iter = 1 96 | C.record_info_iter = 20 97 | C.display_iter = 50 98 | 99 | 100 | def open_tensorboard(): 101 | pass 102 | 103 | 104 | if __name__ == '__main__': 105 | print(config.epoch_num) 106 | parser = argparse.ArgumentParser() 107 | parser.add_argument( 108 | '-tb', '--tensorboard', default=False, action='store_true') 109 | args = parser.parse_args() 110 | 111 | if args.tensorboard: 112 | open_tensorboard() 113 | -------------------------------------------------------------------------------- /model/fcn/voc.fcn32s.R101_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | import torch 5 | from torch.utils import data 6 | 7 | from config import config 8 | from utils.img_utils import random_scale, random_mirror, normalize, \ 9 | generate_random_crop_pos, random_crop_pad_to_shape, random_scale_with_length 10 | 11 | 12 | class TrainPre(object): 13 | def __init__(self, img_mean, img_std, target_size): 14 | self.img_mean = img_mean 15 | self.img_std = img_std 16 | self.target_size = target_size 17 | 18 | def __call__(self, img, gt): 19 | img, gt = random_mirror(img, gt) 20 | if config.train_scale_array is not None: 21 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 22 | 23 | img = normalize(img, self.img_mean, self.img_std) 24 | 25 | crop_size = (config.image_height, config.image_width) 26 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 27 | 28 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 29 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 255) 30 | 31 | p_img = p_img.transpose(2, 0, 1) 32 | 33 | extra_dict = None 34 | 35 | return p_img, p_gt, extra_dict 36 | 37 | 38 | def get_train_loader(engine, dataset): 39 | data_setting = {'img_root': config.img_root_folder, 40 | 'gt_root': config.gt_root_folder, 41 | 'train_source': config.train_source, 42 | 'eval_source': config.eval_source} 43 | train_preprocess = TrainPre(config.image_mean, config.image_std, 44 | config.target_size) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.niters_per_epoch * config.batch_size) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=True, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/fcn/voc.fcn32s.R101_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.voc import VOC 18 | from network import FCN 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | 29 | pred = self.sliding_eval(img, config.eval_crop_size, 30 | config.eval_stride_rate, device) 31 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 32 | pred, 33 | label) 34 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 35 | 'correct': correct_tmp} 36 | 37 | if self.save_path is not None: 38 | fn = name + '.png' 39 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 40 | logger.info('Save the image ' + fn) 41 | 42 | if self.show_image: 43 | colors = self.dataset.get_class_colors 44 | image = img 45 | clean = np.zeros(label.shape) 46 | comp_img = show_img(colors, config.background, image, clean, 47 | label, 48 | pred) 49 | cv2.imshow('comp_image', comp_img) 50 | cv2.waitKey(0) 51 | 52 | return results_dict 53 | 54 | def compute_metric(self, results): 55 | hist = np.zeros((config.num_classes, config.num_classes)) 56 | correct = 0 57 | labeled = 0 58 | count = 0 59 | for d in results: 60 | hist += d['hist'] 61 | correct += d['correct'] 62 | labeled += d['labeled'] 63 | count += 1 64 | 65 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 66 | labeled) 67 | result_line = print_iou(iu, mean_pixel_acc, 68 | dataset.get_class_names(), True) 69 | return result_line 70 | 71 | 72 | if __name__ == "__main__": 73 | parser = argparse.ArgumentParser() 74 | parser.add_argument('-e', '--epochs', default='last', type=str) 75 | parser.add_argument('-d', '--devices', default='1', type=str) 76 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 77 | parser.add_argument('--show_image', '-s', default=False, 78 | action='store_true') 79 | parser.add_argument('--save_path', '-p', default=None) 80 | 81 | args = parser.parse_args() 82 | all_dev = parse_devices(args.devices) 83 | 84 | mp_ctx = mp.get_context('spawn') 85 | network = FCN(config.num_classes, criterion=None) 86 | data_setting = {'img_root': config.img_root_folder, 87 | 'gt_root': config.gt_root_folder, 88 | 'train_source': config.train_source, 89 | 'eval_source': config.eval_source} 90 | dataset = VOC(data_setting, 'val', None) 91 | 92 | with torch.no_grad(): 93 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 94 | config.image_std, network, 95 | config.eval_scale_array, config.eval_flip, 96 | all_dev, args.verbose, args.save_path, 97 | args.show_image) 98 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 99 | config.link_val_log_file) 100 | -------------------------------------------------------------------------------- /model/fcn/voc.fcn32s.R101_v1c/network.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | from torch.utils.checkpoint import checkpoint 7 | 8 | from config import config 9 | from base_model import resnet101 10 | from seg_opr.seg_oprs import ConvBnRelu 11 | 12 | 13 | class FCN(nn.Module): 14 | def __init__(self, out_planes, criterion, inplace=True, 15 | pretrained_model=None, norm_layer=nn.BatchNorm2d): 16 | super(FCN, self).__init__() 17 | self.backbone = resnet101(pretrained_model, inplace=inplace, 18 | norm_layer=norm_layer, 19 | bn_eps=config.bn_eps, 20 | bn_momentum=config.bn_momentum, 21 | deep_stem=True, stem_width=64) 22 | 23 | self.business_layer = [] 24 | self.head = _FCNHead(2048, out_planes, inplace, norm_layer=norm_layer) 25 | self.aux_head = _FCNHead(1024, out_planes, inplace, 26 | norm_layer=norm_layer) 27 | 28 | self.business_layer.append(self.head) 29 | self.business_layer.append(self.aux_head) 30 | 31 | self.criterion = criterion 32 | 33 | def forward(self, data, label=None): 34 | blocks = self.backbone(data) 35 | fm = self.head(blocks[-1]) 36 | pred = F.interpolate(fm, scale_factor=32, mode='bilinear', 37 | align_corners=True) 38 | 39 | aux_fm = self.aux_head(blocks[-2]) 40 | aux_pred = F.interpolate(aux_fm, scale_factor=16, mode='bilinear', 41 | align_corners=True) 42 | 43 | if label is not None: 44 | loss = self.criterion(pred, label) 45 | aux_loss = self.criterion(aux_pred, label) 46 | loss = loss + config.aux_loss_ratio * aux_loss 47 | return loss 48 | 49 | return pred 50 | 51 | 52 | class _FCNHead(nn.Module): 53 | def __init__(self, in_planes, out_planes, inplace=True, 54 | norm_layer=nn.BatchNorm2d): 55 | super(_FCNHead, self).__init__() 56 | inter_planes = in_planes // 4 57 | self.cbr = ConvBnRelu(in_planes, inter_planes, 3, 1, 1, 58 | has_bn=True, norm_layer=norm_layer, 59 | has_relu=True, inplace=inplace, has_bias=False) 60 | self.dropout = nn.Dropout2d(0.1) 61 | self.conv1x1 = nn.Conv2d(inter_planes, out_planes, kernel_size=1, 62 | stride=1, padding=0) 63 | 64 | def forward(self, x): 65 | x = self.cbr(x) 66 | x = self.dropout(x) 67 | x = self.conv1x1(x) 68 | return x 69 | 70 | 71 | if __name__ == "__main__": 72 | model = FCN(21, None) 73 | print(model) 74 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R101_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 304 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/ADE20K/ADE2017/" 39 | # C.dataset_path = "/unsullied/sharefs/yuchangqian/Storage/Datasets/ADE20K/ADE2017" 40 | C.img_root_folder = osp.join(C.dataset_path, "images/") 41 | C.gt_root_folder = osp.join(C.dataset_path, "annotations_sceneparsing/") 42 | C.train_source = osp.join(C.dataset_path, "images/training.txt") 43 | C.eval_source = osp.join(C.dataset_path, "images/validation.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 150 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 480 64 | C.image_height = 480 65 | C.image_width = 480 66 | C.num_train_imgs = 20210 67 | C.num_eval_imgs = 1449 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet101_v1c.pth" 76 | # C.pretrained_model = "/unsullied/sharefs/yuchangqian/Storage/model_zoo/pytorch_model/resnet50_v1c.pth" 77 | 78 | 79 | """Train Config""" 80 | C.lr = 1e-2 81 | C.lr_power = 0.9 82 | C.momentum = 0.9 83 | C.weight_decay = 1e-4 84 | C.batch_size = 16 # 4 * C.num_gpu 85 | C.nepochs = 120 86 | C.niters_per_epoch = int(np.ceil(C.num_train_imgs // C.batch_size)) 87 | C.num_workers = 24 88 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2] 89 | 90 | """Eval Config""" 91 | C.eval_iter = 30 92 | C.eval_stride_rate = 2 / 3 93 | C.eval_scale_array = [1, ] 94 | C.eval_flip = False 95 | C.eval_base_size = 480 96 | C.eval_crop_size = 480 97 | 98 | """Display Config""" 99 | C.snapshot_iter = 10 100 | C.record_info_iter = 20 101 | C.display_iter = 50 102 | 103 | 104 | def open_tensorboard(): 105 | pass 106 | 107 | 108 | if __name__ == '__main__': 109 | print(config.epoch_num) 110 | parser = argparse.ArgumentParser() 111 | parser.add_argument( 112 | '-tb', '--tensorboard', default=False, action='store_true') 113 | args = parser.parse_args() 114 | 115 | if args.tensorboard: 116 | open_tensorboard() 117 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R101_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std, target_size): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | self.target_size = target_size 16 | 17 | def __call__(self, img, gt): 18 | img, gt = random_mirror(img, gt) 19 | if config.train_scale_array is not None: 20 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 21 | 22 | img = normalize(img, self.img_mean, self.img_std) 23 | 24 | crop_size = (config.image_height, config.image_width) 25 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 26 | 27 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 28 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 0) 29 | 30 | p_img = p_img.transpose(2, 0, 1) 31 | p_gt = p_gt - 1 32 | 33 | extra_dict = None 34 | 35 | return p_img, p_gt, extra_dict 36 | 37 | 38 | def get_train_loader(engine, dataset): 39 | data_setting = {'img_root': config.img_root_folder, 40 | 'gt_root': config.gt_root_folder, 41 | 'train_source': config.train_source, 42 | 'eval_source': config.eval_source} 43 | train_preprocess = TrainPre(config.image_mean, config.image_std, 44 | config.target_size) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.niters_per_epoch * config.batch_size) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=False, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R101_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.ade import ADE 18 | from network import PSPNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | label = label - 1 29 | 30 | pred = self.sliding_eval(img, config.eval_crop_size, 31 | config.eval_stride_rate, device) 32 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 33 | pred, 34 | label) 35 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 36 | 'correct': correct_tmp} 37 | 38 | if self.save_path is not None: 39 | fn = name + '.png' 40 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 41 | logger.info('Save the image ' + fn) 42 | 43 | if self.show_image: 44 | colors = self.dataset.get_class_colors 45 | image = img 46 | clean = np.zeros(label.shape) 47 | comp_img = show_img(colors, config.background, image, clean, 48 | label, 49 | pred) 50 | cv2.imshow('comp_image', comp_img) 51 | cv2.waitKey(0) 52 | 53 | return results_dict 54 | 55 | def compute_metric(self, results): 56 | hist = np.zeros((config.num_classes, config.num_classes)) 57 | correct = 0 58 | labeled = 0 59 | count = 0 60 | for d in results: 61 | hist += d['hist'] 62 | correct += d['correct'] 63 | labeled += d['labeled'] 64 | count += 1 65 | 66 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 67 | labeled) 68 | result_line = print_iou(iu, mean_pixel_acc, 69 | dataset.get_class_names(), True) 70 | return result_line 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument('-e', '--epochs', default='last', type=str) 76 | parser.add_argument('-d', '--devices', default='1', type=str) 77 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 78 | parser.add_argument('--show_image', '-s', default=False, 79 | action='store_true') 80 | parser.add_argument('--save_path', '-p', default=None) 81 | 82 | args = parser.parse_args() 83 | all_dev = parse_devices(args.devices) 84 | 85 | mp_ctx = mp.get_context('spawn') 86 | network = PSPNet(config.num_classes, criterion=None) 87 | data_setting = {'img_root': config.img_root_folder, 88 | 'gt_root': config.gt_root_folder, 89 | 'train_source': config.train_source, 90 | 'eval_source': config.eval_source} 91 | dataset = ADE(data_setting, 'val', None) 92 | 93 | with torch.no_grad(): 94 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 95 | config.image_std, network, 96 | config.eval_scale_array, config.eval_flip, 97 | all_dev, args.verbose, args.save_path, 98 | args.show_image) 99 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 100 | config.link_val_log_file) 101 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R50_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 304 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/ADE20K/ADE2017/" 39 | # C.dataset_path = "/unsullied/sharefs/yuchangqian/Storage/Datasets/ADE20K/ADE2017" 40 | C.img_root_folder = osp.join(C.dataset_path, "images/") 41 | C.gt_root_folder = osp.join(C.dataset_path, "annotations_sceneparsing/") 42 | C.train_source = osp.join(C.dataset_path, "images/training.txt") 43 | C.eval_source = osp.join(C.dataset_path, "images/validation.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 150 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 480 64 | C.image_height = 480 65 | C.image_width = 480 66 | C.num_train_imgs = 20210 67 | C.num_eval_imgs = 1449 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet50_v1c.pth" 76 | # C.pretrained_model = "/unsullied/sharefs/yuchangqian/Storage/model_zoo/pytorch_model/resnet50_v1c.pth" 77 | 78 | 79 | """Train Config""" 80 | C.lr = 1e-2 81 | C.lr_power = 0.9 82 | C.momentum = 0.9 83 | C.weight_decay = 1e-4 84 | C.batch_size = 16 # 4 * C.num_gpu 85 | C.nepochs = 120 86 | C.niters_per_epoch = int(np.ceil(C.num_train_imgs // C.batch_size)) 87 | C.num_workers = 24 88 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2] 89 | 90 | """Eval Config""" 91 | C.eval_iter = 30 92 | C.eval_stride_rate = 2 / 3 93 | C.eval_scale_array = [1, ] 94 | C.eval_flip = False 95 | C.eval_base_size = 480 96 | C.eval_crop_size = 480 97 | 98 | """Display Config""" 99 | C.snapshot_iter = 10 100 | C.record_info_iter = 20 101 | C.display_iter = 50 102 | 103 | 104 | def open_tensorboard(): 105 | pass 106 | 107 | 108 | if __name__ == '__main__': 109 | print(config.epoch_num) 110 | parser = argparse.ArgumentParser() 111 | parser.add_argument( 112 | '-tb', '--tensorboard', default=False, action='store_true') 113 | args = parser.parse_args() 114 | 115 | if args.tensorboard: 116 | open_tensorboard() 117 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R50_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std, target_size): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | self.target_size = target_size 16 | 17 | def __call__(self, img, gt): 18 | img, gt = random_mirror(img, gt) 19 | if config.train_scale_array is not None: 20 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 21 | 22 | img = normalize(img, self.img_mean, self.img_std) 23 | 24 | crop_size = (config.image_height, config.image_width) 25 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 26 | 27 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 28 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 0) 29 | 30 | p_img = p_img.transpose(2, 0, 1) 31 | p_gt = p_gt - 1 32 | 33 | extra_dict = None 34 | 35 | return p_img, p_gt, extra_dict 36 | 37 | 38 | def get_train_loader(engine, dataset): 39 | data_setting = {'img_root': config.img_root_folder, 40 | 'gt_root': config.gt_root_folder, 41 | 'train_source': config.train_source, 42 | 'eval_source': config.eval_source} 43 | train_preprocess = TrainPre(config.image_mean, config.image_std, 44 | config.target_size) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.niters_per_epoch * config.batch_size) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=False, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/psanet/ade.psanet.R50_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.ade import ADE 18 | from network import PSPNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | label = label - 1 29 | 30 | pred = self.sliding_eval(img, config.eval_crop_size, 31 | config.eval_stride_rate, device) 32 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 33 | pred, 34 | label) 35 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 36 | 'correct': correct_tmp} 37 | 38 | if self.save_path is not None: 39 | fn = name + '.png' 40 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 41 | logger.info('Save the image ' + fn) 42 | 43 | if self.show_image: 44 | colors = self.dataset.get_class_colors 45 | image = img 46 | clean = np.zeros(label.shape) 47 | comp_img = show_img(colors, config.background, image, clean, 48 | label, 49 | pred) 50 | cv2.imshow('comp_image', comp_img) 51 | cv2.waitKey(0) 52 | 53 | return results_dict 54 | 55 | def compute_metric(self, results): 56 | hist = np.zeros((config.num_classes, config.num_classes)) 57 | correct = 0 58 | labeled = 0 59 | count = 0 60 | for d in results: 61 | hist += d['hist'] 62 | correct += d['correct'] 63 | labeled += d['labeled'] 64 | count += 1 65 | 66 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 67 | labeled) 68 | result_line = print_iou(iu, mean_pixel_acc, 69 | dataset.get_class_names(), True) 70 | return result_line 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument('-e', '--epochs', default='last', type=str) 76 | parser.add_argument('-d', '--devices', default='1', type=str) 77 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 78 | parser.add_argument('--show_image', '-s', default=False, 79 | action='store_true') 80 | parser.add_argument('--save_path', '-p', default=None) 81 | 82 | args = parser.parse_args() 83 | all_dev = parse_devices(args.devices) 84 | 85 | mp_ctx = mp.get_context('spawn') 86 | network = PSPNet(config.num_classes, criterion=None) 87 | data_setting = {'img_root': config.img_root_folder, 88 | 'gt_root': config.gt_root_folder, 89 | 'train_source': config.train_source, 90 | 'eval_source': config.eval_source} 91 | dataset = ADE(data_setting, 'val', None) 92 | 93 | with torch.no_grad(): 94 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 95 | config.image_std, network, 96 | config.eval_scale_array, config.eval_flip, 97 | all_dev, args.verbose, args.save_path, 98 | args.show_image) 99 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 100 | config.link_val_log_file) 101 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R101_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 304 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/ADE20K/ADE2017/" 39 | # C.dataset_path = "/unsullied/sharefs/yuchangqian/Storage/Datasets/ADE20K/ADE2017" 40 | C.img_root_folder = osp.join(C.dataset_path, "images/") 41 | C.gt_root_folder = osp.join(C.dataset_path, "annotations_sceneparsing/") 42 | C.train_source = osp.join(C.dataset_path, "images/training.txt") 43 | C.eval_source = osp.join(C.dataset_path, "images/validation.txt") 44 | C.is_test = False 45 | 46 | """Path Config""" 47 | 48 | 49 | def add_path(path): 50 | if path not in sys.path: 51 | sys.path.insert(0, path) 52 | 53 | 54 | add_path(osp.join(C.root_dir, 'furnace')) 55 | 56 | from utils.pyt_utils import model_urls 57 | 58 | """Image Config""" 59 | C.num_classes = 150 60 | C.background = -1 61 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 62 | C.image_std = np.array([0.229, 0.224, 0.225]) 63 | C.target_size = 480 64 | C.image_height = 480 65 | C.image_width = 480 66 | C.num_train_imgs = 20210 67 | C.num_eval_imgs = 1449 68 | 69 | """ Settings for network, this would be different for each kind of model""" 70 | C.fix_bias = True 71 | C.fix_bn = False 72 | C.sync_bn = True 73 | C.bn_eps = 1e-5 74 | C.bn_momentum = 0.1 75 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet101_v1c.pth" 76 | # C.pretrained_model = "/unsullied/sharefs/yuchangqian/Storage/model_zoo/pytorch_model/resnet50_v1c.pth" 77 | 78 | 79 | """Train Config""" 80 | C.lr = 1e-2 81 | C.lr_power = 0.9 82 | C.momentum = 0.9 83 | C.weight_decay = 1e-4 84 | C.batch_size = 16 # 4 * C.num_gpu 85 | C.nepochs = 120 86 | C.niters_per_epoch = int(np.ceil(C.num_train_imgs // C.batch_size)) 87 | C.num_workers = 24 88 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2] 89 | 90 | """Eval Config""" 91 | C.eval_iter = 30 92 | C.eval_stride_rate = 2 / 3 93 | C.eval_scale_array = [1, ] 94 | C.eval_flip = False 95 | C.eval_base_size = 480 96 | C.eval_crop_size = 480 97 | 98 | """Display Config""" 99 | C.snapshot_iter = 10 100 | C.record_info_iter = 20 101 | C.display_iter = 50 102 | 103 | 104 | def open_tensorboard(): 105 | pass 106 | 107 | 108 | if __name__ == '__main__': 109 | print(config.epoch_num) 110 | parser = argparse.ArgumentParser() 111 | parser.add_argument( 112 | '-tb', '--tensorboard', default=False, action='store_true') 113 | args = parser.parse_args() 114 | 115 | if args.tensorboard: 116 | open_tensorboard() 117 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R101_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std, target_size): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | self.target_size = target_size 16 | 17 | def __call__(self, img, gt): 18 | img, gt = random_mirror(img, gt) 19 | if config.train_scale_array is not None: 20 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 21 | 22 | img = normalize(img, self.img_mean, self.img_std) 23 | 24 | crop_size = (config.image_height, config.image_width) 25 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 26 | 27 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 28 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 0) 29 | 30 | p_img = p_img.transpose(2, 0, 1) 31 | p_gt = p_gt - 1 32 | 33 | extra_dict = None 34 | 35 | return p_img, p_gt, extra_dict 36 | 37 | 38 | def get_train_loader(engine, dataset): 39 | data_setting = {'img_root': config.img_root_folder, 40 | 'gt_root': config.gt_root_folder, 41 | 'train_source': config.train_source, 42 | 'eval_source': config.eval_source} 43 | train_preprocess = TrainPre(config.image_mean, config.image_std, 44 | config.target_size) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.niters_per_epoch * config.batch_size) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=False, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R101_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.ade import ADE 18 | from network import PSPNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | label = label - 1 29 | 30 | pred = self.sliding_eval(img, config.eval_crop_size, 31 | config.eval_stride_rate, device) 32 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 33 | pred, 34 | label) 35 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 36 | 'correct': correct_tmp} 37 | 38 | if self.save_path is not None: 39 | fn = name + '.png' 40 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 41 | logger.info('Save the image ' + fn) 42 | 43 | if self.show_image: 44 | colors = self.dataset.get_class_colors 45 | image = img 46 | clean = np.zeros(label.shape) 47 | comp_img = show_img(colors, config.background, image, clean, 48 | label, 49 | pred) 50 | cv2.imshow('comp_image', comp_img) 51 | cv2.waitKey(0) 52 | 53 | return results_dict 54 | 55 | def compute_metric(self, results): 56 | hist = np.zeros((config.num_classes, config.num_classes)) 57 | correct = 0 58 | labeled = 0 59 | count = 0 60 | for d in results: 61 | hist += d['hist'] 62 | correct += d['correct'] 63 | labeled += d['labeled'] 64 | count += 1 65 | 66 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 67 | labeled) 68 | result_line = print_iou(iu, mean_pixel_acc, 69 | dataset.get_class_names(), True) 70 | return result_line 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument('-e', '--epochs', default='last', type=str) 76 | parser.add_argument('-d', '--devices', default='1', type=str) 77 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 78 | parser.add_argument('--show_image', '-s', default=False, 79 | action='store_true') 80 | parser.add_argument('--save_path', '-p', default=None) 81 | 82 | args = parser.parse_args() 83 | all_dev = parse_devices(args.devices) 84 | 85 | mp_ctx = mp.get_context('spawn') 86 | network = PSPNet(config.num_classes, criterion=None) 87 | data_setting = {'img_root': config.img_root_folder, 88 | 'gt_root': config.gt_root_folder, 89 | 'train_source': config.train_source, 90 | 'eval_source': config.eval_source} 91 | dataset = ADE(data_setting, 'val', None) 92 | 93 | with torch.no_grad(): 94 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 95 | config.image_std, network, 96 | config.eval_scale_array, config.eval_flip, 97 | all_dev, args.verbose, args.save_path, 98 | args.show_image) 99 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 100 | config.link_val_log_file) 101 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R50_v1c/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os.path as osp 8 | import sys 9 | import time 10 | import numpy as np 11 | from easydict import EasyDict as edict 12 | import argparse 13 | 14 | import torch.utils.model_zoo as model_zoo 15 | 16 | C = edict() 17 | config = C 18 | cfg = C 19 | 20 | C.seed = 304 21 | 22 | """please config ROOT_dir and user when u first using""" 23 | C.repo_name = 'TorchSeg' 24 | C.abs_dir = osp.realpath(".") 25 | C.this_dir = C.abs_dir.split(osp.sep)[-1] 26 | C.root_dir = C.abs_dir[:C.abs_dir.index(C.repo_name) + len(C.repo_name)] 27 | C.log_dir = osp.abspath(osp.join(C.root_dir, 'log', C.this_dir)) 28 | C.log_dir_link = osp.join(C.abs_dir, 'log') 29 | C.snapshot_dir = osp.abspath(osp.join(C.log_dir, "snapshot")) 30 | 31 | exp_time = time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime()) 32 | C.log_file = C.log_dir + '/log_' + exp_time + '.log' 33 | C.link_log_file = C.log_file + '/log_last.log' 34 | C.val_log_file = C.log_dir + '/val_' + exp_time + '.log' 35 | C.link_val_log_file = C.log_dir + '/val_last.log' 36 | 37 | """Data Dir and Weight Dir""" 38 | C.dataset_path = "/root/Source/Datasets/Segmentation/ADE20K/ADE2017/" 39 | C.img_root_folder = osp.join(C.dataset_path, "images/") 40 | C.gt_root_folder = osp.join(C.dataset_path, "annotations_sceneparsing/") 41 | C.train_source = osp.join(C.dataset_path, "images/training.txt") 42 | C.eval_source = osp.join(C.dataset_path, "images/validation.txt") 43 | C.is_test = False 44 | 45 | """Path Config""" 46 | 47 | 48 | def add_path(path): 49 | if path not in sys.path: 50 | sys.path.insert(0, path) 51 | 52 | 53 | add_path(osp.join(C.root_dir, 'furnace')) 54 | 55 | 56 | """Image Config""" 57 | C.num_classes = 150 58 | C.background = -1 59 | C.image_mean = np.array([0.485, 0.456, 0.406]) # 0.485, 0.456, 0.406 60 | C.image_std = np.array([0.229, 0.224, 0.225]) 61 | C.target_size = 480 62 | C.image_height = 480 63 | C.image_width = 480 64 | C.num_train_imgs = 20210 65 | C.num_eval_imgs = 1449 66 | 67 | """ Settings for network, this would be different for each kind of model""" 68 | C.fix_bias = True 69 | C.fix_bn = False 70 | C.sync_bn = True 71 | C.bn_eps = 1e-5 72 | C.bn_momentum = 0.1 73 | C.pretrained_model = "/root/Source/model_zoo/pytorch_model/resnet50_v1c.pth" 74 | 75 | """Train Config""" 76 | C.lr = 1e-2 77 | C.lr_power = 0.9 78 | C.momentum = 0.9 79 | C.weight_decay = 1e-4 80 | C.batch_size = 16 # 4 * C.num_gpu 81 | C.nepochs = 120 82 | C.niters_per_epoch = int(np.ceil(C.num_train_imgs // C.batch_size)) 83 | C.num_workers = 24 84 | C.train_scale_array = [0.5, 0.75, 1, 1.5, 1.75, 2] 85 | 86 | """Eval Config""" 87 | C.eval_iter = 30 88 | C.eval_stride_rate = 2 / 3 89 | C.eval_scale_array = [1, ] 90 | C.eval_flip = False 91 | C.eval_base_size = 480 92 | C.eval_crop_size = 480 93 | 94 | """Display Config""" 95 | C.snapshot_iter = 10 96 | C.record_info_iter = 20 97 | C.display_iter = 50 98 | 99 | 100 | def open_tensorboard(): 101 | pass 102 | 103 | 104 | if __name__ == '__main__': 105 | print(config.epoch_num) 106 | parser = argparse.ArgumentParser() 107 | parser.add_argument( 108 | '-tb', '--tensorboard', default=False, action='store_true') 109 | args = parser.parse_args() 110 | 111 | if args.tensorboard: 112 | open_tensorboard() 113 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R50_v1c/dataloader.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | from torch.utils import data 5 | 6 | from config import config 7 | from utils.img_utils import random_scale, random_mirror, normalize, \ 8 | generate_random_crop_pos, random_crop_pad_to_shape 9 | 10 | 11 | class TrainPre(object): 12 | def __init__(self, img_mean, img_std, target_size): 13 | self.img_mean = img_mean 14 | self.img_std = img_std 15 | self.target_size = target_size 16 | 17 | def __call__(self, img, gt): 18 | img, gt = random_mirror(img, gt) 19 | if config.train_scale_array is not None: 20 | img, gt, scale = random_scale(img, gt, config.train_scale_array) 21 | 22 | img = normalize(img, self.img_mean, self.img_std) 23 | 24 | crop_size = (config.image_height, config.image_width) 25 | crop_pos = generate_random_crop_pos(img.shape[:2], crop_size) 26 | 27 | p_img, _ = random_crop_pad_to_shape(img, crop_pos, crop_size, 0) 28 | p_gt, _ = random_crop_pad_to_shape(gt, crop_pos, crop_size, 0) 29 | 30 | p_img = p_img.transpose(2, 0, 1) 31 | p_gt = p_gt - 1 32 | 33 | extra_dict = None 34 | 35 | return p_img, p_gt, extra_dict 36 | 37 | 38 | def get_train_loader(engine, dataset): 39 | data_setting = {'img_root': config.img_root_folder, 40 | 'gt_root': config.gt_root_folder, 41 | 'train_source': config.train_source, 42 | 'eval_source': config.eval_source} 43 | train_preprocess = TrainPre(config.image_mean, config.image_std, 44 | config.target_size) 45 | 46 | train_dataset = dataset(data_setting, "train", train_preprocess, 47 | config.niters_per_epoch * config.batch_size) 48 | 49 | train_sampler = None 50 | is_shuffle = True 51 | batch_size = config.batch_size 52 | 53 | if engine.distributed: 54 | train_sampler = torch.utils.data.distributed.DistributedSampler( 55 | train_dataset) 56 | batch_size = config.batch_size // engine.world_size 57 | is_shuffle = False 58 | 59 | train_loader = data.DataLoader(train_dataset, 60 | batch_size=batch_size, 61 | num_workers=config.num_workers, 62 | drop_last=False, 63 | shuffle=is_shuffle, 64 | pin_memory=True, 65 | sampler=train_sampler) 66 | 67 | return train_loader, train_sampler 68 | -------------------------------------------------------------------------------- /model/pspnet/ade.pspnet.R50_v1c/eval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | import os 4 | import cv2 5 | import argparse 6 | import numpy as np 7 | 8 | import torch 9 | import torch.multiprocessing as mp 10 | 11 | from config import config 12 | from utils.pyt_utils import ensure_dir, link_file, load_model, parse_devices 13 | from utils.visualize import print_iou, show_img 14 | from engine.evaluator import Evaluator 15 | from engine.logger import get_logger 16 | from seg_opr.metric import hist_info, compute_score 17 | from datasets.ade import ADE 18 | from network import PSPNet 19 | 20 | logger = get_logger() 21 | 22 | 23 | class SegEvaluator(Evaluator): 24 | def func_per_iteration(self, data, device): 25 | img = data['data'] 26 | label = data['label'] 27 | name = data['fn'] 28 | label = label - 1 29 | 30 | pred = self.sliding_eval(img, config.eval_crop_size, 31 | config.eval_stride_rate, device) 32 | hist_tmp, labeled_tmp, correct_tmp = hist_info(config.num_classes, 33 | pred, 34 | label) 35 | results_dict = {'hist': hist_tmp, 'labeled': labeled_tmp, 36 | 'correct': correct_tmp} 37 | 38 | if self.save_path is not None: 39 | fn = name + '.png' 40 | cv2.imwrite(os.path.join(self.save_path, fn), pred) 41 | logger.info('Save the image ' + fn) 42 | 43 | if self.show_image: 44 | colors = self.dataset.get_class_colors 45 | image = img 46 | clean = np.zeros(label.shape) 47 | comp_img = show_img(colors, config.background, image, clean, 48 | label, 49 | pred) 50 | cv2.imshow('comp_image', comp_img) 51 | cv2.waitKey(0) 52 | 53 | return results_dict 54 | 55 | def compute_metric(self, results): 56 | hist = np.zeros((config.num_classes, config.num_classes)) 57 | correct = 0 58 | labeled = 0 59 | count = 0 60 | for d in results: 61 | hist += d['hist'] 62 | correct += d['correct'] 63 | labeled += d['labeled'] 64 | count += 1 65 | 66 | iu, mean_IU, _, mean_pixel_acc = compute_score(hist, correct, 67 | labeled) 68 | result_line = print_iou(iu, mean_pixel_acc, 69 | dataset.get_class_names(), True) 70 | return result_line 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument('-e', '--epochs', default='last', type=str) 76 | parser.add_argument('-d', '--devices', default='1', type=str) 77 | parser.add_argument('-v', '--verbose', default=False, action='store_true') 78 | parser.add_argument('--show_image', '-s', default=False, 79 | action='store_true') 80 | parser.add_argument('--save_path', '-p', default=None) 81 | 82 | args = parser.parse_args() 83 | all_dev = parse_devices(args.devices) 84 | 85 | mp_ctx = mp.get_context('spawn') 86 | network = PSPNet(config.num_classes, criterion=None) 87 | data_setting = {'img_root': config.img_root_folder, 88 | 'gt_root': config.gt_root_folder, 89 | 'train_source': config.train_source, 90 | 'eval_source': config.eval_source} 91 | dataset = ADE(data_setting, 'val', None) 92 | 93 | with torch.no_grad(): 94 | segmentor = SegEvaluator(dataset, config.num_classes, config.image_mean, 95 | config.image_std, network, 96 | config.eval_scale_array, config.eval_flip, 97 | all_dev, args.verbose, args.save_path, 98 | args.show_image) 99 | segmentor.run(config.snapshot_dir, args.epochs, config.val_log_file, 100 | config.link_val_log_file) 101 | -------------------------------------------------------------------------------- /stuttgart_00.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/stuttgart_00.avi -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame0.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame1.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame10.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame11.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame2.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame3.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame4.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame5.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame6.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame7.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame8.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/mv_cont/frame9.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame0.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame1.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame10.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame11.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame2.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame3.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame4.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame5.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame6.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame7.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame8.png -------------------------------------------------------------------------------- /val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/l/lindau_000000_000019_leftImg8bit/res_cont/frame9.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000000_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000000_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000001_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000001_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000002_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000002_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000003_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000003_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000004_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000004_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000005_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000005_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000006_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000006_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000007_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000007_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000008_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000008_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000009_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000009_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000010_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000010_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000011_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000011_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000012_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000012_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000013_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000013_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000014_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000014_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000015_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000015_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000016_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000016_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000017_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000017_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000018_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000018_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000019_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000019_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000020_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000020_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000021_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000021_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000022_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000022_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000023_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000023_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000024_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000024_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000025_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000025_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000026_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000026_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000027_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000027_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000028_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000028_leftImg8bit.png -------------------------------------------------------------------------------- /val_sequence/lindau/lindau_000000_000029_leftImg8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sixkplus/TapLab/319801b5f5b3eb343bead74c5c4ffc21ab5236d3/val_sequence/lindau/lindau_000000_000029_leftImg8bit.png --------------------------------------------------------------------------------