From ff37838d40b480c067ddcc8df22445677a960197 Mon Sep 17 00:00:00 2001 From: vaslem Date: Mon, 1 Jul 2019 02:22:48 +0300 Subject: [PATCH] Moved files to subfolder and exposed scripts to console-scripts setuptools mechanism. Now the user can call them by issuing the command faster_rcnn_NAME_OF_THE_SCRIPT in terminal or cmd --- MANIFEST.in | 1 + demo.py | 380 ----------------- {lib/model => faster_rcnn}/__init__.py | 0 _init_paths.py => faster_rcnn/_init_paths.py | 2 + {cfgs => faster_rcnn/cfgs}/res101.yml | 0 {cfgs => faster_rcnn/cfgs}/res101_ls.yml | 0 {cfgs => faster_rcnn/cfgs}/res50.yml | 0 {cfgs => faster_rcnn/cfgs}/vgg16.yml | 0 {images => faster_rcnn/images}/img1.jpg | Bin {images => faster_rcnn/images}/img1_det.jpg | Bin .../images}/img1_det_res101.jpg | Bin {images => faster_rcnn/images}/img2.jpg | Bin {images => faster_rcnn/images}/img2_det.jpg | Bin .../images}/img2_det_res101.jpg | Bin {images => faster_rcnn/images}/img3.jpg | Bin {images => faster_rcnn/images}/img3_det.jpg | Bin .../images}/img3_det_res101.jpg | Bin {images => faster_rcnn/images}/img4.jpg | Bin {images => faster_rcnn/images}/img4_det.jpg | Bin .../images}/img4_det_res101.jpg | Bin .../lib}/__init__.py | 0 .../VOCdevkit-matlab-wrapper/get_voc_opts.m | 0 .../VOCdevkit-matlab-wrapper/voc_eval.m | 0 .../VOCdevkit-matlab-wrapper/xVOCap.m | 0 {lib => faster_rcnn/lib}/datasets/__init__.py | 0 {lib => faster_rcnn/lib}/datasets/coco.py | 2 +- {lib => faster_rcnn/lib}/datasets/ds_utils.py | 0 {lib => faster_rcnn/lib}/datasets/factory.py | 0 {lib => faster_rcnn/lib}/datasets/imagenet.py | 0 {lib => faster_rcnn/lib}/datasets/imdb.py | 4 +- .../lib}/datasets/pascal_voc.py | 2 +- .../lib}/datasets/pascal_voc_rbg.py | 2 +- .../lib}/datasets/tools/mcg_munge.py | 0 {lib => faster_rcnn/lib}/datasets/vg.py | 2 +- {lib => faster_rcnn/lib}/datasets/vg_eval.py | 0 {lib => faster_rcnn/lib}/datasets/voc_eval.py | 0 .../nms => faster_rcnn/lib/model}/__init__.py | 0 .../lib}/model/csrc/ROIAlign.h | 0 {lib => faster_rcnn/lib}/model/csrc/ROIPool.h | 0 .../lib}/model/csrc/cpu/ROIAlign_cpu.cpp | 0 .../lib}/model/csrc/cpu/nms_cpu.cpp | 0 .../lib}/model/csrc/cpu/vision.h | 0 .../lib}/model/csrc/cuda/ROIAlign_cuda.cu | 0 .../lib}/model/csrc/cuda/ROIPool_cuda.cu | 0 .../lib}/model/csrc/cuda/nms.cu | 0 .../lib}/model/csrc/cuda/vision.h | 0 {lib => faster_rcnn/lib}/model/csrc/nms.h | 0 .../lib}/model/csrc/vision.cpp | 0 .../lib/model/faster_rcnn}/__init__.py | 0 .../lib}/model/faster_rcnn/faster_rcnn.py | 14 +- .../lib}/model/faster_rcnn/resnet.py | 4 +- .../lib}/model/faster_rcnn/vgg16.py | 6 +- {lib => faster_rcnn/lib}/model/nms/.gitignore | 0 .../lib/model/nms}/__init__.py | 0 .../lib/model/nms}/_ext/__init__.py | 0 .../lib}/model/nms/_ext/nms/__init__.py | 0 {lib => faster_rcnn/lib}/model/nms/build.py | 0 {lib => faster_rcnn/lib}/model/nms/make.sh | 0 {lib => faster_rcnn/lib}/model/nms/nms_cpu.py | 0 {lib => faster_rcnn/lib}/model/nms/nms_gpu.py | 0 .../lib}/model/nms/nms_kernel.cu | 0 .../lib}/model/nms/nms_wrapper.py | 6 +- .../lib}/model/nms/src/nms_cuda.h | 0 .../lib}/model/nms/src/nms_cuda_kernel.cu | 0 .../lib}/model/nms/src/nms_cuda_kernel.h | 0 .../lib/model/roi_align}/__init__.py | 0 .../lib/model/roi_align/_ext}/__init__.py | 0 .../roi_align/_ext/roi_align/__init__.py | 0 .../lib}/model/roi_align/build.py | 0 .../model/roi_align/functions}/__init__.py | 0 .../model/roi_align/functions/roi_align.py | 0 .../lib}/model/roi_align/make.sh | 0 .../lib/model/roi_align/modules}/__init__.py | 0 .../lib}/model/roi_align/modules/roi_align.py | 0 .../lib}/model/roi_align/src/roi_align.c | 0 .../lib}/model/roi_align/src/roi_align.h | 0 .../lib}/model/roi_align/src/roi_align_cuda.c | 0 .../lib}/model/roi_align/src/roi_align_cuda.h | 0 .../model/roi_align/src/roi_align_kernel.cu | 0 .../model/roi_align/src/roi_align_kernel.h | 0 .../lib/model/roi_crop}/__init__.py | 0 .../lib/model/roi_crop/_ext}/__init__.py | 0 .../roi_crop/_ext/crop_resize/__init__.py | 0 .../model/roi_crop/_ext/roi_crop/__init__.py | 0 .../lib}/model/roi_crop/build.py | 0 .../lib/model/roi_crop/functions}/__init__.py | 0 .../model/roi_crop/functions/crop_resize.py | 0 .../lib}/model/roi_crop/functions/gridgen.py | 0 .../lib}/model/roi_crop/functions/roi_crop.py | 0 .../lib}/model/roi_crop/make.sh | 0 .../lib/model/roi_crop/modules}/__init__.py | 0 .../lib}/model/roi_crop/modules/gridgen.py | 0 .../lib}/model/roi_crop/modules/roi_crop.py | 0 .../lib}/model/roi_crop/src/roi_crop.c | 0 .../lib}/model/roi_crop/src/roi_crop.h | 0 .../lib}/model/roi_crop/src/roi_crop_cuda.c | 0 .../lib}/model/roi_crop/src/roi_crop_cuda.h | 0 .../roi_crop/src/roi_crop_cuda_kernel.cu | 0 .../model/roi_crop/src/roi_crop_cuda_kernel.h | 0 .../lib}/model/roi_layers/__init__.py | 0 .../lib}/model/roi_layers/nms.py | 2 +- .../lib}/model/roi_layers/roi_align.py | 2 +- .../lib}/model/roi_layers/roi_pool.py | 2 +- .../lib/model/roi_pooling}/__init__.py | 0 .../lib/model/roi_pooling/_ext}/__init__.py | 0 .../roi_pooling/_ext/roi_pooling/__init__.py | 0 .../lib}/model/roi_pooling/build.py | 0 .../model/roi_pooling/functions}/__init__.py | 0 .../model/roi_pooling/functions/roi_pool.py | 0 .../model/roi_pooling/modules}/__init__.py | 0 .../model/roi_pooling/modules/roi_pool.py | 0 .../lib}/model/roi_pooling/src/roi_pooling.c | 0 .../lib}/model/roi_pooling/src/roi_pooling.h | 0 .../model/roi_pooling/src/roi_pooling_cuda.c | 0 .../model/roi_pooling/src/roi_pooling_cuda.h | 0 .../roi_pooling/src/roi_pooling_kernel.cu | 0 .../roi_pooling/src/roi_pooling_kernel.h | 0 faster_rcnn/lib/model/rpn/__init__.py | 0 .../lib}/model/rpn/anchor_target_layer.py | 2 +- .../lib}/model/rpn/bbox_transform.py | 0 .../lib}/model/rpn/generate_anchors.py | 0 .../lib}/model/rpn/proposal_layer.py | 6 +- .../rpn/proposal_target_layer_cascade.py | 0 {lib => faster_rcnn/lib}/model/rpn/rpn.py | 6 +- .../lib}/model/utils/.gitignore | 0 faster_rcnn/lib/model/utils/__init__.py | 0 {lib => faster_rcnn/lib}/model/utils/bbox.pyx | 0 {lib => faster_rcnn/lib}/model/utils/blob.py | 2 +- .../lib}/model/utils/config.py | 0 .../lib}/model/utils/logger.py | 0 .../lib}/model/utils/net_utils.py | 2 +- .../lib}/pycocotools/UPSTREAM_REV | 0 .../lib}/pycocotools/__init__.py | 0 {lib => faster_rcnn/lib}/pycocotools/_mask.c | 0 .../lib}/pycocotools/_mask.pyx | 0 {lib => faster_rcnn/lib}/pycocotools/coco.py | 0 .../lib}/pycocotools/cocoeval.py | 0 .../lib}/pycocotools/license.txt | 0 {lib => faster_rcnn/lib}/pycocotools/mask.py | 0 .../lib}/pycocotools/maskApi.c | 0 .../lib}/pycocotools/maskApi.h | 0 .../lib}/roi_data_layer/__init__.py | 0 .../lib}/roi_data_layer/minibatch.py | 10 +- .../lib}/roi_data_layer/roibatchLoader.py | 8 +- .../lib}/roi_data_layer/roidb.py | 12 +- faster_rcnn/scripts/__init__.py | 0 faster_rcnn/scripts/demo.py | 398 ++++++++++++++++++ .../scripts/test_net.py | 33 +- .../scripts/trainval_net.py | 21 +- lib/model/nms/src/nms_cuda.c | 19 - .../roi_crop/_ext/crop_resize/_crop_resize.so | Bin 159103 -> 0 bytes lib/setup.py => setup.py | 32 +- 152 files changed, 505 insertions(+), 477 deletions(-) create mode 100644 MANIFEST.in delete mode 100644 demo.py rename {lib/model => faster_rcnn}/__init__.py (100%) rename _init_paths.py => faster_rcnn/_init_paths.py (85%) rename {cfgs => faster_rcnn/cfgs}/res101.yml (100%) rename {cfgs => faster_rcnn/cfgs}/res101_ls.yml (100%) rename {cfgs => faster_rcnn/cfgs}/res50.yml (100%) rename {cfgs => faster_rcnn/cfgs}/vgg16.yml (100%) rename {images => faster_rcnn/images}/img1.jpg (100%) rename {images => faster_rcnn/images}/img1_det.jpg (100%) rename {images => faster_rcnn/images}/img1_det_res101.jpg (100%) rename {images => faster_rcnn/images}/img2.jpg (100%) rename {images => faster_rcnn/images}/img2_det.jpg (100%) rename {images => faster_rcnn/images}/img2_det_res101.jpg (100%) rename {images => faster_rcnn/images}/img3.jpg (100%) rename {images => faster_rcnn/images}/img3_det.jpg (100%) rename {images => faster_rcnn/images}/img3_det_res101.jpg (100%) rename {images => faster_rcnn/images}/img4.jpg (100%) rename {images => faster_rcnn/images}/img4_det.jpg (100%) rename {images => faster_rcnn/images}/img4_det_res101.jpg (100%) rename {lib/model/faster_rcnn => faster_rcnn/lib}/__init__.py (100%) rename {lib => faster_rcnn/lib}/datasets/VOCdevkit-matlab-wrapper/get_voc_opts.m (100%) rename {lib => faster_rcnn/lib}/datasets/VOCdevkit-matlab-wrapper/voc_eval.m (100%) rename {lib => faster_rcnn/lib}/datasets/VOCdevkit-matlab-wrapper/xVOCap.m (100%) rename {lib => faster_rcnn/lib}/datasets/__init__.py (100%) rename {lib => faster_rcnn/lib}/datasets/coco.py (99%) rename {lib => faster_rcnn/lib}/datasets/ds_utils.py (100%) rename {lib => faster_rcnn/lib}/datasets/factory.py (100%) rename {lib => faster_rcnn/lib}/datasets/imagenet.py (100%) rename {lib => faster_rcnn/lib}/datasets/imdb.py (98%) rename {lib => faster_rcnn/lib}/datasets/pascal_voc.py (99%) rename {lib => faster_rcnn/lib}/datasets/pascal_voc_rbg.py (99%) rename {lib => faster_rcnn/lib}/datasets/tools/mcg_munge.py (100%) rename {lib => faster_rcnn/lib}/datasets/vg.py (99%) rename {lib => faster_rcnn/lib}/datasets/vg_eval.py (100%) rename {lib => faster_rcnn/lib}/datasets/voc_eval.py (100%) rename {lib/model/nms => faster_rcnn/lib/model}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/csrc/ROIAlign.h (100%) rename {lib => faster_rcnn/lib}/model/csrc/ROIPool.h (100%) rename {lib => faster_rcnn/lib}/model/csrc/cpu/ROIAlign_cpu.cpp (100%) rename {lib => faster_rcnn/lib}/model/csrc/cpu/nms_cpu.cpp (100%) rename {lib => faster_rcnn/lib}/model/csrc/cpu/vision.h (100%) rename {lib => faster_rcnn/lib}/model/csrc/cuda/ROIAlign_cuda.cu (100%) rename {lib => faster_rcnn/lib}/model/csrc/cuda/ROIPool_cuda.cu (100%) rename {lib => faster_rcnn/lib}/model/csrc/cuda/nms.cu (100%) rename {lib => faster_rcnn/lib}/model/csrc/cuda/vision.h (100%) rename {lib => faster_rcnn/lib}/model/csrc/nms.h (100%) rename {lib => faster_rcnn/lib}/model/csrc/vision.cpp (100%) rename {lib/model/nms/_ext => faster_rcnn/lib/model/faster_rcnn}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/faster_rcnn/faster_rcnn.py (90%) rename {lib => faster_rcnn/lib}/model/faster_rcnn/resnet.py (98%) rename {lib => faster_rcnn/lib}/model/faster_rcnn/vgg16.py (93%) rename {lib => faster_rcnn/lib}/model/nms/.gitignore (100%) rename {lib/model/roi_align => faster_rcnn/lib/model/nms}/__init__.py (100%) rename {lib/model/roi_align => faster_rcnn/lib/model/nms}/_ext/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/nms/_ext/nms/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/nms/build.py (100%) rename {lib => faster_rcnn/lib}/model/nms/make.sh (100%) rename {lib => faster_rcnn/lib}/model/nms/nms_cpu.py (100%) rename {lib => faster_rcnn/lib}/model/nms/nms_gpu.py (100%) rename {lib => faster_rcnn/lib}/model/nms/nms_kernel.cu (100%) rename {lib => faster_rcnn/lib}/model/nms/nms_wrapper.py (79%) rename {lib => faster_rcnn/lib}/model/nms/src/nms_cuda.h (100%) rename {lib => faster_rcnn/lib}/model/nms/src/nms_cuda_kernel.cu (100%) rename {lib => faster_rcnn/lib}/model/nms/src/nms_cuda_kernel.h (100%) rename {lib/model/roi_align/functions => faster_rcnn/lib/model/roi_align}/__init__.py (100%) rename {lib/model/roi_align/modules => faster_rcnn/lib/model/roi_align/_ext}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/_ext/roi_align/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/build.py (100%) rename {lib/model/roi_crop => faster_rcnn/lib/model/roi_align/functions}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/functions/roi_align.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/make.sh (100%) rename {lib/model/roi_crop/_ext => faster_rcnn/lib/model/roi_align/modules}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/modules/roi_align.py (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align.c (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align.h (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align_cuda.c (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align_cuda.h (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align_kernel.cu (100%) rename {lib => faster_rcnn/lib}/model/roi_align/src/roi_align_kernel.h (100%) rename {lib/model/roi_crop/functions => faster_rcnn/lib/model/roi_crop}/__init__.py (100%) rename {lib/model/roi_crop/modules => faster_rcnn/lib/model/roi_crop/_ext}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/_ext/crop_resize/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/_ext/roi_crop/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/build.py (100%) rename {lib/model/roi_pooling => faster_rcnn/lib/model/roi_crop/functions}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/functions/crop_resize.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/functions/gridgen.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/functions/roi_crop.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/make.sh (100%) rename {lib/model/roi_pooling/_ext => faster_rcnn/lib/model/roi_crop/modules}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/modules/gridgen.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/modules/roi_crop.py (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop.c (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop.h (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop_cuda.c (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop_cuda.h (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop_cuda_kernel.cu (100%) rename {lib => faster_rcnn/lib}/model/roi_crop/src/roi_crop_cuda_kernel.h (100%) rename {lib => faster_rcnn/lib}/model/roi_layers/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_layers/nms.py (83%) rename {lib => faster_rcnn/lib}/model/roi_layers/roi_align.py (98%) rename {lib => faster_rcnn/lib}/model/roi_layers/roi_pool.py (98%) rename {lib/model/roi_pooling/functions => faster_rcnn/lib/model/roi_pooling}/__init__.py (100%) rename {lib/model/roi_pooling/modules => faster_rcnn/lib/model/roi_pooling/_ext}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/_ext/roi_pooling/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/build.py (100%) rename {lib/model/rpn => faster_rcnn/lib/model/roi_pooling/functions}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/functions/roi_pool.py (100%) rename {lib/model/utils => faster_rcnn/lib/model/roi_pooling/modules}/__init__.py (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/modules/roi_pool.py (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling.c (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling.h (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling_cuda.c (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling_cuda.h (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling_kernel.cu (100%) rename {lib => faster_rcnn/lib}/model/roi_pooling/src/roi_pooling_kernel.h (100%) create mode 100644 faster_rcnn/lib/model/rpn/__init__.py rename {lib => faster_rcnn/lib}/model/rpn/anchor_target_layer.py (99%) rename {lib => faster_rcnn/lib}/model/rpn/bbox_transform.py (100%) rename {lib => faster_rcnn/lib}/model/rpn/generate_anchors.py (100%) rename {lib => faster_rcnn/lib}/model/rpn/proposal_layer.py (97%) rename {lib => faster_rcnn/lib}/model/rpn/proposal_target_layer_cascade.py (100%) rename {lib => faster_rcnn/lib}/model/rpn/rpn.py (97%) rename {lib => faster_rcnn/lib}/model/utils/.gitignore (100%) create mode 100644 faster_rcnn/lib/model/utils/__init__.py rename {lib => faster_rcnn/lib}/model/utils/bbox.pyx (100%) rename {lib => faster_rcnn/lib}/model/utils/blob.py (97%) rename {lib => faster_rcnn/lib}/model/utils/config.py (100%) rename {lib => faster_rcnn/lib}/model/utils/logger.py (100%) rename {lib => faster_rcnn/lib}/model/utils/net_utils.py (99%) rename {lib => faster_rcnn/lib}/pycocotools/UPSTREAM_REV (100%) rename {lib => faster_rcnn/lib}/pycocotools/__init__.py (100%) rename {lib => faster_rcnn/lib}/pycocotools/_mask.c (100%) rename {lib => faster_rcnn/lib}/pycocotools/_mask.pyx (100%) rename {lib => faster_rcnn/lib}/pycocotools/coco.py (100%) rename {lib => faster_rcnn/lib}/pycocotools/cocoeval.py (100%) rename {lib => faster_rcnn/lib}/pycocotools/license.txt (100%) rename {lib => faster_rcnn/lib}/pycocotools/mask.py (100%) rename {lib => faster_rcnn/lib}/pycocotools/maskApi.c (100%) rename {lib => faster_rcnn/lib}/pycocotools/maskApi.h (100%) rename {lib => faster_rcnn/lib}/roi_data_layer/__init__.py (100%) rename {lib => faster_rcnn/lib}/roi_data_layer/minibatch.py (94%) rename {lib => faster_rcnn/lib}/roi_data_layer/roibatchLoader.py (97%) rename {lib => faster_rcnn/lib}/roi_data_layer/roidb.py (96%) create mode 100644 faster_rcnn/scripts/__init__.py create mode 100644 faster_rcnn/scripts/demo.py rename test_net.py => faster_rcnn/scripts/test_net.py (92%) rename trainval_net.py => faster_rcnn/scripts/trainval_net.py (97%) delete mode 100644 lib/model/nms/src/nms_cuda.c delete mode 100755 lib/model/roi_crop/_ext/crop_resize/_crop_resize.so rename lib/setup.py => setup.py (62%) diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..ba734d257 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include faster_rcnn * \ No newline at end of file diff --git a/demo.py b/demo.py deleted file mode 100644 index af78b0986..000000000 --- a/demo.py +++ /dev/null @@ -1,380 +0,0 @@ -# -------------------------------------------------------- -# Tensorflow Faster R-CNN -# Licensed under The MIT License [see LICENSE for details] -# Written by Jiasen Lu, Jianwei Yang, based on code from Ross Girshick -# -------------------------------------------------------- -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import _init_paths -import os -import sys -import numpy as np -import argparse -import pprint -import pdb -import time -import cv2 -import torch -from torch.autograd import Variable -import torch.nn as nn -import torch.optim as optim - -import torchvision.transforms as transforms -import torchvision.datasets as dset -from scipy.misc import imread -from roi_data_layer.roidb import combined_roidb -from roi_data_layer.roibatchLoader import roibatchLoader -from model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir -from model.rpn.bbox_transform import clip_boxes -# from model.nms.nms_wrapper import nms -from model.roi_layers import nms -from model.rpn.bbox_transform import bbox_transform_inv -from model.utils.net_utils import save_net, load_net, vis_detections -from model.utils.blob import im_list_to_blob -from model.faster_rcnn.vgg16 import vgg16 -from model.faster_rcnn.resnet import resnet -import pdb - -try: - xrange # Python 2 -except NameError: - xrange = range # Python 3 - - -def parse_args(): - """ - Parse input arguments - """ - parser = argparse.ArgumentParser(description='Train a Fast R-CNN network') - parser.add_argument('--dataset', dest='dataset', - help='training dataset', - default='pascal_voc', type=str) - parser.add_argument('--cfg', dest='cfg_file', - help='optional config file', - default='cfgs/vgg16.yml', type=str) - parser.add_argument('--net', dest='net', - help='vgg16, res50, res101, res152', - default='res101', type=str) - parser.add_argument('--set', dest='set_cfgs', - help='set config keys', default=None, - nargs=argparse.REMAINDER) - parser.add_argument('--load_dir', dest='load_dir', - help='directory to load models', - default="/srv/share/jyang375/models") - parser.add_argument('--image_dir', dest='image_dir', - help='directory to load images for demo', - default="images") - parser.add_argument('--cuda', dest='cuda', - help='whether use CUDA', - action='store_true') - parser.add_argument('--mGPUs', dest='mGPUs', - help='whether use multiple GPUs', - action='store_true') - parser.add_argument('--cag', dest='class_agnostic', - help='whether perform class_agnostic bbox regression', - action='store_true') - parser.add_argument('--parallel_type', dest='parallel_type', - help='which part of model to parallel, 0: all, 1: model before roi pooling', - default=0, type=int) - parser.add_argument('--checksession', dest='checksession', - help='checksession to load model', - default=1, type=int) - parser.add_argument('--checkepoch', dest='checkepoch', - help='checkepoch to load network', - default=1, type=int) - parser.add_argument('--checkpoint', dest='checkpoint', - help='checkpoint to load network', - default=10021, type=int) - parser.add_argument('--bs', dest='batch_size', - help='batch_size', - default=1, type=int) - parser.add_argument('--vis', dest='vis', - help='visualization mode', - action='store_true') - parser.add_argument('--webcam_num', dest='webcam_num', - help='webcam ID number', - default=-1, type=int) - - args = parser.parse_args() - return args - -lr = cfg.TRAIN.LEARNING_RATE -momentum = cfg.TRAIN.MOMENTUM -weight_decay = cfg.TRAIN.WEIGHT_DECAY - -def _get_image_blob(im): - """Converts an image into a network input. - Arguments: - im (ndarray): a color image in BGR order - Returns: - blob (ndarray): a data blob holding an image pyramid - im_scale_factors (list): list of image scales (relative to im) used - in the image pyramid - """ - im_orig = im.astype(np.float32, copy=True) - im_orig -= cfg.PIXEL_MEANS - - im_shape = im_orig.shape - im_size_min = np.min(im_shape[0:2]) - im_size_max = np.max(im_shape[0:2]) - - processed_ims = [] - im_scale_factors = [] - - for target_size in cfg.TEST.SCALES: - im_scale = float(target_size) / float(im_size_min) - # Prevent the biggest axis from being more than MAX_SIZE - if np.round(im_scale * im_size_max) > cfg.TEST.MAX_SIZE: - im_scale = float(cfg.TEST.MAX_SIZE) / float(im_size_max) - im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale, - interpolation=cv2.INTER_LINEAR) - im_scale_factors.append(im_scale) - processed_ims.append(im) - - # Create a blob to hold the input images - blob = im_list_to_blob(processed_ims) - - return blob, np.array(im_scale_factors) - -if __name__ == '__main__': - - args = parse_args() - - print('Called with args:') - print(args) - - if args.cfg_file is not None: - cfg_from_file(args.cfg_file) - if args.set_cfgs is not None: - cfg_from_list(args.set_cfgs) - - cfg.USE_GPU_NMS = args.cuda - - print('Using config:') - pprint.pprint(cfg) - np.random.seed(cfg.RNG_SEED) - - # train set - # -- Note: Use validation set and disable the flipped to enable faster loading. - - input_dir = args.load_dir + "/" + args.net + "/" + args.dataset - if not os.path.exists(input_dir): - raise Exception('There is no input directory for loading network from ' + input_dir) - load_name = os.path.join(input_dir, - 'faster_rcnn_{}_{}_{}.pth'.format(args.checksession, args.checkepoch, args.checkpoint)) - - pascal_classes = np.asarray(['__background__', - 'aeroplane', 'bicycle', 'bird', 'boat', - 'bottle', 'bus', 'car', 'cat', 'chair', - 'cow', 'diningtable', 'dog', 'horse', - 'motorbike', 'person', 'pottedplant', - 'sheep', 'sofa', 'train', 'tvmonitor']) - - # initilize the network here. - if args.net == 'vgg16': - fasterRCNN = vgg16(pascal_classes, pretrained=False, class_agnostic=args.class_agnostic) - elif args.net == 'res101': - fasterRCNN = resnet(pascal_classes, 101, pretrained=False, class_agnostic=args.class_agnostic) - elif args.net == 'res50': - fasterRCNN = resnet(pascal_classes, 50, pretrained=False, class_agnostic=args.class_agnostic) - elif args.net == 'res152': - fasterRCNN = resnet(pascal_classes, 152, pretrained=False, class_agnostic=args.class_agnostic) - else: - print("network is not defined") - pdb.set_trace() - - fasterRCNN.create_architecture() - - print("load checkpoint %s" % (load_name)) - if args.cuda > 0: - checkpoint = torch.load(load_name) - else: - checkpoint = torch.load(load_name, map_location=(lambda storage, loc: storage)) - fasterRCNN.load_state_dict(checkpoint['model']) - if 'pooling_mode' in checkpoint.keys(): - cfg.POOLING_MODE = checkpoint['pooling_mode'] - - - print('load model successfully!') - - # pdb.set_trace() - - print("load checkpoint %s" % (load_name)) - - # initilize the tensor holder here. - im_data = torch.FloatTensor(1) - im_info = torch.FloatTensor(1) - num_boxes = torch.LongTensor(1) - gt_boxes = torch.FloatTensor(1) - - # ship to cuda - if args.cuda > 0: - im_data = im_data.cuda() - im_info = im_info.cuda() - num_boxes = num_boxes.cuda() - gt_boxes = gt_boxes.cuda() - - # make variable - im_data = Variable(im_data, volatile=True) - im_info = Variable(im_info, volatile=True) - num_boxes = Variable(num_boxes, volatile=True) - gt_boxes = Variable(gt_boxes, volatile=True) - - if args.cuda > 0: - cfg.CUDA = True - - if args.cuda > 0: - fasterRCNN.cuda() - - fasterRCNN.eval() - - start = time.time() - max_per_image = 100 - thresh = 0.05 - vis = True - - webcam_num = args.webcam_num - # Set up webcam or get image directories - if webcam_num >= 0 : - cap = cv2.VideoCapture(webcam_num) - num_images = 0 - else: - imglist = os.listdir(args.image_dir) - num_images = len(imglist) - - print('Loaded Photo: {} images.'.format(num_images)) - - - while (num_images >= 0): - total_tic = time.time() - if webcam_num == -1: - num_images -= 1 - - # Get image from the webcam - if webcam_num >= 0: - if not cap.isOpened(): - raise RuntimeError("Webcam could not open. Please check connection.") - ret, frame = cap.read() - im_in = np.array(frame) - # Load the demo image - else: - im_file = os.path.join(args.image_dir, imglist[num_images]) - # im = cv2.imread(im_file) - im_in = np.array(imread(im_file)) - if len(im_in.shape) == 2: - im_in = im_in[:,:,np.newaxis] - im_in = np.concatenate((im_in,im_in,im_in), axis=2) - # rgb -> bgr - im = im_in[:,:,::-1] - - blobs, im_scales = _get_image_blob(im) - assert len(im_scales) == 1, "Only single-image batch implemented" - im_blob = blobs - im_info_np = np.array([[im_blob.shape[1], im_blob.shape[2], im_scales[0]]], dtype=np.float32) - - im_data_pt = torch.from_numpy(im_blob) - im_data_pt = im_data_pt.permute(0, 3, 1, 2) - im_info_pt = torch.from_numpy(im_info_np) - - with torch.no_grad(): - im_data.resize_(im_data_pt.size()).copy_(im_data_pt) - im_info.resize_(im_info_pt.size()).copy_(im_info_pt) - gt_boxes.resize_(1, 1, 5).zero_() - num_boxes.resize_(1).zero_() - - # pdb.set_trace() - det_tic = time.time() - - rois, cls_prob, bbox_pred, \ - rpn_loss_cls, rpn_loss_box, \ - RCNN_loss_cls, RCNN_loss_bbox, \ - rois_label = fasterRCNN(im_data, im_info, gt_boxes, num_boxes) - - scores = cls_prob.data - boxes = rois.data[:, :, 1:5] - - if cfg.TEST.BBOX_REG: - # Apply bounding-box regression deltas - box_deltas = bbox_pred.data - if cfg.TRAIN.BBOX_NORMALIZE_TARGETS_PRECOMPUTED: - # Optionally normalize targets by a precomputed mean and stdev - if args.class_agnostic: - if args.cuda > 0: - box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS).cuda() \ - + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS).cuda() - else: - box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS) \ - + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS) - - box_deltas = box_deltas.view(1, -1, 4) - else: - if args.cuda > 0: - box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS).cuda() \ - + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS).cuda() - else: - box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS) \ - + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS) - box_deltas = box_deltas.view(1, -1, 4 * len(pascal_classes)) - - pred_boxes = bbox_transform_inv(boxes, box_deltas, 1) - pred_boxes = clip_boxes(pred_boxes, im_info.data, 1) - else: - # Simply repeat the boxes, once for each class - pred_boxes = np.tile(boxes, (1, scores.shape[1])) - - pred_boxes /= im_scales[0] - - scores = scores.squeeze() - pred_boxes = pred_boxes.squeeze() - det_toc = time.time() - detect_time = det_toc - det_tic - misc_tic = time.time() - if vis: - im2show = np.copy(im) - for j in xrange(1, len(pascal_classes)): - inds = torch.nonzero(scores[:,j]>thresh).view(-1) - # if there is det - if inds.numel() > 0: - cls_scores = scores[:,j][inds] - _, order = torch.sort(cls_scores, 0, True) - if args.class_agnostic: - cls_boxes = pred_boxes[inds, :] - else: - cls_boxes = pred_boxes[inds][:, j * 4:(j + 1) * 4] - - cls_dets = torch.cat((cls_boxes, cls_scores.unsqueeze(1)), 1) - # cls_dets = torch.cat((cls_boxes, cls_scores), 1) - cls_dets = cls_dets[order] - # keep = nms(cls_dets, cfg.TEST.NMS, force_cpu=not cfg.USE_GPU_NMS) - keep = nms(cls_boxes[order, :], cls_scores[order], cfg.TEST.NMS) - cls_dets = cls_dets[keep.view(-1).long()] - if vis: - im2show = vis_detections(im2show, pascal_classes[j], cls_dets.cpu().numpy(), 0.5) - - misc_toc = time.time() - nms_time = misc_toc - misc_tic - - if webcam_num == -1: - sys.stdout.write('im_detect: {:d}/{:d} {:.3f}s {:.3f}s \r' \ - .format(num_images + 1, len(imglist), detect_time, nms_time)) - sys.stdout.flush() - - if vis and webcam_num == -1: - # cv2.imshow('test', im2show) - # cv2.waitKey(0) - result_path = os.path.join(args.image_dir, imglist[num_images][:-4] + "_det.jpg") - cv2.imwrite(result_path, im2show) - else: - im2showRGB = cv2.cvtColor(im2show, cv2.COLOR_BGR2RGB) - cv2.imshow("frame", im2showRGB) - total_toc = time.time() - total_time = total_toc - total_tic - frame_rate = 1 / total_time - print('Frame rate:', frame_rate) - if cv2.waitKey(1) & 0xFF == ord('q'): - break - if webcam_num >= 0: - cap.release() - cv2.destroyAllWindows() diff --git a/lib/model/__init__.py b/faster_rcnn/__init__.py similarity index 100% rename from lib/model/__init__.py rename to faster_rcnn/__init__.py diff --git a/_init_paths.py b/faster_rcnn/_init_paths.py similarity index 85% rename from _init_paths.py rename to faster_rcnn/_init_paths.py index bdc926d28..0136d64c8 100644 --- a/_init_paths.py +++ b/faster_rcnn/_init_paths.py @@ -1,3 +1,4 @@ +import os import os.path as osp import sys @@ -9,6 +10,7 @@ def add_path(path): # Add lib to PYTHONPATH lib_path = osp.join(this_dir, 'lib') +assert os.path.isdir(lib_path), lib_path add_path(lib_path) coco_path = osp.join(this_dir, 'data', 'coco', 'PythonAPI') diff --git a/cfgs/res101.yml b/faster_rcnn/cfgs/res101.yml similarity index 100% rename from cfgs/res101.yml rename to faster_rcnn/cfgs/res101.yml diff --git a/cfgs/res101_ls.yml b/faster_rcnn/cfgs/res101_ls.yml similarity index 100% rename from cfgs/res101_ls.yml rename to faster_rcnn/cfgs/res101_ls.yml diff --git a/cfgs/res50.yml b/faster_rcnn/cfgs/res50.yml similarity index 100% rename from cfgs/res50.yml rename to faster_rcnn/cfgs/res50.yml diff --git a/cfgs/vgg16.yml b/faster_rcnn/cfgs/vgg16.yml similarity index 100% rename from cfgs/vgg16.yml rename to faster_rcnn/cfgs/vgg16.yml diff --git a/images/img1.jpg b/faster_rcnn/images/img1.jpg similarity index 100% rename from images/img1.jpg rename to faster_rcnn/images/img1.jpg diff --git a/images/img1_det.jpg b/faster_rcnn/images/img1_det.jpg similarity index 100% rename from images/img1_det.jpg rename to faster_rcnn/images/img1_det.jpg diff --git a/images/img1_det_res101.jpg b/faster_rcnn/images/img1_det_res101.jpg similarity index 100% rename from images/img1_det_res101.jpg rename to faster_rcnn/images/img1_det_res101.jpg diff --git a/images/img2.jpg b/faster_rcnn/images/img2.jpg similarity index 100% rename from images/img2.jpg rename to faster_rcnn/images/img2.jpg diff --git a/images/img2_det.jpg b/faster_rcnn/images/img2_det.jpg similarity index 100% rename from images/img2_det.jpg rename to faster_rcnn/images/img2_det.jpg diff --git a/images/img2_det_res101.jpg b/faster_rcnn/images/img2_det_res101.jpg similarity index 100% rename from images/img2_det_res101.jpg rename to faster_rcnn/images/img2_det_res101.jpg diff --git a/images/img3.jpg b/faster_rcnn/images/img3.jpg similarity index 100% rename from images/img3.jpg rename to faster_rcnn/images/img3.jpg diff --git a/images/img3_det.jpg b/faster_rcnn/images/img3_det.jpg similarity index 100% rename from images/img3_det.jpg rename to faster_rcnn/images/img3_det.jpg diff --git a/images/img3_det_res101.jpg b/faster_rcnn/images/img3_det_res101.jpg similarity index 100% rename from images/img3_det_res101.jpg rename to faster_rcnn/images/img3_det_res101.jpg diff --git a/images/img4.jpg b/faster_rcnn/images/img4.jpg similarity index 100% rename from images/img4.jpg rename to faster_rcnn/images/img4.jpg diff --git a/images/img4_det.jpg b/faster_rcnn/images/img4_det.jpg similarity index 100% rename from images/img4_det.jpg rename to faster_rcnn/images/img4_det.jpg diff --git a/images/img4_det_res101.jpg b/faster_rcnn/images/img4_det_res101.jpg similarity index 100% rename from images/img4_det_res101.jpg rename to faster_rcnn/images/img4_det_res101.jpg diff --git a/lib/model/faster_rcnn/__init__.py b/faster_rcnn/lib/__init__.py similarity index 100% rename from lib/model/faster_rcnn/__init__.py rename to faster_rcnn/lib/__init__.py diff --git a/lib/datasets/VOCdevkit-matlab-wrapper/get_voc_opts.m b/faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/get_voc_opts.m similarity index 100% rename from lib/datasets/VOCdevkit-matlab-wrapper/get_voc_opts.m rename to faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/get_voc_opts.m diff --git a/lib/datasets/VOCdevkit-matlab-wrapper/voc_eval.m b/faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/voc_eval.m similarity index 100% rename from lib/datasets/VOCdevkit-matlab-wrapper/voc_eval.m rename to faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/voc_eval.m diff --git a/lib/datasets/VOCdevkit-matlab-wrapper/xVOCap.m b/faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/xVOCap.m similarity index 100% rename from lib/datasets/VOCdevkit-matlab-wrapper/xVOCap.m rename to faster_rcnn/lib/datasets/VOCdevkit-matlab-wrapper/xVOCap.m diff --git a/lib/datasets/__init__.py b/faster_rcnn/lib/datasets/__init__.py similarity index 100% rename from lib/datasets/__init__.py rename to faster_rcnn/lib/datasets/__init__.py diff --git a/lib/datasets/coco.py b/faster_rcnn/lib/datasets/coco.py similarity index 99% rename from lib/datasets/coco.py rename to faster_rcnn/lib/datasets/coco.py index 97df5976d..0dd7cd0b6 100644 --- a/lib/datasets/coco.py +++ b/faster_rcnn/lib/datasets/coco.py @@ -9,7 +9,7 @@ from datasets.imdb import imdb import datasets.ds_utils as ds_utils -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg import os.path as osp import sys import os diff --git a/lib/datasets/ds_utils.py b/faster_rcnn/lib/datasets/ds_utils.py similarity index 100% rename from lib/datasets/ds_utils.py rename to faster_rcnn/lib/datasets/ds_utils.py diff --git a/lib/datasets/factory.py b/faster_rcnn/lib/datasets/factory.py similarity index 100% rename from lib/datasets/factory.py rename to faster_rcnn/lib/datasets/factory.py diff --git a/lib/datasets/imagenet.py b/faster_rcnn/lib/datasets/imagenet.py similarity index 100% rename from lib/datasets/imagenet.py rename to faster_rcnn/lib/datasets/imagenet.py diff --git a/lib/datasets/imdb.py b/faster_rcnn/lib/datasets/imdb.py similarity index 98% rename from lib/datasets/imdb.py rename to faster_rcnn/lib/datasets/imdb.py index 06dfbe556..cec59e195 100644 --- a/lib/datasets/imdb.py +++ b/faster_rcnn/lib/datasets/imdb.py @@ -11,10 +11,10 @@ import os import os.path as osp import PIL -# from model.utils.cython_bbox import bbox_overlaps +# from faster_rcnn.lib.model.utils.cython_bbox import bbox_overlaps import numpy as np import scipy.sparse -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg import pdb ROOT_DIR = osp.join(osp.dirname(__file__), '..', '..') diff --git a/lib/datasets/pascal_voc.py b/faster_rcnn/lib/datasets/pascal_voc.py similarity index 99% rename from lib/datasets/pascal_voc.py rename to faster_rcnn/lib/datasets/pascal_voc.py index 7a29bd9d2..3cb0bb505 100644 --- a/lib/datasets/pascal_voc.py +++ b/faster_rcnn/lib/datasets/pascal_voc.py @@ -27,7 +27,7 @@ # TODO: make fast_rcnn irrelevant # >>>> obsolete, because it depends on sth outside of this project -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg try: xrange # Python 2 diff --git a/lib/datasets/pascal_voc_rbg.py b/faster_rcnn/lib/datasets/pascal_voc_rbg.py similarity index 99% rename from lib/datasets/pascal_voc_rbg.py rename to faster_rcnn/lib/datasets/pascal_voc_rbg.py index 23b42240b..f98a17b27 100644 --- a/lib/datasets/pascal_voc_rbg.py +++ b/faster_rcnn/lib/datasets/pascal_voc_rbg.py @@ -20,7 +20,7 @@ import subprocess import uuid from .voc_eval import voc_eval -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg import pdb diff --git a/lib/datasets/tools/mcg_munge.py b/faster_rcnn/lib/datasets/tools/mcg_munge.py similarity index 100% rename from lib/datasets/tools/mcg_munge.py rename to faster_rcnn/lib/datasets/tools/mcg_munge.py diff --git a/lib/datasets/vg.py b/faster_rcnn/lib/datasets/vg.py similarity index 99% rename from lib/datasets/vg.py rename to faster_rcnn/lib/datasets/vg.py index 3c1a1a38b..57e7f6e76 100755 --- a/lib/datasets/vg.py +++ b/faster_rcnn/lib/datasets/vg.py @@ -17,7 +17,7 @@ import PIL import json from .vg_eval import vg_eval -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg import pickle import pdb try: diff --git a/lib/datasets/vg_eval.py b/faster_rcnn/lib/datasets/vg_eval.py similarity index 100% rename from lib/datasets/vg_eval.py rename to faster_rcnn/lib/datasets/vg_eval.py diff --git a/lib/datasets/voc_eval.py b/faster_rcnn/lib/datasets/voc_eval.py similarity index 100% rename from lib/datasets/voc_eval.py rename to faster_rcnn/lib/datasets/voc_eval.py diff --git a/lib/model/nms/__init__.py b/faster_rcnn/lib/model/__init__.py similarity index 100% rename from lib/model/nms/__init__.py rename to faster_rcnn/lib/model/__init__.py diff --git a/lib/model/csrc/ROIAlign.h b/faster_rcnn/lib/model/csrc/ROIAlign.h similarity index 100% rename from lib/model/csrc/ROIAlign.h rename to faster_rcnn/lib/model/csrc/ROIAlign.h diff --git a/lib/model/csrc/ROIPool.h b/faster_rcnn/lib/model/csrc/ROIPool.h similarity index 100% rename from lib/model/csrc/ROIPool.h rename to faster_rcnn/lib/model/csrc/ROIPool.h diff --git a/lib/model/csrc/cpu/ROIAlign_cpu.cpp b/faster_rcnn/lib/model/csrc/cpu/ROIAlign_cpu.cpp similarity index 100% rename from lib/model/csrc/cpu/ROIAlign_cpu.cpp rename to faster_rcnn/lib/model/csrc/cpu/ROIAlign_cpu.cpp diff --git a/lib/model/csrc/cpu/nms_cpu.cpp b/faster_rcnn/lib/model/csrc/cpu/nms_cpu.cpp similarity index 100% rename from lib/model/csrc/cpu/nms_cpu.cpp rename to faster_rcnn/lib/model/csrc/cpu/nms_cpu.cpp diff --git a/lib/model/csrc/cpu/vision.h b/faster_rcnn/lib/model/csrc/cpu/vision.h similarity index 100% rename from lib/model/csrc/cpu/vision.h rename to faster_rcnn/lib/model/csrc/cpu/vision.h diff --git a/lib/model/csrc/cuda/ROIAlign_cuda.cu b/faster_rcnn/lib/model/csrc/cuda/ROIAlign_cuda.cu similarity index 100% rename from lib/model/csrc/cuda/ROIAlign_cuda.cu rename to faster_rcnn/lib/model/csrc/cuda/ROIAlign_cuda.cu diff --git a/lib/model/csrc/cuda/ROIPool_cuda.cu b/faster_rcnn/lib/model/csrc/cuda/ROIPool_cuda.cu similarity index 100% rename from lib/model/csrc/cuda/ROIPool_cuda.cu rename to faster_rcnn/lib/model/csrc/cuda/ROIPool_cuda.cu diff --git a/lib/model/csrc/cuda/nms.cu b/faster_rcnn/lib/model/csrc/cuda/nms.cu similarity index 100% rename from lib/model/csrc/cuda/nms.cu rename to faster_rcnn/lib/model/csrc/cuda/nms.cu diff --git a/lib/model/csrc/cuda/vision.h b/faster_rcnn/lib/model/csrc/cuda/vision.h similarity index 100% rename from lib/model/csrc/cuda/vision.h rename to faster_rcnn/lib/model/csrc/cuda/vision.h diff --git a/lib/model/csrc/nms.h b/faster_rcnn/lib/model/csrc/nms.h similarity index 100% rename from lib/model/csrc/nms.h rename to faster_rcnn/lib/model/csrc/nms.h diff --git a/lib/model/csrc/vision.cpp b/faster_rcnn/lib/model/csrc/vision.cpp similarity index 100% rename from lib/model/csrc/vision.cpp rename to faster_rcnn/lib/model/csrc/vision.cpp diff --git a/lib/model/nms/_ext/__init__.py b/faster_rcnn/lib/model/faster_rcnn/__init__.py similarity index 100% rename from lib/model/nms/_ext/__init__.py rename to faster_rcnn/lib/model/faster_rcnn/__init__.py diff --git a/lib/model/faster_rcnn/faster_rcnn.py b/faster_rcnn/lib/model/faster_rcnn/faster_rcnn.py similarity index 90% rename from lib/model/faster_rcnn/faster_rcnn.py rename to faster_rcnn/lib/model/faster_rcnn/faster_rcnn.py index 649616260..a2b21b438 100644 --- a/lib/model/faster_rcnn/faster_rcnn.py +++ b/faster_rcnn/lib/model/faster_rcnn/faster_rcnn.py @@ -6,18 +6,18 @@ import torchvision.models as models from torch.autograd import Variable import numpy as np -from model.utils.config import cfg -from model.rpn.rpn import _RPN +from faster_rcnn.lib.model.utils.config import cfg +from faster_rcnn.lib.model.rpn.rpn import _RPN -from model.roi_layers import ROIAlign, ROIPool +from faster_rcnn.lib.model.roi_layers import ROIAlign, ROIPool -# from model.roi_pooling.modules.roi_pool import _RoIPooling -# from model.roi_align.modules.roi_align import RoIAlignAvg +# from faster_rcnn.lib.model.roi_pooling.modules.roi_pool import _RoIPooling +# from faster_rcnn.lib.model.roi_align.modules.roi_align import RoIAlignAvg -from model.rpn.proposal_target_layer_cascade import _ProposalTargetLayer +from faster_rcnn.lib.model.rpn.proposal_target_layer_cascade import _ProposalTargetLayer import time import pdb -from model.utils.net_utils import _smooth_l1_loss, _crop_pool_layer, _affine_grid_gen, _affine_theta +from faster_rcnn.lib.model.utils.net_utils import _smooth_l1_loss, _crop_pool_layer, _affine_grid_gen, _affine_theta class _fasterRCNN(nn.Module): """ faster RCNN """ diff --git a/lib/model/faster_rcnn/resnet.py b/faster_rcnn/lib/model/faster_rcnn/resnet.py similarity index 98% rename from lib/model/faster_rcnn/resnet.py rename to faster_rcnn/lib/model/faster_rcnn/resnet.py index 5457724b3..f27bad836 100644 --- a/lib/model/faster_rcnn/resnet.py +++ b/faster_rcnn/lib/model/faster_rcnn/resnet.py @@ -2,8 +2,8 @@ from __future__ import division from __future__ import print_function -from model.utils.config import cfg -from model.faster_rcnn.faster_rcnn import _fasterRCNN +from faster_rcnn.lib.model.utils.config import cfg +from faster_rcnn.lib.model.faster_rcnn.faster_rcnn import _fasterRCNN import torch import torch.nn as nn diff --git a/lib/model/faster_rcnn/vgg16.py b/faster_rcnn/lib/model/faster_rcnn/vgg16.py similarity index 93% rename from lib/model/faster_rcnn/vgg16.py rename to faster_rcnn/lib/model/faster_rcnn/vgg16.py index 90fe0d7b9..bb6812665 100644 --- a/lib/model/faster_rcnn/vgg16.py +++ b/faster_rcnn/lib/model/faster_rcnn/vgg16.py @@ -13,7 +13,7 @@ from torch.autograd import Variable import math import torchvision.models as models -from model.faster_rcnn.faster_rcnn import _fasterRCNN +from faster_rcnn.lib.model.faster_rcnn.faster_rcnn import _fasterRCNN import pdb class vgg16(_fasterRCNN): @@ -51,10 +51,10 @@ def _init_modules(self): if self.class_agnostic: self.RCNN_bbox_pred = nn.Linear(4096, 4) else: - self.RCNN_bbox_pred = nn.Linear(4096, 4 * self.n_classes) + self.RCNN_bbox_pred = nn.Linear(4096, 4 * self.n_classes) def _head_to_tail(self, pool5): - + pool5_flat = pool5.view(pool5.size(0), -1) fc7 = self.RCNN_top(pool5_flat) diff --git a/lib/model/nms/.gitignore b/faster_rcnn/lib/model/nms/.gitignore similarity index 100% rename from lib/model/nms/.gitignore rename to faster_rcnn/lib/model/nms/.gitignore diff --git a/lib/model/roi_align/__init__.py b/faster_rcnn/lib/model/nms/__init__.py similarity index 100% rename from lib/model/roi_align/__init__.py rename to faster_rcnn/lib/model/nms/__init__.py diff --git a/lib/model/roi_align/_ext/__init__.py b/faster_rcnn/lib/model/nms/_ext/__init__.py similarity index 100% rename from lib/model/roi_align/_ext/__init__.py rename to faster_rcnn/lib/model/nms/_ext/__init__.py diff --git a/lib/model/nms/_ext/nms/__init__.py b/faster_rcnn/lib/model/nms/_ext/nms/__init__.py similarity index 100% rename from lib/model/nms/_ext/nms/__init__.py rename to faster_rcnn/lib/model/nms/_ext/nms/__init__.py diff --git a/lib/model/nms/build.py b/faster_rcnn/lib/model/nms/build.py similarity index 100% rename from lib/model/nms/build.py rename to faster_rcnn/lib/model/nms/build.py diff --git a/lib/model/nms/make.sh b/faster_rcnn/lib/model/nms/make.sh similarity index 100% rename from lib/model/nms/make.sh rename to faster_rcnn/lib/model/nms/make.sh diff --git a/lib/model/nms/nms_cpu.py b/faster_rcnn/lib/model/nms/nms_cpu.py similarity index 100% rename from lib/model/nms/nms_cpu.py rename to faster_rcnn/lib/model/nms/nms_cpu.py diff --git a/lib/model/nms/nms_gpu.py b/faster_rcnn/lib/model/nms/nms_gpu.py similarity index 100% rename from lib/model/nms/nms_gpu.py rename to faster_rcnn/lib/model/nms/nms_gpu.py diff --git a/lib/model/nms/nms_kernel.cu b/faster_rcnn/lib/model/nms/nms_kernel.cu similarity index 100% rename from lib/model/nms/nms_kernel.cu rename to faster_rcnn/lib/model/nms/nms_kernel.cu diff --git a/lib/model/nms/nms_wrapper.py b/faster_rcnn/lib/model/nms/nms_wrapper.py similarity index 79% rename from lib/model/nms/nms_wrapper.py rename to faster_rcnn/lib/model/nms/nms_wrapper.py index 5ae36602b..94a400fd1 100644 --- a/lib/model/nms/nms_wrapper.py +++ b/faster_rcnn/lib/model/nms/nms_wrapper.py @@ -5,10 +5,10 @@ # Written by Ross Girshick # -------------------------------------------------------- import torch -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg if torch.cuda.is_available(): - from model.nms.nms_gpu import nms_gpu -from model.nms.nms_cpu import nms_cpu + from faster_rcnn.lib.model.nms.nms_gpu import nms_gpu +from faster_rcnn.lib.model.nms.nms_cpu import nms_cpu def nms(dets, thresh, force_cpu=False): """Dispatch to either CPU or GPU NMS implementations.""" diff --git a/lib/model/nms/src/nms_cuda.h b/faster_rcnn/lib/model/nms/src/nms_cuda.h similarity index 100% rename from lib/model/nms/src/nms_cuda.h rename to faster_rcnn/lib/model/nms/src/nms_cuda.h diff --git a/lib/model/nms/src/nms_cuda_kernel.cu b/faster_rcnn/lib/model/nms/src/nms_cuda_kernel.cu similarity index 100% rename from lib/model/nms/src/nms_cuda_kernel.cu rename to faster_rcnn/lib/model/nms/src/nms_cuda_kernel.cu diff --git a/lib/model/nms/src/nms_cuda_kernel.h b/faster_rcnn/lib/model/nms/src/nms_cuda_kernel.h similarity index 100% rename from lib/model/nms/src/nms_cuda_kernel.h rename to faster_rcnn/lib/model/nms/src/nms_cuda_kernel.h diff --git a/lib/model/roi_align/functions/__init__.py b/faster_rcnn/lib/model/roi_align/__init__.py similarity index 100% rename from lib/model/roi_align/functions/__init__.py rename to faster_rcnn/lib/model/roi_align/__init__.py diff --git a/lib/model/roi_align/modules/__init__.py b/faster_rcnn/lib/model/roi_align/_ext/__init__.py similarity index 100% rename from lib/model/roi_align/modules/__init__.py rename to faster_rcnn/lib/model/roi_align/_ext/__init__.py diff --git a/lib/model/roi_align/_ext/roi_align/__init__.py b/faster_rcnn/lib/model/roi_align/_ext/roi_align/__init__.py similarity index 100% rename from lib/model/roi_align/_ext/roi_align/__init__.py rename to faster_rcnn/lib/model/roi_align/_ext/roi_align/__init__.py diff --git a/lib/model/roi_align/build.py b/faster_rcnn/lib/model/roi_align/build.py similarity index 100% rename from lib/model/roi_align/build.py rename to faster_rcnn/lib/model/roi_align/build.py diff --git a/lib/model/roi_crop/__init__.py b/faster_rcnn/lib/model/roi_align/functions/__init__.py similarity index 100% rename from lib/model/roi_crop/__init__.py rename to faster_rcnn/lib/model/roi_align/functions/__init__.py diff --git a/lib/model/roi_align/functions/roi_align.py b/faster_rcnn/lib/model/roi_align/functions/roi_align.py similarity index 100% rename from lib/model/roi_align/functions/roi_align.py rename to faster_rcnn/lib/model/roi_align/functions/roi_align.py diff --git a/lib/model/roi_align/make.sh b/faster_rcnn/lib/model/roi_align/make.sh similarity index 100% rename from lib/model/roi_align/make.sh rename to faster_rcnn/lib/model/roi_align/make.sh diff --git a/lib/model/roi_crop/_ext/__init__.py b/faster_rcnn/lib/model/roi_align/modules/__init__.py similarity index 100% rename from lib/model/roi_crop/_ext/__init__.py rename to faster_rcnn/lib/model/roi_align/modules/__init__.py diff --git a/lib/model/roi_align/modules/roi_align.py b/faster_rcnn/lib/model/roi_align/modules/roi_align.py similarity index 100% rename from lib/model/roi_align/modules/roi_align.py rename to faster_rcnn/lib/model/roi_align/modules/roi_align.py diff --git a/lib/model/roi_align/src/roi_align.c b/faster_rcnn/lib/model/roi_align/src/roi_align.c similarity index 100% rename from lib/model/roi_align/src/roi_align.c rename to faster_rcnn/lib/model/roi_align/src/roi_align.c diff --git a/lib/model/roi_align/src/roi_align.h b/faster_rcnn/lib/model/roi_align/src/roi_align.h similarity index 100% rename from lib/model/roi_align/src/roi_align.h rename to faster_rcnn/lib/model/roi_align/src/roi_align.h diff --git a/lib/model/roi_align/src/roi_align_cuda.c b/faster_rcnn/lib/model/roi_align/src/roi_align_cuda.c similarity index 100% rename from lib/model/roi_align/src/roi_align_cuda.c rename to faster_rcnn/lib/model/roi_align/src/roi_align_cuda.c diff --git a/lib/model/roi_align/src/roi_align_cuda.h b/faster_rcnn/lib/model/roi_align/src/roi_align_cuda.h similarity index 100% rename from lib/model/roi_align/src/roi_align_cuda.h rename to faster_rcnn/lib/model/roi_align/src/roi_align_cuda.h diff --git a/lib/model/roi_align/src/roi_align_kernel.cu b/faster_rcnn/lib/model/roi_align/src/roi_align_kernel.cu similarity index 100% rename from lib/model/roi_align/src/roi_align_kernel.cu rename to faster_rcnn/lib/model/roi_align/src/roi_align_kernel.cu diff --git a/lib/model/roi_align/src/roi_align_kernel.h b/faster_rcnn/lib/model/roi_align/src/roi_align_kernel.h similarity index 100% rename from lib/model/roi_align/src/roi_align_kernel.h rename to faster_rcnn/lib/model/roi_align/src/roi_align_kernel.h diff --git a/lib/model/roi_crop/functions/__init__.py b/faster_rcnn/lib/model/roi_crop/__init__.py similarity index 100% rename from lib/model/roi_crop/functions/__init__.py rename to faster_rcnn/lib/model/roi_crop/__init__.py diff --git a/lib/model/roi_crop/modules/__init__.py b/faster_rcnn/lib/model/roi_crop/_ext/__init__.py similarity index 100% rename from lib/model/roi_crop/modules/__init__.py rename to faster_rcnn/lib/model/roi_crop/_ext/__init__.py diff --git a/lib/model/roi_crop/_ext/crop_resize/__init__.py b/faster_rcnn/lib/model/roi_crop/_ext/crop_resize/__init__.py similarity index 100% rename from lib/model/roi_crop/_ext/crop_resize/__init__.py rename to faster_rcnn/lib/model/roi_crop/_ext/crop_resize/__init__.py diff --git a/lib/model/roi_crop/_ext/roi_crop/__init__.py b/faster_rcnn/lib/model/roi_crop/_ext/roi_crop/__init__.py similarity index 100% rename from lib/model/roi_crop/_ext/roi_crop/__init__.py rename to faster_rcnn/lib/model/roi_crop/_ext/roi_crop/__init__.py diff --git a/lib/model/roi_crop/build.py b/faster_rcnn/lib/model/roi_crop/build.py similarity index 100% rename from lib/model/roi_crop/build.py rename to faster_rcnn/lib/model/roi_crop/build.py diff --git a/lib/model/roi_pooling/__init__.py b/faster_rcnn/lib/model/roi_crop/functions/__init__.py similarity index 100% rename from lib/model/roi_pooling/__init__.py rename to faster_rcnn/lib/model/roi_crop/functions/__init__.py diff --git a/lib/model/roi_crop/functions/crop_resize.py b/faster_rcnn/lib/model/roi_crop/functions/crop_resize.py similarity index 100% rename from lib/model/roi_crop/functions/crop_resize.py rename to faster_rcnn/lib/model/roi_crop/functions/crop_resize.py diff --git a/lib/model/roi_crop/functions/gridgen.py b/faster_rcnn/lib/model/roi_crop/functions/gridgen.py similarity index 100% rename from lib/model/roi_crop/functions/gridgen.py rename to faster_rcnn/lib/model/roi_crop/functions/gridgen.py diff --git a/lib/model/roi_crop/functions/roi_crop.py b/faster_rcnn/lib/model/roi_crop/functions/roi_crop.py similarity index 100% rename from lib/model/roi_crop/functions/roi_crop.py rename to faster_rcnn/lib/model/roi_crop/functions/roi_crop.py diff --git a/lib/model/roi_crop/make.sh b/faster_rcnn/lib/model/roi_crop/make.sh similarity index 100% rename from lib/model/roi_crop/make.sh rename to faster_rcnn/lib/model/roi_crop/make.sh diff --git a/lib/model/roi_pooling/_ext/__init__.py b/faster_rcnn/lib/model/roi_crop/modules/__init__.py similarity index 100% rename from lib/model/roi_pooling/_ext/__init__.py rename to faster_rcnn/lib/model/roi_crop/modules/__init__.py diff --git a/lib/model/roi_crop/modules/gridgen.py b/faster_rcnn/lib/model/roi_crop/modules/gridgen.py similarity index 100% rename from lib/model/roi_crop/modules/gridgen.py rename to faster_rcnn/lib/model/roi_crop/modules/gridgen.py diff --git a/lib/model/roi_crop/modules/roi_crop.py b/faster_rcnn/lib/model/roi_crop/modules/roi_crop.py similarity index 100% rename from lib/model/roi_crop/modules/roi_crop.py rename to faster_rcnn/lib/model/roi_crop/modules/roi_crop.py diff --git a/lib/model/roi_crop/src/roi_crop.c b/faster_rcnn/lib/model/roi_crop/src/roi_crop.c similarity index 100% rename from lib/model/roi_crop/src/roi_crop.c rename to faster_rcnn/lib/model/roi_crop/src/roi_crop.c diff --git a/lib/model/roi_crop/src/roi_crop.h b/faster_rcnn/lib/model/roi_crop/src/roi_crop.h similarity index 100% rename from lib/model/roi_crop/src/roi_crop.h rename to faster_rcnn/lib/model/roi_crop/src/roi_crop.h diff --git a/lib/model/roi_crop/src/roi_crop_cuda.c b/faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda.c similarity index 100% rename from lib/model/roi_crop/src/roi_crop_cuda.c rename to faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda.c diff --git a/lib/model/roi_crop/src/roi_crop_cuda.h b/faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda.h similarity index 100% rename from lib/model/roi_crop/src/roi_crop_cuda.h rename to faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda.h diff --git a/lib/model/roi_crop/src/roi_crop_cuda_kernel.cu b/faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda_kernel.cu similarity index 100% rename from lib/model/roi_crop/src/roi_crop_cuda_kernel.cu rename to faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda_kernel.cu diff --git a/lib/model/roi_crop/src/roi_crop_cuda_kernel.h b/faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda_kernel.h similarity index 100% rename from lib/model/roi_crop/src/roi_crop_cuda_kernel.h rename to faster_rcnn/lib/model/roi_crop/src/roi_crop_cuda_kernel.h diff --git a/lib/model/roi_layers/__init__.py b/faster_rcnn/lib/model/roi_layers/__init__.py similarity index 100% rename from lib/model/roi_layers/__init__.py rename to faster_rcnn/lib/model/roi_layers/__init__.py diff --git a/lib/model/roi_layers/nms.py b/faster_rcnn/lib/model/roi_layers/nms.py similarity index 83% rename from lib/model/roi_layers/nms.py rename to faster_rcnn/lib/model/roi_layers/nms.py index c0de3f32d..0df1e787c 100644 --- a/lib/model/roi_layers/nms.py +++ b/faster_rcnn/lib/model/roi_layers/nms.py @@ -1,6 +1,6 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. # from ._utils import _C -from model import _C +from faster_rcnn.lib.model import _C nms = _C.nms # nms.__doc__ = """ diff --git a/lib/model/roi_layers/roi_align.py b/faster_rcnn/lib/model/roi_layers/roi_align.py similarity index 98% rename from lib/model/roi_layers/roi_align.py rename to faster_rcnn/lib/model/roi_layers/roi_align.py index 10a448744..f6012f218 100644 --- a/lib/model/roi_layers/roi_align.py +++ b/faster_rcnn/lib/model/roi_layers/roi_align.py @@ -5,7 +5,7 @@ from torch.autograd.function import once_differentiable from torch.nn.modules.utils import _pair -from model import _C +from faster_rcnn.lib.model import _C import pdb diff --git a/lib/model/roi_layers/roi_pool.py b/faster_rcnn/lib/model/roi_layers/roi_pool.py similarity index 98% rename from lib/model/roi_layers/roi_pool.py rename to faster_rcnn/lib/model/roi_layers/roi_pool.py index e9e6e1069..62d82b6bf 100644 --- a/lib/model/roi_layers/roi_pool.py +++ b/faster_rcnn/lib/model/roi_layers/roi_pool.py @@ -5,7 +5,7 @@ from torch.autograd.function import once_differentiable from torch.nn.modules.utils import _pair -from model import _C +from faster_rcnn.lib.model import _C class _ROIPool(Function): diff --git a/lib/model/roi_pooling/functions/__init__.py b/faster_rcnn/lib/model/roi_pooling/__init__.py similarity index 100% rename from lib/model/roi_pooling/functions/__init__.py rename to faster_rcnn/lib/model/roi_pooling/__init__.py diff --git a/lib/model/roi_pooling/modules/__init__.py b/faster_rcnn/lib/model/roi_pooling/_ext/__init__.py similarity index 100% rename from lib/model/roi_pooling/modules/__init__.py rename to faster_rcnn/lib/model/roi_pooling/_ext/__init__.py diff --git a/lib/model/roi_pooling/_ext/roi_pooling/__init__.py b/faster_rcnn/lib/model/roi_pooling/_ext/roi_pooling/__init__.py similarity index 100% rename from lib/model/roi_pooling/_ext/roi_pooling/__init__.py rename to faster_rcnn/lib/model/roi_pooling/_ext/roi_pooling/__init__.py diff --git a/lib/model/roi_pooling/build.py b/faster_rcnn/lib/model/roi_pooling/build.py similarity index 100% rename from lib/model/roi_pooling/build.py rename to faster_rcnn/lib/model/roi_pooling/build.py diff --git a/lib/model/rpn/__init__.py b/faster_rcnn/lib/model/roi_pooling/functions/__init__.py similarity index 100% rename from lib/model/rpn/__init__.py rename to faster_rcnn/lib/model/roi_pooling/functions/__init__.py diff --git a/lib/model/roi_pooling/functions/roi_pool.py b/faster_rcnn/lib/model/roi_pooling/functions/roi_pool.py similarity index 100% rename from lib/model/roi_pooling/functions/roi_pool.py rename to faster_rcnn/lib/model/roi_pooling/functions/roi_pool.py diff --git a/lib/model/utils/__init__.py b/faster_rcnn/lib/model/roi_pooling/modules/__init__.py similarity index 100% rename from lib/model/utils/__init__.py rename to faster_rcnn/lib/model/roi_pooling/modules/__init__.py diff --git a/lib/model/roi_pooling/modules/roi_pool.py b/faster_rcnn/lib/model/roi_pooling/modules/roi_pool.py similarity index 100% rename from lib/model/roi_pooling/modules/roi_pool.py rename to faster_rcnn/lib/model/roi_pooling/modules/roi_pool.py diff --git a/lib/model/roi_pooling/src/roi_pooling.c b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling.c similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling.c rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling.c diff --git a/lib/model/roi_pooling/src/roi_pooling.h b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling.h similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling.h rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling.h diff --git a/lib/model/roi_pooling/src/roi_pooling_cuda.c b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling_cuda.c similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling_cuda.c rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling_cuda.c diff --git a/lib/model/roi_pooling/src/roi_pooling_cuda.h b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling_cuda.h similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling_cuda.h rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling_cuda.h diff --git a/lib/model/roi_pooling/src/roi_pooling_kernel.cu b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling_kernel.cu similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling_kernel.cu rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling_kernel.cu diff --git a/lib/model/roi_pooling/src/roi_pooling_kernel.h b/faster_rcnn/lib/model/roi_pooling/src/roi_pooling_kernel.h similarity index 100% rename from lib/model/roi_pooling/src/roi_pooling_kernel.h rename to faster_rcnn/lib/model/roi_pooling/src/roi_pooling_kernel.h diff --git a/faster_rcnn/lib/model/rpn/__init__.py b/faster_rcnn/lib/model/rpn/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/model/rpn/anchor_target_layer.py b/faster_rcnn/lib/model/rpn/anchor_target_layer.py similarity index 99% rename from lib/model/rpn/anchor_target_layer.py rename to faster_rcnn/lib/model/rpn/anchor_target_layer.py index ba00ad56b..9a82989ac 100644 --- a/lib/model/rpn/anchor_target_layer.py +++ b/faster_rcnn/lib/model/rpn/anchor_target_layer.py @@ -14,7 +14,7 @@ import numpy as np import numpy.random as npr -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg from .generate_anchors import generate_anchors from .bbox_transform import clip_boxes, bbox_overlaps_batch, bbox_transform_batch diff --git a/lib/model/rpn/bbox_transform.py b/faster_rcnn/lib/model/rpn/bbox_transform.py similarity index 100% rename from lib/model/rpn/bbox_transform.py rename to faster_rcnn/lib/model/rpn/bbox_transform.py diff --git a/lib/model/rpn/generate_anchors.py b/faster_rcnn/lib/model/rpn/generate_anchors.py similarity index 100% rename from lib/model/rpn/generate_anchors.py rename to faster_rcnn/lib/model/rpn/generate_anchors.py diff --git a/lib/model/rpn/proposal_layer.py b/faster_rcnn/lib/model/rpn/proposal_layer.py similarity index 97% rename from lib/model/rpn/proposal_layer.py rename to faster_rcnn/lib/model/rpn/proposal_layer.py index 9c787da91..81580de28 100644 --- a/lib/model/rpn/proposal_layer.py +++ b/faster_rcnn/lib/model/rpn/proposal_layer.py @@ -14,11 +14,11 @@ import numpy as np import math import yaml -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg from .generate_anchors import generate_anchors from .bbox_transform import bbox_transform_inv, clip_boxes, clip_boxes_batch -# from model.nms.nms_wrapper import nms -from model.roi_layers import nms +# from faster_rcnn.lib.model.nms.nms_wrapper import nms +from faster_rcnn.lib.model.roi_layers import nms import pdb DEBUG = False diff --git a/lib/model/rpn/proposal_target_layer_cascade.py b/faster_rcnn/lib/model/rpn/proposal_target_layer_cascade.py similarity index 100% rename from lib/model/rpn/proposal_target_layer_cascade.py rename to faster_rcnn/lib/model/rpn/proposal_target_layer_cascade.py diff --git a/lib/model/rpn/rpn.py b/faster_rcnn/lib/model/rpn/rpn.py similarity index 97% rename from lib/model/rpn/rpn.py rename to faster_rcnn/lib/model/rpn/rpn.py index 29bdaadb3..504fa799b 100644 --- a/lib/model/rpn/rpn.py +++ b/faster_rcnn/lib/model/rpn/rpn.py @@ -4,10 +4,10 @@ import torch.nn.functional as F from torch.autograd import Variable -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg from .proposal_layer import _ProposalLayer from .anchor_target_layer import _AnchorTargetLayer -from model.utils.net_utils import _smooth_l1_loss +from faster_rcnn.lib.model.utils.net_utils import _smooth_l1_loss import numpy as np import math @@ -18,7 +18,7 @@ class _RPN(nn.Module): """ region proposal network """ def __init__(self, din): super(_RPN, self).__init__() - + self.din = din # get depth of input feature map, e.g., 512 self.anchor_scales = cfg.ANCHOR_SCALES self.anchor_ratios = cfg.ANCHOR_RATIOS diff --git a/lib/model/utils/.gitignore b/faster_rcnn/lib/model/utils/.gitignore similarity index 100% rename from lib/model/utils/.gitignore rename to faster_rcnn/lib/model/utils/.gitignore diff --git a/faster_rcnn/lib/model/utils/__init__.py b/faster_rcnn/lib/model/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/model/utils/bbox.pyx b/faster_rcnn/lib/model/utils/bbox.pyx similarity index 100% rename from lib/model/utils/bbox.pyx rename to faster_rcnn/lib/model/utils/bbox.pyx diff --git a/lib/model/utils/blob.py b/faster_rcnn/lib/model/utils/blob.py similarity index 97% rename from lib/model/utils/blob.py rename to faster_rcnn/lib/model/utils/blob.py index 48b233249..21f2f78bf 100644 --- a/lib/model/utils/blob.py +++ b/faster_rcnn/lib/model/utils/blob.py @@ -8,7 +8,7 @@ """Blob helper functions.""" import numpy as np -# from scipy.misc import imread, imresize +# from imageio import imread, imresize import cv2 try: diff --git a/lib/model/utils/config.py b/faster_rcnn/lib/model/utils/config.py similarity index 100% rename from lib/model/utils/config.py rename to faster_rcnn/lib/model/utils/config.py diff --git a/lib/model/utils/logger.py b/faster_rcnn/lib/model/utils/logger.py similarity index 100% rename from lib/model/utils/logger.py rename to faster_rcnn/lib/model/utils/logger.py diff --git a/lib/model/utils/net_utils.py b/faster_rcnn/lib/model/utils/net_utils.py similarity index 99% rename from lib/model/utils/net_utils.py rename to faster_rcnn/lib/model/utils/net_utils.py index fb9dc1f19..f06ae5150 100644 --- a/lib/model/utils/net_utils.py +++ b/faster_rcnn/lib/model/utils/net_utils.py @@ -4,7 +4,7 @@ from torch.autograd import Variable import numpy as np import torchvision.models as models -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg import cv2 import pdb import random diff --git a/lib/pycocotools/UPSTREAM_REV b/faster_rcnn/lib/pycocotools/UPSTREAM_REV similarity index 100% rename from lib/pycocotools/UPSTREAM_REV rename to faster_rcnn/lib/pycocotools/UPSTREAM_REV diff --git a/lib/pycocotools/__init__.py b/faster_rcnn/lib/pycocotools/__init__.py similarity index 100% rename from lib/pycocotools/__init__.py rename to faster_rcnn/lib/pycocotools/__init__.py diff --git a/lib/pycocotools/_mask.c b/faster_rcnn/lib/pycocotools/_mask.c similarity index 100% rename from lib/pycocotools/_mask.c rename to faster_rcnn/lib/pycocotools/_mask.c diff --git a/lib/pycocotools/_mask.pyx b/faster_rcnn/lib/pycocotools/_mask.pyx similarity index 100% rename from lib/pycocotools/_mask.pyx rename to faster_rcnn/lib/pycocotools/_mask.pyx diff --git a/lib/pycocotools/coco.py b/faster_rcnn/lib/pycocotools/coco.py similarity index 100% rename from lib/pycocotools/coco.py rename to faster_rcnn/lib/pycocotools/coco.py diff --git a/lib/pycocotools/cocoeval.py b/faster_rcnn/lib/pycocotools/cocoeval.py similarity index 100% rename from lib/pycocotools/cocoeval.py rename to faster_rcnn/lib/pycocotools/cocoeval.py diff --git a/lib/pycocotools/license.txt b/faster_rcnn/lib/pycocotools/license.txt similarity index 100% rename from lib/pycocotools/license.txt rename to faster_rcnn/lib/pycocotools/license.txt diff --git a/lib/pycocotools/mask.py b/faster_rcnn/lib/pycocotools/mask.py similarity index 100% rename from lib/pycocotools/mask.py rename to faster_rcnn/lib/pycocotools/mask.py diff --git a/lib/pycocotools/maskApi.c b/faster_rcnn/lib/pycocotools/maskApi.c similarity index 100% rename from lib/pycocotools/maskApi.c rename to faster_rcnn/lib/pycocotools/maskApi.c diff --git a/lib/pycocotools/maskApi.h b/faster_rcnn/lib/pycocotools/maskApi.h similarity index 100% rename from lib/pycocotools/maskApi.h rename to faster_rcnn/lib/pycocotools/maskApi.h diff --git a/lib/roi_data_layer/__init__.py b/faster_rcnn/lib/roi_data_layer/__init__.py similarity index 100% rename from lib/roi_data_layer/__init__.py rename to faster_rcnn/lib/roi_data_layer/__init__.py diff --git a/lib/roi_data_layer/minibatch.py b/faster_rcnn/lib/roi_data_layer/minibatch.py similarity index 94% rename from lib/roi_data_layer/minibatch.py rename to faster_rcnn/lib/roi_data_layer/minibatch.py index 4fb44328d..d80a9d3ed 100644 --- a/lib/roi_data_layer/minibatch.py +++ b/faster_rcnn/lib/roi_data_layer/minibatch.py @@ -12,9 +12,9 @@ import numpy as np import numpy.random as npr -from scipy.misc import imread -from model.utils.config import cfg -from model.utils.blob import prep_im_for_blob, im_list_to_blob +from imageio import imread +from faster_rcnn.lib.model.utils.config import cfg +from faster_rcnn.lib.model.utils.blob import prep_im_for_blob, im_list_to_blob import pdb def get_minibatch(roidb, num_classes): """Given a roidb, construct a minibatch sampled from it.""" @@ -33,13 +33,13 @@ def get_minibatch(roidb, num_classes): assert len(im_scales) == 1, "Single batch only" assert len(roidb) == 1, "Single batch only" - + # gt boxes: (x1, y1, x2, y2, cls) if cfg.TRAIN.USE_ALL_GT: # Include all ground truth boxes gt_inds = np.where(roidb[0]['gt_classes'] != 0)[0] else: - # For the COCO ground truth boxes, exclude the ones that are ''iscrowd'' + # For the COCO ground truth boxes, exclude the ones that are ''iscrowd'' gt_inds = np.where((roidb[0]['gt_classes'] != 0) & np.all(roidb[0]['gt_overlaps'].toarray() > -1.0, axis=1))[0] gt_boxes = np.empty((len(gt_inds), 5), dtype=np.float32) gt_boxes[:, 0:4] = roidb[0]['boxes'][gt_inds, :] * im_scales[0] diff --git a/lib/roi_data_layer/roibatchLoader.py b/faster_rcnn/lib/roi_data_layer/roibatchLoader.py similarity index 97% rename from lib/roi_data_layer/roibatchLoader.py rename to faster_rcnn/lib/roi_data_layer/roibatchLoader.py index 9b6e54ecf..016cc743f 100644 --- a/lib/roi_data_layer/roibatchLoader.py +++ b/faster_rcnn/lib/roi_data_layer/roibatchLoader.py @@ -10,9 +10,9 @@ from PIL import Image import torch -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg from roi_data_layer.minibatch import get_minibatch, get_minibatch -from model.rpn.bbox_transform import bbox_transform_inv, clip_boxes +from faster_rcnn.lib.model.rpn.bbox_transform import bbox_transform_inv, clip_boxes import numpy as np import random @@ -93,7 +93,7 @@ def __getitem__(self, index): max_y = int(torch.max(gt_boxes[:,3])) trim_size = int(np.floor(data_width / ratio)) if trim_size > data_height: - trim_size = data_height + trim_size = data_height box_region = max_y - min_y + 1 if min_y == 0: y_s = 0 @@ -129,7 +129,7 @@ def __getitem__(self, index): max_x = int(torch.max(gt_boxes[:,2])) trim_size = int(np.ceil(data_height * ratio)) if trim_size > data_width: - trim_size = data_width + trim_size = data_width box_region = max_x - min_x + 1 if min_x == 0: x_s = 0 diff --git a/lib/roi_data_layer/roidb.py b/faster_rcnn/lib/roi_data_layer/roidb.py similarity index 96% rename from lib/roi_data_layer/roidb.py rename to faster_rcnn/lib/roi_data_layer/roidb.py index df50e60c9..0570a193d 100644 --- a/lib/roi_data_layer/roidb.py +++ b/faster_rcnn/lib/roi_data_layer/roidb.py @@ -5,7 +5,7 @@ import datasets import numpy as np -from model.utils.config import cfg +from faster_rcnn.lib.model.utils.config import cfg from datasets.factory import get_imdb import PIL import pdb @@ -22,7 +22,7 @@ def prepare_roidb(imdb): if not (imdb.name.startswith('coco')): sizes = [PIL.Image.open(imdb.image_path_at(i)).size for i in range(imdb.num_images)] - + for i in range(len(imdb.image_index)): roidb[i]['img_id'] = imdb.image_id_at(i) roidb[i]['image'] = imdb.image_path_at(i) @@ -49,8 +49,8 @@ def prepare_roidb(imdb): def rank_roidb_ratio(roidb): # rank roidb based on the ratio between width and height. ratio_large = 2 # largest ratio to preserve. - ratio_small = 0.5 # smallest ratio to preserve. - + ratio_small = 0.5 # smallest ratio to preserve. + ratio_list = [] for i in range(len(roidb)): width = roidb[i]['width'] @@ -62,7 +62,7 @@ def rank_roidb_ratio(roidb): ratio = ratio_large elif ratio < ratio_small: roidb[i]['need_crop'] = 1 - ratio = ratio_small + ratio = ratio_small else: roidb[i]['need_crop'] = 0 @@ -104,7 +104,7 @@ def get_training_roidb(imdb): print('done') return imdb.roidb - + def get_roidb(imdb_name): imdb = get_imdb(imdb_name) print('Loaded dataset `{:s}` for training'.format(imdb.name)) diff --git a/faster_rcnn/scripts/__init__.py b/faster_rcnn/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/faster_rcnn/scripts/demo.py b/faster_rcnn/scripts/demo.py new file mode 100644 index 000000000..08009d7b8 --- /dev/null +++ b/faster_rcnn/scripts/demo.py @@ -0,0 +1,398 @@ +# -------------------------------------------------------- +# Tensorflow Faster R-CNN +# Licensed under The MIT License [see LICENSE for details] +# Written by Jiasen Lu, Jianwei Yang, based on code from Ross Girshick +# -------------------------------------------------------- +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import faster_rcnn._init_paths +import os +import sys +import numpy as np +import argparse +import pprint +import pdb +import time +import cv2 +import torch +from torch.autograd import Variable +import torch.nn as nn +import torch.optim as optim + +import torchvision.transforms as transforms +import torchvision.datasets as dset +from imageio import imread +from roi_data_layer.roidb import combined_roidb +from roi_data_layer.roibatchLoader import roibatchLoader +from faster_rcnn.lib.model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir +from faster_rcnn.lib.model.rpn.bbox_transform import clip_boxes +# from faster_rcnn.lib.model.nms.nms_wrapper import nms +from faster_rcnn.lib.model.roi_layers import nms +from faster_rcnn.lib.model.rpn.bbox_transform import bbox_transform_inv +from faster_rcnn.lib.model.utils.net_utils import save_net, load_net, vis_detections +from faster_rcnn.lib.model.utils.blob import im_list_to_blob +from faster_rcnn.lib.model.faster_rcnn.vgg16 import vgg16 +from faster_rcnn.lib.model.faster_rcnn.resnet import resnet +import pdb + +try: + xrange # Python 2 +except NameError: + xrange = range # Python 3 + + +def parse_args(): + """ + Parse input arguments + """ + parser = argparse.ArgumentParser(description='Train a Fast R-CNN network') + parser.add_argument('--dataset', dest='dataset', + help='training dataset', + default='pascal_voc', type=str) + parser.add_argument('--cfg', dest='cfg_file', + help='optional config file', + default= + os.path.join(os.sep.join(faster_rcnn.__file__.split(os.sep)[:-1]), + 'cfgs', 'vgg16.yml'), type=str) + parser.add_argument('--net', dest='net', + help='vgg16, res50, res101, res152', + default='res101', type=str) + parser.add_argument('--set', dest='set_cfgs', + help='set config keys', default=None, + nargs=argparse.REMAINDER) + parser.add_argument('--load_dir', dest='load_dir', + help='directory to load models', + default="/srv/share/jyang375/models") + parser.add_argument('--image_dir', dest='image_dir', + help='directory to load images for demo', + default="images") + parser.add_argument('--cuda', dest='cuda', + help='whether use CUDA', + action='store_true') + parser.add_argument('--mGPUs', dest='mGPUs', + help='whether use multiple GPUs', + action='store_true') + parser.add_argument('--cag', dest='class_agnostic', + help='whether perform class_agnostic bbox regression', + action='store_true') + parser.add_argument('--parallel_type', dest='parallel_type', + help='which part of model to parallel, 0: all, 1: model before roi pooling', + default=0, type=int) + parser.add_argument('--checksession', dest='checksession', + help='checksession to load model', + default=1, type=int) + parser.add_argument('--checkepoch', dest='checkepoch', + help='checkepoch to load network', + default=1, type=int) + parser.add_argument('--checkpoint', dest='checkpoint', + help='checkpoint to load network', + default=10021, type=int) + parser.add_argument('--bs', dest='batch_size', + help='batch_size', + default=1, type=int) + parser.add_argument('--vis', dest='vis', + help='visualization mode', + action='store_true') + parser.add_argument('--webcam_num', dest='webcam_num', + help='webcam ID number', + default=-1, type=int) + + args = parser.parse_args() + return args + + +lr = cfg.TRAIN.LEARNING_RATE +momentum = cfg.TRAIN.MOMENTUM +weight_decay = cfg.TRAIN.WEIGHT_DECAY + + +def _get_image_blob(im): + """Converts an image into a network input. + Arguments: + im (ndarray): a color image in BGR order + Returns: + blob (ndarray): a data blob holding an image pyramid + im_scale_factors (list): list of image scales (relative to im) used + in the image pyramid + """ + im_orig = im.astype(np.float32, copy=True) + im_orig -= cfg.PIXEL_MEANS + + im_shape = im_orig.shape + im_size_min = np.min(im_shape[0:2]) + im_size_max = np.max(im_shape[0:2]) + + processed_ims = [] + im_scale_factors = [] + + for target_size in cfg.TEST.SCALES: + im_scale = float(target_size) / float(im_size_min) + # Prevent the biggest axis from being more than MAX_SIZE + if np.round(im_scale * im_size_max) > cfg.TEST.MAX_SIZE: + im_scale = float(cfg.TEST.MAX_SIZE) / float(im_size_max) + im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale, + interpolation=cv2.INTER_LINEAR) + im_scale_factors.append(im_scale) + processed_ims.append(im) + + # Create a blob to hold the input images + blob = im_list_to_blob(processed_ims) + + return blob, np.array(im_scale_factors) + + +def main(): + args = parse_args() + + print('Called with args:') + print(args) + + if args.cfg_file is not None: + cfg_from_file(args.cfg_file) + if args.set_cfgs is not None: + cfg_from_list(args.set_cfgs) + + cfg.USE_GPU_NMS = args.cuda + + print('Using config:') + pprint.pprint(cfg) + np.random.seed(cfg.RNG_SEED) + + # train set + # -- Note: Use validation set and disable the flipped to enable faster loading. + + input_dir = args.load_dir + "/" + args.net + "/" + args.dataset + if not os.path.exists(input_dir): + raise Exception( + 'There is no input directory for loading network from ' + input_dir) + load_name = os.path.join(input_dir, + 'faster_rcnn_{}_{}_{}.pth'.format(args.checksession, args.checkepoch, args.checkpoint)) + + pascal_classes = np.asarray(['__background__', + 'aeroplane', 'bicycle', 'bird', 'boat', + 'bottle', 'bus', 'car', 'cat', 'chair', + 'cow', 'diningtable', 'dog', 'horse', + 'motorbike', 'person', 'pottedplant', + 'sheep', 'sofa', 'train', 'tvmonitor']) + + # initilize the network here. + if args.net == 'vgg16': + fasterRCNN = vgg16(pascal_classes, pretrained=False, + class_agnostic=args.class_agnostic) + elif args.net == 'res101': + fasterRCNN = resnet(pascal_classes, 101, pretrained=False, + class_agnostic=args.class_agnostic) + elif args.net == 'res50': + fasterRCNN = resnet(pascal_classes, 50, pretrained=False, + class_agnostic=args.class_agnostic) + elif args.net == 'res152': + fasterRCNN = resnet(pascal_classes, 152, pretrained=False, + class_agnostic=args.class_agnostic) + else: + print("network is not defined") + pdb.set_trace() + + fasterRCNN.create_architecture() + + print("load checkpoint %s" % (load_name)) + if args.cuda > 0: + checkpoint = torch.load(load_name) + else: + checkpoint = torch.load( + load_name, map_location=(lambda storage, loc: storage)) + fasterRCNN.load_state_dict(checkpoint['model']) + if 'pooling_mode' in checkpoint.keys(): + cfg.POOLING_MODE = checkpoint['pooling_mode'] + + print('load model successfully!') + + # pdb.set_trace() + + print("load checkpoint %s" % (load_name)) + + # initilize the tensor holder here. + im_data = torch.FloatTensor(1) + im_info = torch.FloatTensor(1) + num_boxes = torch.LongTensor(1) + gt_boxes = torch.FloatTensor(1) + + # ship to cuda + if args.cuda > 0: + im_data = im_data.cuda() + im_info = im_info.cuda() + num_boxes = num_boxes.cuda() + gt_boxes = gt_boxes.cuda() + + # make variable + im_data = Variable(im_data, volatile=True) + im_info = Variable(im_info, volatile=True) + num_boxes = Variable(num_boxes, volatile=True) + gt_boxes = Variable(gt_boxes, volatile=True) + + if args.cuda > 0: + cfg.CUDA = True + + if args.cuda > 0: + fasterRCNN.cuda() + + fasterRCNN.eval() + + start = time.time() + max_per_image = 100 + thresh = 0.05 + vis = True + + webcam_num = args.webcam_num + # Set up webcam or get image directories + if webcam_num >= 0: + cap = cv2.VideoCapture(webcam_num) + num_images = 0 + else: + imglist = os.listdir(args.image_dir) + num_images = len(imglist) + + print('Loaded Photo: {} images.'.format(num_images)) + + while (num_images >= 0): + total_tic = time.time() + if webcam_num == -1: + num_images -= 1 + + # Get image from the webcam + if webcam_num >= 0: + if not cap.isOpened(): + raise RuntimeError( + "Webcam could not open. Please check connection.") + ret, frame = cap.read() + im_in = np.array(frame) + # Load the demo image + else: + im_file = os.path.join(args.image_dir, imglist[num_images]) + # im = cv2.imread(im_file) + im_in = np.array(imread(im_file)) + if len(im_in.shape) == 2: + im_in = im_in[:, :, np.newaxis] + im_in = np.concatenate((im_in, im_in, im_in), axis=2) + # rgb -> bgr + im = im_in[:, :, ::-1] + + blobs, im_scales = _get_image_blob(im) + assert len(im_scales) == 1, "Only single-image batch implemented" + im_blob = blobs + im_info_np = np.array( + [[im_blob.shape[1], im_blob.shape[2], im_scales[0]]], dtype=np.float32) + + im_data_pt = torch.from_numpy(im_blob) + im_data_pt = im_data_pt.permute(0, 3, 1, 2) + im_info_pt = torch.from_numpy(im_info_np) + + with torch.no_grad(): + im_data.resize_(im_data_pt.size()).copy_(im_data_pt) + im_info.resize_(im_info_pt.size()).copy_(im_info_pt) + gt_boxes.resize_(1, 1, 5).zero_() + num_boxes.resize_(1).zero_() + + # pdb.set_trace() + det_tic = time.time() + + rois, cls_prob, bbox_pred, \ + rpn_loss_cls, rpn_loss_box, \ + RCNN_loss_cls, RCNN_loss_bbox, \ + rois_label = fasterRCNN(im_data, im_info, gt_boxes, num_boxes) + + scores = cls_prob.data + boxes = rois.data[:, :, 1:5] + + if cfg.TEST.BBOX_REG: + # Apply bounding-box regression deltas + box_deltas = bbox_pred.data + if cfg.TRAIN.BBOX_NORMALIZE_TARGETS_PRECOMPUTED: + # Optionally normalize targets by a precomputed mean and stdev + if args.class_agnostic: + if args.cuda > 0: + box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS).cuda() \ + + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS).cuda() + else: + box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS) \ + + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS) + + box_deltas = box_deltas.view(1, -1, 4) + else: + if args.cuda > 0: + box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS).cuda() \ + + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS).cuda() + else: + box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS) \ + + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS) + box_deltas = box_deltas.view( + 1, -1, 4 * len(pascal_classes)) + + pred_boxes = bbox_transform_inv(boxes, box_deltas, 1) + pred_boxes = clip_boxes(pred_boxes, im_info.data, 1) + else: + # Simply repeat the boxes, once for each class + pred_boxes = np.tile(boxes, (1, scores.shape[1])) + + pred_boxes /= im_scales[0] + + scores = scores.squeeze() + pred_boxes = pred_boxes.squeeze() + det_toc = time.time() + detect_time = det_toc - det_tic + misc_tic = time.time() + if vis: + im2show = np.copy(im) + for j in xrange(1, len(pascal_classes)): + inds = torch.nonzero(scores[:, j] > thresh).view(-1) + # if there is det + if inds.numel() > 0: + cls_scores = scores[:, j][inds] + _, order = torch.sort(cls_scores, 0, True) + if args.class_agnostic: + cls_boxes = pred_boxes[inds, :] + else: + cls_boxes = pred_boxes[inds][:, j * 4:(j + 1) * 4] + + cls_dets = torch.cat((cls_boxes, cls_scores.unsqueeze(1)), 1) + # cls_dets = torch.cat((cls_boxes, cls_scores), 1) + cls_dets = cls_dets[order] + # keep = nms(cls_dets, cfg.TEST.NMS, force_cpu=not cfg.USE_GPU_NMS) + keep = nms(cls_boxes[order, :], + cls_scores[order], cfg.TEST.NMS) + cls_dets = cls_dets[keep.view(-1).long()] + if vis: + im2show = vis_detections( + im2show, pascal_classes[j], cls_dets.cpu().numpy(), 0.5) + + misc_toc = time.time() + nms_time = misc_toc - misc_tic + + if webcam_num == -1: + sys.stdout.write('im_detect: {:d}/{:d} {:.3f}s {:.3f}s \r' + .format(num_images + 1, len(imglist), detect_time, nms_time)) + sys.stdout.flush() + + if vis and webcam_num == -1: + # cv2.imshow('test', im2show) + # cv2.waitKey(0) + result_path = os.path.join( + args.image_dir, imglist[num_images][:-4] + "_det.jpg") + cv2.imwrite(result_path, im2show) + else: + im2showRGB = cv2.cvtColor(im2show, cv2.COLOR_BGR2RGB) + cv2.imshow("frame", im2showRGB) + total_toc = time.time() + total_time = total_toc - total_tic + frame_rate = 1 / total_time + print('Frame rate:', frame_rate) + if cv2.waitKey(1) & 0xFF == ord('q'): + break + if webcam_num >= 0: + cap.release() + cv2.destroyAllWindows() + + +if __name__ == '__main__': + main() diff --git a/test_net.py b/faster_rcnn/scripts/test_net.py similarity index 92% rename from test_net.py rename to faster_rcnn/scripts/test_net.py index 7e8522a2a..abc5f3b6c 100644 --- a/test_net.py +++ b/faster_rcnn/scripts/test_net.py @@ -7,7 +7,7 @@ from __future__ import division from __future__ import print_function -import _init_paths +import faster_rcnn._init_paths import os import sys import numpy as np @@ -25,14 +25,14 @@ import pickle from roi_data_layer.roidb import combined_roidb from roi_data_layer.roibatchLoader import roibatchLoader -from model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir -from model.rpn.bbox_transform import clip_boxes -# from model.nms.nms_wrapper import nms -from model.roi_layers import nms -from model.rpn.bbox_transform import bbox_transform_inv -from model.utils.net_utils import save_net, load_net, vis_detections -from model.faster_rcnn.vgg16 import vgg16 -from model.faster_rcnn.resnet import resnet +from faster_rcnn.lib.model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir +from faster_rcnn.lib.model.rpn.bbox_transform import clip_boxes +# from faster_rcnn.lib.model.nms.nms_wrapper import nms +from faster_rcnn.lib.model.roi_layers import nms +from faster_rcnn.lib.model.rpn.bbox_transform import bbox_transform_inv +from faster_rcnn.lib.model.utils.net_utils import save_net, load_net, vis_detections +from faster_rcnn.lib.model.faster_rcnn.vgg16 import vgg16 +from faster_rcnn.lib.model.faster_rcnn.resnet import resnet try: xrange # Python 2 @@ -50,7 +50,8 @@ def parse_args(): default='pascal_voc', type=str) parser.add_argument('--cfg', dest='cfg_file', help='optional config file', - default='cfgs/vgg16.yml', type=str) + default=os.path.join(os.sep.join(faster_rcnn.__file__.split(os.sep)[:-1]), + 'cfgs', 'vgg16.yml'), type=str) parser.add_argument('--net', dest='net', help='vgg16, res50, res101, res152', default='res101', type=str) @@ -94,8 +95,7 @@ def parse_args(): momentum = cfg.TRAIN.MOMENTUM weight_decay = cfg.TRAIN.WEIGHT_DECAY -if __name__ == '__main__': - +def main(): args = parse_args() print('Called with args:') @@ -126,7 +126,10 @@ def parse_args(): args.imdbval_name = "vg_150-50-50_minival" args.set_cfgs = ['ANCHOR_SCALES', '[4, 8, 16, 32]', 'ANCHOR_RATIOS', '[0.5,1,2]'] - args.cfg_file = "cfgs/{}_ls.yml".format(args.net) if args.large_scale else "cfgs/{}.yml".format(args.net) + args.cfg_file = os.path.join(os.sep.join(faster_rcnn.__file__.split(os.sep)[:-1]), + 'cfgs', + ("{}_ls.yml".format(args.net) if + args.large_scale else "{}.yml".format(args.net))) if args.cfg_file is not None: cfg_from_file(args.cfg_file) @@ -283,7 +286,7 @@ def parse_args(): cls_boxes = pred_boxes[inds, :] else: cls_boxes = pred_boxes[inds][:, j * 4:(j + 1) * 4] - + cls_dets = torch.cat((cls_boxes, cls_scores.unsqueeze(1)), 1) # cls_dets = torch.cat((cls_boxes, cls_scores), 1) cls_dets = cls_dets[order] @@ -326,3 +329,5 @@ def parse_args(): end = time.time() print("test time: %0.4fs" % (end - start)) +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/trainval_net.py b/faster_rcnn/scripts/trainval_net.py similarity index 97% rename from trainval_net.py rename to faster_rcnn/scripts/trainval_net.py index 4bc817307..e0dfe3f73 100644 --- a/trainval_net.py +++ b/faster_rcnn/scripts/trainval_net.py @@ -7,7 +7,7 @@ from __future__ import division from __future__ import print_function -import _init_paths +import faster_rcnn._init_paths import os import sys import numpy as np @@ -26,12 +26,12 @@ from roi_data_layer.roidb import combined_roidb from roi_data_layer.roibatchLoader import roibatchLoader -from model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir -from model.utils.net_utils import weights_normal_init, save_net, load_net, \ +from faster_rcnn.lib.model.utils.config import cfg, cfg_from_file, cfg_from_list, get_output_dir +from faster_rcnn.lib.model.utils.net_utils import weights_normal_init, save_net, load_net, \ adjust_learning_rate, save_checkpoint, clip_gradient -from model.faster_rcnn.vgg16 import vgg16 -from model.faster_rcnn.resnet import resnet +from faster_rcnn.lib.model.faster_rcnn.vgg16 import vgg16 +from faster_rcnn.lib.model.faster_rcnn.resnet import resnet def parse_args(): """ @@ -68,7 +68,7 @@ def parse_args(): action='store_true') parser.add_argument('--ls', dest='large_scale', help='whether use large imag scale', - action='store_true') + action='store_true') parser.add_argument('--mGPUs', dest='mGPUs', help='whether use multiple GPUs', action='store_true') @@ -145,8 +145,8 @@ def __iter__(self): def __len__(self): return self.num_data -if __name__ == '__main__': +def main(): args = parse_args() print('Called with args:') @@ -264,7 +264,7 @@ def __len__(self): if args.cuda: fasterRCNN.cuda() - + if args.optimizer == "adam": lr = lr * 0.1 optimizer = torch.optim.Adam(params) @@ -369,7 +369,7 @@ def __len__(self): loss_temp = 0 start = time.time() - + save_name = os.path.join(output_dir, 'faster_rcnn_{}_{}_{}.pth'.format(args.session, epoch, step)) save_checkpoint({ 'session': args.session, @@ -383,3 +383,6 @@ def __len__(self): if args.use_tfboard: logger.close() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/lib/model/nms/src/nms_cuda.c b/lib/model/nms/src/nms_cuda.c deleted file mode 100644 index 3667c7d2f..000000000 --- a/lib/model/nms/src/nms_cuda.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include "nms_cuda_kernel.h" - -// this symbol will be resolved automatically from PyTorch libs -extern THCState *state; - -int nms_cuda(THCudaIntTensor *keep_out, THCudaTensor *boxes_host, - THCudaIntTensor *num_out, float nms_overlap_thresh) { - - nms_cuda_compute(THCudaIntTensor_data(state, keep_out), - THCudaIntTensor_data(state, num_out), - THCudaTensor_data(state, boxes_host), - THCudaTensor_size(state, boxes_host, 0), - THCudaTensor_size(state, boxes_host, 1), - nms_overlap_thresh); - - return 1; -} diff --git a/lib/model/roi_crop/_ext/crop_resize/_crop_resize.so b/lib/model/roi_crop/_ext/crop_resize/_crop_resize.so deleted file mode 100755 index 9baf6615c37b3a600f3315c0297d00b55c143846..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159103 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 E5Ac0#_y7O^ diff --git a/lib/setup.py b/setup.py similarity index 62% rename from lib/setup.py rename to setup.py index 7e7e20018..043b38406 100644 --- a/lib/setup.py +++ b/setup.py @@ -11,11 +11,11 @@ from torch.utils.cpp_extension import CppExtension from torch.utils.cpp_extension import CUDAExtension -requirements = ["torch", "torchvision"] - +with open('requirements.txt') as inp: + requirements = inp.read().splitlines() def get_extensions(): - this_dir = os.path.dirname(os.path.abspath(__file__)) + this_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'faster_rcnn', 'lib') extensions_dir = os.path.join(this_dir, "model", "csrc") main_file = glob.glob(os.path.join(extensions_dir, "*.cpp")) @@ -45,7 +45,7 @@ def get_extensions(): ext_modules = [ extension( - "model._C", + "faster_rcnn.lib.model._C", sources, include_dirs=include_dirs, define_macros=define_macros, @@ -56,12 +56,30 @@ def get_extensions(): return ext_modules +def get_scripts_dict(): + """Construct the scripts dictionary, ie the dictionary of the executables + """ + scripts_dict = {} + for root, _, files in os.walk(os.path.join('faster_rcnn', 'scripts')): + for fil in files: + if fil.endswith('.py') and fil != '__init__.py': + path = os.path.join(root, fil) + module = 'faster_rcnn' + '.'.join(path.split( + 'faster_rcnn')[-1][:-3].split(os.sep)) + ":main" + scripts_dict[fil[:-3]] = module + return scripts_dict + + setup( name="faster_rcnn", - version="0.1", + version="0.2", description="object detection in pytorch", - packages=find_packages(exclude=("configs", "tests",)), - # install_requires=requirements, + install_requires=requirements, + packages=find_packages(), ext_modules=get_extensions(), cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension}, + entry_points={ + 'console_scripts': [ + "faster_rcnn_" + script + + '=' + d[script] for d in [get_scripts_dict()] for script in d]} )