diff --git a/app.py b/app.py index 9b07a3a2cebbf173138749035b5dcf5a83391e15..26070dcaa8b9006bc76c32448855724e38c25527 100644 --- a/app.py +++ b/app.py @@ -2,23 +2,25 @@ import os import sys import time -from pathlib import Path -from omegaconf import OmegaConf from glob import glob from os.path import join as opj +from pathlib import Path +import apply_net import gradio as gr -from PIL import Image import torch +from omegaconf import OmegaConf +from PIL import Image -from utils_stableviton import get_mask_location, get_batch, tensor2img from cldm.model import create_model from cldm.plms_hacked import PLMSSampler +from detectron2.data.detection_utils import _apply_exif_orientation, convert_PIL_to_numpy +from utils_stableviton import get_batch, get_mask_location, tensor2img PROJECT_ROOT = Path(__file__).absolute().parents[1].absolute() sys.path.insert(0, str(PROJECT_ROOT)) -from preprocess.detectron2.projects.DensePose.apply_net_gradio import DensePose4Gradio +# from detectron2.projects.DensePose.apply_net_gradio import DensePose4Gradio from preprocess.humanparsing.run_parsing import Parsing from preprocess.openpose.run_openpose import OpenPose @@ -30,10 +32,10 @@ IMG_W = 384 openpose_model_hd = OpenPose(0) openpose_model_hd.preprocessor.body_estimation.model.to('cuda') parsing_model_hd = Parsing(0) -densepose_model_hd = DensePose4Gradio( - cfg='preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x.yaml', - model='https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl', -) +# densepose_model_hd = DensePose4Gradio( +# cfg='preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x.yaml', +# model='https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl', +# ) category_dict = ['upperbody', 'lowerbody', 'dress'] category_dict_utils = ['upper_body', 'lower_body', 'dresses'] @@ -50,6 +52,8 @@ model = model.cuda() model.eval() sampler = PLMSSampler(model) # #### model init <<<< + + def stable_viton_model_hd( batch, n_steps, @@ -69,25 +73,27 @@ def stable_viton_model_hd( sampler.model.batch = batch ts = torch.full((1,), 999, device=z.device, dtype=torch.long) - start_code = model.q_sample(z, ts) + start_code = model.q_sample(z, ts) output, _, _ = sampler.sample( n_steps, bs, - (4, IMG_H//8, IMG_W//8), + (4, IMG_H // 8, IMG_W // 8), cond, - x_T=start_code, + x_T=start_code, verbose=False, eta=0.0, - unconditional_conditioning=uc_full, + unconditional_conditioning=uc_full, ) output = model.decode_first_stage(output) output = tensor2img(output) pil_output = Image.fromarray(output) return pil_output - + # @spaces.GPU # TODO: turn on when final upload + + @torch.no_grad() def process_hd(vton_img, garm_img, n_steps): model_type = 'hd' @@ -112,19 +118,28 @@ def process_hd(vton_img, garm_img, n_steps): stt = time.time() print('get densepose... ', end='') vton_img = vton_img.resize((IMG_W, IMG_H)) # size for densepose - densepose = densepose_model_hd.execute(vton_img) # densepose + # densepose = densepose_model_hd.execute(vton_img) # densepose + + human_img_arg = _apply_exif_orientation(vton_img.resize((IMG_W, IMG_H))) + human_img_arg = convert_PIL_to_numpy(human_img_arg, format="BGR") + args = apply_net.create_argument_parser().parse_args(('show', './configs/densepose_rcnn_R_50_FPN_s1x.yaml', './ckpt/densepose/model_final_162be9.pkl', 'dp_segm', '-v', '--opts', 'MODEL.DEVICE', 'cuda')) + # verbosity = getattr(args, "verbosity", None) + pose_img = args.func(args, human_img_arg) + pose_img = pose_img[:, :, ::-1] + pose_img = Image.fromarray(pose_img).resize((IMG_W, IMG_H)) + print('%.2fs' % (time.time() - stt)) batch = get_batch( - vton_img, - garm_img, - densepose, - masked_vton_img, - mask, - IMG_H, + vton_img, + garm_img, + densepose, + masked_vton_img, + mask, + IMG_H, IMG_W ) - + sample = stable_viton_model_hd( batch, n_steps diff --git a/preprocess/detectron2/projects/DensePose/apply_net.py b/apply_net.py old mode 100755 new mode 100644 similarity index 63% rename from preprocess/detectron2/projects/DensePose/apply_net.py rename to apply_net.py index c55ab68e772b6926ef43bcad5372179a67320527..732539d616d7dd9d039302f97b5d6438a5cb4892 --- a/preprocess/detectron2/projects/DensePose/apply_net.py +++ b/apply_net.py @@ -7,29 +7,40 @@ import logging import os import sys from typing import Any, ClassVar, Dict, List - -import cv2 -import numpy as np import torch -from densepose import add_densepose_config -from densepose.structures import DensePoseChartPredictorOutput, DensePoseEmbeddingPredictorOutput -from densepose.utils.logger import verbosity_to_level -from densepose.vis.base import CompoundVisualizer -from densepose.vis.bounding_box import ScoredBoundingBoxVisualizer -from densepose.vis.densepose_outputs_vertex import (DensePoseOutputsTextureVisualizer, DensePoseOutputsVertexVisualizer, - get_texture_atlases) -from densepose.vis.densepose_results import (DensePoseResultsContourVisualizer, - DensePoseResultsFineSegmentationVisualizer, DensePoseResultsUVisualizer, - DensePoseResultsVVisualizer) -from densepose.vis.densepose_results_textures import DensePoseResultsVisualizerWithTexture, get_texture_atlas -from densepose.vis.extractor import (CompoundExtractor, DensePoseOutputsExtractor, DensePoseResultExtractor, - create_extractor) + from detectron2.config import CfgNode, get_cfg from detectron2.data.detection_utils import read_image from detectron2.engine.defaults import DefaultPredictor from detectron2.structures.instances import Instances from detectron2.utils.logger import setup_logger -from PIL import Image + +from densepose import add_densepose_config +from densepose.structures import DensePoseChartPredictorOutput, DensePoseEmbeddingPredictorOutput +from densepose.utils.logger import verbosity_to_level +from densepose.vis.base import CompoundVisualizer +from densepose.vis.bounding_box import ScoredBoundingBoxVisualizer +from densepose.vis.densepose_outputs_vertex import ( + DensePoseOutputsTextureVisualizer, + DensePoseOutputsVertexVisualizer, + get_texture_atlases, +) +from densepose.vis.densepose_results import ( + DensePoseResultsContourVisualizer, + DensePoseResultsFineSegmentationVisualizer, + DensePoseResultsUVisualizer, + DensePoseResultsVVisualizer, +) +from densepose.vis.densepose_results_textures import ( + DensePoseResultsVisualizerWithTexture, + get_texture_atlas, +) +from densepose.vis.extractor import ( + CompoundExtractor, + DensePoseOutputsExtractor, + DensePoseResultExtractor, + create_extractor, +) DOC = """Apply Net - a tool to print / visualize DensePose results """ @@ -40,9 +51,9 @@ logger = logging.getLogger(LOGGER_NAME) _ACTION_REGISTRY: Dict[str, "Action"] = {} -class Action(object): +class Action: @classmethod - def add_arguments(cls, parser: argparse.ArgumentParser): + def add_arguments(cls: type, parser: argparse.ArgumentParser): parser.add_argument( "-v", "--verbosity", @@ -51,7 +62,7 @@ class Action(object): ) -def register_action(cls): +def register_action(cls: type): """ Decorator for action classes to automate action registration """ @@ -62,11 +73,10 @@ def register_action(cls): class InferenceAction(Action): @classmethod - def add_arguments(cls, parser: argparse.ArgumentParser): + def add_arguments(cls: type, parser: argparse.ArgumentParser): super(InferenceAction, cls).add_arguments(parser) parser.add_argument("cfg", metavar="", help="Config file") parser.add_argument("model", metavar="", help="Model file") - parser.add_argument("input", metavar="", help="Input data") parser.add_argument( "--opts", help="Modify config options using the command-line 'KEY VALUE' pairs", @@ -75,28 +85,29 @@ class InferenceAction(Action): ) @classmethod - def execute(cls, args: argparse.Namespace): + def execute(cls: type, args: argparse.Namespace, human_img): logger.info(f"Loading config from {args.cfg}") opts = [] cfg = cls.setup_config(args.cfg, args.model, args, opts) logger.info(f"Loading model from {args.model}") predictor = DefaultPredictor(cfg) - logger.info(f"Loading data from {args.input}") - file_list = cls._get_input_file_list(args.input) - if len(file_list) == 0: - logger.warning(f"No input images for {args.input}") - return + # logger.info(f"Loading data from {args.input}") + # file_list = cls._get_input_file_list(args.input) + # if len(file_list) == 0: + # logger.warning(f"No input images for {args.input}") + # return context = cls.create_context(args, cfg) - for file_name in file_list: - img = read_image(file_name, format="BGR") # predictor expects BGR image. - with torch.no_grad(): - outputs = predictor(img)["instances"] - cls.execute_on_outputs(context, {"file_name": file_name, "image": img}, outputs) + # for file_name in file_list: + # img = read_image(file_name, format="BGR") # predictor expects BGR image. + with torch.no_grad(): + outputs = predictor(human_img)["instances"] + out_pose = cls.execute_on_outputs(context, {"image": human_img}, outputs) cls.postexecute(context) + return out_pose @classmethod def setup_config( - cls, config_fpath: str, model_fpath: str, args: argparse.Namespace, opts: List[str] + cls: type, config_fpath: str, model_fpath: str, args: argparse.Namespace, opts: List[str] ): cfg = get_cfg() add_densepose_config(cfg) @@ -109,7 +120,7 @@ class InferenceAction(Action): return cfg @classmethod - def _get_input_file_list(cls, input_spec: str): + def _get_input_file_list(cls: type, input_spec: str): if os.path.isdir(input_spec): file_list = [ os.path.join(input_spec, fname) @@ -132,13 +143,13 @@ class DumpAction(InferenceAction): COMMAND: ClassVar[str] = "dump" @classmethod - def add_parser(cls, subparsers: argparse._SubParsersAction): + def add_parser(cls: type, subparsers: argparse._SubParsersAction): parser = subparsers.add_parser(cls.COMMAND, help="Dump model outputs to a file.") cls.add_arguments(parser) parser.set_defaults(func=cls.execute) @classmethod - def add_arguments(cls, parser: argparse.ArgumentParser): + def add_arguments(cls: type, parser: argparse.ArgumentParser): super(DumpAction, cls).add_arguments(parser) parser.add_argument( "--output", @@ -149,7 +160,7 @@ class DumpAction(InferenceAction): @classmethod def execute_on_outputs( - cls, context: Dict[str, Any], entry: Dict[str, Any], outputs: Instances + cls: type, context: Dict[str, Any], entry: Dict[str, Any], outputs: Instances ): image_fpath = entry["file_name"] logger.info(f"Processing {image_fpath}") @@ -167,12 +178,12 @@ class DumpAction(InferenceAction): context["results"].append(result) @classmethod - def create_context(cls, args: argparse.Namespace, cfg: CfgNode): + def create_context(cls: type, args: argparse.Namespace, cfg: CfgNode): context = {"results": [], "out_fname": args.output} return context @classmethod - def postexecute(cls, context: Dict[str, Any]): + def postexecute(cls: type, context: Dict[str, Any]): out_fname = context["out_fname"] out_dir = os.path.dirname(out_fname) if len(out_dir) > 0 and not os.path.exists(out_dir): @@ -201,13 +212,13 @@ class ShowAction(InferenceAction): } @classmethod - def add_parser(cls, subparsers: argparse._SubParsersAction): + def add_parser(cls: type, subparsers: argparse._SubParsersAction): parser = subparsers.add_parser(cls.COMMAND, help="Visualize selected entries") cls.add_arguments(parser) parser.set_defaults(func=cls.execute) @classmethod - def add_arguments(cls, parser: argparse.ArgumentParser): + def add_arguments(cls: type, parser: argparse.ArgumentParser): super(ShowAction, cls).add_arguments(parser) parser.add_argument( "visualizations", @@ -246,7 +257,7 @@ class ShowAction(InferenceAction): @classmethod def setup_config( - cls, config_fpath: str, model_fpath: str, args: argparse.Namespace, opts: List[str] + cls: type, config_fpath: str, model_fpath: str, args: argparse.Namespace, opts: List[str] ): opts.append("MODEL.ROI_HEADS.SCORE_THRESH_TEST") opts.append(str(args.min_score)) @@ -258,21 +269,23 @@ class ShowAction(InferenceAction): @classmethod def execute_on_outputs( - cls, context: Dict[str, Any], entry: Dict[str, Any], outputs: Instances + cls: type, context: Dict[str, Any], entry: Dict[str, Any], outputs: Instances ): import cv2 import numpy as np - visualizer = context["visualizer"] extractor = context["extractor"] - image_fpath = entry["file_name"] - logger.info(f"Processing {image_fpath}") + # image_fpath = entry["file_name"] + # logger.info(f"Processing {image_fpath}") image = cv2.cvtColor(entry["image"], cv2.COLOR_BGR2GRAY) image = np.tile(image[:, :, np.newaxis], [1, 1, 3]) data = extractor(outputs) image_vis = visualizer.visualize(image, data) + + return image_vis entry_idx = context["entry_idx"] + 1 - out_fname = cls._get_out_fname(entry_idx, context["out_fname"]) + out_fname = './image-densepose/' + image_fpath.split('/')[-1] + out_dir = './image-densepose' out_dir = os.path.dirname(out_fname) if len(out_dir) > 0 and not os.path.exists(out_dir): os.makedirs(out_dir) @@ -281,16 +294,17 @@ class ShowAction(InferenceAction): context["entry_idx"] += 1 @classmethod - def postexecute(cls, context: Dict[str, Any]): + def postexecute(cls: type, context: Dict[str, Any]): pass +# python ./apply_net.py show ./configs/densepose_rcnn_R_50_FPN_s1x.yaml https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl /home/alin0222/DressCode/upper_body/images dp_segm -v --opts MODEL.DEVICE cpu @classmethod - def _get_out_fname(cls, entry_idx: int, fname_base: str): + def _get_out_fname(cls: type, entry_idx: int, fname_base: str): base, ext = os.path.splitext(fname_base) return base + ".{0:04d}".format(entry_idx) + ext @classmethod - def create_context(cls, args: argparse.Namespace, cfg: CfgNode) -> Dict[str, Any]: + def create_context(cls: type, args: argparse.Namespace, cfg: CfgNode) -> Dict[str, Any]: vis_specs = args.visualizations.split(",") visualizers = [] extractors = [] @@ -316,80 +330,6 @@ class ShowAction(InferenceAction): return context -@register_action -class GetAction(InferenceAction): - """ - Get action that outputs results to a pickle file - """ - - COMMAND: ClassVar[str] = "get" - - @classmethod - def add_parser(cls, subparsers: argparse._SubParsersAction): - parser = subparsers.add_parser(cls.COMMAND, help="Get model outputs to a file.") - cls.add_arguments(parser) - parser.set_defaults(func=cls.execute) - - @classmethod - def add_arguments(cls, parser: argparse.ArgumentParser): - super(GetAction, cls).add_arguments(parser) - parser.add_argument( - "--output", - metavar="", - default="", - help="File name to save images to", - ) - - @classmethod - def execute_on_outputs( - cls, context: Dict[str, Any], entry: Dict[str, Any], outputs: Instances - ): - image_fpath = entry["file_name"] - logger.info(f"Processing {image_fpath}") - result = {"file_name": image_fpath} - if outputs.has("scores"): - result["scores"] = outputs.get("scores").cpu() - if outputs.has("pred_boxes"): - result["pred_boxes_XYXY"] = outputs.get("pred_boxes").tensor.cpu() - if outputs.has("pred_densepose"): - if isinstance(outputs.pred_densepose, DensePoseChartPredictorOutput): - extractor = DensePoseResultExtractor() - elif isinstance(outputs.pred_densepose, DensePoseEmbeddingPredictorOutput): - extractor = DensePoseOutputsExtractor() - result["pred_densepose"] = extractor(outputs)[0] - - # decode - out_dir = context["out_fname"] - H, W, _ = entry['image'].shape - - i = result['pred_densepose'][0].labels.cpu().numpy() - i_scale = (i.astype(np.float32) * 255 / 24).astype(np.uint8) - i_color = cv2.applyColorMap(i_scale, cv2.COLORMAP_PARULA) - i_color = cv2.cvtColor(i_color, cv2.COLOR_RGB2BGR) - i_color[i == 0] = [0, 0, 0] - - box = result["pred_boxes_XYXY"][0] - box[2] = box[2] - box[0] - box[3] = box[3] - box[1] - x, y, w, h = [int(v) for v in box] - - bg = np.zeros((H, W, 3)) - bg[y:y + h, x:x + w, :] = i_color - - bg_img = Image.fromarray(np.uint8(bg), "RGB") - os.makedirs(out_dir, exist_ok=True) - bg_img.save(os.path.join(out_dir, os.path.splitext(os.path.basename(result['file_name']))[0] + '.jpg')) - - @classmethod - def create_context(cls, args: argparse.Namespace, cfg: CfgNode): - context = {"results": [], "out_fname": args.output} - return context - - @classmethod - def postexecute(cls, context: Dict[str, Any]): - pass - - def create_argument_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description=DOC, @@ -405,7 +345,7 @@ def create_argument_parser() -> argparse.ArgumentParser: def main(): parser = create_argument_parser() args = parser.parse_args() - verbosity = args.verbosity if hasattr(args, "verbosity") else None + verbosity = getattr(args, "verbosity", None) global logger logger = setup_logger(name=LOGGER_NAME) logger.setLevel(verbosity_to_level(verbosity)) @@ -414,3 +354,6 @@ def main(): if __name__ == "__main__": main() + + +# python ./apply_net.py show ./configs/densepose_rcnn_R_50_FPN_s1x.yaml https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl /home/alin0222/Dresscode/dresses/humanonly dp_segm -v --opts MODEL.DEVICE cuda diff --git a/densepose b/densepose deleted file mode 120000 index 26404c88936bcad96d3c95fe97f3194f081a1007..0000000000000000000000000000000000000000 --- a/densepose +++ /dev/null @@ -1 +0,0 @@ -preprocess/detectron2/projects/DensePose/densepose/ \ No newline at end of file diff --git a/preprocess/detectron2/projects/DensePose/densepose/__init__.py b/densepose/__init__.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/__init__.py rename to densepose/__init__.py index 0fc9e977ed3174e244414378dd85d48ea02e635e..b50a3da91dd0d2a69502af9d5d62f2f4280d973f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/__init__.py +++ b/densepose/__init__.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from .data.datasets import builtin # just to register data from .converters import builtin as builtin_converters # register converters from .config import ( diff --git a/preprocess/detectron2/projects/DensePose/densepose/config.py b/densepose/config.py similarity index 100% rename from preprocess/detectron2/projects/DensePose/densepose/config.py rename to densepose/config.py diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/__init__.py b/densepose/converters/__init__.py similarity index 97% rename from preprocess/detectron2/projects/DensePose/densepose/converters/__init__.py rename to densepose/converters/__init__.py index 9b700f44437bd4e68be358ed5aae62a22df8d88a..930339e13f408ad46d0504fac557ef8cf0a57a56 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/__init__.py +++ b/densepose/converters/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .hflip import HFlipConverter from .to_mask import ToMaskConverter from .to_chart_result import ToChartResultConverter, ToChartResultConverterWithConfidences diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/base.py b/densepose/converters/base.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/base.py rename to densepose/converters/base.py index 25e3155a87b819fe526b7b2735e006aeb3a56dda..c9dbe56cecff6dbbc1a1fda5a89c5f917513dcd8 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/base.py +++ b/densepose/converters/base.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any, Tuple, Type import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/builtin.py b/densepose/converters/builtin.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/converters/builtin.py rename to densepose/converters/builtin.py index 5234410307d7bfff932da982ca44926afb729c23..3bd48f8f7afc49cf38bf410f01bc673d446f37d7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/builtin.py +++ b/densepose/converters/builtin.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from ..structures import DensePoseChartPredictorOutput, DensePoseEmbeddingPredictorOutput from . import ( HFlipConverter, diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_hflip.py b/densepose/converters/chart_output_hflip.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_hflip.py rename to densepose/converters/chart_output_hflip.py index f7f0061c858c80b083d40807c0bdfb4dfcc5d86b..17d294841264c248cf7fa9e3d2d2b4efdbb9a5e8 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_hflip.py +++ b/densepose/converters/chart_output_hflip.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from dataclasses import fields import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_to_chart_result.py b/densepose/converters/chart_output_to_chart_result.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_to_chart_result.py rename to densepose/converters/chart_output_to_chart_result.py index b2e9c2280a60f80d2e32861a392fc78b3148cac8..4248f6c91b641a4ad1d00d0316ee82d701f9152f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/chart_output_to_chart_result.py +++ b/densepose/converters/chart_output_to_chart_result.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Dict import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/hflip.py b/densepose/converters/hflip.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/converters/hflip.py rename to densepose/converters/hflip.py index 711b73b3701adfd0217132519aea46f30f9ed74a..6df144280b2b84308acbb607e3313d0992faa68c 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/hflip.py +++ b/densepose/converters/hflip.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any from .base import BaseConverter diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/segm_to_mask.py b/densepose/converters/segm_to_mask.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/segm_to_mask.py rename to densepose/converters/segm_to_mask.py index e5843a2186f441aa9cb48b680fd67051aa1236f6..6433d5dec75c3d6141252af144b61d8999077bb7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/segm_to_mask.py +++ b/densepose/converters/segm_to_mask.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/to_chart_result.py b/densepose/converters/to_chart_result.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/to_chart_result.py rename to densepose/converters/to_chart_result.py index 82e126a922ff8ac4d8ebc3008f67d3928b982c25..3eabd2614c285e8ea39d241b73f0d4b5762e6baa 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/to_chart_result.py +++ b/densepose/converters/to_chart_result.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any from detectron2.structures import Boxes diff --git a/preprocess/detectron2/projects/DensePose/densepose/converters/to_mask.py b/densepose/converters/to_mask.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/converters/to_mask.py rename to densepose/converters/to_mask.py index 7a47e2a7d7aa5f0d9c41ab46a4f1806184b7b4ba..a57fd71afc448a7d269a8a38c2014b14c8c5074f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/converters/to_mask.py +++ b/densepose/converters/to_mask.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any, Tuple from detectron2.structures import BitMasks, Boxes diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/__init__.py b/densepose/data/__init__.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/__init__.py rename to densepose/data/__init__.py index 5278887bd723f1606debd3de09b7e3e0ff5b3a03..bf21ba75306970fd6a44069b49107320a84182b8 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/__init__.py +++ b/densepose/data/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .meshes import builtin from .build import ( build_detection_test_loader, diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/build.py b/densepose/data/build.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/build.py rename to densepose/data/build.py index e9ae5d595af3684459ad47d71dd6c72c655ce398..39edbd89d88b7f66e4952add5d23289c8e7b9348 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/build.py +++ b/densepose/data/build.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import itertools import logging import numpy as np diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/combined_loader.py b/densepose/data/combined_loader.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/combined_loader.py rename to densepose/data/combined_loader.py index c038c23a3b436b1cc6c29427c8dbf940f56250c9..5bfbbdeaf53e184b83a6e0f951867b79d3d9f1fd 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/combined_loader.py +++ b/densepose/data/combined_loader.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random from collections import deque from typing import Any, Collection, Deque, Iterable, Iterator, List, Sequence diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/dataset_mapper.py b/densepose/data/dataset_mapper.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/dataset_mapper.py rename to densepose/data/dataset_mapper.py index 5537a94c0811f7f6849f534612222e8dc154b59d..3229c4d7b9eab3e8e2d4f895d5209dd655d716a5 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/dataset_mapper.py +++ b/densepose/data/dataset_mapper.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import copy import logging from typing import Any, Dict, List, Tuple diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/__init__.py b/densepose/data/datasets/__init__.py similarity index 93% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/__init__.py rename to densepose/data/datasets/__init__.py index ccf0cf1c1dd2e21e096bd7c849150d9c261b9b4f..260ccb9c43e5aa2d0f1fd28cfcbdd4f31913d16a 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/__init__.py +++ b/densepose/data/datasets/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from . import builtin # ensure the builtin datasets are registered __all__ = [k for k in globals().keys() if "builtin" not in k and not k.startswith("_")] diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/builtin.py b/densepose/data/datasets/builtin.py similarity index 97% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/builtin.py rename to densepose/data/datasets/builtin.py index 759c295e064b29c7968ec7db5e78d3d4de033578..7572cd6abc550fdce9d1fd079a7af4870de303bb 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/builtin.py +++ b/densepose/data/datasets/builtin.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from .chimpnsee import register_dataset as register_chimpnsee_dataset from .coco import BASE_DATASETS as BASE_COCO_DATASETS from .coco import DATASETS as COCO_DATASETS diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/chimpnsee.py b/densepose/data/datasets/chimpnsee.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/chimpnsee.py rename to densepose/data/datasets/chimpnsee.py index 7a0ee3768597f730f8230f52807a953148350f16..61e0b506dc4ed6ad78c9c4ce4677415a27f5f6cd 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/chimpnsee.py +++ b/densepose/data/datasets/chimpnsee.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Optional from detectron2.data import DatasetCatalog, MetadataCatalog diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/coco.py b/densepose/data/datasets/coco.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/coco.py rename to densepose/data/datasets/coco.py index 47c9a5e1dc7422a970b7804277f9ba07841bc714..c19f7b034b1641c9ccd88634f12fcdc3013bce09 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/coco.py +++ b/densepose/data/datasets/coco.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import contextlib import io import logging diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/dataset_type.py b/densepose/data/datasets/dataset_type.py similarity index 93% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/dataset_type.py rename to densepose/data/datasets/dataset_type.py index 4e546f2aa74b4586d97618d41c69432ed01e21e9..ed8f8f299af96847d9d16a77920429fe0195c526 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/dataset_type.py +++ b/densepose/data/datasets/dataset_type.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from enum import Enum diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/lvis.py b/densepose/data/datasets/lvis.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/datasets/lvis.py rename to densepose/data/datasets/lvis.py index e90caac4bb429f9500a98998df18d238254a709e..b4af9fa292f445c81dc840ab53d07c1af313dfc7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/datasets/lvis.py +++ b/densepose/data/datasets/lvis.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import logging import os from typing import Any, Dict, Iterable, List, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/image_list_dataset.py b/densepose/data/image_list_dataset.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/image_list_dataset.py rename to densepose/data/image_list_dataset.py index 2d948f3c3b238bfb7e1b6c7f9784febf74f00ab4..92a95d3d5e7d4d7d6bf1d29d51295d32ae2104d2 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/image_list_dataset.py +++ b/densepose/data/image_list_dataset.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import logging import numpy as np from typing import Any, Callable, Dict, List, Optional, Union diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/inference_based_loader.py b/densepose/data/inference_based_loader.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/inference_based_loader.py rename to densepose/data/inference_based_loader.py index b643935cb7cbcaa06f66ca1c459ef25c5753cffd..cb89544500c29c4055353060ebbc8b428bd0262a 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/inference_based_loader.py +++ b/densepose/data/inference_based_loader.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/__init__.py b/densepose/data/meshes/__init__.py similarity index 92% rename from preprocess/detectron2/projects/DensePose/densepose/data/meshes/__init__.py rename to densepose/data/meshes/__init__.py index 7552c251b2225af62212aae69d4ce273608f7a67..1e1f0d5dc439dc58914238b23572f586dd1c693e 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/__init__.py +++ b/densepose/data/meshes/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from . import builtin __all__ = [k for k in globals().keys() if "builtin" not in k and not k.startswith("_")] diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/builtin.py b/densepose/data/meshes/builtin.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/meshes/builtin.py rename to densepose/data/meshes/builtin.py index fc8ec8418852dc344d7c4bd9f6c5fdd049b30a6d..c0b23760e8268b068149931b173a4285ba451993 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/builtin.py +++ b/densepose/data/meshes/builtin.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from .catalog import MeshInfo, register_meshes DENSEPOSE_MESHES_DIR = "https://dl.fbaipublicfiles.com/densepose/meshes/" diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/catalog.py b/densepose/data/meshes/catalog.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/meshes/catalog.py rename to densepose/data/meshes/catalog.py index ae624a8aa21fb11cc3c3f7ee467f28b896959781..b258f3ce11a90666b9c764541ce299384cfddf4e 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/meshes/catalog.py +++ b/densepose/data/meshes/catalog.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import logging from collections import UserDict from dataclasses import dataclass diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/__init__.py b/densepose/data/samplers/__init__.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/__init__.py rename to densepose/data/samplers/__init__.py index 7bf28288d8929c1b250720a2c6decfc9978dd903..7dba87ea1c6f37ab56071d2f5d715bd78fe8816f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/__init__.py +++ b/densepose/data/samplers/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .densepose_uniform import DensePoseUniformSampler from .densepose_confidence_based import DensePoseConfidenceBasedSampler from .densepose_cse_uniform import DensePoseCSEUniformSampler diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_base.py b/densepose/data/samplers/densepose_base.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_base.py rename to densepose/data/samplers/densepose_base.py index 260413a5b65853d12b4cdb1bcff906f02ed7d63c..4d499d8f20d811fb8197d7bdae358540bb5b0dfc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_base.py +++ b/densepose/data/samplers/densepose_base.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any, Dict, List, Tuple import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_confidence_based.py b/densepose/data/samplers/densepose_confidence_based.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_confidence_based.py rename to densepose/data/samplers/densepose_confidence_based.py index 5a9a637e214cbd584773a9fb6031368b5d32417b..48e325b06e46817dafc0da2d984a8626d754e119 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_confidence_based.py +++ b/densepose/data/samplers/densepose_confidence_based.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random from typing import Optional, Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_base.py b/densepose/data/samplers/densepose_cse_base.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_base.py rename to densepose/data/samplers/densepose_cse_base.py index 593f1339f29308ff93ba98ed1426ee1dbd47be27..845545c1438b9d2a4fbb4c6dac0642461a7e539f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_base.py +++ b/densepose/data/samplers/densepose_cse_base.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any, Dict, List, Tuple import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_confidence_based.py b/densepose/data/samplers/densepose_cse_confidence_based.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_confidence_based.py rename to densepose/data/samplers/densepose_cse_confidence_based.py index d656a5ab853152c65d8f4c88fe7210cf68ee8df7..964b7f4ac41d2e1bb3da1cf6861af7f644b859fc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_confidence_based.py +++ b/densepose/data/samplers/densepose_cse_confidence_based.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random from typing import Optional, Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_uniform.py b/densepose/data/samplers/densepose_cse_uniform.py similarity index 95% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_uniform.py rename to densepose/data/samplers/densepose_cse_uniform.py index 482c650caf404bfe96dd28c5092d2508b17a1dbf..567636cc7dfbcc9167dd7f4aa2b752c6e53d311f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_cse_uniform.py +++ b/densepose/data/samplers/densepose_cse_uniform.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .densepose_cse_base import DensePoseCSEBaseSampler from .densepose_uniform import DensePoseUniformSampler diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_uniform.py b/densepose/data/samplers/densepose_uniform.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_uniform.py rename to densepose/data/samplers/densepose_uniform.py index af0e35b667047674a498433e4c153475a5b5a1fc..0d72cc30c9342b36efd6a7e80e55bf088b5c797c 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/densepose_uniform.py +++ b/densepose/data/samplers/densepose_uniform.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/mask_from_densepose.py b/densepose/data/samplers/mask_from_densepose.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/mask_from_densepose.py rename to densepose/data/samplers/mask_from_densepose.py index 9d631dff320bbec264675e6772c565cd06fc6b9f..0e6e812ba5af4675a81aec3ef8fd9b96d53325cc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/mask_from_densepose.py +++ b/densepose/data/samplers/mask_from_densepose.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from detectron2.structures import BitMasks, Instances from densepose.converters import ToMaskConverter diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/prediction_to_gt.py b/densepose/data/samplers/prediction_to_gt.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/samplers/prediction_to_gt.py rename to densepose/data/samplers/prediction_to_gt.py index 42a28ff4f19012e96fdf3fb4923500839429a999..3881fa5503c32c9e2f0602971971995f1211e054 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/samplers/prediction_to_gt.py +++ b/densepose/data/samplers/prediction_to_gt.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import dataclass from typing import Any, Callable, Dict, List, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/transform/__init__.py b/densepose/data/transform/__init__.py similarity index 85% rename from preprocess/detectron2/projects/DensePose/densepose/data/transform/__init__.py rename to densepose/data/transform/__init__.py index 147671e198475ce4a82b17e8f81a688d697207d8..369e1b278899b225d55bfc729514873b4259c7b9 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/transform/__init__.py +++ b/densepose/data/transform/__init__.py @@ -1,5 +1,3 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .image import ImageResizeTransform diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/transform/image.py b/densepose/data/transform/image.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/transform/image.py rename to densepose/data/transform/image.py index 0f35b3ab1de3b1b58e9d7f9763c73eb1236f67d2..8139b67841633841199a1aae3b25e326afaaf5e2 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/transform/image.py +++ b/densepose/data/transform/image.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/utils.py b/densepose/data/utils.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/data/utils.py rename to densepose/data/utils.py index 7625f3d5f7894d2d1519e8672d6fb2e6411e07ba..9878c31d03bd4114425f89dd1c6dda74337fe2e2 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/utils.py +++ b/densepose/data/utils.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import os from typing import Dict, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/video/__init__.py b/densepose/data/video/__init__.py similarity index 95% rename from preprocess/detectron2/projects/DensePose/densepose/data/video/__init__.py rename to densepose/data/video/__init__.py index dbd83443be8d6fff40b35a13758c31984f3d89be..72406e153b688461bfcb0ef21e35020399239309 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/video/__init__.py +++ b/densepose/data/video/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .frame_selector import ( FrameSelectionStrategy, RandomKFramesSelector, diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/video/frame_selector.py b/densepose/data/video/frame_selector.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/video/frame_selector.py rename to densepose/data/video/frame_selector.py index 77a97a82f7c7bb95b2023df946b246f9de71a7d2..c28f0e96475537319ff584f73fa422f838ae7b40 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/video/frame_selector.py +++ b/densepose/data/video/frame_selector.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import random from collections.abc import Callable from enum import Enum diff --git a/preprocess/detectron2/projects/DensePose/densepose/data/video/video_keyframe_dataset.py b/densepose/data/video/video_keyframe_dataset.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/data/video/video_keyframe_dataset.py rename to densepose/data/video/video_keyframe_dataset.py index ad9a88366cb5a8eb4d4827e0f918c7387e2605f8..be379d12bff5b6348087ba343d3c027b52524136 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/data/video/video_keyframe_dataset.py +++ b/densepose/data/video/video_keyframe_dataset.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import csv import logging import numpy as np diff --git a/preprocess/detectron2/projects/DensePose/densepose/engine/__init__.py b/densepose/engine/__init__.py similarity index 84% rename from preprocess/detectron2/projects/DensePose/densepose/engine/__init__.py rename to densepose/engine/__init__.py index 4709c1b2d87e3c578d98aaa083e41323e4047ac9..539b93a7beca07d229a6b6d387f885469242ad86 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/engine/__init__.py +++ b/densepose/engine/__init__.py @@ -1,5 +1,3 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .trainer import Trainer diff --git a/preprocess/detectron2/projects/DensePose/densepose/engine/trainer.py b/densepose/engine/trainer.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/engine/trainer.py rename to densepose/engine/trainer.py index 0c9046312244dc2381ea722413986010f4ba75e7..a8ffe82c3d64d01ae36bb3c07cc6d75950937389 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/engine/trainer.py +++ b/densepose/engine/trainer.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import logging import os from collections import OrderedDict diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/__init__.py b/densepose/evaluation/__init__.py similarity index 86% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/__init__.py rename to densepose/evaluation/__init__.py index cffabf0808c913a309b791ba8869c80db52a0ac8..e5ae1f20cdc822ebf3c870f1289a0ad210c57ae7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/__init__.py +++ b/densepose/evaluation/__init__.py @@ -1,5 +1,3 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .evaluator import DensePoseCOCOEvaluator diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/d2_evaluator_adapter.py b/densepose/evaluation/d2_evaluator_adapter.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/d2_evaluator_adapter.py rename to densepose/evaluation/d2_evaluator_adapter.py index a7fbb9e34f42bce02c71eab9efad742491c6b4aa..1fbc526059a191f9414231c1b21ed3e8b7b58580 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/d2_evaluator_adapter.py +++ b/densepose/evaluation/d2_evaluator_adapter.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from detectron2.data.catalog import Metadata from detectron2.evaluation import COCOEvaluator diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/densepose_coco_evaluation.py b/densepose/evaluation/densepose_coco_evaluation.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/densepose_coco_evaluation.py rename to densepose/evaluation/densepose_coco_evaluation.py index 4c153ee30debfd8bbbb54873f09e33163e659089..6370ba2a1bce45493e3d4bebd05b1b449334871d 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/densepose_coco_evaluation.py +++ b/densepose/evaluation/densepose_coco_evaluation.py @@ -5,8 +5,6 @@ # LICENSE file in the root directory of this source tree. # This is a modified version of cocoeval.py where we also have the densepose evaluation. -# pyre-unsafe - __author__ = "tsungyi" import copy @@ -18,7 +16,6 @@ import time from collections import defaultdict from enum import Enum from typing import Any, Dict, Tuple -# pyre-fixme[21]: Could not find module `scipy.spatial.distance`. import scipy.spatial.distance as ssd import torch import torch.nn.functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/evaluator.py b/densepose/evaluation/evaluator.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/evaluator.py rename to densepose/evaluation/evaluator.py index 803d3dccbe60a637e349a22e3364f3c0b5f4f1e5..d5d1d789bbe4b8791aa8529518ba1b964d31daca 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/evaluator.py +++ b/densepose/evaluation/evaluator.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import contextlib import copy import io diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/mesh_alignment_evaluator.py b/densepose/evaluation/mesh_alignment_evaluator.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/mesh_alignment_evaluator.py rename to densepose/evaluation/mesh_alignment_evaluator.py index f6c76f3cf2d54250f7fa1d9a2a3a1d2c60eb0aad..9d67c1a88a56332fb708c4618a34e96900926083 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/mesh_alignment_evaluator.py +++ b/densepose/evaluation/mesh_alignment_evaluator.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import json import logging from typing import List, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/evaluation/tensor_storage.py b/densepose/evaluation/tensor_storage.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/evaluation/tensor_storage.py rename to densepose/evaluation/tensor_storage.py index 369a29470807e60be377516f7910a9f95ab0a47d..db57c6ac73a423e39b1ed2e5a4a1f824aa233737 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/evaluation/tensor_storage.py +++ b/densepose/evaluation/tensor_storage.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import io import numpy as np import os diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/__init__.py b/densepose/modeling/__init__.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/__init__.py rename to densepose/modeling/__init__.py index 5c5b48b1fc6100dd531f7b61467876e222e40bdd..4c49f6da0d182cc97f5fe6b21d77c8f8330d3c3d 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/__init__.py +++ b/densepose/modeling/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .confidence import DensePoseConfidenceModelConfig, DensePoseUVConfidenceType from .filter import DensePoseDataFilter from .inference import densepose_inference diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/build.py b/densepose/modeling/build.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/build.py rename to densepose/modeling/build.py index 82e40d9284eeb9c90bf5e2ac13a95f587c76a595..bb7f54b4a1044bc518d66d89432dd52c79fdf293 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/build.py +++ b/densepose/modeling/build.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Optional from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/confidence.py b/densepose/modeling/confidence.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/confidence.py rename to densepose/modeling/confidence.py index 364e389078e78935da9e432bc04b5530d2d9963f..6f4a72efec06e055036ba70bc75b2624d20e1e0e 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/confidence.py +++ b/densepose/modeling/confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import dataclass from enum import Enum diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/__init__.py b/densepose/modeling/cse/__init__.py similarity index 93% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/cse/__init__.py rename to densepose/modeling/cse/__init__.py index 80248c94c5cc23f1503a6338af225f63bc8cec42..a2273609cc54fb96d002a49dcd58788060945059 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/__init__.py +++ b/densepose/modeling/cse/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from .vertex_direct_embedder import VertexDirectEmbedder from .vertex_feature_embedder import VertexFeatureEmbedder from .embedder import Embedder diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/embedder.py b/densepose/modeling/cse/embedder.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/cse/embedder.py rename to densepose/modeling/cse/embedder.py index 69082294acee57517b4b4ab8c11814b7c99e5232..56f5cb9860b13aa38b2069e6b25c3f5f71ab1ecc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/embedder.py +++ b/densepose/modeling/cse/embedder.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import logging import numpy as np import pickle diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/utils.py b/densepose/modeling/cse/utils.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/cse/utils.py rename to densepose/modeling/cse/utils.py index bb83b1af580ef76d8eddb03980fa14fe97298965..6e70d25df7c8e2c1c408866cf7a6f0156b64114a 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/utils.py +++ b/densepose/modeling/cse/utils.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_direct_embedder.py b/densepose/modeling/cse/vertex_direct_embedder.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_direct_embedder.py rename to densepose/modeling/cse/vertex_direct_embedder.py index 32d92e7786336da0ed9582793620c33a3853195e..9d802adf10c18beaedb3bd56963366662ba753f7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_direct_embedder.py +++ b/densepose/modeling/cse/vertex_direct_embedder.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import pickle import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_feature_embedder.py b/densepose/modeling/cse/vertex_feature_embedder.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_feature_embedder.py rename to densepose/modeling/cse/vertex_feature_embedder.py index cb495f88bc5a205e3639d797910c899d6344cca5..e9c7709c1eaec8f3e39441aadbc2b749c67874f2 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/cse/vertex_feature_embedder.py +++ b/densepose/modeling/cse/vertex_feature_embedder.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import pickle import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/densepose_checkpoint.py b/densepose/modeling/densepose_checkpoint.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/densepose_checkpoint.py rename to densepose/modeling/densepose_checkpoint.py index c85711e976efdf56f0c6494fd19636e7411be2b4..8c2b4f2e2cc9c6c798cf1bdb9c38dedc84058bd5 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/densepose_checkpoint.py +++ b/densepose/modeling/densepose_checkpoint.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from collections import OrderedDict from detectron2.checkpoint import DetectionCheckpointer diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/filter.py b/densepose/modeling/filter.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/filter.py rename to densepose/modeling/filter.py index 503321004e39c1bd96be3512a3811e33fed4d008..4682b225dbba1ce330c8f4ed6ad14dafcc935e5c 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/filter.py +++ b/densepose/modeling/filter.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import List import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/hrfpn.py b/densepose/modeling/hrfpn.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/hrfpn.py rename to densepose/modeling/hrfpn.py index a19c3261198798738130267cb4c35022ddf8a9e6..08ec420fa24e1e8f5074baf2e9ae737aff2ab12e 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/hrfpn.py +++ b/densepose/modeling/hrfpn.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe """ MIT License Copyright (c) 2019 Microsoft diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/hrnet.py b/densepose/modeling/hrnet.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/hrnet.py rename to densepose/modeling/hrnet.py index f8e3cab545c7f999300676bb27fa0461abd143e2..ca2467107e8e5a50167de38ef6827fac646d1245 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/hrnet.py +++ b/densepose/modeling/hrnet.py @@ -7,8 +7,6 @@ # Adapted from https://github.com/HRNet/Higher-HRNet-Human-Pose-Estimation/blob/master/lib/models/pose_higher_hrnet.py # noqa # ------------------------------------------------------------------------------ -# pyre-unsafe - from __future__ import absolute_import, division, print_function import logging import torch.nn as nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/inference.py b/densepose/modeling/inference.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/inference.py rename to densepose/modeling/inference.py index a797ff9b28e61827f5553045a6147ff3390d9fe3..81049649edddb23aeebeac4085514da838f1463b 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/inference.py +++ b/densepose/modeling/inference.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from dataclasses import fields from typing import Any, List import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/__init__.py b/densepose/modeling/losses/__init__.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/__init__.py rename to densepose/modeling/losses/__init__.py index b028a23924b030e0bac4d554b61ed34f3110a798..e5c593700e7274ea9cbaf8f4a52e8a229ef4c5a1 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/__init__.py +++ b/densepose/modeling/losses/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .chart import DensePoseChartLoss from .chart_with_confidences import DensePoseChartWithConfidenceLoss from .cse import DensePoseCseLoss diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart.py b/densepose/modeling/losses/chart.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart.py rename to densepose/modeling/losses/chart.py index 770648f3d3fddbfc553c18a3e7f5101396913593..02cdae8db3a41fc197be7fcc792c7119c7a21726 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart.py +++ b/densepose/modeling/losses/chart.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any, List import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart_with_confidences.py b/densepose/modeling/losses/chart_with_confidences.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart_with_confidences.py rename to densepose/modeling/losses/chart_with_confidences.py index d061488d7d5fb8fe0e220e7dfe3f03ea2eda7977..78ce7c6cb02fa01f6319d088349ff4f422001839 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/chart_with_confidences.py +++ b/densepose/modeling/losses/chart_with_confidences.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import math from typing import Any, List import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cse.py b/densepose/modeling/losses/cse.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cse.py rename to densepose/modeling/losses/cse.py index ffe219c5474392da8048bcf409257cbfce817236..dd561ad518f42c769fd9a5c8517409ddc33edf6f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cse.py +++ b/densepose/modeling/losses/cse.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, List from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_pix2shape.py b/densepose/modeling/losses/cycle_pix2shape.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_pix2shape.py rename to densepose/modeling/losses/cycle_pix2shape.py index f4e0a94a68370a994179d9d3eb5fb0ed9ed4af39..e305d29850ef04a712a0a3e7bdbffba887257777 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_pix2shape.py +++ b/densepose/modeling/losses/cycle_pix2shape.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, List import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_shape2shape.py b/densepose/modeling/losses/cycle_shape2shape.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_shape2shape.py rename to densepose/modeling/losses/cycle_shape2shape.py index c6e2ca89a39f391eadc915154964f82d6ddecdd4..f71dbab7c5bd7484cd9001c3c15059971ff0f0cf 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/cycle_shape2shape.py +++ b/densepose/modeling/losses/cycle_shape2shape.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import random from typing import Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed.py b/densepose/modeling/losses/embed.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed.py rename to densepose/modeling/losses/embed.py index 2fc8a16a478649847a6ce9200004eb4da64bb01e..1e3a069763ca6fab0acc7c455b416b9634ceaedf 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed.py +++ b/densepose/modeling/losses/embed.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, Dict, List import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed_utils.py b/densepose/modeling/losses/embed_utils.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed_utils.py rename to densepose/modeling/losses/embed_utils.py index 894417fe1a880bbf44dbd62eab0aaec85ff00711..f2ca16fd3809b89e1c05636242a84d02d3a42d88 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/embed_utils.py +++ b/densepose/modeling/losses/embed_utils.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from dataclasses import dataclass from typing import Any, Optional import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask.py b/densepose/modeling/losses/mask.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask.py rename to densepose/modeling/losses/mask.py index 2f8f75a425d288e1167eaf8cb48e4dc0f851ff45..c16b15c53de9f02dc734148e05f2bde799046aa0 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask.py +++ b/densepose/modeling/losses/mask.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from dataclasses import dataclass from typing import Any, Iterable, List, Optional import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask_or_segm.py b/densepose/modeling/losses/mask_or_segm.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask_or_segm.py rename to densepose/modeling/losses/mask_or_segm.py index 350a2ebf81b13839c3a16545984c05c1aa68f5bf..98b773d99fd29a48cbdfa94c5882c9c3d94003ee 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/mask_or_segm.py +++ b/densepose/modeling/losses/mask_or_segm.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, List import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/registry.py b/densepose/modeling/losses/registry.py similarity index 91% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/registry.py rename to densepose/modeling/losses/registry.py index 3e8db8e82343abd352482e3d740a6922a1e12ac5..d9c8817a743e42b2aec382818f0cc1bb39a66004 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/registry.py +++ b/densepose/modeling/losses/registry.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from detectron2.utils.registry import Registry DENSEPOSE_LOSS_REGISTRY = Registry("DENSEPOSE_LOSS") diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/segm.py b/densepose/modeling/losses/segm.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/segm.py rename to densepose/modeling/losses/segm.py index cd04d129c1d05ee0f3273bc7256a60cf7cbe64b9..1962b886e1946fa4896776da8a007ae0a9a4fab3 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/segm.py +++ b/densepose/modeling/losses/segm.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, List import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/soft_embed.py b/densepose/modeling/losses/soft_embed.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/soft_embed.py rename to densepose/modeling/losses/soft_embed.py index f746d67a75738c9d38f84830f59f72da55a99280..03b69ec36a59ae0d69bb77efa77f93c6f95fad97 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/soft_embed.py +++ b/densepose/modeling/losses/soft_embed.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from typing import Any, Dict, List import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/utils.py b/densepose/modeling/losses/utils.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/losses/utils.py rename to densepose/modeling/losses/utils.py index 8193c537c1fd3496103ecbfce10779be17ef8ace..ceea981d11650af80cb007fe129a3ee4864fc48f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/losses/utils.py +++ b/densepose/modeling/losses/utils.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any, Dict, List, Optional, Tuple diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/__init__.py b/densepose/modeling/predictors/__init__.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/__init__.py rename to densepose/modeling/predictors/__init__.py index c749ea264690d0b4c85abc520e7476bc4365175d..1ece0757acf2a4924079c884cab44a71cea22c37 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/__init__.py +++ b/densepose/modeling/predictors/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .chart import DensePoseChartPredictor from .chart_confidence import DensePoseChartConfidencePredictorMixin from .chart_with_confidence import DensePoseChartWithConfidencePredictor diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart.py b/densepose/modeling/predictors/chart.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart.py rename to densepose/modeling/predictors/chart.py index 67fc401d70fe5e7d7baec3530d435955d4a23f7c..3bcd13f7c592e37c2751556cda1f6e9cd3400b73 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart.py +++ b/densepose/modeling/predictors/chart.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_confidence.py b/densepose/modeling/predictors/chart_confidence.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_confidence.py rename to densepose/modeling/predictors/chart_confidence.py index d2220efa3a8c48e8f86bb4d1d11b3643c3cd6157..0c0099952f3e675e42aa7d3b6d35065fdaf43dbb 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_confidence.py +++ b/densepose/modeling/predictors/chart_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_with_confidence.py b/densepose/modeling/predictors/chart_with_confidence.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_with_confidence.py rename to densepose/modeling/predictors/chart_with_confidence.py index 902032c77c65408e0268077f776bd957e80091a1..9c1cd6cc8fda56e831fbc02a8ffdd844866c0e4f 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/chart_with_confidence.py +++ b/densepose/modeling/predictors/chart_with_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from . import DensePoseChartConfidencePredictorMixin, DensePoseChartPredictor from .registry import DENSEPOSE_PREDICTOR_REGISTRY diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse.py b/densepose/modeling/predictors/cse.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse.py rename to densepose/modeling/predictors/cse.py index 8494b7975bab1f64e704c4d7c6bdcca4a43ba817..466a5ecddbfa338a2b603facf06d1f4510fff6eb 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse.py +++ b/densepose/modeling/predictors/cse.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_confidence.py b/densepose/modeling/predictors/cse_confidence.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_confidence.py rename to densepose/modeling/predictors/cse_confidence.py index 7d19b354fa14eb5f79e584c090f2bc0cb4d28c5f..8220337cea8eb87bbdf74378079551259dcc37e2 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_confidence.py +++ b/densepose/modeling/predictors/cse_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from typing import Any import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_with_confidence.py b/densepose/modeling/predictors/cse_with_confidence.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_with_confidence.py rename to densepose/modeling/predictors/cse_with_confidence.py index 02389dbcbe734c89e6eb86757d877c9657fd12b1..17ecef67ffb67cd0e64de73632eaede1d8f3c701 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/cse_with_confidence.py +++ b/densepose/modeling/predictors/cse_with_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from . import DensePoseEmbeddingConfidencePredictorMixin, DensePoseEmbeddingPredictor from .registry import DENSEPOSE_PREDICTOR_REGISTRY diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/registry.py b/densepose/modeling/predictors/registry.py similarity index 91% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/registry.py rename to densepose/modeling/predictors/registry.py index c883ba3538e8d8e5b11c68811fdf1990a2964a71..f96901d3242fa8f3d35d053ed0bdd7649a045b88 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/predictors/registry.py +++ b/densepose/modeling/predictors/registry.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from detectron2.utils.registry import Registry DENSEPOSE_PREDICTOR_REGISTRY = Registry("DENSEPOSE_PREDICTOR") diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/__init__.py b/densepose/modeling/roi_heads/__init__.py similarity index 94% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/__init__.py rename to densepose/modeling/roi_heads/__init__.py index 0a055a65454517876107c621ba53e4742fa5eb54..8403589f23ec2ffa8afafcd566ca0b0b7b2671a7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/__init__.py +++ b/densepose/modeling/roi_heads/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .v1convx import DensePoseV1ConvXHead from .deeplab import DensePoseDeepLabHead from .registry import ROI_DENSEPOSE_HEAD_REGISTRY diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/deeplab.py b/densepose/modeling/roi_heads/deeplab.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/deeplab.py rename to densepose/modeling/roi_heads/deeplab.py index df2c13fa2f75d967f22d2c69f3e5db55c5cb1cb9..4e5cb483037b302ff1fb2c305275a65e4ba4e941 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/deeplab.py +++ b/densepose/modeling/roi_heads/deeplab.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import fvcore.nn.weight_init as weight_init import torch from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/registry.py b/densepose/modeling/roi_heads/registry.py similarity index 91% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/registry.py rename to densepose/modeling/roi_heads/registry.py index 89514279ffba6a65fc499e03bc0177ed8039482f..e1cea432f1fda3861266fa636d002667b3fb46a0 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/registry.py +++ b/densepose/modeling/roi_heads/registry.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from detectron2.utils.registry import Registry ROI_DENSEPOSE_HEAD_REGISTRY = Registry("ROI_DENSEPOSE_HEAD") diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/roi_head.py b/densepose/modeling/roi_heads/roi_head.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/roi_head.py rename to densepose/modeling/roi_heads/roi_head.py index 2b8f869f84aa59a09286c421123b31c9db436ae6..aee645fde0d8321de9181a624a0c921b6dc167c4 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/roi_head.py +++ b/densepose/modeling/roi_heads/roi_head.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import numpy as np from typing import Dict, List, Optional import fvcore.nn.weight_init as weight_init diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/v1convx.py b/densepose/modeling/roi_heads/v1convx.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/v1convx.py rename to densepose/modeling/roi_heads/v1convx.py index d81c375c5a488af4cb9ab41676d5e6688f740e61..df79f658d8f7149e44aa1a31072adc4dadd89a48 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/roi_heads/v1convx.py +++ b/densepose/modeling/roi_heads/v1convx.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - import torch from torch import nn from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/test_time_augmentation.py b/densepose/modeling/test_time_augmentation.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/test_time_augmentation.py rename to densepose/modeling/test_time_augmentation.py index 2e4cfa038f2fe3072a2520978ff4408df9bca5b3..ec2022ed16727f538993d2c7db60a60a1183b90d 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/test_time_augmentation.py +++ b/densepose/modeling/test_time_augmentation.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import copy import numpy as np import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/modeling/utils.py b/densepose/modeling/utils.py similarity index 96% rename from preprocess/detectron2/projects/DensePose/densepose/modeling/utils.py rename to densepose/modeling/utils.py index 64f53369b5ae3bc69f064c590e0837583ebc213e..2e76eb9535a68dcb4ccb065556c55289294e42c8 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/modeling/utils.py +++ b/densepose/modeling/utils.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from torch import nn diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/__init__.py b/densepose/structures/__init__.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/structures/__init__.py rename to densepose/structures/__init__.py index 4ee84836219994a54bb1249c90a7d0d6f8b72e8b..ed32c5e9d6c4c1599ba960681d9e86889e2cdbd8 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/__init__.py +++ b/densepose/structures/__init__.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from .chart import DensePoseChartPredictorOutput from .chart_confidence import decorate_predictor_output_class_with_confidences from .cse_confidence import decorate_cse_predictor_output_class_with_confidences diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/chart.py b/densepose/structures/chart.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/chart.py rename to densepose/structures/chart.py index 4f8640ef3dc9ca7e66e1a639e2e23211300dbbac..115cc084e98115c537382494af9eb0e246cd375b 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/chart.py +++ b/densepose/structures/chart.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import dataclass from typing import Union import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/chart_confidence.py b/densepose/structures/chart_confidence.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/chart_confidence.py rename to densepose/structures/chart_confidence.py index faec3a0f161939591a8424058871d50198327b08..57c63257a7c176af1522e2f143ed594c26906c76 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/chart_confidence.py +++ b/densepose/structures/chart_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import make_dataclass from functools import lru_cache from typing import Any, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/chart_result.py b/densepose/structures/chart_result.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/chart_result.py rename to densepose/structures/chart_result.py index 3a9e56dee9fb81fd6a6596c524dcd9f2e471af19..003933d03d153d045c0bf551c465bc7a224d90cb 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/chart_result.py +++ b/densepose/structures/chart_result.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import dataclass from typing import Any, Optional, Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/cse.py b/densepose/structures/cse.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/cse.py rename to densepose/structures/cse.py index 381f1384a8d4d42f81cda8ff1558002149bdea74..9cd65da96c04613053e21494bc2dcc04f37fe1fd 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/cse.py +++ b/densepose/structures/cse.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - from dataclasses import dataclass from typing import Union import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/cse_confidence.py b/densepose/structures/cse_confidence.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/cse_confidence.py rename to densepose/structures/cse_confidence.py index 251a7e823e38931fb1b86b017417538af5350944..ee5166f82d45ecb4ea829ec2ecab248161c19421 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/cse_confidence.py +++ b/densepose/structures/cse_confidence.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. -# pyre-unsafe - from dataclasses import make_dataclass from functools import lru_cache from typing import Any, Optional diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/data_relative.py b/densepose/structures/data_relative.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/data_relative.py rename to densepose/structures/data_relative.py index bcf27ef9bb69f5d9f74d6499e55408e8d4ec5803..187e140495f94a740fdd91d756f2195a0c8f4f30 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/data_relative.py +++ b/densepose/structures/data_relative.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import numpy as np import torch from torch.nn import functional as F diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/list.py b/densepose/structures/list.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/list.py rename to densepose/structures/list.py index e7dde3acd42ff33c103a50bcf6eebff21a59ce53..7631f8f78f4e9b1a94653d4e47639c50affe58eb 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/list.py +++ b/densepose/structures/list.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import torch from densepose.structures.data_relative import DensePoseDataRelative diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/mesh.py b/densepose/structures/mesh.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/mesh.py rename to densepose/structures/mesh.py index faaad9cb5650f5e6a1bef76c599d5fd370238e4c..a5abd3419b35234e6b44c0577bef2818f99a5cdc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/mesh.py +++ b/densepose/structures/mesh.py @@ -1,7 +1,5 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -# pyre-unsafe - import pickle from functools import lru_cache from typing import Dict, Optional, Tuple diff --git a/preprocess/detectron2/projects/DensePose/densepose/structures/transform_data.py b/densepose/structures/transform_data.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/structures/transform_data.py rename to densepose/structures/transform_data.py index c85ec88514205679d39808a794c00613a8c0f495..a345d66945fbd709ea6644caa7a71435aa0ed569 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/structures/transform_data.py +++ b/densepose/structures/transform_data.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from typing import BinaryIO, Dict, Union import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/utils/__init__.py b/densepose/utils/__init__.py similarity index 100% rename from preprocess/detectron2/projects/DensePose/densepose/utils/__init__.py rename to densepose/utils/__init__.py diff --git a/preprocess/detectron2/projects/DensePose/densepose/utils/dbhelper.py b/densepose/utils/dbhelper.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/utils/dbhelper.py rename to densepose/utils/dbhelper.py index ba380303a06f42674aa59f03690504f825b56ed7..772e31874b2f65da9ae8b4e03c7515d5af282586 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/utils/dbhelper.py +++ b/densepose/utils/dbhelper.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from typing import Any, Dict, Optional, Tuple diff --git a/preprocess/detectron2/projects/DensePose/densepose/utils/logger.py b/densepose/utils/logger.py similarity index 95% rename from preprocess/detectron2/projects/DensePose/densepose/utils/logger.py rename to densepose/utils/logger.py index 7aad2c0895afff0514c59b10cc80d01e47d50918..70cd3cb0eb0fc7495b1a4b50a05725a0e5b1baba 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/utils/logger.py +++ b/densepose/utils/logger.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import logging diff --git a/preprocess/detectron2/projects/DensePose/densepose/utils/transform.py b/densepose/utils/transform.py similarity index 97% rename from preprocess/detectron2/projects/DensePose/densepose/utils/transform.py rename to densepose/utils/transform.py index 5f8a8ba038588bf8c014390f8b8feadfcdc40307..8dc4ae7be878302ec39b7f235e3ae1b7a3ca29ee 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/utils/transform.py +++ b/densepose/utils/transform.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from detectron2.data import MetadataCatalog from detectron2.utils.file_io import PathManager diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/__init__.py b/densepose/vis/__init__.py similarity index 100% rename from preprocess/detectron2/projects/DensePose/densepose/vis/__init__.py rename to densepose/vis/__init__.py diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/base.py b/densepose/vis/base.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/vis/base.py rename to densepose/vis/base.py index 6a7b07000c41f49386de5d7752c0d277b9da1979..a5c7e4ad19b6df600d8dcecacde6a3488c83a3e1 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/base.py +++ b/densepose/vis/base.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import logging import numpy as np import cv2 @@ -37,7 +35,8 @@ class MatrixVisualizer: if self.inplace: image_target_bgr = image_bgr else: - image_target_bgr = image_bgr * 0 + image_target_bgr = image_bgr + image_target_bgr *= 0 x, y, w, h = [int(v) for v in bbox_xywh] if w <= 0 or h <= 0: return image_bgr diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/bounding_box.py b/densepose/vis/bounding_box.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/bounding_box.py rename to densepose/vis/bounding_box.py index a88ba0ce74b8da539ea3a25c703a9795be8163a6..6a9d37f40b1b64832a53d8c2cc8ce3bf90b30a3b 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/bounding_box.py +++ b/densepose/vis/bounding_box.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe from .base import RectangleVisualizer, TextVisualizer diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_data_points.py b/densepose/vis/densepose_data_points.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/densepose_data_points.py rename to densepose/vis/densepose_data_points.py index de809f64ee09a50291999774d91443e3edd869ea..17e67cbf96022e09363cf1deac21814e4544f570 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_data_points.py +++ b/densepose/vis/densepose_data_points.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import numpy as np from typing import Iterable, Optional, Tuple import cv2 diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_iuv.py b/densepose/vis/densepose_outputs_iuv.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_iuv.py rename to densepose/vis/densepose_outputs_iuv.py index 960ffba0d4146eda0a4dcd2220c724d944834b33..454627cbe9fd5507cae8cbb9aab7c7bc0ffcfab7 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_iuv.py +++ b/densepose/vis/densepose_outputs_iuv.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import numpy as np from typing import Optional, Tuple import cv2 diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_vertex.py b/densepose/vis/densepose_outputs_vertex.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_vertex.py rename to densepose/vis/densepose_outputs_vertex.py index fe296fcf81e5711eea21049a1b4de17eb2541b3f..4e10bf82cfea92f488480d423d3ced5d61d04c49 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_outputs_vertex.py +++ b/densepose/vis/densepose_outputs_vertex.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -# pyre-unsafe import json import numpy as np from functools import lru_cache diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results.py b/densepose/vis/densepose_results.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results.py rename to densepose/vis/densepose_results.py index d49a3828339b6ff03735924d3621396ca8f00e5c..a660d26eec6c873bd5cf9b35d0c8387075789afc 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results.py +++ b/densepose/vis/densepose_results.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import logging import numpy as np from typing import List, Optional, Tuple @@ -319,7 +317,7 @@ except ModuleNotFoundError: class DensePoseResultsFineSegmentationVisualizer(DensePoseMaskedColormapResultsVisualizer): - def __init__(self, inplace=True, cmap=cv2.COLORMAP_PARULA, alpha=0.7, **kwargs): + def __init__(self, inplace=False, cmap=cv2.COLORMAP_PARULA, alpha=1, **kwargs): super(DensePoseResultsFineSegmentationVisualizer, self).__init__( _extract_i_from_iuvarr, _extract_i_from_iuvarr, diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results_textures.py b/densepose/vis/densepose_results_textures.py similarity index 99% rename from preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results_textures.py rename to densepose/vis/densepose_results_textures.py index aa33b861100b796f411f3aade1c03a68c279262e..8b02f2bdbaa8bb1b70bc0f690a568ac4f8f1c91a 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/densepose_results_textures.py +++ b/densepose/vis/densepose_results_textures.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import numpy as np from typing import List, Optional, Tuple import torch diff --git a/preprocess/detectron2/projects/DensePose/densepose/vis/extractor.py b/densepose/vis/extractor.py similarity index 98% rename from preprocess/detectron2/projects/DensePose/densepose/vis/extractor.py rename to densepose/vis/extractor.py index ace61e78374f76f8fe8cd016386eccfefebf7fac..543efac9272746b8cc130534d5d09251404c8d97 100644 --- a/preprocess/detectron2/projects/DensePose/densepose/vis/extractor.py +++ b/densepose/vis/extractor.py @@ -1,11 +1,8 @@ # Copyright (c) Facebook, Inc. and its affiliates. - -# pyre-unsafe import logging from typing import List, Optional, Sequence, Tuple import torch -# pyre-fixme[21]: Could not find module `detectron2.layers.nms`. from detectron2.layers.nms import batched_nms from detectron2.structures.instances import Instances diff --git a/detectron2 b/detectron2 deleted file mode 120000 index 3cf55bd44c9d7faa588717cd4ca5b8dd4ce195e2..0000000000000000000000000000000000000000 --- a/detectron2 +++ /dev/null @@ -1 +0,0 @@ -preprocess/detectron2/detectron2 \ No newline at end of file diff --git a/preprocess/detectron2/detectron2/__init__.py b/detectron2/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/__init__.py rename to detectron2/__init__.py diff --git a/preprocess/detectron2/detectron2/checkpoint/__init__.py b/detectron2/checkpoint/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/checkpoint/__init__.py rename to detectron2/checkpoint/__init__.py diff --git a/preprocess/detectron2/detectron2/checkpoint/c2_model_loading.py b/detectron2/checkpoint/c2_model_loading.py similarity index 100% rename from preprocess/detectron2/detectron2/checkpoint/c2_model_loading.py rename to detectron2/checkpoint/c2_model_loading.py diff --git a/preprocess/detectron2/detectron2/checkpoint/catalog.py b/detectron2/checkpoint/catalog.py similarity index 100% rename from preprocess/detectron2/detectron2/checkpoint/catalog.py rename to detectron2/checkpoint/catalog.py diff --git a/preprocess/detectron2/detectron2/checkpoint/detection_checkpoint.py b/detectron2/checkpoint/detection_checkpoint.py similarity index 100% rename from preprocess/detectron2/detectron2/checkpoint/detection_checkpoint.py rename to detectron2/checkpoint/detection_checkpoint.py diff --git a/preprocess/detectron2/detectron2/config/__init__.py b/detectron2/config/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/config/__init__.py rename to detectron2/config/__init__.py diff --git a/preprocess/detectron2/detectron2/config/compat.py b/detectron2/config/compat.py similarity index 100% rename from preprocess/detectron2/detectron2/config/compat.py rename to detectron2/config/compat.py diff --git a/preprocess/detectron2/detectron2/config/config.py b/detectron2/config/config.py similarity index 100% rename from preprocess/detectron2/detectron2/config/config.py rename to detectron2/config/config.py diff --git a/preprocess/detectron2/detectron2/config/defaults.py b/detectron2/config/defaults.py similarity index 99% rename from preprocess/detectron2/detectron2/config/defaults.py rename to detectron2/config/defaults.py index 5d97ec92d21d2da93a8756560bfcb004481ddb8a..bd2a5f6b2de4af2caa1f65c64ab93a5e3ac21780 100644 --- a/preprocess/detectron2/detectron2/config/defaults.py +++ b/detectron2/config/defaults.py @@ -121,8 +121,6 @@ _C.DATALOADER.ASPECT_RATIO_GROUPING = True _C.DATALOADER.SAMPLER_TRAIN = "TrainingSampler" # Repeat threshold for RepeatFactorTrainingSampler _C.DATALOADER.REPEAT_THRESHOLD = 0.0 -# if True, take square root when computing repeating factor -_C.DATALOADER.REPEAT_SQRT = True # Tf True, when working on datasets that have instance annotations, the # training dataloader will filter out images without associated annotations _C.DATALOADER.FILTER_EMPTY_ANNOTATIONS = True diff --git a/preprocess/detectron2/detectron2/config/instantiate.py b/detectron2/config/instantiate.py similarity index 100% rename from preprocess/detectron2/detectron2/config/instantiate.py rename to detectron2/config/instantiate.py diff --git a/preprocess/detectron2/detectron2/config/lazy.py b/detectron2/config/lazy.py similarity index 100% rename from preprocess/detectron2/detectron2/config/lazy.py rename to detectron2/config/lazy.py diff --git a/preprocess/detectron2/detectron2/data/__init__.py b/detectron2/data/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/data/__init__.py rename to detectron2/data/__init__.py diff --git a/preprocess/detectron2/detectron2/data/benchmark.py b/detectron2/data/benchmark.py similarity index 100% rename from preprocess/detectron2/detectron2/data/benchmark.py rename to detectron2/data/benchmark.py diff --git a/preprocess/detectron2/detectron2/data/build.py b/detectron2/data/build.py similarity index 99% rename from preprocess/detectron2/detectron2/data/build.py rename to detectron2/data/build.py index a3bd94b4edb86c8b50d2a7f054034c772871fd92..42867687e329c67f37cb7c5e938fd44150500d20 100644 --- a/preprocess/detectron2/detectron2/data/build.py +++ b/detectron2/data/build.py @@ -430,7 +430,7 @@ def _build_weighted_sampler(cfg, enable_category_balance=False): """ category_repeat_factors = [ RepeatFactorTrainingSampler.repeat_factors_from_category_frequency( - dataset_dict, cfg.DATALOADER.REPEAT_THRESHOLD, sqrt=cfg.DATALOADER.REPEAT_SQRT + dataset_dict, cfg.DATALOADER.REPEAT_THRESHOLD ) for dataset_dict in dataset_name_to_dicts.values() ] @@ -482,7 +482,7 @@ def _train_loader_from_config(cfg, mapper=None, *, dataset=None, sampler=None): sampler = TrainingSampler(len(dataset)) elif sampler_name == "RepeatFactorTrainingSampler": repeat_factors = RepeatFactorTrainingSampler.repeat_factors_from_category_frequency( - dataset, cfg.DATALOADER.REPEAT_THRESHOLD, sqrt=cfg.DATALOADER.REPEAT_SQRT + dataset, cfg.DATALOADER.REPEAT_THRESHOLD ) sampler = RepeatFactorTrainingSampler(repeat_factors) elif sampler_name == "RandomSubsetTrainingSampler": diff --git a/preprocess/detectron2/detectron2/data/catalog.py b/detectron2/data/catalog.py similarity index 100% rename from preprocess/detectron2/detectron2/data/catalog.py rename to detectron2/data/catalog.py diff --git a/preprocess/detectron2/detectron2/data/common.py b/detectron2/data/common.py similarity index 100% rename from preprocess/detectron2/detectron2/data/common.py rename to detectron2/data/common.py diff --git a/preprocess/detectron2/detectron2/data/dataset_mapper.py b/detectron2/data/dataset_mapper.py similarity index 100% rename from preprocess/detectron2/detectron2/data/dataset_mapper.py rename to detectron2/data/dataset_mapper.py diff --git a/preprocess/detectron2/detectron2/data/datasets/README.md b/detectron2/data/datasets/README.md similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/README.md rename to detectron2/data/datasets/README.md diff --git a/preprocess/detectron2/detectron2/data/datasets/__init__.py b/detectron2/data/datasets/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/__init__.py rename to detectron2/data/datasets/__init__.py diff --git a/preprocess/detectron2/detectron2/data/datasets/builtin.py b/detectron2/data/datasets/builtin.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/builtin.py rename to detectron2/data/datasets/builtin.py diff --git a/preprocess/detectron2/detectron2/data/datasets/builtin_meta.py b/detectron2/data/datasets/builtin_meta.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/builtin_meta.py rename to detectron2/data/datasets/builtin_meta.py diff --git a/preprocess/detectron2/detectron2/data/datasets/cityscapes.py b/detectron2/data/datasets/cityscapes.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/cityscapes.py rename to detectron2/data/datasets/cityscapes.py diff --git a/preprocess/detectron2/detectron2/data/datasets/cityscapes_panoptic.py b/detectron2/data/datasets/cityscapes_panoptic.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/cityscapes_panoptic.py rename to detectron2/data/datasets/cityscapes_panoptic.py diff --git a/preprocess/detectron2/detectron2/data/datasets/coco.py b/detectron2/data/datasets/coco.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/coco.py rename to detectron2/data/datasets/coco.py diff --git a/preprocess/detectron2/detectron2/data/datasets/coco_panoptic.py b/detectron2/data/datasets/coco_panoptic.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/coco_panoptic.py rename to detectron2/data/datasets/coco_panoptic.py diff --git a/preprocess/detectron2/detectron2/data/datasets/lvis.py b/detectron2/data/datasets/lvis.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/lvis.py rename to detectron2/data/datasets/lvis.py diff --git a/preprocess/detectron2/detectron2/data/datasets/lvis_v0_5_categories.py b/detectron2/data/datasets/lvis_v0_5_categories.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/lvis_v0_5_categories.py rename to detectron2/data/datasets/lvis_v0_5_categories.py diff --git a/preprocess/detectron2/detectron2/data/datasets/lvis_v1_categories.py b/detectron2/data/datasets/lvis_v1_categories.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/lvis_v1_categories.py rename to detectron2/data/datasets/lvis_v1_categories.py diff --git a/preprocess/detectron2/detectron2/data/datasets/lvis_v1_category_image_count.py b/detectron2/data/datasets/lvis_v1_category_image_count.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/lvis_v1_category_image_count.py rename to detectron2/data/datasets/lvis_v1_category_image_count.py diff --git a/preprocess/detectron2/detectron2/data/datasets/pascal_voc.py b/detectron2/data/datasets/pascal_voc.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/pascal_voc.py rename to detectron2/data/datasets/pascal_voc.py diff --git a/preprocess/detectron2/detectron2/data/datasets/register_coco.py b/detectron2/data/datasets/register_coco.py similarity index 100% rename from preprocess/detectron2/detectron2/data/datasets/register_coco.py rename to detectron2/data/datasets/register_coco.py diff --git a/preprocess/detectron2/detectron2/data/detection_utils.py b/detectron2/data/detection_utils.py similarity index 100% rename from preprocess/detectron2/detectron2/data/detection_utils.py rename to detectron2/data/detection_utils.py diff --git a/preprocess/detectron2/detectron2/data/samplers/__init__.py b/detectron2/data/samplers/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/data/samplers/__init__.py rename to detectron2/data/samplers/__init__.py diff --git a/preprocess/detectron2/detectron2/data/samplers/distributed_sampler.py b/detectron2/data/samplers/distributed_sampler.py similarity index 95% rename from preprocess/detectron2/detectron2/data/samplers/distributed_sampler.py rename to detectron2/data/samplers/distributed_sampler.py index c4dc22a7a27a33ca94667600678fc67afbed3d64..a098e6ac07c1b193fddcb69e6e54aced82e6081c 100644 --- a/preprocess/detectron2/detectron2/data/samplers/distributed_sampler.py +++ b/detectron2/data/samplers/distributed_sampler.py @@ -155,7 +155,7 @@ class RepeatFactorTrainingSampler(Sampler): self._frac_part = repeat_factors - self._int_part @staticmethod - def repeat_factors_from_category_frequency(dataset_dicts, repeat_thresh, sqrt=True): + def repeat_factors_from_category_frequency(dataset_dicts, repeat_thresh): """ Compute (fractional) per-image repeat factors based on category frequency. The repeat factor for an image is a function of the frequency of the rarest @@ -169,7 +169,6 @@ class RepeatFactorTrainingSampler(Sampler): repeat_thresh (float): frequency threshold below which data is repeated. If the frequency is half of `repeat_thresh`, the image will be repeated twice. - sqrt (bool): if True, apply :func:`math.sqrt` to the repeat factor. Returns: torch.Tensor: @@ -188,20 +187,9 @@ class RepeatFactorTrainingSampler(Sampler): # 2. For each category c, compute the category-level repeat factor: # r(c) = max(1, sqrt(t / f(c))) category_rep = { - cat_id: max( - 1.0, - ( - math.sqrt(repeat_thresh / cat_freq) - if sqrt - else (repeat_thresh / cat_freq) - ), - ) + cat_id: max(1.0, math.sqrt(repeat_thresh / cat_freq)) for cat_id, cat_freq in category_freq.items() } - for cat_id in sorted(category_rep.keys()): - logger.info( - f"Cat ID {cat_id}: freq={category_freq[cat_id]:.2f}, rep={category_rep[cat_id]:.2f}" - ) # 3. For each image I, compute the image-level repeat factor: # r(I) = max_{c in I} r(c) diff --git a/preprocess/detectron2/detectron2/data/samplers/grouped_batch_sampler.py b/detectron2/data/samplers/grouped_batch_sampler.py similarity index 100% rename from preprocess/detectron2/detectron2/data/samplers/grouped_batch_sampler.py rename to detectron2/data/samplers/grouped_batch_sampler.py diff --git a/preprocess/detectron2/detectron2/data/transforms/__init__.py b/detectron2/data/transforms/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/data/transforms/__init__.py rename to detectron2/data/transforms/__init__.py diff --git a/preprocess/detectron2/detectron2/data/transforms/augmentation.py b/detectron2/data/transforms/augmentation.py similarity index 100% rename from preprocess/detectron2/detectron2/data/transforms/augmentation.py rename to detectron2/data/transforms/augmentation.py diff --git a/preprocess/detectron2/detectron2/data/transforms/augmentation_impl.py b/detectron2/data/transforms/augmentation_impl.py similarity index 100% rename from preprocess/detectron2/detectron2/data/transforms/augmentation_impl.py rename to detectron2/data/transforms/augmentation_impl.py diff --git a/preprocess/detectron2/detectron2/data/transforms/transform.py b/detectron2/data/transforms/transform.py similarity index 100% rename from preprocess/detectron2/detectron2/data/transforms/transform.py rename to detectron2/data/transforms/transform.py diff --git a/preprocess/detectron2/detectron2/engine/__init__.py b/detectron2/engine/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/engine/__init__.py rename to detectron2/engine/__init__.py diff --git a/preprocess/detectron2/detectron2/engine/defaults.py b/detectron2/engine/defaults.py similarity index 100% rename from preprocess/detectron2/detectron2/engine/defaults.py rename to detectron2/engine/defaults.py diff --git a/preprocess/detectron2/detectron2/engine/hooks.py b/detectron2/engine/hooks.py similarity index 100% rename from preprocess/detectron2/detectron2/engine/hooks.py rename to detectron2/engine/hooks.py diff --git a/preprocess/detectron2/detectron2/engine/launch.py b/detectron2/engine/launch.py similarity index 100% rename from preprocess/detectron2/detectron2/engine/launch.py rename to detectron2/engine/launch.py diff --git a/preprocess/detectron2/detectron2/engine/train_loop.py b/detectron2/engine/train_loop.py similarity index 100% rename from preprocess/detectron2/detectron2/engine/train_loop.py rename to detectron2/engine/train_loop.py diff --git a/preprocess/detectron2/detectron2/evaluation/__init__.py b/detectron2/evaluation/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/__init__.py rename to detectron2/evaluation/__init__.py diff --git a/preprocess/detectron2/detectron2/evaluation/cityscapes_evaluation.py b/detectron2/evaluation/cityscapes_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/cityscapes_evaluation.py rename to detectron2/evaluation/cityscapes_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/coco_evaluation.py b/detectron2/evaluation/coco_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/coco_evaluation.py rename to detectron2/evaluation/coco_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/evaluator.py b/detectron2/evaluation/evaluator.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/evaluator.py rename to detectron2/evaluation/evaluator.py diff --git a/preprocess/detectron2/detectron2/evaluation/fast_eval_api.py b/detectron2/evaluation/fast_eval_api.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/fast_eval_api.py rename to detectron2/evaluation/fast_eval_api.py diff --git a/preprocess/detectron2/detectron2/evaluation/lvis_evaluation.py b/detectron2/evaluation/lvis_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/lvis_evaluation.py rename to detectron2/evaluation/lvis_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/panoptic_evaluation.py b/detectron2/evaluation/panoptic_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/panoptic_evaluation.py rename to detectron2/evaluation/panoptic_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/pascal_voc_evaluation.py b/detectron2/evaluation/pascal_voc_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/pascal_voc_evaluation.py rename to detectron2/evaluation/pascal_voc_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/rotated_coco_evaluation.py b/detectron2/evaluation/rotated_coco_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/rotated_coco_evaluation.py rename to detectron2/evaluation/rotated_coco_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/sem_seg_evaluation.py b/detectron2/evaluation/sem_seg_evaluation.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/sem_seg_evaluation.py rename to detectron2/evaluation/sem_seg_evaluation.py diff --git a/preprocess/detectron2/detectron2/evaluation/testing.py b/detectron2/evaluation/testing.py similarity index 100% rename from preprocess/detectron2/detectron2/evaluation/testing.py rename to detectron2/evaluation/testing.py diff --git a/preprocess/detectron2/detectron2/export/README.md b/detectron2/export/README.md similarity index 100% rename from preprocess/detectron2/detectron2/export/README.md rename to detectron2/export/README.md diff --git a/preprocess/detectron2/detectron2/export/__init__.py b/detectron2/export/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/export/__init__.py rename to detectron2/export/__init__.py diff --git a/preprocess/detectron2/detectron2/export/api.py b/detectron2/export/api.py similarity index 100% rename from preprocess/detectron2/detectron2/export/api.py rename to detectron2/export/api.py diff --git a/preprocess/detectron2/detectron2/export/c10.py b/detectron2/export/c10.py similarity index 100% rename from preprocess/detectron2/detectron2/export/c10.py rename to detectron2/export/c10.py diff --git a/preprocess/detectron2/detectron2/export/caffe2_export.py b/detectron2/export/caffe2_export.py similarity index 100% rename from preprocess/detectron2/detectron2/export/caffe2_export.py rename to detectron2/export/caffe2_export.py diff --git a/preprocess/detectron2/detectron2/export/caffe2_inference.py b/detectron2/export/caffe2_inference.py similarity index 100% rename from preprocess/detectron2/detectron2/export/caffe2_inference.py rename to detectron2/export/caffe2_inference.py diff --git a/preprocess/detectron2/detectron2/export/caffe2_modeling.py b/detectron2/export/caffe2_modeling.py similarity index 100% rename from preprocess/detectron2/detectron2/export/caffe2_modeling.py rename to detectron2/export/caffe2_modeling.py diff --git a/preprocess/detectron2/detectron2/export/caffe2_patch.py b/detectron2/export/caffe2_patch.py similarity index 100% rename from preprocess/detectron2/detectron2/export/caffe2_patch.py rename to detectron2/export/caffe2_patch.py diff --git a/preprocess/detectron2/detectron2/export/flatten.py b/detectron2/export/flatten.py similarity index 100% rename from preprocess/detectron2/detectron2/export/flatten.py rename to detectron2/export/flatten.py diff --git a/preprocess/detectron2/detectron2/export/shared.py b/detectron2/export/shared.py similarity index 100% rename from preprocess/detectron2/detectron2/export/shared.py rename to detectron2/export/shared.py diff --git a/preprocess/detectron2/detectron2/export/torchscript.py b/detectron2/export/torchscript.py similarity index 100% rename from preprocess/detectron2/detectron2/export/torchscript.py rename to detectron2/export/torchscript.py diff --git a/preprocess/detectron2/detectron2/export/torchscript_patch.py b/detectron2/export/torchscript_patch.py similarity index 100% rename from preprocess/detectron2/detectron2/export/torchscript_patch.py rename to detectron2/export/torchscript_patch.py diff --git a/preprocess/detectron2/detectron2/layers/__init__.py b/detectron2/layers/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/__init__.py rename to detectron2/layers/__init__.py diff --git a/preprocess/detectron2/detectron2/layers/aspp.py b/detectron2/layers/aspp.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/aspp.py rename to detectron2/layers/aspp.py diff --git a/preprocess/detectron2/detectron2/layers/batch_norm.py b/detectron2/layers/batch_norm.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/batch_norm.py rename to detectron2/layers/batch_norm.py diff --git a/preprocess/detectron2/detectron2/layers/blocks.py b/detectron2/layers/blocks.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/blocks.py rename to detectron2/layers/blocks.py diff --git a/preprocess/detectron2/detectron2/layers/csrc/README.md b/detectron2/layers/csrc/README.md similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/README.md rename to detectron2/layers/csrc/README.md diff --git a/preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated.h b/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated.h rename to detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cpu.cpp b/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cpu.cpp similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cpu.cpp rename to detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cpu.cpp diff --git a/preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu b/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu rename to detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated.h b/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated.h rename to detectron2/layers/csrc/box_iou_rotated/box_iou_rotated.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cpu.cpp b/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cpu.cpp similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cpu.cpp rename to detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cpu.cpp diff --git a/preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cuda.cu b/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cuda.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cuda.cu rename to detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_cuda.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_utils.h b/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_utils.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_utils.h rename to detectron2/layers/csrc/box_iou_rotated/box_iou_rotated_utils.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/cocoeval/cocoeval.cpp b/detectron2/layers/csrc/cocoeval/cocoeval.cpp similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/cocoeval/cocoeval.cpp rename to detectron2/layers/csrc/cocoeval/cocoeval.cpp diff --git a/preprocess/detectron2/detectron2/layers/csrc/cocoeval/cocoeval.h b/detectron2/layers/csrc/cocoeval/cocoeval.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/cocoeval/cocoeval.h rename to detectron2/layers/csrc/cocoeval/cocoeval.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/cuda_version.cu b/detectron2/layers/csrc/cuda_version.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/cuda_version.cu rename to detectron2/layers/csrc/cuda_version.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv.h b/detectron2/layers/csrc/deformable/deform_conv.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv.h rename to detectron2/layers/csrc/deformable/deform_conv.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda.cu b/detectron2/layers/csrc/deformable/deform_conv_cuda.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda.cu rename to detectron2/layers/csrc/deformable/deform_conv_cuda.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu b/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu rename to detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated.h b/detectron2/layers/csrc/nms_rotated/nms_rotated.h similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated.h rename to detectron2/layers/csrc/nms_rotated/nms_rotated.h diff --git a/preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated_cpu.cpp b/detectron2/layers/csrc/nms_rotated/nms_rotated_cpu.cpp similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated_cpu.cpp rename to detectron2/layers/csrc/nms_rotated/nms_rotated_cpu.cpp diff --git a/preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated_cuda.cu b/detectron2/layers/csrc/nms_rotated/nms_rotated_cuda.cu similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/nms_rotated/nms_rotated_cuda.cu rename to detectron2/layers/csrc/nms_rotated/nms_rotated_cuda.cu diff --git a/preprocess/detectron2/detectron2/layers/csrc/vision.cpp b/detectron2/layers/csrc/vision.cpp similarity index 100% rename from preprocess/detectron2/detectron2/layers/csrc/vision.cpp rename to detectron2/layers/csrc/vision.cpp diff --git a/preprocess/detectron2/detectron2/layers/deform_conv.py b/detectron2/layers/deform_conv.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/deform_conv.py rename to detectron2/layers/deform_conv.py diff --git a/preprocess/detectron2/detectron2/layers/losses.py b/detectron2/layers/losses.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/losses.py rename to detectron2/layers/losses.py diff --git a/preprocess/detectron2/detectron2/layers/mask_ops.py b/detectron2/layers/mask_ops.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/mask_ops.py rename to detectron2/layers/mask_ops.py diff --git a/preprocess/detectron2/detectron2/layers/nms.py b/detectron2/layers/nms.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/nms.py rename to detectron2/layers/nms.py diff --git a/preprocess/detectron2/detectron2/layers/roi_align.py b/detectron2/layers/roi_align.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/roi_align.py rename to detectron2/layers/roi_align.py diff --git a/preprocess/detectron2/detectron2/layers/roi_align_rotated.py b/detectron2/layers/roi_align_rotated.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/roi_align_rotated.py rename to detectron2/layers/roi_align_rotated.py diff --git a/preprocess/detectron2/detectron2/layers/rotated_boxes.py b/detectron2/layers/rotated_boxes.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/rotated_boxes.py rename to detectron2/layers/rotated_boxes.py diff --git a/preprocess/detectron2/detectron2/layers/shape_spec.py b/detectron2/layers/shape_spec.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/shape_spec.py rename to detectron2/layers/shape_spec.py diff --git a/preprocess/detectron2/detectron2/layers/wrappers.py b/detectron2/layers/wrappers.py similarity index 100% rename from preprocess/detectron2/detectron2/layers/wrappers.py rename to detectron2/layers/wrappers.py diff --git a/preprocess/detectron2/detectron2/model_zoo/__init__.py b/detectron2/model_zoo/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/model_zoo/__init__.py rename to detectron2/model_zoo/__init__.py diff --git a/preprocess/detectron2/detectron2/model_zoo/model_zoo.py b/detectron2/model_zoo/model_zoo.py similarity index 100% rename from preprocess/detectron2/detectron2/model_zoo/model_zoo.py rename to detectron2/model_zoo/model_zoo.py diff --git a/preprocess/detectron2/detectron2/modeling/__init__.py b/detectron2/modeling/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/__init__.py rename to detectron2/modeling/__init__.py diff --git a/preprocess/detectron2/detectron2/modeling/anchor_generator.py b/detectron2/modeling/anchor_generator.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/anchor_generator.py rename to detectron2/modeling/anchor_generator.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/__init__.py b/detectron2/modeling/backbone/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/__init__.py rename to detectron2/modeling/backbone/__init__.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/backbone.py b/detectron2/modeling/backbone/backbone.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/backbone.py rename to detectron2/modeling/backbone/backbone.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/build.py b/detectron2/modeling/backbone/build.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/build.py rename to detectron2/modeling/backbone/build.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/fpn.py b/detectron2/modeling/backbone/fpn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/fpn.py rename to detectron2/modeling/backbone/fpn.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/mvit.py b/detectron2/modeling/backbone/mvit.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/mvit.py rename to detectron2/modeling/backbone/mvit.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/regnet.py b/detectron2/modeling/backbone/regnet.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/regnet.py rename to detectron2/modeling/backbone/regnet.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/resnet.py b/detectron2/modeling/backbone/resnet.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/resnet.py rename to detectron2/modeling/backbone/resnet.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/swin.py b/detectron2/modeling/backbone/swin.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/swin.py rename to detectron2/modeling/backbone/swin.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/utils.py b/detectron2/modeling/backbone/utils.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/utils.py rename to detectron2/modeling/backbone/utils.py diff --git a/preprocess/detectron2/detectron2/modeling/backbone/vit.py b/detectron2/modeling/backbone/vit.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/backbone/vit.py rename to detectron2/modeling/backbone/vit.py diff --git a/preprocess/detectron2/detectron2/modeling/box_regression.py b/detectron2/modeling/box_regression.py similarity index 99% rename from preprocess/detectron2/detectron2/modeling/box_regression.py rename to detectron2/modeling/box_regression.py index 6fb5d8299546bb98fe980b935324ed54a42bf717..09fa097424d99518874c972efd3cdfb0bb96fd16 100644 --- a/preprocess/detectron2/detectron2/modeling/box_regression.py +++ b/detectron2/modeling/box_regression.py @@ -180,7 +180,7 @@ class Box2BoxTransformRotated: ), "Input boxes to Box2BoxTransformRotated are not valid!" return deltas - def apply_deltas(self, deltas: torch.Tensor, boxes: torch.Tensor): + def apply_deltas(self, deltas, boxes): """ Apply transformation `deltas` (dx, dy, dw, dh, da) to `boxes`. diff --git a/preprocess/detectron2/detectron2/modeling/matcher.py b/detectron2/modeling/matcher.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/matcher.py rename to detectron2/modeling/matcher.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/__init__.py b/detectron2/modeling/meta_arch/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/__init__.py rename to detectron2/modeling/meta_arch/__init__.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/build.py b/detectron2/modeling/meta_arch/build.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/build.py rename to detectron2/modeling/meta_arch/build.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/dense_detector.py b/detectron2/modeling/meta_arch/dense_detector.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/dense_detector.py rename to detectron2/modeling/meta_arch/dense_detector.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/fcos.py b/detectron2/modeling/meta_arch/fcos.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/fcos.py rename to detectron2/modeling/meta_arch/fcos.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/panoptic_fpn.py b/detectron2/modeling/meta_arch/panoptic_fpn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/panoptic_fpn.py rename to detectron2/modeling/meta_arch/panoptic_fpn.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/rcnn.py b/detectron2/modeling/meta_arch/rcnn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/rcnn.py rename to detectron2/modeling/meta_arch/rcnn.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/retinanet.py b/detectron2/modeling/meta_arch/retinanet.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/retinanet.py rename to detectron2/modeling/meta_arch/retinanet.py diff --git a/preprocess/detectron2/detectron2/modeling/meta_arch/semantic_seg.py b/detectron2/modeling/meta_arch/semantic_seg.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/meta_arch/semantic_seg.py rename to detectron2/modeling/meta_arch/semantic_seg.py diff --git a/preprocess/detectron2/detectron2/modeling/mmdet_wrapper.py b/detectron2/modeling/mmdet_wrapper.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/mmdet_wrapper.py rename to detectron2/modeling/mmdet_wrapper.py diff --git a/preprocess/detectron2/detectron2/modeling/poolers.py b/detectron2/modeling/poolers.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/poolers.py rename to detectron2/modeling/poolers.py diff --git a/preprocess/detectron2/detectron2/modeling/postprocessing.py b/detectron2/modeling/postprocessing.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/postprocessing.py rename to detectron2/modeling/postprocessing.py diff --git a/preprocess/detectron2/detectron2/modeling/proposal_generator/__init__.py b/detectron2/modeling/proposal_generator/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/proposal_generator/__init__.py rename to detectron2/modeling/proposal_generator/__init__.py diff --git a/preprocess/detectron2/detectron2/modeling/proposal_generator/build.py b/detectron2/modeling/proposal_generator/build.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/proposal_generator/build.py rename to detectron2/modeling/proposal_generator/build.py diff --git a/preprocess/detectron2/detectron2/modeling/proposal_generator/proposal_utils.py b/detectron2/modeling/proposal_generator/proposal_utils.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/proposal_generator/proposal_utils.py rename to detectron2/modeling/proposal_generator/proposal_utils.py diff --git a/preprocess/detectron2/detectron2/modeling/proposal_generator/rpn.py b/detectron2/modeling/proposal_generator/rpn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/proposal_generator/rpn.py rename to detectron2/modeling/proposal_generator/rpn.py diff --git a/preprocess/detectron2/detectron2/modeling/proposal_generator/rrpn.py b/detectron2/modeling/proposal_generator/rrpn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/proposal_generator/rrpn.py rename to detectron2/modeling/proposal_generator/rrpn.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/__init__.py b/detectron2/modeling/roi_heads/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/__init__.py rename to detectron2/modeling/roi_heads/__init__.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/box_head.py b/detectron2/modeling/roi_heads/box_head.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/box_head.py rename to detectron2/modeling/roi_heads/box_head.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/cascade_rcnn.py b/detectron2/modeling/roi_heads/cascade_rcnn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/cascade_rcnn.py rename to detectron2/modeling/roi_heads/cascade_rcnn.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/fast_rcnn.py b/detectron2/modeling/roi_heads/fast_rcnn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/fast_rcnn.py rename to detectron2/modeling/roi_heads/fast_rcnn.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/keypoint_head.py b/detectron2/modeling/roi_heads/keypoint_head.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/keypoint_head.py rename to detectron2/modeling/roi_heads/keypoint_head.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/mask_head.py b/detectron2/modeling/roi_heads/mask_head.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/mask_head.py rename to detectron2/modeling/roi_heads/mask_head.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/roi_heads.py b/detectron2/modeling/roi_heads/roi_heads.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/roi_heads.py rename to detectron2/modeling/roi_heads/roi_heads.py diff --git a/preprocess/detectron2/detectron2/modeling/roi_heads/rotated_fast_rcnn.py b/detectron2/modeling/roi_heads/rotated_fast_rcnn.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/roi_heads/rotated_fast_rcnn.py rename to detectron2/modeling/roi_heads/rotated_fast_rcnn.py diff --git a/preprocess/detectron2/detectron2/modeling/sampling.py b/detectron2/modeling/sampling.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/sampling.py rename to detectron2/modeling/sampling.py diff --git a/preprocess/detectron2/detectron2/modeling/test_time_augmentation.py b/detectron2/modeling/test_time_augmentation.py similarity index 100% rename from preprocess/detectron2/detectron2/modeling/test_time_augmentation.py rename to detectron2/modeling/test_time_augmentation.py diff --git a/preprocess/detectron2/detectron2/projects/README.md b/detectron2/projects/README.md similarity index 100% rename from preprocess/detectron2/detectron2/projects/README.md rename to detectron2/projects/README.md diff --git a/preprocess/detectron2/detectron2/projects/__init__.py b/detectron2/projects/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/projects/__init__.py rename to detectron2/projects/__init__.py diff --git a/preprocess/detectron2/detectron2/solver/__init__.py b/detectron2/solver/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/solver/__init__.py rename to detectron2/solver/__init__.py diff --git a/preprocess/detectron2/detectron2/solver/build.py b/detectron2/solver/build.py similarity index 100% rename from preprocess/detectron2/detectron2/solver/build.py rename to detectron2/solver/build.py diff --git a/preprocess/detectron2/detectron2/solver/lr_scheduler.py b/detectron2/solver/lr_scheduler.py similarity index 100% rename from preprocess/detectron2/detectron2/solver/lr_scheduler.py rename to detectron2/solver/lr_scheduler.py diff --git a/preprocess/detectron2/detectron2/structures/__init__.py b/detectron2/structures/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/__init__.py rename to detectron2/structures/__init__.py diff --git a/preprocess/detectron2/detectron2/structures/boxes.py b/detectron2/structures/boxes.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/boxes.py rename to detectron2/structures/boxes.py diff --git a/preprocess/detectron2/detectron2/structures/image_list.py b/detectron2/structures/image_list.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/image_list.py rename to detectron2/structures/image_list.py diff --git a/preprocess/detectron2/detectron2/structures/instances.py b/detectron2/structures/instances.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/instances.py rename to detectron2/structures/instances.py diff --git a/preprocess/detectron2/detectron2/structures/keypoints.py b/detectron2/structures/keypoints.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/keypoints.py rename to detectron2/structures/keypoints.py diff --git a/preprocess/detectron2/detectron2/structures/masks.py b/detectron2/structures/masks.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/masks.py rename to detectron2/structures/masks.py diff --git a/preprocess/detectron2/detectron2/structures/rotated_boxes.py b/detectron2/structures/rotated_boxes.py similarity index 100% rename from preprocess/detectron2/detectron2/structures/rotated_boxes.py rename to detectron2/structures/rotated_boxes.py diff --git a/preprocess/detectron2/detectron2/tracking/__init__.py b/detectron2/tracking/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/__init__.py rename to detectron2/tracking/__init__.py diff --git a/preprocess/detectron2/detectron2/tracking/base_tracker.py b/detectron2/tracking/base_tracker.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/base_tracker.py rename to detectron2/tracking/base_tracker.py diff --git a/preprocess/detectron2/detectron2/tracking/bbox_iou_tracker.py b/detectron2/tracking/bbox_iou_tracker.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/bbox_iou_tracker.py rename to detectron2/tracking/bbox_iou_tracker.py diff --git a/preprocess/detectron2/detectron2/tracking/hungarian_tracker.py b/detectron2/tracking/hungarian_tracker.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/hungarian_tracker.py rename to detectron2/tracking/hungarian_tracker.py diff --git a/preprocess/detectron2/detectron2/tracking/iou_weighted_hungarian_bbox_iou_tracker.py b/detectron2/tracking/iou_weighted_hungarian_bbox_iou_tracker.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/iou_weighted_hungarian_bbox_iou_tracker.py rename to detectron2/tracking/iou_weighted_hungarian_bbox_iou_tracker.py diff --git a/preprocess/detectron2/detectron2/tracking/utils.py b/detectron2/tracking/utils.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/utils.py rename to detectron2/tracking/utils.py diff --git a/preprocess/detectron2/detectron2/tracking/vanilla_hungarian_bbox_iou_tracker.py b/detectron2/tracking/vanilla_hungarian_bbox_iou_tracker.py similarity index 100% rename from preprocess/detectron2/detectron2/tracking/vanilla_hungarian_bbox_iou_tracker.py rename to detectron2/tracking/vanilla_hungarian_bbox_iou_tracker.py diff --git a/preprocess/detectron2/detectron2/utils/README.md b/detectron2/utils/README.md similarity index 100% rename from preprocess/detectron2/detectron2/utils/README.md rename to detectron2/utils/README.md diff --git a/preprocess/detectron2/detectron2/utils/__init__.py b/detectron2/utils/__init__.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/__init__.py rename to detectron2/utils/__init__.py diff --git a/preprocess/detectron2/detectron2/utils/analysis.py b/detectron2/utils/analysis.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/analysis.py rename to detectron2/utils/analysis.py diff --git a/preprocess/detectron2/detectron2/utils/collect_env.py b/detectron2/utils/collect_env.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/collect_env.py rename to detectron2/utils/collect_env.py diff --git a/preprocess/detectron2/detectron2/utils/colormap.py b/detectron2/utils/colormap.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/colormap.py rename to detectron2/utils/colormap.py diff --git a/preprocess/detectron2/detectron2/utils/comm.py b/detectron2/utils/comm.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/comm.py rename to detectron2/utils/comm.py diff --git a/preprocess/detectron2/detectron2/utils/develop.py b/detectron2/utils/develop.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/develop.py rename to detectron2/utils/develop.py diff --git a/preprocess/detectron2/detectron2/utils/env.py b/detectron2/utils/env.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/env.py rename to detectron2/utils/env.py diff --git a/preprocess/detectron2/detectron2/utils/events.py b/detectron2/utils/events.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/events.py rename to detectron2/utils/events.py diff --git a/preprocess/detectron2/detectron2/utils/file_io.py b/detectron2/utils/file_io.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/file_io.py rename to detectron2/utils/file_io.py diff --git a/preprocess/detectron2/detectron2/utils/logger.py b/detectron2/utils/logger.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/logger.py rename to detectron2/utils/logger.py diff --git a/preprocess/detectron2/detectron2/utils/memory.py b/detectron2/utils/memory.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/memory.py rename to detectron2/utils/memory.py diff --git a/preprocess/detectron2/detectron2/utils/registry.py b/detectron2/utils/registry.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/registry.py rename to detectron2/utils/registry.py diff --git a/preprocess/detectron2/detectron2/utils/serialize.py b/detectron2/utils/serialize.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/serialize.py rename to detectron2/utils/serialize.py diff --git a/preprocess/detectron2/detectron2/utils/testing.py b/detectron2/utils/testing.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/testing.py rename to detectron2/utils/testing.py diff --git a/preprocess/detectron2/detectron2/utils/tracing.py b/detectron2/utils/tracing.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/tracing.py rename to detectron2/utils/tracing.py diff --git a/preprocess/detectron2/detectron2/utils/video_visualizer.py b/detectron2/utils/video_visualizer.py similarity index 100% rename from preprocess/detectron2/detectron2/utils/video_visualizer.py rename to detectron2/utils/video_visualizer.py diff --git a/preprocess/detectron2/detectron2/utils/visualizer.py b/detectron2/utils/visualizer.py similarity index 98% rename from preprocess/detectron2/detectron2/utils/visualizer.py rename to detectron2/utils/visualizer.py index 8324dfcdf6af5a84828ac0ec670fe7fe1e833700..5d2cc1762d9b7c018b1f2cb32481485594d1d397 100644 --- a/preprocess/detectron2/detectron2/utils/visualizer.py +++ b/detectron2/utils/visualizer.py @@ -354,9 +354,7 @@ class Visualizer: # TODO implement a fast, rasterized version using OpenCV - def __init__( - self, img_rgb, metadata=None, scale=1.0, instance_mode=ColorMode.IMAGE, font_size_scale=1.0 - ): + def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=ColorMode.IMAGE): """ Args: img_rgb: a numpy array of shape (H, W, C), where H and W correspond to @@ -367,7 +365,6 @@ class Visualizer: metadata (Metadata): dataset metadata (e.g. class names and colors) instance_mode (ColorMode): defines one of the pre-defined style for drawing instances on an image. - font_size_scale: extra scaling of font size on top of default font size """ self.img = np.asarray(img_rgb).clip(0, 255).astype(np.uint8) if metadata is None: @@ -379,11 +376,11 @@ class Visualizer: # too small texts are useless, therefore clamp to 9 self._default_font_size = max( np.sqrt(self.output.height * self.output.width) // 90, 10 // scale - ) * font_size_scale + ) self._instance_mode = instance_mode self.keypoint_threshold = _KEYPOINT_THRESHOLD - def draw_instance_predictions(self, predictions, jittering: bool = True): + def draw_instance_predictions(self, predictions): """ Draw instance-level prediction results on an image. @@ -391,8 +388,6 @@ class Visualizer: predictions (Instances): the output of an instance detection/segmentation model. Following fields will be used to draw: "pred_boxes", "pred_classes", "scores", "pred_masks" (or "pred_masks_rle"). - jittering: if True, in color mode SEGMENTATION, randomly jitter the colors per class - to distinguish instances from the same class Returns: output (VisImage): image object with visualizations. @@ -412,12 +407,7 @@ class Visualizer: if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"): colors = [ self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in classes - ] if jittering else [ - tuple( - mplc.to_rgb([x / 255 for x in self.metadata.thing_colors[c]]) - ) for c in classes ] - alpha = 0.8 else: colors = None diff --git a/preprocess/detectron2/.circleci/config.yml b/preprocess/detectron2/.circleci/config.yml deleted file mode 100644 index 9a2148c3c8df3efadc7b0e3f1e755078fcade3d5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.circleci/config.yml +++ /dev/null @@ -1,271 +0,0 @@ -version: 2.1 - -# ------------------------------------------------------------------------------------- -# Environments to run the jobs in -# ------------------------------------------------------------------------------------- -cpu: &cpu - machine: - image: ubuntu-2004:202107-02 - resource_class: medium - -gpu: &gpu - machine: - # NOTE: use a cuda version that's supported by all our pytorch versions - image: ubuntu-1604-cuda-11.1:202012-01 - resource_class: gpu.nvidia.small - -windows-cpu: &windows_cpu - machine: - resource_class: windows.medium - image: windows-server-2019-vs2019:stable - shell: powershell.exe - -# windows-gpu: &windows_gpu -# machine: -# resource_class: windows.gpu.nvidia.medium -# image: windows-server-2019-nvidia:stable - -version_parameters: &version_parameters - parameters: - pytorch_version: - type: string - torchvision_version: - type: string - pytorch_index: - type: string - # use test wheels index to have access to RC wheels - # https://download.pytorch.org/whl/test/torch_test.html - default: "https://download.pytorch.org/whl/torch_stable.html" - python_version: # NOTE: only affect linux - type: string - default: '3.8.6' - - environment: - PYTORCH_VERSION: << parameters.pytorch_version >> - TORCHVISION_VERSION: << parameters.torchvision_version >> - PYTORCH_INDEX: << parameters.pytorch_index >> - PYTHON_VERSION: << parameters.python_version>> - # point datasets to ~/.torch so it's cached in CI - DETECTRON2_DATASETS: ~/.torch/datasets - -# ------------------------------------------------------------------------------------- -# Re-usable commands -# ------------------------------------------------------------------------------------- -# install_nvidia_driver: &install_nvidia_driver -# - run: -# name: Install nvidia driver -# working_directory: ~/ -# command: | -# wget -q 'https://s3.amazonaws.com/ossci-linux/nvidia_driver/NVIDIA-Linux-x86_64-430.40.run' -# sudo /bin/bash ./NVIDIA-Linux-x86_64-430.40.run -s --no-drm -# nvidia-smi - -add_ssh_keys: &add_ssh_keys - # https://circleci.com/docs/2.0/add-ssh-key/ - - add_ssh_keys: - fingerprints: - - "e4:13:f2:22:d4:49:e8:e4:57:5a:ac:20:2f:3f:1f:ca" - -install_python: &install_python - - run: - name: Install Python - working_directory: ~/ - command: | - # upgrade pyenv - cd /opt/circleci/.pyenv/plugins/python-build/../.. && git pull && cd - - pyenv install -s $PYTHON_VERSION - pyenv global $PYTHON_VERSION - python --version - which python - pip install --upgrade pip - -setup_venv: &setup_venv - - run: - name: Setup Virtual Env - working_directory: ~/ - command: | - python -m venv ~/venv - echo ". ~/venv/bin/activate" >> $BASH_ENV - . ~/venv/bin/activate - python --version - which python - which pip - pip install --upgrade pip - -setup_venv_win: &setup_venv_win - - run: - name: Setup Virtual Env for Windows - command: | - pip install virtualenv - python -m virtualenv env - .\env\Scripts\activate - python --version - which python - which pip - -install_linux_dep: &install_linux_dep - - run: - name: Install Dependencies - command: | - # disable crash coredump, so unittests fail fast - sudo systemctl stop apport.service - # install from github to get latest; install iopath first since fvcore depends on it - pip install --progress-bar off -U 'git+https://github.com/facebookresearch/iopath' - pip install --progress-bar off -U 'git+https://github.com/facebookresearch/fvcore' - # Don't use pytest-xdist: cuda tests are unstable under multi-process workers. - # Don't use opencv 4.7.0.68: https://github.com/opencv/opencv-python/issues/765 - pip install --progress-bar off ninja opencv-python-headless!=4.7.0.68 pytest tensorboard pycocotools onnx - pip install --progress-bar off torch==$PYTORCH_VERSION -f $PYTORCH_INDEX - if [[ "$TORCHVISION_VERSION" == "master" ]]; then - pip install git+https://github.com/pytorch/vision.git - else - pip install --progress-bar off torchvision==$TORCHVISION_VERSION -f $PYTORCH_INDEX - fi - - python -c 'import torch; print("CUDA:", torch.cuda.is_available())' - gcc --version - -install_detectron2: &install_detectron2 - - run: - name: Install Detectron2 - command: | - # Remove first, in case it's in the CI cache - pip uninstall -y detectron2 - - pip install --progress-bar off -e .[all] - python -m detectron2.utils.collect_env - ./datasets/prepare_for_tests.sh - -run_unittests: &run_unittests - - run: - name: Run Unit Tests - command: | - pytest -sv --durations=15 tests # parallel causes some random failures - -uninstall_tests: &uninstall_tests - - run: - name: Run Tests After Uninstalling - command: | - pip uninstall -y detectron2 - # Remove built binaries - rm -rf build/ detectron2/*.so - # Tests that code is importable without installation - PYTHONPATH=. ./.circleci/import-tests.sh - - -# ------------------------------------------------------------------------------------- -# Jobs to run -# ------------------------------------------------------------------------------------- -jobs: - linux_cpu_tests: - <<: *cpu - <<: *version_parameters - - working_directory: ~/detectron2 - - steps: - - checkout - - # Cache the venv directory that contains python, dependencies, and checkpoints - # Refresh the key when dependencies should be updated (e.g. when pytorch releases) - - restore_cache: - keys: - - cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210827 - - - <<: *install_python - - <<: *install_linux_dep - - <<: *install_detectron2 - - <<: *run_unittests - - <<: *uninstall_tests - - - save_cache: - paths: - - /opt/circleci/.pyenv - - ~/.torch - key: cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210827 - - - linux_gpu_tests: - <<: *gpu - <<: *version_parameters - - working_directory: ~/detectron2 - - steps: - - checkout - - - restore_cache: - keys: - - cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210827 - - - <<: *install_python - - <<: *install_linux_dep - - <<: *install_detectron2 - - <<: *run_unittests - - <<: *uninstall_tests - - - save_cache: - paths: - - /opt/circleci/.pyenv - - ~/.torch - key: cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210827 - - windows_cpu_build: - <<: *windows_cpu - <<: *version_parameters - steps: - - <<: *add_ssh_keys - - checkout - - <<: *setup_venv_win - - # Cache the env directory that contains dependencies - - restore_cache: - keys: - - cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210404 - - - run: - name: Install Dependencies - command: | - pip install certifi --ignore-installed # required on windows to workaround some cert issue - pip install numpy cython # required on windows before pycocotools - pip install opencv-python-headless pytest-xdist pycocotools tensorboard onnx - pip install -U git+https://github.com/facebookresearch/iopath - pip install -U git+https://github.com/facebookresearch/fvcore - pip install torch==$env:PYTORCH_VERSION torchvision==$env:TORCHVISION_VERSION -f $env:PYTORCH_INDEX - - - save_cache: - paths: - - env - key: cache-{{ arch }}-<< parameters.pytorch_version >>-{{ .Branch }}-20210404 - - - <<: *install_detectron2 - # TODO: unittest fails for now - -workflows: - version: 2 - regular_test: - jobs: - - linux_cpu_tests: - name: linux_cpu_tests_pytorch1.10 - pytorch_version: '1.10.0+cpu' - torchvision_version: '0.11.1+cpu' - - linux_gpu_tests: - name: linux_gpu_tests_pytorch1.8 - pytorch_version: '1.8.1+cu111' - torchvision_version: '0.9.1+cu111' - - linux_gpu_tests: - name: linux_gpu_tests_pytorch1.9 - pytorch_version: '1.9+cu111' - torchvision_version: '0.10+cu111' - - linux_gpu_tests: - name: linux_gpu_tests_pytorch1.10 - pytorch_version: '1.10+cu111' - torchvision_version: '0.11.1+cu111' - - linux_gpu_tests: - name: linux_gpu_tests_pytorch1.10_python39 - pytorch_version: '1.10+cu111' - torchvision_version: '0.11.1+cu111' - python_version: '3.9.6' - - windows_cpu_build: - pytorch_version: '1.10+cpu' - torchvision_version: '0.11.1+cpu' diff --git a/preprocess/detectron2/.circleci/import-tests.sh b/preprocess/detectron2/.circleci/import-tests.sh deleted file mode 100755 index 8e8deb6ad699fd673fea0f66b91aa3ec6e3c7c7c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.circleci/import-tests.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -# Test that import works without building detectron2. - -# Check that _C is not importable -python -c "from detectron2 import _C" > /dev/null 2>&1 && { - echo "This test should be run without building detectron2." - exit 1 -} - -# Check that other modules are still importable, even when _C is not importable -python -c "from detectron2 import modeling" -python -c "from detectron2 import modeling, data" -python -c "from detectron2 import evaluation, export, checkpoint" -python -c "from detectron2 import utils, engine" diff --git a/preprocess/detectron2/.clang-format b/preprocess/detectron2/.clang-format deleted file mode 100644 index 39b1b3d603ed0cf6b7f94c9c08067f148f35613f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.clang-format +++ /dev/null @@ -1,85 +0,0 @@ -AccessModifierOffset: -1 -AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: true -AlignOperands: false -AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: true -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: false -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ForEachMacros: [ FOR_EACH, FOR_EACH_R, FOR_EACH_RANGE, ] -IncludeCategories: - - Regex: '^<.*\.h(pp)?>' - Priority: 1 - - Regex: '^<.*' - Priority: 2 - - Regex: '.*' - Priority: 3 -IndentCaseLabels: true -IndentWidth: 2 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: false -PenaltyBreakBeforeFirstCallParameter: 1 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 8 -UseTab: Never diff --git a/preprocess/detectron2/.flake8 b/preprocess/detectron2/.flake8 deleted file mode 100644 index 28881e488263c5693835063be9455f2fb1fdc849..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.flake8 +++ /dev/null @@ -1,15 +0,0 @@ -# This is an example .flake8 config, used when developing *Black* itself. -# Keep in sync with setup.cfg which is used for source packages. - -[flake8] -ignore = W503, E203, E221, C901, C408, E741, C407, B017, F811, C101, EXE001, EXE002 -max-line-length = 100 -max-complexity = 18 -select = B,C,E,F,W,T4,B9 -exclude = build -per-file-ignores = - **/__init__.py:F401,F403,E402 - **/configs/**.py:F401,E402 - configs/**.py:F401,E402 - **/tests/config/**.py:F401,E402 - tests/config/**.py:F401,E402 diff --git a/preprocess/detectron2/.github/CODE_OF_CONDUCT.md b/preprocess/detectron2/.github/CODE_OF_CONDUCT.md deleted file mode 100644 index 0f7ad8bfc173eac554f0b6ef7c684861e8014bbe..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,5 +0,0 @@ -# Code of Conduct - -Facebook has adopted a Code of Conduct that we expect project participants to adhere to. -Please read the [full text](https://code.fb.com/codeofconduct/) -so that you can understand what actions will and will not be tolerated. diff --git a/preprocess/detectron2/.github/CONTRIBUTING.md b/preprocess/detectron2/.github/CONTRIBUTING.md deleted file mode 100644 index 9bab709cae689ba3b92dd52f7fbcc0c6926f4a38..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/CONTRIBUTING.md +++ /dev/null @@ -1,68 +0,0 @@ -# Contributing to detectron2 - -## Issues -We use GitHub issues to track public bugs and questions. -Please make sure to follow one of the -[issue templates](https://github.com/facebookresearch/detectron2/issues/new/choose) -when reporting any issues. - -Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe -disclosure of security bugs. In those cases, please go through the process -outlined on that page and do not file a public issue. - -## Pull Requests -We actively welcome pull requests. - -However, if you're adding any significant features (e.g. > 50 lines), please -make sure to discuss with maintainers about your motivation and proposals in an issue -before sending a PR. This is to save your time so you don't spend time on a PR that we'll not accept. - -We do not always accept new features, and we take the following -factors into consideration: - -1. Whether the same feature can be achieved without modifying detectron2. - Detectron2 is designed so that you can implement many extensions from the outside, e.g. - those in [projects](https://github.com/facebookresearch/detectron2/tree/master/projects). - * If some part of detectron2 is not extensible enough, you can also bring up a more general issue to - improve it. Such feature request may be useful to more users. -2. Whether the feature is potentially useful to a large audience (e.g. an impactful detection paper, a popular dataset, - a significant speedup, a widely useful utility), - or only to a small portion of users (e.g., a less-known paper, an improvement not in the object - detection field, a trick that's not very popular in the community, code to handle a non-standard type of data) - * Adoption of additional models, datasets, new task are by default not added to detectron2 before they - receive significant popularity in the community. - We sometimes accept such features in `projects/`, or as a link in `projects/README.md`. -3. Whether the proposed solution has a good design / interface. This can be discussed in the issue prior to PRs, or - in the form of a draft PR. -4. Whether the proposed solution adds extra mental/practical overhead to users who don't - need such feature. -5. Whether the proposed solution breaks existing APIs. - -To add a feature to an existing function/class `Func`, there are always two approaches: -(1) add new arguments to `Func`; (2) write a new `Func_with_new_feature`. -To meet the above criteria, we often prefer approach (2), because: - -1. It does not involve modifying or potentially breaking existing code. -2. It does not add overhead to users who do not need the new feature. -3. Adding new arguments to a function/class is not scalable w.r.t. all the possible new research ideas in the future. - -When sending a PR, please do: - -1. If a PR contains multiple orthogonal changes, split it to several PRs. -2. If you've added code that should be tested, add tests. -3. For PRs that need experiments (e.g. adding a new model or new methods), - you don't need to update model zoo, but do provide experiment results in the description of the PR. -4. If APIs are changed, update the documentation. -5. We use the [Google style docstrings](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) in python. -6. Make sure your code lints with `./dev/linter.sh`. - - -## Contributor License Agreement ("CLA") -In order to accept your pull request, we need you to submit a CLA. You only need -to do this once to work on any of Facebook's open source projects. - -Complete your CLA here: - -## License -By contributing to detectron2, you agree that your contributions will be licensed -under the LICENSE file in the root directory of this source tree. diff --git a/preprocess/detectron2/.github/Detectron2-Logo-Horz.svg b/preprocess/detectron2/.github/Detectron2-Logo-Horz.svg deleted file mode 100644 index eb2d643ddd940cd8bdb5eaad093029969ff2364c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/Detectron2-Logo-Horz.svg +++ /dev/null @@ -1 +0,0 @@ -Detectron2-Logo-Horz \ No newline at end of file diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE.md b/preprocess/detectron2/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 5e8aaa2d3722e7e73a3d94b2b7dfc4f751d7a240..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,5 +0,0 @@ - -Please select an issue template from -https://github.com/facebookresearch/detectron2/issues/new/choose . - -Otherwise your issue will be closed. diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE/bugs.md b/preprocess/detectron2/.github/ISSUE_TEMPLATE/bugs.md deleted file mode 100644 index d0235c708ab6b0cdadb5865110e9e8c22ca313aa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE/bugs.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: "🐛 Bugs" -about: Report bugs in detectron2 -title: Please read & provide the following - ---- - -## Instructions To Reproduce the 🐛 Bug: -1. Full runnable code or full changes you made: -``` -If making changes to the project itself, please use output of the following command: -git rev-parse HEAD; git diff - - -``` -2. What exact command you run: -3. __Full logs__ or other relevant observations: -``` - -``` -4. please simplify the steps as much as possible so they do not require additional resources to - run, such as a private dataset. - -## Expected behavior: - -If there are no obvious error in "full logs" provided above, -please tell us the expected behavior. - -## Environment: - -Provide your environment information using the following command: -``` -wget -nc -q https://github.com/facebookresearch/detectron2/raw/main/detectron2/utils/collect_env.py && python collect_env.py -``` - -If your issue looks like an installation issue / environment issue, -please first try to solve it yourself with the instructions in -https://detectron2.readthedocs.io/tutorials/install.html#common-installation-issues diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE/config.yml b/preprocess/detectron2/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index c60c2e14309be9a93293a64e7481f2a91385f76a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,17 +0,0 @@ -# require an issue template to be chosen -blank_issues_enabled: false - -contact_links: - - name: How-To / All Other Questions - url: https://github.com/facebookresearch/detectron2/discussions - about: Use "github discussions" for community support on general questions that don't belong to the above issue categories - - name: Detectron2 Documentation - url: https://detectron2.readthedocs.io/index.html - about: Check if your question is answered in tutorials or API docs - -# Unexpected behaviors & bugs are split to two templates. -# When they are one template, users think "it's not a bug" and don't choose the template. -# -# But the file name is still "unexpected-problems-bugs.md" so that old references -# to this issue template still works. -# It's ok since this template should be a superset of "bugs.md" (unexpected behaviors is a superset of bugs) diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE/documentation.md b/preprocess/detectron2/.github/ISSUE_TEMPLATE/documentation.md deleted file mode 100644 index 88214d62e5228639491e019c78bb4171d535cdd1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE/documentation.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: "\U0001F4DA Documentation Issue" -about: Report a problem about existing documentation, comments, website or tutorials. -labels: documentation - ---- - -## 📚 Documentation Issue - -This issue category is for problems about existing documentation, not for asking how-to questions. - -* Provide a link to an existing documentation/comment/tutorial: - -* How should the above documentation/comment/tutorial improve: diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE/feature-request.md b/preprocess/detectron2/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index 03a1e93d7293948042120b875af8be0c6964e59c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: "\U0001F680Feature Request" -about: Suggest an improvement or new feature -labels: enhancement - ---- - -## 🚀 Feature -A clear and concise description of the feature proposal. - -## Motivation & Examples - -Tell us why the feature is useful. - -Describe what the feature would look like, if it is implemented. -Best demonstrated using **code examples** in addition to words. - -## Note - -We only consider adding new features if they are relevant to many users. - -If you request implementation of research papers -- we only consider papers that have enough significance and prevalance in the object detection field. - -We do not take requests for most projects in the `projects/` directory, because they are research code release that is mainly for other researchers to reproduce results. - -"Make X faster/accurate" is not a valid feature request. "Implement a concrete feature that can make X faster/accurate" can be a valid feature request. - -Instead of adding features inside detectron2, -you can implement many features by [extending detectron2](https://detectron2.readthedocs.io/tutorials/extend.html). -The [projects/](https://github.com/facebookresearch/detectron2/tree/main/projects/) directory contains many of such examples. - diff --git a/preprocess/detectron2/.github/ISSUE_TEMPLATE/unexpected-problems-bugs.md b/preprocess/detectron2/.github/ISSUE_TEMPLATE/unexpected-problems-bugs.md deleted file mode 100644 index 5db8f22415ff5c857ce83fb0d3de68211f775080..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/ISSUE_TEMPLATE/unexpected-problems-bugs.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: "😩 Unexpected behaviors" -about: Report unexpected behaviors when using detectron2 -title: Please read & provide the following - ---- - -If you do not know the root cause of the problem, please post according to this template: - -## Instructions To Reproduce the Issue: - -Check https://stackoverflow.com/help/minimal-reproducible-example for how to ask good questions. -Simplify the steps to reproduce the issue using suggestions from the above link, and provide them below: - -1. Full runnable code or full changes you made: -``` -If making changes to the project itself, please use output of the following command: -git rev-parse HEAD; git diff - - -``` -2. What exact command you run: -3. __Full logs__ or other relevant observations: -``` - -``` - -## Expected behavior: - -If there are no obvious crash in "full logs" provided above, -please tell us the expected behavior. - -If you expect a model to converge / work better, we do not help with such issues, unless -a model fails to reproduce the results in detectron2 model zoo, or proves existence of bugs. - -## Environment: - -Paste the output of the following command: -``` -wget -nc -nv https://github.com/facebookresearch/detectron2/raw/main/detectron2/utils/collect_env.py && python collect_env.py -``` - -If your issue looks like an installation issue / environment issue, -please first check common issues in https://detectron2.readthedocs.io/tutorials/install.html#common-installation-issues diff --git a/preprocess/detectron2/.github/pull_request_template.md b/preprocess/detectron2/.github/pull_request_template.md deleted file mode 100644 index d71729baee1ec324ab9db6e7562965cf9e2a091b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/pull_request_template.md +++ /dev/null @@ -1,10 +0,0 @@ -Thanks for your contribution! - -If you're sending a large PR (e.g., >100 lines), -please open an issue first about the feature / bug, and indicate how you want to contribute. - -We do not always accept features. -See https://detectron2.readthedocs.io/notes/contributing.html#pull-requests about how we handle PRs. - -Before submitting a PR, please run `dev/linter.sh` to lint the code. - diff --git a/preprocess/detectron2/.github/workflows/check-template.yml b/preprocess/detectron2/.github/workflows/check-template.yml deleted file mode 100644 index 3caed9df3caa50c0d3b606e4a56a1959c463b710..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/workflows/check-template.yml +++ /dev/null @@ -1,86 +0,0 @@ -name: Check issue template - -on: - issues: - types: [opened] - -jobs: - check-template: - runs-on: ubuntu-latest - # comment this out when testing with https://github.com/nektos/act - if: ${{ github.repository_owner == 'facebookresearch' }} - steps: - - uses: actions/checkout@v2 - - uses: actions/github-script@v3 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - // Arguments available: - // - github: A pre-authenticated octokit/rest.js client - // - context: An object containing the context of the workflow run - // - core: A reference to the @actions/core package - // - io: A reference to the @actions/io package - const fs = require('fs'); - const editDistance = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/levenshtein.js`).getEditDistance - issue = await github.issues.get({ - owner: context.issue.owner, - repo: context.issue.repo, - issue_number: context.issue.number, - }); - const hasLabel = issue.data.labels.length > 0; - if (hasLabel || issue.state === "closed") { - // don't require template on them - core.debug("Issue " + issue.data.title + " was skipped."); - return; - } - - sameAsTemplate = function(filename, body) { - let tmpl = fs.readFileSync(`.github/ISSUE_TEMPLATE/${filename}`, 'utf8'); - tmpl = tmpl.toLowerCase().split("---").slice(2).join("").trim(); - tmpl = tmpl.replace(/(\r\n|\n|\r)/gm, ""); - let bodyr = body.replace(/(\r\n|\n|\r)/gm, ""); - let dist = editDistance(tmpl, bodyr); - return dist < 8; - }; - - checkFail = async function(msg) { - core.info("Processing '" + issue.data.title + "' with message: " + msg); - await github.issues.addLabels({ - owner: context.issue.owner, - repo: context.issue.repo, - issue_number: context.issue.number, - labels: ["needs-more-info"], - }); - await github.issues.createComment({ - owner: context.issue.owner, - repo: context.issue.repo, - issue_number: context.issue.number, - body: msg, - }); - }; - - const body = issue.data.body.toLowerCase().trim(); - - if (sameAsTemplate("bugs.md", body) || sameAsTemplate("unexpected-problems-bugs.md", body)) { - await checkFail(` - We found that not enough information is provided about this issue. - Please provide details following the [issue template](https://github.com/facebookresearch/detectron2/issues/new/choose).`) - return; - } - - const hasInstructions = body.indexOf("reproduce") != -1; - const hasEnvironment = (body.indexOf("environment") != -1) || (body.indexOf("colab") != -1) || (body.indexOf("docker") != -1); - if (hasInstructions && hasEnvironment) { - core.debug("Issue " + issue.data.title + " follows template."); - return; - } - - let message = "You've chosen to report an unexpected problem or bug. Unless you already know the root cause of it, please include details about it by filling the [issue template](https://github.com/facebookresearch/detectron2/issues/new/choose).\n"; - message += "The following information is missing: "; - if (!hasInstructions) { - message += "\"Instructions To Reproduce the Issue and __Full__ Logs\"; "; - } - if (!hasEnvironment) { - message += "\"Your Environment\"; "; - } - await checkFail(message); diff --git a/preprocess/detectron2/.github/workflows/levenshtein.js b/preprocess/detectron2/.github/workflows/levenshtein.js deleted file mode 100644 index 67a5e3613c0072d124035ee8933a23de2105cfe3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/workflows/levenshtein.js +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (c) 2011 Andrei Mackenzie - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -// Compute the edit distance between the two given strings -exports.getEditDistance = function(a, b){ - if(a.length == 0) return b.length; - if(b.length == 0) return a.length; - - var matrix = []; - - // increment along the first column of each row - var i; - for(i = 0; i <= b.length; i++){ - matrix[i] = [i]; - } - - // increment each column in the first row - var j; - for(j = 0; j <= a.length; j++){ - matrix[0][j] = j; - } - - // Fill in the rest of the matrix - for(i = 1; i <= b.length; i++){ - for(j = 1; j <= a.length; j++){ - if(b.charAt(i-1) == a.charAt(j-1)){ - matrix[i][j] = matrix[i-1][j-1]; - } else { - matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution - Math.min(matrix[i][j-1] + 1, // insertion - matrix[i-1][j] + 1)); // deletion - } - } - } - - return matrix[b.length][a.length]; -}; diff --git a/preprocess/detectron2/.github/workflows/needs-reply.yml b/preprocess/detectron2/.github/workflows/needs-reply.yml deleted file mode 100644 index 4affabd3498290a752fab6d848fc667758bedaf2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/workflows/needs-reply.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Close/Lock issues after inactivity - -on: - schedule: - - cron: "0 0 * * *" - -jobs: - close-issues-needs-more-info: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'facebookresearch' }} - steps: - - name: Close old issues that need reply - uses: actions/github-script@v3 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - # Modified from https://github.com/dwieeb/needs-reply - script: | - // Arguments available: - // - github: A pre-authenticated octokit/rest.js client - // - context: An object containing the context of the workflow run - // - core: A reference to the @actions/core package - // - io: A reference to the @actions/io package - const kLabelToCheck = "needs-more-info"; - const kInvalidLabel = "invalid/unrelated"; - const kDaysBeforeClose = 7; - const kMessage = "Requested information was not provided in 7 days, so we're closing this issue.\n\nPlease open new issue if information becomes available. Otherwise, use [github discussions](https://github.com/facebookresearch/detectron2/discussions) for free-form discussions." - - issues = await github.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: kLabelToCheck, - sort: 'updated', - direction: 'asc', - per_page: 30, - page: 1, - }); - issues = issues.data; - if (issues.length === 0) { - core.info('No more issues found to process. Exiting.'); - return; - } - for (const issue of issues) { - if (!!issue.pull_request) - continue; - core.info(`Processing issue #${issue.number}`); - - let updatedAt = new Date(issue.updated_at).getTime(); - const numComments = issue.comments; - const comments = await github.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - per_page: 30, - page: Math.floor((numComments - 1) / 30) + 1, // the last page - }); - const lastComments = comments.data - .map(l => new Date(l.created_at).getTime()) - .sort(); - if (lastComments.length > 0) { - updatedAt = lastComments[lastComments.length - 1]; - } - - const now = new Date().getTime(); - const daysSinceUpdated = (now - updatedAt) / 1000 / 60 / 60 / 24; - - if (daysSinceUpdated < kDaysBeforeClose) { - core.info(`Skipping #${issue.number} because it has been updated in the last ${daysSinceUpdated} days`); - continue; - } - core.info(`Closing #${issue.number} because it has not been updated in the last ${daysSinceUpdated} days`); - await github.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - body: kMessage, - }); - const newLabels = numComments <= 2 ? [kInvalidLabel, kLabelToCheck] : issue.labels; - await github.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - labels: newLabels, - state: 'closed', - }); - } - - lock-issues-after-closed: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'facebookresearch' }} - steps: - - name: Lock closed issues that have no activity for a while - uses: dessant/lock-threads@v2 - with: - github-token: ${{ github.token }} - issue-lock-inactive-days: '300' - process-only: 'issues' - issue-exclude-labels: 'enhancement,bug,documentation' diff --git a/preprocess/detectron2/.github/workflows/remove-needs-reply.yml b/preprocess/detectron2/.github/workflows/remove-needs-reply.yml deleted file mode 100644 index 1f000b28ca27ef9c219d197f95251be1cb8c0979..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/workflows/remove-needs-reply.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Remove needs-more-info label - -on: - issue_comment: - types: [created] - issues: - types: [edited] - -jobs: - remove-needs-more-info-label: - runs-on: ubuntu-latest - # 1. issue_comment events could include PR comment, filter them out - # 2. Only trigger action if event was produced by the original author - if: ${{ !github.event.issue.pull_request && github.event.sender.login == github.event.issue.user.login }} - steps: - - name: Remove needs-more-info label - uses: octokit/request-action@v2.x - continue-on-error: true - with: - route: DELETE /repos/:repository/issues/:issue/labels/:label - repository: ${{ github.repository }} - issue: ${{ github.event.issue.number }} - label: needs-more-info - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/preprocess/detectron2/.github/workflows/workflow.yml b/preprocess/detectron2/.github/workflows/workflow.yml deleted file mode 100644 index 3de246c9a04850ecec7f52f5264ba2e6102e6881..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.github/workflows/workflow.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: CI -on: [push, pull_request] - -# Run linter with github actions for quick feedbacks. -# Run macos tests with github actions. Linux (CPU & GPU) tests currently runs on CircleCI -jobs: - linter: - runs-on: ubuntu-latest - # run on PRs, or commits to facebookresearch (not internal) - if: ${{ github.repository_owner == 'facebookresearch' || github.event_name == 'pull_request' }} - steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Install dependencies - # flake8-bugbear flake8-comprehensions are useful but not available internally - run: | - python -m pip install --upgrade pip - python -m pip install flake8==3.8.1 isort==4.3.21 - python -m pip install black==22.3.0 - flake8 --version - - name: Lint - run: | - echo "Running isort" - isort -c -sp . - echo "Running black" - black -l 100 --check . - echo "Running flake8" - flake8 . - - macos_tests: - runs-on: macos-latest - # run on PRs, or commits to facebookresearch (not internal) - if: ${{ github.repository_owner == 'facebookresearch' || github.event_name == 'pull_request' }} - strategy: - fail-fast: false - matrix: - torch: ["1.8", "1.9", "1.10"] - include: - - torch: "1.8" - torchvision: 0.9 - - torch: "1.9" - torchvision: "0.10" - - torch: "1.10" - torchvision: "0.11.1" - env: - # point datasets to ~/.torch so it's cached by CI - DETECTRON2_DATASETS: ~/.torch/datasets - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Python 3.8 - uses: actions/setup-python@v2 - with: - python-version: 3.8 - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: | - ${{ env.pythonLocation }}/lib/python3.8/site-packages - ~/.torch - key: ${{ runner.os }}-torch${{ matrix.torch }}-${{ hashFiles('setup.py') }}-20220119 - - - name: Install dependencies - run: | - python -m pip install -U pip - python -m pip install ninja opencv-python-headless onnx pytest-xdist - python -m pip install torch==${{matrix.torch}} torchvision==${{matrix.torchvision}} -f https://download.pytorch.org/whl/torch_stable.html - # install from github to get latest; install iopath first since fvcore depends on it - python -m pip install -U 'git+https://github.com/facebookresearch/iopath' - python -m pip install -U 'git+https://github.com/facebookresearch/fvcore' - - - name: Build and install - run: | - CC=clang CXX=clang++ python -m pip install -e .[all] - python -m detectron2.utils.collect_env - ./datasets/prepare_for_tests.sh - - name: Run unittests - run: python -m pytest -n 4 --durations=15 -sv tests/ diff --git a/preprocess/detectron2/.gitignore b/preprocess/detectron2/.gitignore deleted file mode 100644 index 9953d9b49bd150ffb251886f755b7a4150c4e35d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/.gitignore +++ /dev/null @@ -1,53 +0,0 @@ -# output dir -output -instant_test_output -inference_test_output - - -*.png -*.json -*.diff -*.jpg -!/projects/DensePose/doc/images/*.jpg - -# compilation and distribution -__pycache__ -_ext -*.pyc -*.pyd -*.so -*.dll -*.egg-info/ -build/ -dist/ -wheels/ - -# pytorch/python/numpy formats -*.pth -*.pkl -*.npy -*.ts -model_ts*.txt - -# ipython/jupyter notebooks -*.ipynb -**/.ipynb_checkpoints/ - -# Editor temporaries -*.swn -*.swo -*.swp -*~ - -# editor settings -.idea -.vscode -_darcs - -# project dirs -/detectron2/model_zoo/configs -/datasets/* -!/datasets/*.* -/projects/*/datasets -/models -/snippet diff --git a/preprocess/detectron2/GETTING_STARTED.md b/preprocess/detectron2/GETTING_STARTED.md deleted file mode 100644 index 404b0c8f467264d1adf61e8274e5f864e24018e8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/GETTING_STARTED.md +++ /dev/null @@ -1,79 +0,0 @@ -## Getting Started with Detectron2 - -This document provides a brief intro of the usage of builtin command-line tools in detectron2. - -For a tutorial that involves actual coding with the API, -see our [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5) -which covers how to run inference with an -existing model, and how to train a builtin model on a custom dataset. - - -### Inference Demo with Pre-trained Models - -1. Pick a model and its config file from - [model zoo](MODEL_ZOO.md), - for example, `mask_rcnn_R_50_FPN_3x.yaml`. -2. We provide `demo.py` that is able to demo builtin configs. Run it with: -``` -cd demo/ -python demo.py --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ - --input input1.jpg input2.jpg \ - [--other-options] - --opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl -``` -The configs are made for training, therefore we need to specify `MODEL.WEIGHTS` to a model from model zoo for evaluation. -This command will run the inference and show visualizations in an OpenCV window. - -For details of the command line arguments, see `demo.py -h` or look at its source code -to understand its behavior. Some common arguments are: -* To run __on your webcam__, replace `--input files` with `--webcam`. -* To run __on a video__, replace `--input files` with `--video-input video.mp4`. -* To run __on cpu__, add `MODEL.DEVICE cpu` after `--opts`. -* To save outputs to a directory (for images) or a file (for webcam or video), use `--output`. - - -### Training & Evaluation in Command Line - -We provide two scripts in "tools/plain_train_net.py" and "tools/train_net.py", -that are made to train all the configs provided in detectron2. You may want to -use it as a reference to write your own training script. - -Compared to "train_net.py", "plain_train_net.py" supports fewer default -features. It also includes fewer abstraction, therefore is easier to add custom -logic. - -To train a model with "train_net.py", first -setup the corresponding datasets following -[datasets/README.md](./datasets/README.md), -then run: -``` -cd tools/ -./train_net.py --num-gpus 8 \ - --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml -``` - -The configs are made for 8-GPU training. -To train on 1 GPU, you may need to [change some parameters](https://arxiv.org/abs/1706.02677), e.g.: -``` -./train_net.py \ - --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \ - --num-gpus 1 SOLVER.IMS_PER_BATCH 2 SOLVER.BASE_LR 0.0025 -``` - -To evaluate a model's performance, use -``` -./train_net.py \ - --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \ - --eval-only MODEL.WEIGHTS /path/to/checkpoint_file -``` -For more options, see `./train_net.py -h`. - -### Use Detectron2 APIs in Your Code - -See our [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5) -to learn how to use detectron2 APIs to: -1. run inference with an existing model -2. train a builtin model on a custom dataset - -See [detectron2/projects](https://github.com/facebookresearch/detectron2/tree/main/projects) -for more ways to build your project on detectron2. diff --git a/preprocess/detectron2/INSTALL.md b/preprocess/detectron2/INSTALL.md deleted file mode 100644 index f522e6f624372f39ee5366f5b032c0cd1ebcf5c8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/INSTALL.md +++ /dev/null @@ -1,261 +0,0 @@ -## Installation - -### Requirements -- Linux or macOS with Python ≥ 3.7 -- PyTorch ≥ 1.8 and [torchvision](https://github.com/pytorch/vision/) that matches the PyTorch installation. - Install them together at [pytorch.org](https://pytorch.org) to make sure of this -- OpenCV is optional but needed by demo and visualization - - -### Build Detectron2 from Source - -gcc & g++ ≥ 5.4 are required. [ninja](https://ninja-build.org/) is optional but recommended for faster build. -After having them, run: -``` -python -m pip install 'git+https://github.com/facebookresearch/detectron2.git' -# (add --user if you don't have permission) - -# Or, to install it from a local clone: -git clone https://github.com/facebookresearch/detectron2.git -python -m pip install -e detectron2 - -# On macOS, you may need to prepend the above commands with a few environment variables: -CC=clang CXX=clang++ ARCHFLAGS="-arch x86_64" python -m pip install ... -``` - -To __rebuild__ detectron2 that's built from a local clone, use `rm -rf build/ **/*.so` to clean the -old build first. You often need to rebuild detectron2 after reinstalling PyTorch. - -### Install Pre-Built Detectron2 (Linux only) - -Choose from this table to install [v0.6 (Oct 2021)](https://github.com/facebookresearch/detectron2/releases): - -
CUDA torch 1.10torch 1.9torch 1.8
11.3
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html
-
11.1
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.10/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.9/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.8/index.html
-
10.2
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.10/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.9/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.8/index.html
-
10.1
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.8/index.html
-
cpu
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.10/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.9/index.html
-
install
python -m pip install detectron2 -f \
-  https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.8/index.html
-
- -Note that: -1. The pre-built packages have to be used with corresponding version of CUDA and the official package of PyTorch. - Otherwise, please build detectron2 from source. -2. New packages are released every few months. Therefore, packages may not contain latest features in the main - branch and may not be compatible with the main branch of a research project that uses detectron2 - (e.g. those in [projects](projects)). - -### Common Installation Issues - -Click each issue for its solutions: - -
- -Undefined symbols that looks like "TH..","at::Tensor...","torch..." - -
- -This usually happens when detectron2 or torchvision is not -compiled with the version of PyTorch you're running. - -If the error comes from a pre-built torchvision, uninstall torchvision and pytorch and reinstall them -following [pytorch.org](http://pytorch.org). So the versions will match. - -If the error comes from a pre-built detectron2, check [release notes](https://github.com/facebookresearch/detectron2/releases), -uninstall and reinstall the correct pre-built detectron2 that matches pytorch version. - -If the error comes from detectron2 or torchvision that you built manually from source, -remove files you built (`build/`, `**/*.so`) and rebuild it so it can pick up the version of pytorch currently in your environment. - -If the above instructions do not resolve this problem, please provide an environment (e.g. a dockerfile) that can reproduce the issue. -
- -
- -Missing torch dynamic libraries, OR segmentation fault immediately when using detectron2. - -This usually happens when detectron2 or torchvision is not -compiled with the version of PyTorch you're running. See the previous common issue for the solution. -
- -
- -Undefined C++ symbols (e.g. "GLIBCXX..") or C++ symbols not found. - -
-Usually it's because the library is compiled with a newer C++ compiler but run with an old C++ runtime. - -This often happens with old anaconda. -It may help to run `conda update libgcc` to upgrade its runtime. - -The fundamental solution is to avoid the mismatch, either by compiling using older version of C++ -compiler, or run the code with proper C++ runtime. -To run the code with a specific C++ runtime, you can use environment variable `LD_PRELOAD=/path/to/libstdc++.so`. - -
- -
- -"nvcc not found" or "Not compiled with GPU support" or "Detectron2 CUDA Compiler: not available". - -
-CUDA is not found when building detectron2. -You should make sure - -``` -python -c 'import torch; from torch.utils.cpp_extension import CUDA_HOME; print(torch.cuda.is_available(), CUDA_HOME)' -``` - -print `(True, a directory with cuda)` at the time you build detectron2. - -Most models can run inference (but not training) without GPU support. To use CPUs, set `MODEL.DEVICE='cpu'` in the config. -
- -
- -"invalid device function" or "no kernel image is available for execution". - -
-Two possibilities: - -* You build detectron2 with one version of CUDA but run it with a different version. - - To check whether it is the case, - use `python -m detectron2.utils.collect_env` to find out inconsistent CUDA versions. - In the output of this command, you should expect "Detectron2 CUDA Compiler", "CUDA_HOME", "PyTorch built with - CUDA" - to contain cuda libraries of the same version. - - When they are inconsistent, - you need to either install a different build of PyTorch (or build by yourself) - to match your local CUDA installation, or install a different version of CUDA to match PyTorch. - -* PyTorch/torchvision/Detectron2 is not built for the correct GPU SM architecture (aka. compute capability). - - The architecture included by PyTorch/detectron2/torchvision is available in the "architecture flags" in - `python -m detectron2.utils.collect_env`. It must include - the architecture of your GPU, which can be found at [developer.nvidia.com/cuda-gpus](https://developer.nvidia.com/cuda-gpus). - - If you're using pre-built PyTorch/detectron2/torchvision, they have included support for most popular GPUs already. - If not supported, you need to build them from source. - - When building detectron2/torchvision from source, they detect the GPU device and build for only the device. - This means the compiled code may not work on a different GPU device. - To recompile them for the correct architecture, remove all installed/compiled files, - and rebuild them with the `TORCH_CUDA_ARCH_LIST` environment variable set properly. - For example, `export TORCH_CUDA_ARCH_LIST="6.0;7.0"` makes it compile for both P100s and V100s. -
- -
- -Undefined CUDA symbols; Cannot open libcudart.so - -
-The version of NVCC you use to build detectron2 or torchvision does -not match the version of CUDA you are running with. -This often happens when using anaconda's CUDA runtime. - -Use `python -m detectron2.utils.collect_env` to find out inconsistent CUDA versions. -In the output of this command, you should expect "Detectron2 CUDA Compiler", "CUDA_HOME", "PyTorch built with - CUDA" -to contain cuda libraries of the same version. - -When they are inconsistent, -you need to either install a different build of PyTorch (or build by yourself) -to match your local CUDA installation, or install a different version of CUDA to match PyTorch. -
- - -
- -C++ compilation errors from NVCC / NVRTC, or "Unsupported gpu architecture" - -
-A few possibilities: - -1. Local CUDA/NVCC version has to match the CUDA version of your PyTorch. Both can be found in `python collect_env.py` - (download from [here](./detectron2/utils/collect_env.py)). - When they are inconsistent, you need to either install a different build of PyTorch (or build by yourself) - to match your local CUDA installation, or install a different version of CUDA to match PyTorch. - -2. Local CUDA/NVCC version shall support the SM architecture (a.k.a. compute capability) of your GPU. - The capability of your GPU can be found at [developer.nvidia.com/cuda-gpus](https://developer.nvidia.com/cuda-gpus). - The capability supported by NVCC is listed at [here](https://gist.github.com/ax3l/9489132). - If your NVCC version is too old, this can be workaround by setting environment variable - `TORCH_CUDA_ARCH_LIST` to a lower, supported capability. - -3. The combination of NVCC and GCC you use is incompatible. You need to change one of their versions. - See [here](https://gist.github.com/ax3l/9489132) for some valid combinations. - Notably, CUDA<=10.1.105 doesn't support GCC>7.3. - - The CUDA/GCC version used by PyTorch can be found by `print(torch.__config__.show())`. - -
- - -
- -"ImportError: cannot import name '_C'". - -
-Please build and install detectron2 following the instructions above. - -Or, if you are running code from detectron2's root directory, `cd` to a different one. -Otherwise you may not import the code that you installed. -
- - -
- -Any issue on windows. - -
- -Detectron2 is continuously built on windows with [CircleCI](https://app.circleci.com/pipelines/github/facebookresearch/detectron2?branch=main). -However we do not provide official support for it. -PRs that improves code compatibility on windows are welcome. -
- -
- -ONNX conversion segfault after some "TraceWarning". - -
-The ONNX package is compiled with a too old compiler. - -Please build and install ONNX from its source code using a compiler -whose version is closer to what's used by PyTorch (available in `torch.__config__.show()`). -
- - -
- -"library not found for -lstdc++" on older version of MacOS - -
- -See [this stackoverflow answer](https://stackoverflow.com/questions/56083725/macos-build-issues-lstdc-not-found-while-building-python-package). - -
- - -### Installation inside specific environments: - -* __Colab__: see our [Colab Tutorial](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5) - which has step-by-step instructions. - -* __Docker__: The official [Dockerfile](docker) installs detectron2 with a few simple commands. diff --git a/preprocess/detectron2/LICENSE b/preprocess/detectron2/LICENSE deleted file mode 100644 index cd1b070674331757508398d99c830664dce6eaec..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, -and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by -the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all -other entities that control, are controlled by, or are under common -control with that entity. For the purposes of this definition, -"control" means (i) the power, direct or indirect, to cause the -direction or management of such entity, whether by contract or -otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity -exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation -source, and configuration files. - -"Object" form shall mean any form resulting from mechanical -transformation or translation of a Source form, including but -not limited to compiled object code, generated documentation, -and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or -Object form, made available under the License, as indicated by a -copyright notice that is included in or attached to the work -(an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object -form, that is based on (or derived from) the Work and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. For the purposes -of this License, Derivative Works shall not include works that remain -separable from, or merely link (or bind by name) to the interfaces of, -the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including -the original version of the Work and any modifications or additions -to that Work or Derivative Works thereof, that is intentionally -submitted to Licensor for inclusion in the Work by the copyright owner -or by an individual or Legal Entity authorized to submit on behalf of -the copyright owner. For the purposes of this definition, "submitted" -means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, -and issue tracking systems that are managed by, or on behalf of, the -Licensor for the purpose of discussing and improving the Work, but -excluding communication that is conspicuously marked or otherwise -designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity -on behalf of whom a Contribution has been received by Licensor and -subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the -Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -(except as stated in this section) patent license to make, have made, -use, offer to sell, sell, import, and otherwise transfer the Work, -where such license applies only to those patent claims licensable -by such Contributor that are necessarily infringed by their -Contribution(s) alone or by combination of their Contribution(s) -with the Work to which such Contribution(s) was submitted. If You -institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work -or a Contribution incorporated within the Work constitutes direct -or contributory patent infringement, then any patent licenses -granted to You under this License for that Work shall terminate -as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the -Work or Derivative Works thereof in any medium, with or without -modifications, and in Source or Object form, provided that You -meet the following conditions: - -(a) You must give any other recipients of the Work or -Derivative Works a copy of this License; and - -(b) You must cause any modified files to carry prominent notices -stating that You changed the files; and - -(c) You must retain, in the Source form of any Derivative Works -that You distribute, all copyright, patent, trademark, and -attribution notices from the Source form of the Work, -excluding those notices that do not pertain to any part of -the Derivative Works; and - -(d) If the Work includes a "NOTICE" text file as part of its -distribution, then any Derivative Works that You distribute must -include a readable copy of the attribution notices contained -within such NOTICE file, excluding those notices that do not -pertain to any part of the Derivative Works, in at least one -of the following places: within a NOTICE text file distributed -as part of the Derivative Works; within the Source form or -documentation, if provided along with the Derivative Works; or, -within a display generated by the Derivative Works, if and -wherever such third-party notices normally appear. The contents -of the NOTICE file are for informational purposes only and -do not modify the License. You may add Your own attribution -notices within Derivative Works that You distribute, alongside -or as an addendum to the NOTICE text from the Work, provided -that such additional attribution notices cannot be construed -as modifying the License. - -You may add Your own copyright statement to Your modifications and -may provide additional or different license terms and conditions -for use, reproduction, or distribution of Your modifications, or -for any such Derivative Works as a whole, provided Your use, -reproduction, and distribution of the Work otherwise complies with -the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, -any Contribution intentionally submitted for inclusion in the Work -by You to the Licensor shall be under the terms and conditions of -this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify -the terms of any separate license agreement you may have executed -with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade -names, trademarks, service marks, or product names of the Licensor, -except as required for reasonable and customary use in describing the -origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or -agreed to in writing, Licensor provides the Work (and each -Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied, including, without limitation, any warranties or conditions -of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -PARTICULAR PURPOSE. You are solely responsible for determining the -appropriateness of using or redistributing the Work and assume any -risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, -whether in tort (including negligence), contract, or otherwise, -unless required by applicable law (such as deliberate and grossly -negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, -incidental, or consequential damages of any character arising as a -result of this License or out of the use or inability to use the -Work (including but not limited to damages for loss of goodwill, -work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses), even if such Contributor -has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing -the Work or Derivative Works thereof, You may choose to offer, -and charge a fee for, acceptance of support, warranty, indemnity, -or other liability obligations and/or rights consistent with this -License. However, in accepting such obligations, You may act only -on Your own behalf and on Your sole responsibility, not on behalf -of any other Contributor, and only if You agree to indemnify, -defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason -of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - -To apply the Apache License to your work, attach the following -boilerplate notice, with the fields enclosed by brackets "[]" -replaced with your own identifying information. (Don't include -the brackets!) The text should be enclosed in the appropriate -comment syntax for the file format. We also recommend that a -file or class name and description of purpose be included on the -same "printed page" as the copyright notice for easier -identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/preprocess/detectron2/MODEL_ZOO.md b/preprocess/detectron2/MODEL_ZOO.md deleted file mode 100644 index 69db2728563c680e89a0d5d3e6ba272b8d78bdbd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/MODEL_ZOO.md +++ /dev/null @@ -1,1052 +0,0 @@ -# Detectron2 Model Zoo and Baselines - -## Introduction - -This file documents a large collection of baselines trained -with detectron2 in Sep-Oct, 2019. -All numbers were obtained on [Big Basin](https://engineering.fb.com/data-center-engineering/introducing-big-basin-our-next-generation-ai-hardware/) -servers with 8 NVIDIA V100 GPUs & NVLink. The speed numbers are periodically updated with latest PyTorch/CUDA/cuDNN versions. -You can access these models from code using [detectron2.model_zoo](https://detectron2.readthedocs.io/modules/model_zoo.html) APIs. - -In addition to these official baseline models, you can find more models in [projects/](projects/). - -#### How to Read the Tables -* The "Name" column contains a link to the config file. Models can be reproduced using `tools/train_net.py` with the corresponding yaml config file, - or `tools/lazyconfig_train_net.py` for python config files. -* Training speed is averaged across the entire training. - We keep updating the speed with latest version of detectron2/pytorch/etc., - so they might be different from the `metrics` file. - Training speed for multi-machine jobs is not provided. -* Inference speed is measured by `tools/train_net.py --eval-only`, or [inference_on_dataset()](https://detectron2.readthedocs.io/modules/evaluation.html#detectron2.evaluation.inference_on_dataset), - with batch size 1 in detectron2 directly. - Measuring it with custom code may introduce other overhead. - Actual deployment in production should in general be faster than the given inference - speed due to more optimizations. -* The *model id* column is provided for ease of reference. - To check downloaded file integrity, any model on this page contains its md5 prefix in its file name. -* Training curves and other statistics can be found in `metrics` for each model. - -#### Common Settings for COCO Models -* All COCO models were trained on `train2017` and evaluated on `val2017`. -* The default settings are __not directly comparable__ with Detectron's standard settings. - For example, our default training data augmentation uses scale jittering in addition to horizontal flipping. - - To make fair comparisons with Detectron's settings, see - [Detectron1-Comparisons](configs/Detectron1-Comparisons/) for accuracy comparison, - and [benchmarks](https://detectron2.readthedocs.io/notes/benchmarks.html) - for speed comparison. -* For Faster/Mask R-CNN, we provide baselines based on __3 different backbone combinations__: - * __FPN__: Use a ResNet+FPN backbone with standard conv and FC heads for mask and box prediction, - respectively. It obtains the best - speed/accuracy tradeoff, but the other two are still useful for research. - * __C4__: Use a ResNet conv4 backbone with conv5 head. The original baseline in the Faster R-CNN paper. - * __DC5__ (Dilated-C5): Use a ResNet conv5 backbone with dilations in conv5, and standard conv and FC heads - for mask and box prediction, respectively. - This is used by the Deformable ConvNet paper. -* Most models are trained with the 3x schedule (~37 COCO epochs). - Although 1x models are heavily under-trained, we provide some ResNet-50 models with the 1x (~12 COCO epochs) - training schedule for comparison when doing quick research iteration. - -#### ImageNet Pretrained Models - -It's common to initialize from backbone models pre-trained on ImageNet classification tasks. The following backbone models are available: - -* [R-50.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/MSRA/R-50.pkl): converted copy of [MSRA's original ResNet-50](https://github.com/KaimingHe/deep-residual-networks) model. -* [R-101.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/MSRA/R-101.pkl): converted copy of [MSRA's original ResNet-101](https://github.com/KaimingHe/deep-residual-networks) model. -* [X-101-32x8d.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/FAIR/X-101-32x8d.pkl): ResNeXt-101-32x8d model trained with Caffe2 at FB. -* [R-50.pkl (torchvision)](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/torchvision/R-50.pkl): converted copy of [torchvision's ResNet-50](https://pytorch.org/docs/stable/torchvision/models.html#torchvision.models.resnet50) model. - More details can be found in [the conversion script](tools/convert-torchvision-to-d2.py). - -Note that the above models have __different__ format from those provided in Detectron: we do not fuse BatchNorm into an affine layer. -Pretrained models in Detectron's format can still be used. For example: -* [X-152-32x8d-IN5k.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/25093814/X-152-32x8d-IN5k.pkl): - ResNeXt-152-32x8d model trained on ImageNet-5k with Caffe2 at FB (see ResNeXt paper for details on ImageNet-5k). -* [R-50-GN.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/47261647/R-50-GN.pkl): - ResNet-50 with Group Normalization. -* [R-101-GN.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/47592356/R-101-GN.pkl): - ResNet-101 with Group Normalization. - -These models require slightly different settings regarding normalization and architecture. See the model zoo configs for reference. - -#### License - -All models available for download through this document are licensed under the -[Creative Commons Attribution-ShareAlike 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/). - -### COCO Object Detection Baselines - -#### Faster R-CNN: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
model iddownload
R50-C41x0.5510.1024.835.7137257644model | metrics
R50-DC51x0.3800.0685.037.3137847829model | metrics
R50-FPN1x0.2100.0383.037.9137257794model | metrics
R50-C43x0.5430.1044.838.4137849393model | metrics
R50-DC53x0.3780.0705.039.0137849425model | metrics
R50-FPN3x0.2090.0383.040.2137849458model | metrics
R101-C43x0.6190.1395.941.1138204752model | metrics
R101-DC53x0.4520.0866.140.6138204841model | metrics
R101-FPN3x0.2860.0514.142.0137851257model | metrics
X101-FPN3x0.6380.0986.743.0139173657model | metrics
- -#### RetinaNet: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
model iddownload
R501x0.2050.0414.137.4190397773model | metrics
R503x0.2050.0414.138.7190397829model | metrics
R1013x0.2910.0545.240.4190397697model | metrics
- - -#### RPN & Fast R-CNN: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
prop.
AR
model iddownload
RPN R50-C41x0.1300.0341.551.6137258005model | metrics
RPN R50-FPN1x0.1860.0322.758.0137258492model | metrics
Fast R-CNN R50-FPN1x0.1400.0292.637.8137635226model | metrics
- -### COCO Instance Segmentation Baselines with Mask R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
R50-C41x0.5840.1105.236.832.2137259246model | metrics
R50-DC51x0.4710.0766.538.334.2137260150model | metrics
R50-FPN1x0.2610.0433.438.635.2137260431model | metrics
R50-C43x0.5750.1115.239.834.4137849525model | metrics
R50-DC53x0.4700.0766.540.035.9137849551model | metrics
R50-FPN3x0.2610.0433.441.037.2137849600model | metrics
R101-C43x0.6520.1456.342.636.7138363239model | metrics
R101-DC53x0.5450.0927.641.937.3138363294model | metrics
R101-FPN3x0.3400.0564.642.938.6138205316model | metrics
X101-FPN3x0.6900.1037.244.339.5139653917model | metrics
- - - -#### New baselines using Large-Scale Jitter and Longer Training Schedule - -The following baselines of COCO Instance Segmentation with Mask R-CNN are generated -using a longer training schedule and large-scale jitter as described in Google's -[Simple Copy-Paste Data Augmentation](https://arxiv.org/pdf/2012.07177.pdf) paper. These -models are trained from scratch using random initialization. These baselines exceed the -previous Mask R-CNN baselines. - -In the following table, one epoch consists of training on 118000 COCO images. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nameepochstrain
time
(s/im)
inference
time
(s/im)
box
AP
mask
AP
model iddownload
R50-FPN1000.3760.06944.640.342047764model | metrics
R50-FPN2000.3760.06946.341.742047638model | metrics
R50-FPN4000.3760.06947.442.542019571model | metrics
R101-FPN1000.5180.07346.441.642025812model | metrics
R101-FPN2000.5180.07348.043.142131867model | metrics
R101-FPN4000.5180.07348.943.742073830model | metrics
regnetx_4gf_dds_FPN1000.4740.07146.041.342047771model | metrics
regnetx_4gf_dds_FPN2000.4740.07148.143.142132721model | metrics
regnetx_4gf_dds_FPN4000.4740.07148.643.542025447model | metrics
regnety_4gf_dds_FPN1000.4870.07346.141.642047784model | metrics
regnety_4gf_dds_FPN2000.4870.07247.843.042047642model | metrics
regnety_4gf_dds_FPN4000.4870.07248.243.342045954model | metrics
- -### COCO Person Keypoint Detection Baselines with Keypoint R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
kp.
AP
model iddownload
R50-FPN1x0.3150.0725.053.664.0137261548model | metrics
R50-FPN3x0.3160.0665.055.465.5137849621model | metrics
R101-FPN3x0.3900.0766.156.466.1138363331model | metrics
X101-FPN3x0.7380.1218.757.366.0139686956model | metrics
- -### COCO Panoptic Segmentation Baselines with Panoptic FPN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
PQmodel iddownload
R50-FPN1x0.3040.0534.837.634.739.4139514544model | metrics
R50-FPN3x0.3020.0534.840.036.541.5139514569model | metrics
R101-FPN3x0.3920.0666.042.438.543.0139514519model | metrics
- - -### LVIS Instance Segmentation Baselines with Mask R-CNN - -Mask R-CNN baselines on the [LVIS dataset](https://lvisdataset.org), v0.5. -These baselines are described in Table 3(c) of the [LVIS paper](https://arxiv.org/abs/1908.03195). - -NOTE: the 1x schedule here has the same amount of __iterations__ as the COCO 1x baselines. -They are roughly 24 epochs of LVISv0.5 data. -The final results of these configs have large variance across different runs. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
R50-FPN1x0.2920.1077.123.624.4144219072model | metrics
R101-FPN1x0.3710.1147.825.625.9144219035model | metrics
X101-FPN1x0.7120.15110.226.727.1144219108model | metrics
- - - -### Cityscapes & Pascal VOC Baselines - -Simple baselines for -* Mask R-CNN on Cityscapes instance segmentation (initialized from COCO pre-training, then trained on Cityscapes fine annotations only) -* Faster R-CNN on PASCAL VOC object detection (trained on VOC 2007 train+val + VOC 2012 train+val, tested on VOC 2007 using 11-point interpolated AP) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nametrain
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
box
AP50
mask
AP
model iddownload
R50-FPN, Cityscapes0.2400.0784.436.5142423278model | metrics
R50-C4, VOC0.5370.0814.851.980.3142202221model | metrics
- - - -### Other Settings - -Ablations for Deformable Conv and Cascade R-CNN: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
Baseline R50-FPN1x0.2610.0433.438.635.2137260431model | metrics
Deformable Conv1x0.3420.0483.541.537.5138602867model | metrics
Cascade R-CNN1x0.3170.0524.042.136.4138602847model | metrics
Baseline R50-FPN3x0.2610.0433.441.037.2137849600model | metrics
Deformable Conv3x0.3490.0473.542.738.5144998336model | metrics
Cascade R-CNN3x0.3280.0534.044.338.5144998488model | metrics
- - -Ablations for normalization methods, and a few models trained from scratch following [Rethinking ImageNet Pre-training](https://arxiv.org/abs/1811.08883). -(Note: The baseline uses `2fc` head while the others use [`4conv1fc` head](https://arxiv.org/abs/1803.08494)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
Baseline R50-FPN3x0.2610.0433.441.037.2137849600model | metrics
GN3x0.3090.0605.642.638.6138602888model | metrics
SyncBN3x0.3450.0535.541.937.8169527823model | metrics
GN (from scratch)3x0.3380.0617.239.936.6138602908model | metrics
GN (from scratch)9xN/A0.0617.243.739.6183808979model | metrics
SyncBN (from scratch)9xN/A0.0557.243.639.3184226666model | metrics
- - -A few very large models trained for a long time, for demo purposes. They are trained using multiple machines: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nameinference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
PQmodel iddownload
Panoptic FPN R1010.09811.447.441.346.1139797668model | metrics
Mask R-CNN X1520.23415.150.244.018131413model | metrics
above + test-time aug.51.945.9
diff --git a/preprocess/detectron2/README.md b/preprocess/detectron2/README.md deleted file mode 100644 index 75db3c52f216dbcff9a4730ff0fa139853fc4670..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/README.md +++ /dev/null @@ -1,68 +0,0 @@ - - - - Support Ukraine - Help Provide Humanitarian Aid to Ukraine. - - -Detectron2 is Facebook AI Research's next generation library -that provides state-of-the-art detection and segmentation algorithms. -It is the successor of -[Detectron](https://github.com/facebookresearch/Detectron/) -and [maskrcnn-benchmark](https://github.com/facebookresearch/maskrcnn-benchmark/). -It supports a number of computer vision research projects and production applications in Facebook. - -
- -
-
- -## Learn More about Detectron2 - -Explain Like I’m 5: Detectron2 | Using Machine Learning with Detectron2 -:-------------------------:|:-------------------------: -[![Explain Like I’m 5: Detectron2](https://img.youtube.com/vi/1oq1Ye7dFqc/0.jpg)](https://www.youtube.com/watch?v=1oq1Ye7dFqc) | [![Using Machine Learning with Detectron2](https://img.youtube.com/vi/eUSgtfK4ivk/0.jpg)](https://www.youtube.com/watch?v=eUSgtfK4ivk) - -## What's New -* Includes new capabilities such as panoptic segmentation, Densepose, Cascade R-CNN, rotated bounding boxes, PointRend, - DeepLab, ViTDet, MViTv2 etc. -* Used as a library to support building [research projects](projects/) on top of it. -* Models can be exported to TorchScript format or Caffe2 format for deployment. -* It [trains much faster](https://detectron2.readthedocs.io/notes/benchmarks.html). - -See our [blog post](https://ai.facebook.com/blog/-detectron2-a-pytorch-based-modular-object-detection-library-/) -to see more demos and learn about detectron2. - -## Installation - -See [installation instructions](https://detectron2.readthedocs.io/tutorials/install.html). - -## Getting Started - -See [Getting Started with Detectron2](https://detectron2.readthedocs.io/tutorials/getting_started.html), -and the [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5) -to learn about basic usage. - -Learn more at our [documentation](https://detectron2.readthedocs.org). -And see [projects/](projects/) for some projects that are built on top of detectron2. - -## Model Zoo and Baselines - -We provide a large set of baseline results and trained models available for download in the [Detectron2 Model Zoo](MODEL_ZOO.md). - -## License - -Detectron2 is released under the [Apache 2.0 license](LICENSE). - -## Citing Detectron2 - -If you use Detectron2 in your research or wish to refer to the baseline results published in the [Model Zoo](MODEL_ZOO.md), please use the following BibTeX entry. - -```BibTeX -@misc{wu2019detectron2, - author = {Yuxin Wu and Alexander Kirillov and Francisco Massa and - Wan-Yen Lo and Ross Girshick}, - title = {Detectron2}, - howpublished = {\url{https://github.com/facebookresearch/detectron2}}, - year = {2019} -} -``` diff --git a/preprocess/detectron2/configs/Base-RCNN-C4.yaml b/preprocess/detectron2/configs/Base-RCNN-C4.yaml deleted file mode 100644 index fbf34a0ea57a587e09997edd94c4012d69d0b6ad..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Base-RCNN-C4.yaml +++ /dev/null @@ -1,18 +0,0 @@ -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - RPN: - PRE_NMS_TOPK_TEST: 6000 - POST_NMS_TOPK_TEST: 1000 - ROI_HEADS: - NAME: "Res5ROIHeads" -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/configs/Base-RCNN-DilatedC5.yaml b/preprocess/detectron2/configs/Base-RCNN-DilatedC5.yaml deleted file mode 100644 index c0d6d16bdaf532f09e4976f0aa240a49e748da27..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Base-RCNN-DilatedC5.yaml +++ /dev/null @@ -1,31 +0,0 @@ -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - RESNETS: - OUT_FEATURES: ["res5"] - RES5_DILATION: 2 - RPN: - IN_FEATURES: ["res5"] - PRE_NMS_TOPK_TEST: 6000 - POST_NMS_TOPK_TEST: 1000 - ROI_HEADS: - NAME: "StandardROIHeads" - IN_FEATURES: ["res5"] - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_FC: 2 - POOLER_RESOLUTION: 7 - ROI_MASK_HEAD: - NAME: "MaskRCNNConvUpsampleHead" - NUM_CONV: 4 - POOLER_RESOLUTION: 14 -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/configs/Base-RCNN-FPN.yaml b/preprocess/detectron2/configs/Base-RCNN-FPN.yaml deleted file mode 100644 index 3e020f2e7b2f26765be317f907126a1556621abf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Base-RCNN-FPN.yaml +++ /dev/null @@ -1,42 +0,0 @@ -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - BACKBONE: - NAME: "build_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res2", "res3", "res4", "res5"] - FPN: - IN_FEATURES: ["res2", "res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: [[32], [64], [128], [256], [512]] # One size for each in feature map - ASPECT_RATIOS: [[0.5, 1.0, 2.0]] # Three aspect ratios (same for all in feature maps) - RPN: - IN_FEATURES: ["p2", "p3", "p4", "p5", "p6"] - PRE_NMS_TOPK_TRAIN: 2000 # Per FPN level - PRE_NMS_TOPK_TEST: 1000 # Per FPN level - # Detectron1 uses 2000 proposals per-batch, - # (See "modeling/rpn/rpn_outputs.py" for details of this legacy issue) - # which is approximately 1000 proposals per-image since the default batch size for FPN is 2. - POST_NMS_TOPK_TRAIN: 1000 - POST_NMS_TOPK_TEST: 1000 - ROI_HEADS: - NAME: "StandardROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_FC: 2 - POOLER_RESOLUTION: 7 - ROI_MASK_HEAD: - NAME: "MaskRCNNConvUpsampleHead" - NUM_CONV: 4 - POOLER_RESOLUTION: 14 -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/configs/Base-RetinaNet.yaml b/preprocess/detectron2/configs/Base-RetinaNet.yaml deleted file mode 100644 index 8b45b982bbf84b34d2a6a172ab0a946b1029f7c8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Base-RetinaNet.yaml +++ /dev/null @@ -1,25 +0,0 @@ -MODEL: - META_ARCHITECTURE: "RetinaNet" - BACKBONE: - NAME: "build_retinanet_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: !!python/object/apply:eval ["[[x, x * 2**(1.0/3), x * 2**(2.0/3) ] for x in [32, 64, 128, 256, 512 ]]"] - FPN: - IN_FEATURES: ["res3", "res4", "res5"] - RETINANET: - IOU_THRESHOLDS: [0.4, 0.5] - IOU_LABELS: [0, -1, 1] - SMOOTH_L1_LOSS_BETA: 0.0 -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.01 # Note that RetinaNet uses a different default learning rate - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/configs/COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index 773ac10e87c626760d00d831bf664ce9ff073c49..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,17 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - LOAD_PROPOSALS: True - RESNETS: - DEPTH: 50 - PROPOSAL_GENERATOR: - NAME: "PrecomputedProposals" -DATASETS: - TRAIN: ("coco_2017_train",) - PROPOSAL_FILES_TRAIN: ("detectron2://COCO-Detection/rpn_R_50_FPN_1x/137258492/coco_2017_train_box_proposals_21bc3a.pkl", ) - TEST: ("coco_2017_val",) - PROPOSAL_FILES_TEST: ("detectron2://COCO-Detection/rpn_R_50_FPN_1x/137258492/coco_2017_val_box_proposals_ee0dad.pkl", ) -DATALOADER: - # proposals are part of the dataset_dicts, and take a lot of RAM - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_C4_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_C4_3x.yaml deleted file mode 100644 index db142cd671c1841b4f64cf130bee7f7954ecdd28..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: False - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_DC5_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_DC5_3x.yaml deleted file mode 100644 index bceb6b343618d8cd9a6c414ff9eb86ab31cc230a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_DC5_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: False - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml deleted file mode 100644 index 57a098f53ee8c54ecfa354cc96efefd890dc1b72..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: False - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml deleted file mode 100644 index f96130105c3ba6ab393e0932870903875f5cb732..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_3x.yaml deleted file mode 100644 index bc51bce390a85ee3529ffdcebde05748e1646be0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_1x.yaml deleted file mode 100644 index 0fe96f57febdac5790ea4cec168fa4b97ac4807a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_3x.yaml deleted file mode 100644 index 33fadeb87d1ef67ab2b55926b9a652ab4ac4a27d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_DC5_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index 3262019a1211b910d3b371569199ed1afaacf6a4..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml deleted file mode 100644 index 41395182bf5c9dd8ab1241c4414068817298d554..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml deleted file mode 100644 index 9c9b5ab77157baa581d90d9847c045c19ed6ffa3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - MASK_ON: False - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/fcos_R_50_FPN_1x.py b/preprocess/detectron2/configs/COCO-Detection/fcos_R_50_FPN_1x.py deleted file mode 100644 index 86f83c68786f5995c462ade5f3067072d69f047e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/fcos_R_50_FPN_1x.py +++ /dev/null @@ -1,11 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.fcos import model -from ..common.train import train - -dataloader.train.mapper.use_instance_mask = False -optimizer.lr = 0.01 - -model.backbone.bottom_up.freeze_at = 2 -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_101_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/retinanet_R_101_FPN_3x.yaml deleted file mode 100644 index 4abb1b9a547957aa6afc0b29129e00f89cf98d59..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_101_FPN_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "../Base-RetinaNet.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.py b/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.py deleted file mode 100644 index 43057a8eeed38c78183e26d21b74261eb4dbc1b9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.py +++ /dev/null @@ -1,11 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.retinanet import model -from ..common.train import train - -dataloader.train.mapper.use_instance_mask = False -model.backbone.bottom_up.freeze_at = 2 -optimizer.lr = 0.01 - -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.yaml deleted file mode 100644 index 4a24ce3a9a108a8792e18c8aabfb7b712f0d3725..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_1x.yaml +++ /dev/null @@ -1,5 +0,0 @@ -_BASE_: "../Base-RetinaNet.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_3x.yaml deleted file mode 100644 index 3b5412d4a7aef1d6c3f7c1e34f94007de639b833..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/retinanet_R_50_FPN_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "../Base-RetinaNet.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_C4_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_C4_1x.yaml deleted file mode 100644 index e04821156b0376ba5215d5ce5b7010a36b43e6a1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_C4_1x.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - META_ARCHITECTURE: "ProposalNetwork" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 - RPN: - PRE_NMS_TOPK_TEST: 12000 - POST_NMS_TOPK_TEST: 2000 diff --git a/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_FPN_1x.yaml deleted file mode 100644 index dc9c95203b1c3c9cd9bb9876bb8d9a5dd9b31d9a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Detection/rpn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "ProposalNetwork" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 - RPN: - POST_NMS_TOPK_TEST: 2000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x.yaml deleted file mode 100644 index 1a94cc45a0f2aaa8c92e14871c553b736545e327..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: True - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x.yaml deleted file mode 100644 index 67b70cf4be8c19f5dc735b6f55a8690698f34b69..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: True - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml deleted file mode 100644 index 1935a302d2d0fa7f69553b3fd50b5a7082c6c0d1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: True - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.py b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.py deleted file mode 100644 index 22016be150df4abbe912700d7ca29f8b7b72554a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..common.train import train -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.mask_rcnn_c4 import model - -model.backbone.freeze_at = 2 -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.yaml deleted file mode 100644 index a9aeb4eac38026dbb867e799f9fd3a8d8eb3af80..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml deleted file mode 100644 index 38ed867d897dfec839cbcf11a2e2dc8abb92f07c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x.yaml deleted file mode 100644 index b13eefab2a049c48d94d5051c82ceb6dbde40579..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x.yaml deleted file mode 100644 index d401016358f967f6619d88b1c9bd5673a1cdeba8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-DilatedC5.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.py b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.py deleted file mode 100644 index 40844ddeb8d47ff58a6af49ab35bad84e14f5721..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.mask_rcnn_fpn import model -from ..common.train import train - -model.backbone.bottom_up.freeze_at = 2 -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index d50fb866ca7811a87b42555c7213f88e00bf6df1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x_giou.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x_giou.yaml deleted file mode 100644 index bec680ee17a474fefe527b7b79d26266e75c09f0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x_giou.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - RPN: - BBOX_REG_LOSS_TYPE: "giou" - BBOX_REG_LOSS_WEIGHT: 2.0 - ROI_BOX_HEAD: - BBOX_REG_LOSS_TYPE: "giou" - BBOX_REG_LOSS_WEIGHT: 10.0 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml deleted file mode 100644 index be7d06b8e0f032ee7fcaabd7c122158518489fd2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml deleted file mode 100644 index d14c63f74383bfc308750f51d51344398b02a239..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - MASK_ON: True - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnetx_4gf_dds_fpn_1x.py b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnetx_4gf_dds_fpn_1x.py deleted file mode 100644 index d7bbdd7d00505f1e51154379c99ab621cb648a6d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnetx_4gf_dds_fpn_1x.py +++ /dev/null @@ -1,34 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.mask_rcnn_fpn import model -from ..common.train import train - -from detectron2.config import LazyCall as L -from detectron2.modeling.backbone import RegNet -from detectron2.modeling.backbone.regnet import SimpleStem, ResBottleneckBlock - - -# Replace default ResNet with RegNetX-4GF from the DDS paper. Config source: -# https://github.com/facebookresearch/pycls/blob/2c152a6e5d913e898cca4f0a758f41e6b976714d/configs/dds_baselines/regnetx/RegNetX-4.0GF_dds_8gpu.yaml#L4-L9 # noqa -model.backbone.bottom_up = L(RegNet)( - stem_class=SimpleStem, - stem_width=32, - block_class=ResBottleneckBlock, - depth=23, - w_a=38.65, - w_0=96, - w_m=2.43, - group_width=40, - freeze_at=2, - norm="FrozenBN", - out_features=["s1", "s2", "s3", "s4"], -) -model.pixel_std = [57.375, 57.120, 58.395] - -optimizer.weight_decay = 5e-5 -train.init_checkpoint = ( - "https://dl.fbaipublicfiles.com/pycls/dds_baselines/160906383/RegNetX-4.0GF_dds_8gpu.pyth" -) -# RegNets benefit from enabling cudnn benchmark mode -train.cudnn_benchmark = True diff --git a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnety_4gf_dds_fpn_1x.py b/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnety_4gf_dds_fpn_1x.py deleted file mode 100644 index 72c6b7a5c8939970bd0e1e4a3c1155695943b19a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-InstanceSegmentation/mask_rcnn_regnety_4gf_dds_fpn_1x.py +++ /dev/null @@ -1,35 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco import dataloader -from ..common.models.mask_rcnn_fpn import model -from ..common.train import train - -from detectron2.config import LazyCall as L -from detectron2.modeling.backbone import RegNet -from detectron2.modeling.backbone.regnet import SimpleStem, ResBottleneckBlock - - -# Replace default ResNet with RegNetY-4GF from the DDS paper. Config source: -# https://github.com/facebookresearch/pycls/blob/2c152a6e5d913e898cca4f0a758f41e6b976714d/configs/dds_baselines/regnety/RegNetY-4.0GF_dds_8gpu.yaml#L4-L10 # noqa -model.backbone.bottom_up = L(RegNet)( - stem_class=SimpleStem, - stem_width=32, - block_class=ResBottleneckBlock, - depth=22, - w_a=31.41, - w_0=96, - w_m=2.24, - group_width=64, - se_ratio=0.25, - freeze_at=2, - norm="FrozenBN", - out_features=["s1", "s2", "s3", "s4"], -) -model.pixel_std = [57.375, 57.120, 58.395] - -optimizer.weight_decay = 5e-5 -train.init_checkpoint = ( - "https://dl.fbaipublicfiles.com/pycls/dds_baselines/160906838/RegNetY-4.0GF_dds_8gpu.pyth" -) -# RegNets benefit from enabling cudnn benchmark mode -train.cudnn_benchmark = True diff --git a/preprocess/detectron2/configs/COCO-Keypoints/Base-Keypoint-RCNN-FPN.yaml b/preprocess/detectron2/configs/COCO-Keypoints/Base-Keypoint-RCNN-FPN.yaml deleted file mode 100644 index 4e03944a42d2e497da5ceca17c8fda797dac3f82..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/Base-Keypoint-RCNN-FPN.yaml +++ /dev/null @@ -1,15 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - KEYPOINT_ON: True - ROI_HEADS: - NUM_CLASSES: 1 - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 0.5 # Keypoint AP degrades (though box AP improves) when using plain L1 loss - RPN: - # Detectron1 uses 2000 proposals per-batch, but this option is per-image in detectron2. - # 1000 proposals per-image is found to hurt box AP. - # Therefore we increase it to 1500 per-image. - POST_NMS_TOPK_TRAIN: 1500 -DATASETS: - TRAIN: ("keypoints_coco_2017_train",) - TEST: ("keypoints_coco_2017_val",) diff --git a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml deleted file mode 100644 index 9309535c57a1aa7d23297aac80a9bd78a6c79fcc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-Keypoint-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.py b/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.py deleted file mode 100644 index 1aad53bfef62fb584d5022585d567e346f671a55..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco_keypoint import dataloader -from ..common.models.keypoint_rcnn_fpn import model -from ..common.train import train - -model.backbone.bottom_up.freeze_at = 2 -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index 7bf85cf745b53b3e7ab28fe94b7f4f9e7fe6e335..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,5 +0,0 @@ -_BASE_: "Base-Keypoint-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x.yaml deleted file mode 100644 index a07f243f650a497b9372501e3face75194cf0941..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-Keypoint-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x.yaml b/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x.yaml deleted file mode 100644 index d4bfa20a98c0a65c6bd60e93b07e8f4b7d92a867..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-Keypoint-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-PanopticSegmentation/Base-Panoptic-FPN.yaml b/preprocess/detectron2/configs/COCO-PanopticSegmentation/Base-Panoptic-FPN.yaml deleted file mode 100644 index f00d54b760c2b9271c75643e0a1ab1ffc0d9543a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-PanopticSegmentation/Base-Panoptic-FPN.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "PanopticFPN" - MASK_ON: True - SEM_SEG_HEAD: - LOSS_WEIGHT: 0.5 -DATASETS: - TRAIN: ("coco_2017_train_panoptic_separated",) - TEST: ("coco_2017_val_panoptic_separated",) -DATALOADER: - FILTER_EMPTY_ANNOTATIONS: False diff --git a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x.yaml b/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x.yaml deleted file mode 100644 index 0e01f6fb31e9b00b1857b7de3b5074184d1f4a21..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-Panoptic-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.py b/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.py deleted file mode 100644 index 40cf18131810307157a9a7d1f6d5922b00fd73d5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..common.optim import SGD as optimizer -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.data.coco_panoptic_separated import dataloader -from ..common.models.panoptic_fpn import model -from ..common.train import train - -model.backbone.bottom_up.freeze_at = 2 -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" diff --git a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.yaml b/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.yaml deleted file mode 100644 index 6afa2c1cc92495309ed1553a17359fe5d7d6566e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.yaml +++ /dev/null @@ -1,5 +0,0 @@ -_BASE_: "Base-Panoptic-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x.yaml b/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x.yaml deleted file mode 100644 index b956b3f673e78649184fe2c50e2700b3f1f14794..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-Panoptic-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/Cityscapes/mask_rcnn_R_50_FPN.yaml b/preprocess/detectron2/configs/Cityscapes/mask_rcnn_R_50_FPN.yaml deleted file mode 100644 index 1a7aaeb961581ed9492c4cfe5a69a1eb60495b3e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Cityscapes/mask_rcnn_R_50_FPN.yaml +++ /dev/null @@ -1,27 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - # WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - # For better, more stable performance initialize from COCO - WEIGHTS: "detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl" - MASK_ON: True - ROI_HEADS: - NUM_CLASSES: 8 -# This is similar to the setting used in Mask R-CNN paper, Appendix A -# But there are some differences, e.g., we did not initialize the output -# layer using the corresponding classes from COCO -INPUT: - MIN_SIZE_TRAIN: (800, 832, 864, 896, 928, 960, 992, 1024) - MIN_SIZE_TRAIN_SAMPLING: "choice" - MIN_SIZE_TEST: 1024 - MAX_SIZE_TRAIN: 2048 - MAX_SIZE_TEST: 2048 -DATASETS: - TRAIN: ("cityscapes_fine_instance_seg_train",) - TEST: ("cityscapes_fine_instance_seg_val",) -SOLVER: - BASE_LR: 0.01 - STEPS: (18000,) - MAX_ITER: 24000 - IMS_PER_BATCH: 8 -TEST: - EVAL_PERIOD: 8000 diff --git a/preprocess/detectron2/configs/Detectron1-Comparisons/README.md b/preprocess/detectron2/configs/Detectron1-Comparisons/README.md deleted file mode 100644 index 924fd00af642ddf1a4ff4c4f5947f676134eb7de..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Detectron1-Comparisons/README.md +++ /dev/null @@ -1,84 +0,0 @@ - -Detectron2 model zoo's experimental settings and a few implementation details are different from Detectron. - -The differences in implementation details are shared in -[Compatibility with Other Libraries](../../docs/notes/compatibility.md). - -The differences in model zoo's experimental settings include: -* Use scale augmentation during training. This improves AP with lower training cost. -* Use L1 loss instead of smooth L1 loss for simplicity. This sometimes improves box AP but may - affect other AP. -* Use `POOLER_SAMPLING_RATIO=0` instead of 2. This does not significantly affect AP. -* Use `ROIAlignV2`. This does not significantly affect AP. - -In this directory, we provide a few configs that __do not__ have the above changes. -They mimic Detectron's behavior as close as possible, -and provide a fair comparison of accuracy and speed against Detectron. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
kp.
AP
model iddownload
Faster R-CNN1x0.2190.0383.136.9137781054model | metrics
Keypoint R-CNN1x0.3130.0715.053.164.2137781195model | metrics
Mask R-CNN1x0.2730.0433.437.834.9137781281model | metrics
- -## Comparisons: - -* Faster R-CNN: Detectron's AP is 36.7, similar to ours. -* Keypoint R-CNN: Detectron's AP is box 53.6, keypoint 64.2. Fixing a Detectron's - [bug](https://github.com/facebookresearch/Detectron/issues/459) lead to a drop in box AP, and can be - compensated back by some parameter tuning. -* Mask R-CNN: Detectron's AP is box 37.7, mask 33.9. We're 1 AP better in mask AP, due to more correct implementation. - See [this article](https://ppwwyyxx.com/blog/2021/Where-are-Pixels/) for details. - -For speed comparison, see [benchmarks](https://detectron2.readthedocs.io/notes/benchmarks.html). diff --git a/preprocess/detectron2/configs/Detectron1-Comparisons/faster_rcnn_R_50_FPN_noaug_1x.yaml b/preprocess/detectron2/configs/Detectron1-Comparisons/faster_rcnn_R_50_FPN_noaug_1x.yaml deleted file mode 100644 index 6ce77f137fa2c4e5254a62b58c18b8b76096f2aa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Detectron1-Comparisons/faster_rcnn_R_50_FPN_noaug_1x.yaml +++ /dev/null @@ -1,17 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 - # Detectron1 uses smooth L1 loss with some magic beta values. - # The defaults are changed to L1 loss in Detectron2. - RPN: - SMOOTH_L1_BETA: 0.1111 - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 1.0 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" -INPUT: - # no scale augmentation - MIN_SIZE_TRAIN: (800, ) diff --git a/preprocess/detectron2/configs/Detectron1-Comparisons/keypoint_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/Detectron1-Comparisons/keypoint_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index aacf868ba5290c752031c130a2081af48afc0808..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Detectron1-Comparisons/keypoint_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,27 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - KEYPOINT_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 1 - ROI_KEYPOINT_HEAD: - POOLER_RESOLUTION: 14 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" - # Detectron1 uses smooth L1 loss with some magic beta values. - # The defaults are changed to L1 loss in Detectron2. - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 1.0 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" - RPN: - SMOOTH_L1_BETA: 0.1111 - # Detectron1 uses 2000 proposals per-batch, but this option is per-image in detectron2 - # 1000 proposals per-image is found to hurt box AP. - # Therefore we increase it to 1500 per-image. - POST_NMS_TOPK_TRAIN: 1500 -DATASETS: - TRAIN: ("keypoints_coco_2017_train",) - TEST: ("keypoints_coco_2017_val",) diff --git a/preprocess/detectron2/configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml b/preprocess/detectron2/configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml deleted file mode 100644 index 4ea86a8d8e2cd3e51cbc7311b0d00710c07d01f6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - # Detectron1 uses smooth L1 loss with some magic beta values. - # The defaults are changed to L1 loss in Detectron2. - RPN: - SMOOTH_L1_BETA: 0.1111 - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 1.0 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" - ROI_MASK_HEAD: - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" -INPUT: - # no scale augmentation - MIN_SIZE_TRAIN: (800, ) diff --git a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml deleted file mode 100644 index f0c3a1bbc0a09e1384de522f30c443ba1e36fafa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: True - RESNETS: - DEPTH: 101 - ROI_HEADS: - NUM_CLASSES: 1230 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v0.5_train",) - TEST: ("lvis_v0.5_val",) -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index 64b4caa4ef2b284782367ea702e1ae6653472630..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 1230 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v0.5_train",) - TEST: ("lvis_v0.5_val",) -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml deleted file mode 100644 index c8b822c6c006ba642f4caf9b55e7983f6797427a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml +++ /dev/null @@ -1,23 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - MASK_ON: True - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 - ROI_HEADS: - NUM_CLASSES: 1230 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v0.5_train",) - TEST: ("lvis_v0.5_val",) -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml deleted file mode 100644 index ca4dd97144561276ecaabbb6c254e3a7737ac157..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml +++ /dev/null @@ -1,22 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: True - RESNETS: - DEPTH: 101 - ROI_HEADS: - NUM_CLASSES: 1203 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v1_train",) - TEST: ("lvis_v1_val",) -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -SOLVER: - STEPS: (120000, 160000) - MAX_ITER: 180000 # 180000 * 16 / 100000 ~ 28.8 epochs -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index f313295ee5f0d553d394ce2efe003810c79af47d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,22 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 1203 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v1_train",) - TEST: ("lvis_v1_val",) -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -SOLVER: - STEPS: (120000, 160000) - MAX_ITER: 180000 # 180000 * 16 / 100000 ~ 28.8 epochs -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml b/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml deleted file mode 100644 index f6528f7c31c8cfbf139c14fd0cae598592d8e898..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/LVISv1-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml +++ /dev/null @@ -1,26 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - MASK_ON: True - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 - ROI_HEADS: - NUM_CLASSES: 1203 - SCORE_THRESH_TEST: 0.0001 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DATASETS: - TRAIN: ("lvis_v1_train",) - TEST: ("lvis_v1_val",) -SOLVER: - STEPS: (120000, 160000) - MAX_ITER: 180000 # 180000 * 16 / 100000 ~ 28.8 epochs -TEST: - DETECTIONS_PER_IMAGE: 300 # LVIS allows up to 300 -DATALOADER: - SAMPLER_TRAIN: "RepeatFactorTrainingSampler" - REPEAT_THRESHOLD: 0.001 diff --git a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_1x.yaml deleted file mode 100644 index abb33b618932e94b66239945ac892f4c84a6e8f8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - NAME: CascadeROIHeads - ROI_BOX_HEAD: - CLS_AGNOSTIC_BBOX_REG: True - RPN: - POST_NMS_TOPK_TRAIN: 2000 diff --git a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml b/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml deleted file mode 100644 index e2201ad5c46ded91ccfa47b7698a521625c5e447..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml +++ /dev/null @@ -1,15 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - NAME: CascadeROIHeads - ROI_BOX_HEAD: - CLS_AGNOSTIC_BBOX_REG: True - RPN: - POST_NMS_TOPK_TRAIN: 2000 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv.yaml b/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv.yaml deleted file mode 100644 index fc117f6b5e3e51558ec2f01b73c5365622e5ce25..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv.yaml +++ /dev/null @@ -1,36 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - MASK_ON: True - WEIGHTS: "catalog://ImageNetPretrained/FAIR/X-152-32x8d-IN5k" - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 152 - DEFORM_ON_PER_STAGE: [False, True, True, True] - ROI_HEADS: - NAME: "CascadeROIHeads" - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_CONV: 4 - NUM_FC: 1 - NORM: "GN" - CLS_AGNOSTIC_BBOX_REG: True - ROI_MASK_HEAD: - NUM_CONV: 8 - NORM: "GN" - RPN: - POST_NMS_TOPK_TRAIN: 2000 -SOLVER: - IMS_PER_BATCH: 128 - STEPS: (35000, 45000) - MAX_ITER: 50000 - BASE_LR: 0.16 -INPUT: - MIN_SIZE_TRAIN: (640, 864) - MIN_SIZE_TRAIN_SAMPLING: "range" - MAX_SIZE_TRAIN: 1440 - CROP: - ENABLED: True -TEST: - EVAL_PERIOD: 2500 diff --git a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_cls_agnostic.yaml b/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_cls_agnostic.yaml deleted file mode 100644 index 4c3b767ff473bbab7225cc8a4a92608543d78246..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_cls_agnostic.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_BOX_HEAD: - CLS_AGNOSTIC_BBOX_REG: True - ROI_MASK_HEAD: - CLS_AGNOSTIC_MASK: True diff --git a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5.yaml b/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5.yaml deleted file mode 100644 index 04ff988d073ef9169ee4ca2cbce0d6f030c15232..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - DEFORM_ON_PER_STAGE: [False, True, True, True] # on Res3,Res4,Res5 - DEFORM_MODULATED: False diff --git a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5.yaml b/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5.yaml deleted file mode 100644 index 68c0ca58d7df97ca728c339da0ca9828fe6be318..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - DEFORM_ON_PER_STAGE: [False, True, True, True] # on Res3,Res4,Res5 - DEFORM_MODULATED: False -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_gn.yaml b/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_gn.yaml deleted file mode 100644 index 74d274e5a529b5a8afe186940868f9d48c6112b3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_gn.yaml +++ /dev/null @@ -1,21 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "catalog://ImageNetPretrained/FAIR/R-50-GN" - MASK_ON: True - RESNETS: - DEPTH: 50 - NORM: "GN" - STRIDE_IN_1X1: False - FPN: - NORM: "GN" - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_CONV: 4 - NUM_FC: 1 - NORM: "GN" - ROI_MASK_HEAD: - NORM: "GN" -SOLVER: - # 3x schedule - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_syncbn.yaml b/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_syncbn.yaml deleted file mode 100644 index 11ebb076ba529f26c71a0d972e96ca4c2d6a830b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mask_rcnn_R_50_FPN_3x_syncbn.yaml +++ /dev/null @@ -1,24 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - NORM: "SyncBN" - STRIDE_IN_1X1: True - FPN: - NORM: "SyncBN" - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_CONV: 4 - NUM_FC: 1 - NORM: "SyncBN" - ROI_MASK_HEAD: - NORM: "SyncBN" -SOLVER: - # 3x schedule - STEPS: (210000, 250000) - MAX_ITER: 270000 -TEST: - PRECISE_BN: - ENABLED: True diff --git a/preprocess/detectron2/configs/Misc/mmdet_mask_rcnn_R_50_FPN_1x.py b/preprocess/detectron2/configs/Misc/mmdet_mask_rcnn_R_50_FPN_1x.py deleted file mode 100644 index bdd49a4566d1d0c79d0613c34a8cffd616f74fd2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/mmdet_mask_rcnn_R_50_FPN_1x.py +++ /dev/null @@ -1,152 +0,0 @@ -# An example config to train a mmdetection model using detectron2. - -from ..common.data.coco import dataloader -from ..common.coco_schedule import lr_multiplier_1x as lr_multiplier -from ..common.optim import SGD as optimizer -from ..common.train import train -from ..common.data.constants import constants - -from detectron2.modeling.mmdet_wrapper import MMDetDetector -from detectron2.config import LazyCall as L - -model = L(MMDetDetector)( - detector=dict( - type="MaskRCNN", - pretrained="torchvision://resnet50", - backbone=dict( - type="ResNet", - depth=50, - num_stages=4, - out_indices=(0, 1, 2, 3), - frozen_stages=1, - norm_cfg=dict(type="BN", requires_grad=True), - norm_eval=True, - style="pytorch", - ), - neck=dict(type="FPN", in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=5), - rpn_head=dict( - type="RPNHead", - in_channels=256, - feat_channels=256, - anchor_generator=dict( - type="AnchorGenerator", - scales=[8], - ratios=[0.5, 1.0, 2.0], - strides=[4, 8, 16, 32, 64], - ), - bbox_coder=dict( - type="DeltaXYWHBBoxCoder", - target_means=[0.0, 0.0, 0.0, 0.0], - target_stds=[1.0, 1.0, 1.0, 1.0], - ), - loss_cls=dict(type="CrossEntropyLoss", use_sigmoid=True, loss_weight=1.0), - loss_bbox=dict(type="L1Loss", loss_weight=1.0), - ), - roi_head=dict( - type="StandardRoIHead", - bbox_roi_extractor=dict( - type="SingleRoIExtractor", - roi_layer=dict(type="RoIAlign", output_size=7, sampling_ratio=0), - out_channels=256, - featmap_strides=[4, 8, 16, 32], - ), - bbox_head=dict( - type="Shared2FCBBoxHead", - in_channels=256, - fc_out_channels=1024, - roi_feat_size=7, - num_classes=80, - bbox_coder=dict( - type="DeltaXYWHBBoxCoder", - target_means=[0.0, 0.0, 0.0, 0.0], - target_stds=[0.1, 0.1, 0.2, 0.2], - ), - reg_class_agnostic=False, - loss_cls=dict(type="CrossEntropyLoss", use_sigmoid=False, loss_weight=1.0), - loss_bbox=dict(type="L1Loss", loss_weight=1.0), - ), - mask_roi_extractor=dict( - type="SingleRoIExtractor", - roi_layer=dict(type="RoIAlign", output_size=14, sampling_ratio=0), - out_channels=256, - featmap_strides=[4, 8, 16, 32], - ), - mask_head=dict( - type="FCNMaskHead", - num_convs=4, - in_channels=256, - conv_out_channels=256, - num_classes=80, - loss_mask=dict(type="CrossEntropyLoss", use_mask=True, loss_weight=1.0), - ), - ), - # model training and testing settings - train_cfg=dict( - rpn=dict( - assigner=dict( - type="MaxIoUAssigner", - pos_iou_thr=0.7, - neg_iou_thr=0.3, - min_pos_iou=0.3, - match_low_quality=True, - ignore_iof_thr=-1, - ), - sampler=dict( - type="RandomSampler", - num=256, - pos_fraction=0.5, - neg_pos_ub=-1, - add_gt_as_proposals=False, - ), - allowed_border=-1, - pos_weight=-1, - debug=False, - ), - rpn_proposal=dict( - nms_pre=2000, - max_per_img=1000, - nms=dict(type="nms", iou_threshold=0.7), - min_bbox_size=0, - ), - rcnn=dict( - assigner=dict( - type="MaxIoUAssigner", - pos_iou_thr=0.5, - neg_iou_thr=0.5, - min_pos_iou=0.5, - match_low_quality=True, - ignore_iof_thr=-1, - ), - sampler=dict( - type="RandomSampler", - num=512, - pos_fraction=0.25, - neg_pos_ub=-1, - add_gt_as_proposals=True, - ), - mask_size=28, - pos_weight=-1, - debug=False, - ), - ), - test_cfg=dict( - rpn=dict( - nms_pre=1000, - max_per_img=1000, - nms=dict(type="nms", iou_threshold=0.7), - min_bbox_size=0, - ), - rcnn=dict( - score_thr=0.05, - nms=dict(type="nms", iou_threshold=0.5), - max_per_img=100, - mask_thr_binary=0.5, - ), - ), - ), - pixel_mean=constants.imagenet_rgb256_mean, - pixel_std=constants.imagenet_rgb256_std, -) - -dataloader.train.mapper.image_format = "RGB" # torchvision pretrained model -train.init_checkpoint = None # pretrained model is loaded inside backbone diff --git a/preprocess/detectron2/configs/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x.yaml b/preprocess/detectron2/configs/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x.yaml deleted file mode 100644 index 34016cea3ca9d7fb69ef4fe01d6b47ee8690a13b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# A large PanopticFPN for demo purposes. -# Use GN on backbone to support semantic seg. -# Use Cascade + Deform Conv to improve localization. -_BASE_: "../COCO-PanopticSegmentation/Base-Panoptic-FPN.yaml" -MODEL: - WEIGHTS: "catalog://ImageNetPretrained/FAIR/R-101-GN" - RESNETS: - DEPTH: 101 - NORM: "GN" - DEFORM_ON_PER_STAGE: [False, True, True, True] - STRIDE_IN_1X1: False - FPN: - NORM: "GN" - ROI_HEADS: - NAME: CascadeROIHeads - ROI_BOX_HEAD: - CLS_AGNOSTIC_BBOX_REG: True - ROI_MASK_HEAD: - NORM: "GN" - RPN: - POST_NMS_TOPK_TRAIN: 2000 -SOLVER: - STEPS: (105000, 125000) - MAX_ITER: 135000 - IMS_PER_BATCH: 32 - BASE_LR: 0.04 diff --git a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml b/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml deleted file mode 100644 index f3400288cde242fcf66eef7f63b5a9165ca663c5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "mask_rcnn_R_50_FPN_3x_gn.yaml" -MODEL: - # Train from random initialization. - WEIGHTS: "" - # It makes sense to divide by STD when training from scratch - # But it seems to make no difference on the results and C2's models didn't do this. - # So we keep things consistent with C2. - # PIXEL_STD: [57.375, 57.12, 58.395] - MASK_ON: True - BACKBONE: - FREEZE_AT: 0 -# NOTE: Please refer to Rethinking ImageNet Pre-training https://arxiv.org/abs/1811.08883 -# to learn what you need for training from scratch. diff --git a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn.yaml b/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn.yaml deleted file mode 100644 index d90c9ff0ef4573252ee165b4c958ec5f74178176..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "mask_rcnn_R_50_FPN_3x_gn.yaml" -MODEL: - PIXEL_STD: [57.375, 57.12, 58.395] - WEIGHTS: "" - MASK_ON: True - RESNETS: - STRIDE_IN_1X1: False - BACKBONE: - FREEZE_AT: 0 -SOLVER: - # 9x schedule - IMS_PER_BATCH: 64 # 4x the standard - STEPS: (187500, 197500) # last 60/4==15k and last 20/4==5k - MAX_ITER: 202500 # 90k * 9 / 4 - BASE_LR: 0.08 -TEST: - EVAL_PERIOD: 2500 -# NOTE: Please refer to Rethinking ImageNet Pre-training https://arxiv.org/abs/1811.08883 -# to learn what you need for training from scratch. diff --git a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn.yaml b/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn.yaml deleted file mode 100644 index 60d4e42330e396a1901437df8e17b262d5ad547a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "mask_rcnn_R_50_FPN_3x_syncbn.yaml" -MODEL: - PIXEL_STD: [57.375, 57.12, 58.395] - WEIGHTS: "" - MASK_ON: True - RESNETS: - STRIDE_IN_1X1: False - BACKBONE: - FREEZE_AT: 0 -SOLVER: - # 9x schedule - IMS_PER_BATCH: 64 # 4x the standard - STEPS: (187500, 197500) # last 60/4==15k and last 20/4==5k - MAX_ITER: 202500 # 90k * 9 / 4 - BASE_LR: 0.08 -TEST: - EVAL_PERIOD: 2500 -# NOTE: Please refer to Rethinking ImageNet Pre-training https://arxiv.org/abs/1811.08883 -# to learn what you need for training from scratch. diff --git a/preprocess/detectron2/configs/Misc/semantic_R_50_FPN_1x.yaml b/preprocess/detectron2/configs/Misc/semantic_R_50_FPN_1x.yaml deleted file mode 100644 index ac256e1372770ab3d9ae522c962de0fd0dbceeb5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/semantic_R_50_FPN_1x.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -DATASETS: - TRAIN: ("coco_2017_train_panoptic_stuffonly",) - TEST: ("coco_2017_val_panoptic_stuffonly",) -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) diff --git a/preprocess/detectron2/configs/Misc/torchvision_imagenet_R_50.py b/preprocess/detectron2/configs/Misc/torchvision_imagenet_R_50.py deleted file mode 100644 index 0d75305bcf7445b98db84b3d489a1505d2fce5af..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/Misc/torchvision_imagenet_R_50.py +++ /dev/null @@ -1,150 +0,0 @@ -""" -An example config file to train a ImageNet classifier with detectron2. -Model and dataloader both come from torchvision. -This shows how to use detectron2 as a general engine for any new models and tasks. - -To run, use the following command: - -python tools/lazyconfig_train_net.py --config-file configs/Misc/torchvision_imagenet_R_50.py \ - --num-gpus 8 dataloader.train.dataset.root=/path/to/imagenet/ - -""" - - -import torch -from torch import nn -from torch.nn import functional as F -from omegaconf import OmegaConf -import torchvision -from torchvision.transforms import transforms as T -from torchvision.models.resnet import ResNet, Bottleneck -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2.solver import WarmupParamScheduler -from detectron2.solver.build import get_default_optimizer_params -from detectron2.config import LazyCall as L -from detectron2.model_zoo import get_config -from detectron2.data.samplers import TrainingSampler, InferenceSampler -from detectron2.evaluation import DatasetEvaluator -from detectron2.utils import comm - - -""" -Note: Here we put reusable code (models, evaluation, data) together with configs just as a -proof-of-concept, to easily demonstrate what's needed to train a ImageNet classifier in detectron2. -Writing code in configs offers extreme flexibility but is often not a good engineering practice. -In practice, you might want to put code in your project and import them instead. -""" - - -def build_data_loader(dataset, batch_size, num_workers, training=True): - return torch.utils.data.DataLoader( - dataset, - sampler=(TrainingSampler if training else InferenceSampler)(len(dataset)), - batch_size=batch_size, - num_workers=num_workers, - pin_memory=True, - ) - - -class ClassificationNet(nn.Module): - def __init__(self, model: nn.Module): - super().__init__() - self.model = model - - @property - def device(self): - return list(self.model.parameters())[0].device - - def forward(self, inputs): - image, label = inputs - pred = self.model(image.to(self.device)) - if self.training: - label = label.to(self.device) - return F.cross_entropy(pred, label) - else: - return pred - - -class ClassificationAcc(DatasetEvaluator): - def reset(self): - self.corr = self.total = 0 - - def process(self, inputs, outputs): - image, label = inputs - self.corr += (outputs.argmax(dim=1).cpu() == label.cpu()).sum().item() - self.total += len(label) - - def evaluate(self): - all_corr_total = comm.all_gather([self.corr, self.total]) - corr = sum(x[0] for x in all_corr_total) - total = sum(x[1] for x in all_corr_total) - return {"accuracy": corr / total} - - -# --- End of code that could be in a project and be imported - - -dataloader = OmegaConf.create() -dataloader.train = L(build_data_loader)( - dataset=L(torchvision.datasets.ImageNet)( - root="/path/to/imagenet", - split="train", - transform=L(T.Compose)( - transforms=[ - L(T.RandomResizedCrop)(size=224), - L(T.RandomHorizontalFlip)(), - T.ToTensor(), - L(T.Normalize)(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), - ] - ), - ), - batch_size=256 // 8, - num_workers=4, - training=True, -) - -dataloader.test = L(build_data_loader)( - dataset=L(torchvision.datasets.ImageNet)( - root="${...train.dataset.root}", - split="val", - transform=L(T.Compose)( - transforms=[ - L(T.Resize)(size=256), - L(T.CenterCrop)(size=224), - T.ToTensor(), - L(T.Normalize)(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), - ] - ), - ), - batch_size=256 // 8, - num_workers=4, - training=False, -) - -dataloader.evaluator = L(ClassificationAcc)() - -model = L(ClassificationNet)( - model=(ResNet)(block=Bottleneck, layers=[3, 4, 6, 3], zero_init_residual=True) -) - - -optimizer = L(torch.optim.SGD)( - params=L(get_default_optimizer_params)(), - lr=0.1, - momentum=0.9, - weight_decay=1e-4, -) - -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01, 0.001], milestones=[30, 60, 90, 100] - ), - warmup_length=1 / 100, - warmup_factor=0.1, -) - - -train = get_config("common/train.py").train -train.init_checkpoint = None -train.max_iter = 100 * 1281167 // 256 diff --git a/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_C4.yaml b/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_C4.yaml deleted file mode 100644 index ea2a6baaebd1a186db18f2904430ffb25901898e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_C4.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 20 -INPUT: - MIN_SIZE_TRAIN: (480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800) - MIN_SIZE_TEST: 800 -DATASETS: - TRAIN: ('voc_2007_trainval', 'voc_2012_trainval') - TEST: ('voc_2007_test',) -SOLVER: - STEPS: (12000, 16000) - MAX_ITER: 18000 # 17.4 epochs - WARMUP_ITERS: 100 diff --git a/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_FPN.yaml b/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_FPN.yaml deleted file mode 100644 index e554cab18a358a27b630c1ab0c2359666b0e1514..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/PascalVOC-Detection/faster_rcnn_R_50_FPN.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 20 -INPUT: - MIN_SIZE_TRAIN: (480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800) - MIN_SIZE_TEST: 800 -DATASETS: - TRAIN: ('voc_2007_trainval', 'voc_2012_trainval') - TEST: ('voc_2007_test',) -SOLVER: - STEPS: (12000, 16000) - MAX_ITER: 18000 # 17.4 epochs - WARMUP_ITERS: 100 diff --git a/preprocess/detectron2/configs/common/README.md b/preprocess/detectron2/configs/common/README.md deleted file mode 100644 index 912cc29927542bfe4258d3208cf52d73cb0ea477..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This directory provides definitions for a few common models, dataloaders, scheduler, -and optimizers that are often used in training. -The definition of these objects are provided in the form of lazy instantiation: -their arguments can be edited by users before constructing the objects. - -They can be imported, or loaded by `model_zoo.get_config` API in users' own configs. diff --git a/preprocess/detectron2/configs/common/coco_schedule.py b/preprocess/detectron2/configs/common/coco_schedule.py deleted file mode 100644 index 355e66a1d213cb599a7ffe55089d854089c8ead2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/coco_schedule.py +++ /dev/null @@ -1,47 +0,0 @@ -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler - - -def default_X_scheduler(num_X): - """ - Returns the config for a default multi-step LR scheduler such as "1x", "3x", - commonly referred to in papers, where every 1x has the total length of 1440k - training images (~12 COCO epochs). LR is decayed twice at the end of training - following the strategy defined in "Rethinking ImageNet Pretraining", Sec 4. - - Args: - num_X: a positive real number - - Returns: - DictConfig: configs that define the multiplier for LR during training - """ - # total number of iterations assuming 16 batch size, using 1440000/16=90000 - total_steps_16bs = num_X * 90000 - - if num_X <= 2: - scheduler = L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - # note that scheduler is scale-invariant. This is equivalent to - # milestones=[6, 8, 9] - milestones=[60000, 80000, 90000], - ) - else: - scheduler = L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[total_steps_16bs - 60000, total_steps_16bs - 20000, total_steps_16bs], - ) - return L(WarmupParamScheduler)( - scheduler=scheduler, - warmup_length=1000 / total_steps_16bs, - warmup_method="linear", - warmup_factor=0.001, - ) - - -lr_multiplier_1x = default_X_scheduler(1) -lr_multiplier_2x = default_X_scheduler(2) -lr_multiplier_3x = default_X_scheduler(3) -lr_multiplier_6x = default_X_scheduler(6) -lr_multiplier_9x = default_X_scheduler(9) diff --git a/preprocess/detectron2/configs/common/data/coco.py b/preprocess/detectron2/configs/common/data/coco.py deleted file mode 100644 index 703c4385c7ddc7eb0759c98d102ab2384d6a9e3e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/data/coco.py +++ /dev/null @@ -1,48 +0,0 @@ -from omegaconf import OmegaConf - -import detectron2.data.transforms as T -from detectron2.config import LazyCall as L -from detectron2.data import ( - DatasetMapper, - build_detection_test_loader, - build_detection_train_loader, - get_detection_dataset_dicts, -) -from detectron2.evaluation import COCOEvaluator - -dataloader = OmegaConf.create() - -dataloader.train = L(build_detection_train_loader)( - dataset=L(get_detection_dataset_dicts)(names="coco_2017_train"), - mapper=L(DatasetMapper)( - is_train=True, - augmentations=[ - L(T.ResizeShortestEdge)( - short_edge_length=(640, 672, 704, 736, 768, 800), - sample_style="choice", - max_size=1333, - ), - L(T.RandomFlip)(horizontal=True), - ], - image_format="BGR", - use_instance_mask=True, - ), - total_batch_size=16, - num_workers=4, -) - -dataloader.test = L(build_detection_test_loader)( - dataset=L(get_detection_dataset_dicts)(names="coco_2017_val", filter_empty=False), - mapper=L(DatasetMapper)( - is_train=False, - augmentations=[ - L(T.ResizeShortestEdge)(short_edge_length=800, max_size=1333), - ], - image_format="${...train.mapper.image_format}", - ), - num_workers=4, -) - -dataloader.evaluator = L(COCOEvaluator)( - dataset_name="${..test.dataset.names}", -) diff --git a/preprocess/detectron2/configs/common/data/coco_keypoint.py b/preprocess/detectron2/configs/common/data/coco_keypoint.py deleted file mode 100644 index b4ceb066faf696954244205dc75376b767071217..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/data/coco_keypoint.py +++ /dev/null @@ -1,13 +0,0 @@ -from detectron2.data.detection_utils import create_keypoint_hflip_indices - -from .coco import dataloader - -dataloader.train.dataset.min_keypoints = 1 -dataloader.train.dataset.names = "keypoints_coco_2017_train" -dataloader.test.dataset.names = "keypoints_coco_2017_val" - -dataloader.train.mapper.update( - use_instance_mask=False, - use_keypoint=True, - keypoint_hflip_indices=create_keypoint_hflip_indices(dataloader.train.dataset.names), -) diff --git a/preprocess/detectron2/configs/common/data/coco_panoptic_separated.py b/preprocess/detectron2/configs/common/data/coco_panoptic_separated.py deleted file mode 100644 index 5ccbc77e64d1c92c99cbd7158d047bab54cb9f3d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/data/coco_panoptic_separated.py +++ /dev/null @@ -1,26 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.evaluation import ( - COCOEvaluator, - COCOPanopticEvaluator, - DatasetEvaluators, - SemSegEvaluator, -) - -from .coco import dataloader - -dataloader.train.dataset.names = "coco_2017_train_panoptic_separated" -dataloader.train.dataset.filter_empty = False -dataloader.test.dataset.names = "coco_2017_val_panoptic_separated" - - -dataloader.evaluator = [ - L(COCOEvaluator)( - dataset_name="${...test.dataset.names}", - ), - L(SemSegEvaluator)( - dataset_name="${...test.dataset.names}", - ), - L(COCOPanopticEvaluator)( - dataset_name="${...test.dataset.names}", - ), -] diff --git a/preprocess/detectron2/configs/common/data/constants.py b/preprocess/detectron2/configs/common/data/constants.py deleted file mode 100644 index be11cb5ac7c32a260af96ed27c32ed767b2f2bcd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/data/constants.py +++ /dev/null @@ -1,9 +0,0 @@ -constants = dict( - imagenet_rgb256_mean=[123.675, 116.28, 103.53], - imagenet_rgb256_std=[58.395, 57.12, 57.375], - imagenet_bgr256_mean=[103.530, 116.280, 123.675], - # When using pre-trained models in Detectron1 or any MSRA models, - # std has been absorbed into its conv1 weights, so the std needs to be set 1. - # Otherwise, you can use [57.375, 57.120, 58.395] (ImageNet std) - imagenet_bgr256_std=[1.0, 1.0, 1.0], -) diff --git a/preprocess/detectron2/configs/common/models/cascade_rcnn.py b/preprocess/detectron2/configs/common/models/cascade_rcnn.py deleted file mode 100644 index c7372a801dc00d7fec4db8cda8c2612ce281d48a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/cascade_rcnn.py +++ /dev/null @@ -1,36 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import FastRCNNOutputLayers, FastRCNNConvFCHead, CascadeROIHeads - -from .mask_rcnn_fpn import model - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[], - fc_dims=[1024, 1024], - ) - for k in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - cls_agnostic_bbox_reg=True, - num_classes="${...num_classes}", - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) diff --git a/preprocess/detectron2/configs/common/models/fcos.py b/preprocess/detectron2/configs/common/models/fcos.py deleted file mode 100644 index 1c752029b7fc64ec375a55182e5342c9eb48bb33..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/fcos.py +++ /dev/null @@ -1,23 +0,0 @@ -from detectron2.modeling.meta_arch.fcos import FCOS, FCOSHead - -from .retinanet import model - -model._target_ = FCOS - -del model.anchor_generator -del model.box2box_transform -del model.anchor_matcher -del model.input_format - -# Use P5 instead of C5 to compute P6/P7 -# (Sec 2.2 of https://arxiv.org/abs/2006.09214) -model.backbone.top_block.in_feature = "p5" -model.backbone.top_block.in_channels = 256 - -# New score threshold determined based on sqrt(cls_score * centerness) -model.test_score_thresh = 0.2 -model.test_nms_thresh = 0.6 - -model.head._target_ = FCOSHead -del model.head.num_anchors -model.head.norm = "GN" diff --git a/preprocess/detectron2/configs/common/models/keypoint_rcnn_fpn.py b/preprocess/detectron2/configs/common/models/keypoint_rcnn_fpn.py deleted file mode 100644 index 56b3994df249884d4816fc9a5c7f553a9ab6f400..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/keypoint_rcnn_fpn.py +++ /dev/null @@ -1,33 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.poolers import ROIPooler -from detectron2.modeling.roi_heads import KRCNNConvDeconvUpsampleHead - -from .mask_rcnn_fpn import model - -[model.roi_heads.pop(x) for x in ["mask_in_features", "mask_pooler", "mask_head"]] - -model.roi_heads.update( - num_classes=1, - keypoint_in_features=["p2", "p3", "p4", "p5"], - keypoint_pooler=L(ROIPooler)( - output_size=14, - scales=(1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), - sampling_ratio=0, - pooler_type="ROIAlignV2", - ), - keypoint_head=L(KRCNNConvDeconvUpsampleHead)( - input_shape=ShapeSpec(channels=256, width=14, height=14), - num_keypoints=17, - conv_dims=[512] * 8, - loss_normalizer="visible", - ), -) - -# Detectron1 uses 2000 proposals per-batch, but this option is per-image in detectron2. -# 1000 proposals per-image is found to hurt box AP. -# Therefore we increase it to 1500 per-image. -model.proposal_generator.post_nms_topk = (1500, 1000) - -# Keypoint AP degrades (though box AP improves) when using plain L1 loss -model.roi_heads.box_predictor.smooth_l1_beta = 0.5 diff --git a/preprocess/detectron2/configs/common/models/mask_rcnn_c4.py b/preprocess/detectron2/configs/common/models/mask_rcnn_c4.py deleted file mode 100644 index 902d5b195f66881c67a37ec0fe606101a6812260..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/mask_rcnn_c4.py +++ /dev/null @@ -1,90 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.meta_arch import GeneralizedRCNN -from detectron2.modeling.anchor_generator import DefaultAnchorGenerator -from detectron2.modeling.backbone import BasicStem, BottleneckBlock, ResNet -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.poolers import ROIPooler -from detectron2.modeling.proposal_generator import RPN, StandardRPNHead -from detectron2.modeling.roi_heads import ( - FastRCNNOutputLayers, - MaskRCNNConvUpsampleHead, - Res5ROIHeads, -) - -from ..data.constants import constants - -model = L(GeneralizedRCNN)( - backbone=L(ResNet)( - stem=L(BasicStem)(in_channels=3, out_channels=64, norm="FrozenBN"), - stages=L(ResNet.make_default_stages)( - depth=50, - stride_in_1x1=True, - norm="FrozenBN", - ), - out_features=["res4"], - ), - proposal_generator=L(RPN)( - in_features=["res4"], - head=L(StandardRPNHead)(in_channels=1024, num_anchors=15), - anchor_generator=L(DefaultAnchorGenerator)( - sizes=[[32, 64, 128, 256, 512]], - aspect_ratios=[0.5, 1.0, 2.0], - strides=[16], - offset=0.0, - ), - anchor_matcher=L(Matcher)( - thresholds=[0.3, 0.7], labels=[0, -1, 1], allow_low_quality_matches=True - ), - box2box_transform=L(Box2BoxTransform)(weights=[1.0, 1.0, 1.0, 1.0]), - batch_size_per_image=256, - positive_fraction=0.5, - pre_nms_topk=(12000, 6000), - post_nms_topk=(2000, 1000), - nms_thresh=0.7, - ), - roi_heads=L(Res5ROIHeads)( - num_classes=80, - batch_size_per_image=512, - positive_fraction=0.25, - proposal_matcher=L(Matcher)( - thresholds=[0.5], labels=[0, 1], allow_low_quality_matches=False - ), - in_features=["res4"], - pooler=L(ROIPooler)( - output_size=14, - scales=(1.0 / 16,), - sampling_ratio=0, - pooler_type="ROIAlignV2", - ), - res5=L(ResNet.make_stage)( - block_class=BottleneckBlock, - num_blocks=3, - stride_per_block=[2, 1, 1], - in_channels=1024, - bottleneck_channels=512, - out_channels=2048, - norm="FrozenBN", - stride_in_1x1=True, - ), - box_predictor=L(FastRCNNOutputLayers)( - input_shape=L(ShapeSpec)(channels="${...res5.out_channels}", height=1, width=1), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(10, 10, 5, 5)), - num_classes="${..num_classes}", - ), - mask_head=L(MaskRCNNConvUpsampleHead)( - input_shape=L(ShapeSpec)( - channels="${...res5.out_channels}", - width="${...pooler.output_size}", - height="${...pooler.output_size}", - ), - num_classes="${..num_classes}", - conv_dims=[256], - ), - ), - pixel_mean=constants.imagenet_bgr256_mean, - pixel_std=constants.imagenet_bgr256_std, - input_format="BGR", -) diff --git a/preprocess/detectron2/configs/common/models/mask_rcnn_fpn.py b/preprocess/detectron2/configs/common/models/mask_rcnn_fpn.py deleted file mode 100644 index 5e5c501cd1da6cece55210efefc4ec712075ca8a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/mask_rcnn_fpn.py +++ /dev/null @@ -1,95 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.meta_arch import GeneralizedRCNN -from detectron2.modeling.anchor_generator import DefaultAnchorGenerator -from detectron2.modeling.backbone.fpn import LastLevelMaxPool -from detectron2.modeling.backbone import BasicStem, FPN, ResNet -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.poolers import ROIPooler -from detectron2.modeling.proposal_generator import RPN, StandardRPNHead -from detectron2.modeling.roi_heads import ( - StandardROIHeads, - FastRCNNOutputLayers, - MaskRCNNConvUpsampleHead, - FastRCNNConvFCHead, -) - -from ..data.constants import constants - -model = L(GeneralizedRCNN)( - backbone=L(FPN)( - bottom_up=L(ResNet)( - stem=L(BasicStem)(in_channels=3, out_channels=64, norm="FrozenBN"), - stages=L(ResNet.make_default_stages)( - depth=50, - stride_in_1x1=True, - norm="FrozenBN", - ), - out_features=["res2", "res3", "res4", "res5"], - ), - in_features="${.bottom_up.out_features}", - out_channels=256, - top_block=L(LastLevelMaxPool)(), - ), - proposal_generator=L(RPN)( - in_features=["p2", "p3", "p4", "p5", "p6"], - head=L(StandardRPNHead)(in_channels=256, num_anchors=3), - anchor_generator=L(DefaultAnchorGenerator)( - sizes=[[32], [64], [128], [256], [512]], - aspect_ratios=[0.5, 1.0, 2.0], - strides=[4, 8, 16, 32, 64], - offset=0.0, - ), - anchor_matcher=L(Matcher)( - thresholds=[0.3, 0.7], labels=[0, -1, 1], allow_low_quality_matches=True - ), - box2box_transform=L(Box2BoxTransform)(weights=[1.0, 1.0, 1.0, 1.0]), - batch_size_per_image=256, - positive_fraction=0.5, - pre_nms_topk=(2000, 1000), - post_nms_topk=(1000, 1000), - nms_thresh=0.7, - ), - roi_heads=L(StandardROIHeads)( - num_classes=80, - batch_size_per_image=512, - positive_fraction=0.25, - proposal_matcher=L(Matcher)( - thresholds=[0.5], labels=[0, 1], allow_low_quality_matches=False - ), - box_in_features=["p2", "p3", "p4", "p5"], - box_pooler=L(ROIPooler)( - output_size=7, - scales=(1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), - sampling_ratio=0, - pooler_type="ROIAlignV2", - ), - box_head=L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[], - fc_dims=[1024, 1024], - ), - box_predictor=L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(10, 10, 5, 5)), - num_classes="${..num_classes}", - ), - mask_in_features=["p2", "p3", "p4", "p5"], - mask_pooler=L(ROIPooler)( - output_size=14, - scales=(1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), - sampling_ratio=0, - pooler_type="ROIAlignV2", - ), - mask_head=L(MaskRCNNConvUpsampleHead)( - input_shape=ShapeSpec(channels=256, width=14, height=14), - num_classes="${..num_classes}", - conv_dims=[256, 256, 256, 256, 256], - ), - ), - pixel_mean=constants.imagenet_bgr256_mean, - pixel_std=constants.imagenet_bgr256_std, - input_format="BGR", -) diff --git a/preprocess/detectron2/configs/common/models/mask_rcnn_vitdet.py b/preprocess/detectron2/configs/common/models/mask_rcnn_vitdet.py deleted file mode 100644 index d6f5244402734a3f9f675c5c4e42439ea708d24d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/mask_rcnn_vitdet.py +++ /dev/null @@ -1,59 +0,0 @@ -from functools import partial -import torch.nn as nn -from detectron2.config import LazyCall as L -from detectron2.modeling import ViT, SimpleFeaturePyramid -from detectron2.modeling.backbone.fpn import LastLevelMaxPool - -from .mask_rcnn_fpn import model -from ..data.constants import constants - -model.pixel_mean = constants.imagenet_rgb256_mean -model.pixel_std = constants.imagenet_rgb256_std -model.input_format = "RGB" - -# Base -embed_dim, depth, num_heads, dp = 768, 12, 12, 0.1 -# Creates Simple Feature Pyramid from ViT backbone -model.backbone = L(SimpleFeaturePyramid)( - net=L(ViT)( # Single-scale ViT backbone - img_size=1024, - patch_size=16, - embed_dim=embed_dim, - depth=depth, - num_heads=num_heads, - drop_path_rate=dp, - window_size=14, - mlp_ratio=4, - qkv_bias=True, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - window_block_indexes=[ - # 2, 5, 8 11 for global attention - 0, - 1, - 3, - 4, - 6, - 7, - 9, - 10, - ], - residual_block_indexes=[], - use_rel_pos=True, - out_feature="last_feat", - ), - in_feature="${.net.out_feature}", - out_channels=256, - scale_factors=(4.0, 2.0, 1.0, 0.5), - top_block=L(LastLevelMaxPool)(), - norm="LN", - square_pad=1024, -) - -model.roi_heads.box_head.conv_norm = model.roi_heads.mask_head.conv_norm = "LN" - -# 2conv in RPN: -model.proposal_generator.head.conv_dims = [-1, -1] - -# 4conv1fc box head -model.roi_heads.box_head.conv_dims = [256, 256, 256, 256] -model.roi_heads.box_head.fc_dims = [1024] diff --git a/preprocess/detectron2/configs/common/models/panoptic_fpn.py b/preprocess/detectron2/configs/common/models/panoptic_fpn.py deleted file mode 100644 index 88f55d2ce9db62e61445d6a3700067d9d864ecae..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/panoptic_fpn.py +++ /dev/null @@ -1,20 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling import PanopticFPN -from detectron2.modeling.meta_arch.semantic_seg import SemSegFPNHead - -from .mask_rcnn_fpn import model - -model._target_ = PanopticFPN -model.sem_seg_head = L(SemSegFPNHead)( - input_shape={ - f: L(ShapeSpec)(stride=s, channels="${....backbone.out_channels}") - for f, s in zip(["p2", "p3", "p4", "p5"], [4, 8, 16, 32]) - }, - ignore_value=255, - num_classes=54, # COCO stuff + 1 - conv_dims=128, - common_stride=4, - loss_weight=0.5, - norm="GN", -) diff --git a/preprocess/detectron2/configs/common/models/retinanet.py b/preprocess/detectron2/configs/common/models/retinanet.py deleted file mode 100644 index 784e5317f594db966dac02792e9c9db1774623d6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/models/retinanet.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- - -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.meta_arch import RetinaNet -from detectron2.modeling.anchor_generator import DefaultAnchorGenerator -from detectron2.modeling.backbone.fpn import LastLevelP6P7 -from detectron2.modeling.backbone import BasicStem, FPN, ResNet -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.meta_arch.retinanet import RetinaNetHead - -from ..data.constants import constants - -model = L(RetinaNet)( - backbone=L(FPN)( - bottom_up=L(ResNet)( - stem=L(BasicStem)(in_channels=3, out_channels=64, norm="FrozenBN"), - stages=L(ResNet.make_default_stages)( - depth=50, - stride_in_1x1=True, - norm="FrozenBN", - ), - out_features=["res3", "res4", "res5"], - ), - in_features=["res3", "res4", "res5"], - out_channels=256, - top_block=L(LastLevelP6P7)(in_channels=2048, out_channels="${..out_channels}"), - ), - head=L(RetinaNetHead)( - # Shape for each input feature map - input_shape=[ShapeSpec(channels=256)] * 5, - num_classes="${..num_classes}", - conv_dims=[256, 256, 256, 256], - prior_prob=0.01, - num_anchors=9, - ), - anchor_generator=L(DefaultAnchorGenerator)( - sizes=[[x, x * 2 ** (1.0 / 3), x * 2 ** (2.0 / 3)] for x in [32, 64, 128, 256, 512]], - aspect_ratios=[0.5, 1.0, 2.0], - strides=[8, 16, 32, 64, 128], - offset=0.0, - ), - box2box_transform=L(Box2BoxTransform)(weights=[1.0, 1.0, 1.0, 1.0]), - anchor_matcher=L(Matcher)( - thresholds=[0.4, 0.5], labels=[0, -1, 1], allow_low_quality_matches=True - ), - num_classes=80, - head_in_features=["p3", "p4", "p5", "p6", "p7"], - focal_loss_alpha=0.25, - focal_loss_gamma=2.0, - pixel_mean=constants.imagenet_bgr256_mean, - pixel_std=constants.imagenet_bgr256_std, - input_format="BGR", -) diff --git a/preprocess/detectron2/configs/common/optim.py b/preprocess/detectron2/configs/common/optim.py deleted file mode 100644 index 6cf43e835f55739fbb80102b870efab950a0486d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/optim.py +++ /dev/null @@ -1,28 +0,0 @@ -import torch - -from detectron2.config import LazyCall as L -from detectron2.solver.build import get_default_optimizer_params - -SGD = L(torch.optim.SGD)( - params=L(get_default_optimizer_params)( - # params.model is meant to be set to the model object, before instantiating - # the optimizer. - weight_decay_norm=0.0 - ), - lr=0.02, - momentum=0.9, - weight_decay=1e-4, -) - - -AdamW = L(torch.optim.AdamW)( - params=L(get_default_optimizer_params)( - # params.model is meant to be set to the model object, before instantiating - # the optimizer. - base_lr="${..lr}", - weight_decay_norm=0.0, - ), - lr=1e-4, - betas=(0.9, 0.999), - weight_decay=0.1, -) diff --git a/preprocess/detectron2/configs/common/train.py b/preprocess/detectron2/configs/common/train.py deleted file mode 100644 index b6ed02bd59f540ca58df20bf72d462f195210a32..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/common/train.py +++ /dev/null @@ -1,18 +0,0 @@ -# Common training-related configs that are designed for "tools/lazyconfig_train_net.py" -# You can use your own instead, together with your own train_net.py -train = dict( - output_dir="./output", - init_checkpoint="", - max_iter=90000, - amp=dict(enabled=False), # options for Automatic Mixed Precision - ddp=dict( # options for DistributedDataParallel - broadcast_buffers=False, - find_unused_parameters=False, - fp16_compression=False, - ), - checkpointer=dict(period=5000, max_to_keep=100), # options for PeriodicCheckpointer - eval_period=5000, - log_period=20, - device="cuda" - # ... -) diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ.py deleted file mode 100644 index 3740e9bb08c5f168a9ab3a6d94561678bad1775c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ.py +++ /dev/null @@ -1,9 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -model.backbone.bottom_up.stages.depth = 101 diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ.py deleted file mode 100644 index 18e5f0720c568db4ef0c97b59688b5e7866df606..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_R_101_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 2 # 100ep -> 200ep - -lr_multiplier.scheduler.milestones = [ - milestone * 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ.py deleted file mode 100644 index 63c54ee9a5ce2368494b775cc90fada1439feaa5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_R_101_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 4 # 100ep -> 400ep - -lr_multiplier.scheduler.milestones = [ - milestone * 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ.py deleted file mode 100644 index df7a2aedf480ed8dc4aa3645e37420e9b893fae4..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ.py +++ /dev/null @@ -1,72 +0,0 @@ -import detectron2.data.transforms as T -from detectron2.config.lazy import LazyCall as L -from detectron2.layers.batch_norm import NaiveSyncBatchNorm -from detectron2.solver import WarmupParamScheduler -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from ..common.data.coco import dataloader -from ..common.models.mask_rcnn_fpn import model -from ..common.optim import SGD as optimizer -from ..common.train import train - -# train from scratch -train.init_checkpoint = "" -train.amp.enabled = True -train.ddp.fp16_compression = True -model.backbone.bottom_up.freeze_at = 0 - -# SyncBN -# fmt: off -model.backbone.bottom_up.stem.norm = \ - model.backbone.bottom_up.stages.norm = \ - model.backbone.norm = "SyncBN" - -# Using NaiveSyncBatchNorm becase heads may have empty input. That is not supported by -# torch.nn.SyncBatchNorm. We can remove this after -# https://github.com/pytorch/pytorch/issues/36530 is fixed. -model.roi_heads.box_head.conv_norm = \ - model.roi_heads.mask_head.conv_norm = lambda c: NaiveSyncBatchNorm(c, - stats_mode="N") -# fmt: on - -# 2conv in RPN: -# https://github.com/tensorflow/tpu/blob/b24729de804fdb751b06467d3dce0637fa652060/models/official/detection/modeling/architecture/heads.py#L95-L97 # noqa: E501, B950 -model.proposal_generator.head.conv_dims = [-1, -1] - -# 4conv1fc box head -model.roi_heads.box_head.conv_dims = [256, 256, 256, 256] -model.roi_heads.box_head.fc_dims = [1024] - -# resize_and_crop_image in: -# https://github.com/tensorflow/tpu/blob/b24729de804fdb751b06467d3dce0637fa652060/models/official/detection/utils/input_utils.py#L127 # noqa: E501, B950 -image_size = 1024 -dataloader.train.mapper.augmentations = [ - L(T.ResizeScale)( - min_scale=0.1, max_scale=2.0, target_height=image_size, target_width=image_size - ), - L(T.FixedSizeCrop)(crop_size=(image_size, image_size)), - L(T.RandomFlip)(horizontal=True), -] - -# recompute boxes due to cropping -dataloader.train.mapper.recompute_boxes = True - -# larger batch-size. -dataloader.train.total_batch_size = 64 - -# Equivalent to 100 epochs. -# 100 ep = 184375 iters * 64 images/iter / 118000 images/ep -train.max_iter = 184375 - -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[163889, 177546], - num_updates=train.max_iter, - ), - warmup_length=500 / train.max_iter, - warmup_factor=0.067, -) - -optimizer.lr = 0.1 -optimizer.weight_decay = 4e-5 diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ.py deleted file mode 100644 index 2a7c376da5f9269197c44079f3e0f3b09cdc63fa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 2 # 100ep -> 200ep - -lr_multiplier.scheduler.milestones = [ - milestone * 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ.py deleted file mode 100644 index 97586b8f5330a9d995a0bffd1f5e7bd5b5656462..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 4 # 100ep -> 400ep - -lr_multiplier.scheduler.milestones = [ - milestone * 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_50ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_50ep_LSJ.py deleted file mode 100644 index 2ca1ede262cf5c37a3a54778458c74aff1479411..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_R_50_FPN_50ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter //= 2 # 100ep -> 50ep - -lr_multiplier.scheduler.milestones = [ - milestone // 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ.py deleted file mode 100644 index ef0b6d16d4403fb5d16a3aeb71a22621a0be5e21..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ.py +++ /dev/null @@ -1,29 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) -from detectron2.config import LazyCall as L -from detectron2.modeling.backbone import RegNet -from detectron2.modeling.backbone.regnet import SimpleStem, ResBottleneckBlock - -# Config source: -# https://github.com/facebookresearch/detectron2/blob/main/configs/COCO-InstanceSegmentation/mask_rcnn_regnetx_4gf_dds_fpn_1x.py # noqa -model.backbone.bottom_up = L(RegNet)( - stem_class=SimpleStem, - stem_width=32, - block_class=ResBottleneckBlock, - depth=23, - w_a=38.65, - w_0=96, - w_m=2.43, - group_width=40, - norm="SyncBN", - out_features=["s1", "s2", "s3", "s4"], -) -model.pixel_std = [57.375, 57.120, 58.395] - -# RegNets benefit from enabling cudnn benchmark mode -train.cudnn_benchmark = True diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ.py deleted file mode 100644 index 731320e74ebed4d8ceec58c07cb906542b8b021b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 2 # 100ep -> 200ep - -lr_multiplier.scheduler.milestones = [ - milestone * 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ.py deleted file mode 100644 index 8f369a2afedb6c6e69fd52ff9a9a6b1cdf965937..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 4 # 100ep -> 400ep - -lr_multiplier.scheduler.milestones = [ - milestone * 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ.py deleted file mode 100644 index ba2c3274a493d5136507364558c8289eb6ee6259..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ.py +++ /dev/null @@ -1,30 +0,0 @@ -from .mask_rcnn_R_50_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) -from detectron2.config import LazyCall as L -from detectron2.modeling.backbone import RegNet -from detectron2.modeling.backbone.regnet import SimpleStem, ResBottleneckBlock - -# Config source: -# https://github.com/facebookresearch/detectron2/blob/main/configs/COCO-InstanceSegmentation/mask_rcnn_regnety_4gf_dds_fpn_1x.py # noqa -model.backbone.bottom_up = L(RegNet)( - stem_class=SimpleStem, - stem_width=32, - block_class=ResBottleneckBlock, - depth=22, - w_a=31.41, - w_0=96, - w_m=2.24, - group_width=64, - se_ratio=0.25, - norm="SyncBN", - out_features=["s1", "s2", "s3", "s4"], -) -model.pixel_std = [57.375, 57.120, 58.395] - -# RegNets benefit from enabling cudnn benchmark mode -train.cudnn_benchmark = True diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ.py deleted file mode 100644 index b867cc865e5ac4d7b70221da141894efd7cbd75c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 2 # 100ep -> 200ep - -lr_multiplier.scheduler.milestones = [ - milestone * 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ.py b/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ.py deleted file mode 100644 index 7b86ea8c6c5c48f5d26c9e0df7cf96e745b17b34..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ.py +++ /dev/null @@ -1,14 +0,0 @@ -from .mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -train.max_iter *= 4 # 100ep -> 400ep - -lr_multiplier.scheduler.milestones = [ - milestone * 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/configs/quick_schedules/README.md b/preprocess/detectron2/configs/quick_schedules/README.md deleted file mode 100644 index 4e6c82ef3f75a73c7006f33d7c850a0d4781a58f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/README.md +++ /dev/null @@ -1,8 +0,0 @@ -These are quick configs for performance or accuracy regression tracking purposes. - -* `*instance_test.yaml`: can train on 2 GPUs. They are used to test whether the training can - successfully finish. They are not expected to produce reasonable training results. -* `*inference_acc_test.yaml`: They should be run using `--eval-only`. They run inference using pre-trained models and verify - the results are as expected. -* `*training_acc_test.yaml`: They should be trained on 8 GPUs. They finish in about an hour and verify the training accuracy - is within the normal range. diff --git a/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index fc5a4116cb096278823049c1f823e99f8e16e97e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml" -MODEL: - WEIGHTS: "detectron2://Misc/cascade_mask_rcnn_R_50_FPN_3x/144998488/model_final_480dd8.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 50.18, 0.02], ["segm", "AP", 43.87, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_instant_test.yaml deleted file mode 100644 index e41a0fe7ffe9c3531741df49e546aa45cfe4fdee..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/cascade_mask_rcnn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml" -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index a2f37e5e2cc2a9e195e13703e9930e67e0f9a896..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-Detection/fast_rcnn_R_50_FPN_1x/137635226/model_final_e5f7ce.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 45.70, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_instant_test.yaml deleted file mode 100644 index 52fc0ec03c8b87ab2be1dda97bec1e8c93e6bb5c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/fast_rcnn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,15 +0,0 @@ -_BASE_: "../COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -DATASETS: - TRAIN: ("coco_2017_val_100",) - PROPOSAL_FILES_TRAIN: ("detectron2://COCO-Detection/rpn_R_50_FPN_1x/137258492/coco_2017_val_box_proposals_ee0dad.pkl", ) - TEST: ("coco_2017_val_100",) - PROPOSAL_FILES_TEST: ("detectron2://COCO-Detection/rpn_R_50_FPN_1x/137258492/coco_2017_val_box_proposals_ee0dad.pkl", ) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index 14cf2aa82aec52ad44e28ead0665dad811d55457..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x/137849621/model_final_a6e10b.pkl" -DATASETS: - TEST: ("keypoints_coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 52.47, 0.02], ["keypoints", "AP", 67.36, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_instant_test.yaml deleted file mode 100644 index 3dd209f693bd0bfdd46a2c9e7e750dede3abc141..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - KEYPOINT_ON: True - ROI_HEADS: - NUM_CLASSES: 1 -DATASETS: - TRAIN: ("keypoints_coco_2017_val_100",) - TEST: ("keypoints_coco_2017_val_100",) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_normalized_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_normalized_training_acc_test.yaml deleted file mode 100644 index 4b92392f1c4457033ae4c87a521e339fe9e184ce..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_normalized_training_acc_test.yaml +++ /dev/null @@ -1,30 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - KEYPOINT_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - BATCH_SIZE_PER_IMAGE: 256 - NUM_CLASSES: 1 - ROI_KEYPOINT_HEAD: - POOLER_RESOLUTION: 14 - POOLER_SAMPLING_RATIO: 2 - NORMALIZE_LOSS_BY_VISIBLE_KEYPOINTS: False - LOSS_WEIGHT: 4.0 - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 1.0 # Keypoint AP degrades when using plain L1 loss - RPN: - SMOOTH_L1_BETA: 0.2 # Keypoint AP degrades when using plain L1 loss -DATASETS: - TRAIN: ("keypoints_coco_2017_val",) - TEST: ("keypoints_coco_2017_val",) -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -SOLVER: - WARMUP_FACTOR: 0.33333333 - WARMUP_ITERS: 100 - STEPS: (5500, 5800) - MAX_ITER: 6000 -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 55.35, 1.0], ["keypoints", "AP", 76.91, 1.0]] diff --git a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_training_acc_test.yaml deleted file mode 100644 index 9bd962878fea64035887c48981beeb8d41bfdbd0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/keypoint_rcnn_R_50_FPN_training_acc_test.yaml +++ /dev/null @@ -1,28 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - KEYPOINT_ON: True - RESNETS: - DEPTH: 50 - ROI_HEADS: - BATCH_SIZE_PER_IMAGE: 256 - NUM_CLASSES: 1 - ROI_KEYPOINT_HEAD: - POOLER_RESOLUTION: 14 - POOLER_SAMPLING_RATIO: 2 - ROI_BOX_HEAD: - SMOOTH_L1_BETA: 1.0 # Keypoint AP degrades when using plain L1 loss - RPN: - SMOOTH_L1_BETA: 0.2 # Keypoint AP degrades when using plain L1 loss -DATASETS: - TRAIN: ("keypoints_coco_2017_val",) - TEST: ("keypoints_coco_2017_val",) -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -SOLVER: - WARMUP_FACTOR: 0.33333333 - WARMUP_ITERS: 100 - STEPS: (5500, 5800) - MAX_ITER: 6000 -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 53.5, 1.0], ["keypoints", "AP", 72.4, 1.0]] diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_GCV_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_GCV_instant_test.yaml deleted file mode 100644 index ab6e69812b94ea7e071f29d9a6937d5c70805b5b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_GCV_instant_test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - BASE_LR: 0.001 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: "value" - CLIP_VALUE: 1.0 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_inference_acc_test.yaml deleted file mode 100644 index b2d5b7ff87e069f8c774a230bdfd47b8c12d18a3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x/137849525/model_final_4ce675.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 47.37, 0.02], ["segm", "AP", 40.99, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_instant_test.yaml deleted file mode 100644 index 6c4f1214efa520944fd941daec082ad45c164a23..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_instant_test.yaml +++ /dev/null @@ -1,14 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - BASE_LR: 0.001 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_training_acc_test.yaml deleted file mode 100644 index f68dd8f96c7896b5fc95d694a399f2ce417c1deb..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_C4_training_acc_test.yaml +++ /dev/null @@ -1,22 +0,0 @@ -_BASE_: "../Base-RCNN-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - ROI_HEADS: - BATCH_SIZE_PER_IMAGE: 256 - MASK_ON: True -DATASETS: - TRAIN: ("coco_2017_val",) - TEST: ("coco_2017_val",) -INPUT: - MIN_SIZE_TRAIN: (600,) - MAX_SIZE_TRAIN: 1000 - MIN_SIZE_TEST: 800 - MAX_SIZE_TEST: 1000 -SOLVER: - IMS_PER_BATCH: 8 # base uses 16 - WARMUP_FACTOR: 0.33333 - WARMUP_ITERS: 100 - STEPS: (11000, 11600) - MAX_ITER: 12000 -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 41.88, 0.7], ["segm", "AP", 33.79, 0.5]] diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_DC5_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_DC5_inference_acc_test.yaml deleted file mode 100644 index e3ce6cf922ae07fba5b5e01edbac19bf58a8e9dd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_DC5_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x/137849551/model_final_84107b.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 47.44, 0.02], ["segm", "AP", 42.94, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index e5454bfd95cc37749c50aec7866f32d9a80ca2b7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "../COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 47.34, 0.02], ["segm", "AP", 42.67, 0.02], ["bbox_TTA", "AP", 49.11, 0.02], ["segm_TTA", "AP", 45.04, 0.02]] - AUG: - ENABLED: True - MIN_SIZES: (700, 800) # to save some time diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_instant_test.yaml deleted file mode 100644 index 6dbfcde0bf837990634d419a6dda1e2909c3cd7f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,14 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_pred_boxes_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_pred_boxes_training_acc_test.yaml deleted file mode 100644 index 52f78762bda23331c97afd523cf98a5c118b113e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_pred_boxes_training_acc_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "./mask_rcnn_R_50_FPN_training_acc_test.yaml" -MODEL: - ROI_BOX_HEAD: - TRAIN_ON_PRED_BOXES: True -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 42.6, 1.0], ["segm", "AP", 35.8, 0.8]] diff --git a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_training_acc_test.yaml deleted file mode 100644 index aadae4ce898761e1e40e5af65a9e5ea01053b936..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/mask_rcnn_R_50_FPN_training_acc_test.yaml +++ /dev/null @@ -1,21 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - ROI_HEADS: - BATCH_SIZE_PER_IMAGE: 256 - MASK_ON: True -DATASETS: - TRAIN: ("coco_2017_val",) - TEST: ("coco_2017_val",) -INPUT: - MIN_SIZE_TRAIN: (600,) - MAX_SIZE_TRAIN: 1000 - MIN_SIZE_TEST: 800 - MAX_SIZE_TEST: 1000 -SOLVER: - WARMUP_FACTOR: 0.3333333 - WARMUP_ITERS: 100 - STEPS: (5500, 5800) - MAX_ITER: 6000 -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 42.5, 1.0], ["segm", "AP", 35.8, 0.8]] diff --git a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_inference_acc_test.yaml deleted file mode 100644 index 70874e3a92c9034d75cbbebb145b61084ba15e42..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-PanopticSegmentation/panoptic_fpn_R_50_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-PanopticSegmentation/panoptic_fpn_R_50_3x/139514569/model_final_c10459.pkl" -DATASETS: - TEST: ("coco_2017_val_100_panoptic_separated",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 46.47, 0.02], ["segm", "AP", 43.39, 0.02], ["sem_seg", "mIoU", 42.55, 0.02], ["panoptic_seg", "PQ", 38.99, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_instant_test.yaml deleted file mode 100644 index 7cdee7bfcf6dc75dda52602a0d9177ad0a9cc6ed..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_instant_test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "PanopticFPN" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - SEM_SEG_HEAD: - LOSS_WEIGHT: 0.5 -DATASETS: - TRAIN: ("coco_2017_val_100_panoptic_separated",) - TEST: ("coco_2017_val_100_panoptic_separated",) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 1 diff --git a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_training_acc_test.yaml deleted file mode 100644 index f3bbf30196cb35434340d4c343cab0c96283cd4f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/panoptic_fpn_R_50_training_acc_test.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "PanopticFPN" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - SEM_SEG_HEAD: - LOSS_WEIGHT: 0.5 -DATASETS: - TRAIN: ("coco_2017_val_panoptic_separated",) - TEST: ("coco_2017_val_panoptic_separated",) -SOLVER: - BASE_LR: 0.01 - WARMUP_FACTOR: 0.001 - WARMUP_ITERS: 500 - STEPS: (5500,) - MAX_ITER: 7000 -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 46.70, 1.1], ["segm", "AP", 39.0, 0.7], ["sem_seg", "mIoU", 64.73, 1.3], ["panoptic_seg", "PQ", 48.13, 0.8]] diff --git a/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index cb666c1a6b3e351227046bc9c2af8799408858e8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-Detection/retinanet_R_50_FPN_3x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-Detection/retinanet_R_50_FPN_3x/190397829/model_final_5bd44e.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 44.45, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_instant_test.yaml deleted file mode 100644 index 8d95c1f614296716374686b22055a587ccd052b9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/retinanet_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "../COCO-Detection/retinanet_R_50_FPN_1x.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index c7c3f908a9e80e98b2d25b6d384a60acaba9d4f8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_BASE_: "../COCO-Detection/rpn_R_50_FPN_1x.yaml" -MODEL: - WEIGHTS: "detectron2://COCO-Detection/rpn_R_50_FPN_1x/137258492/model_final_02ce48.pkl" -DATASETS: - TEST: ("coco_2017_val_100",) -TEST: - EXPECTED_RESULTS: [["box_proposals", "AR@1000", 58.16, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_instant_test.yaml deleted file mode 100644 index 402d432477507dc36f04c4a9777cb80fe06b2809..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/rpn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "../COCO-Detection/rpn_R_50_FPN_1x.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -DATASETS: - TRAIN: ("coco_2017_val_100",) - TEST: ("coco_2017_val_100",) -SOLVER: - STEPS: (30,) - MAX_ITER: 40 - BASE_LR: 0.005 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index bca74987d5218736983617883e0fe37f79d219b7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - WEIGHTS: "detectron2://semantic_R_50_FPN_1x/111802073/model_final_c18079783c55a94968edc28b7101c5f0.pkl" - RESNETS: - DEPTH: 50 -DATASETS: - TEST: ("coco_2017_val_100_panoptic_stuffonly",) -TEST: - EXPECTED_RESULTS: [["sem_seg", "mIoU", 39.53, 0.02], ["sem_seg", "mACC", 51.50, 0.02]] diff --git a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_instant_test.yaml b/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_instant_test.yaml deleted file mode 100644 index 14ab606f219b462fe37fcc7d5fbdbe65cb5c2642..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -DATASETS: - TRAIN: ("coco_2017_val_100_panoptic_stuffonly",) - TEST: ("coco_2017_val_100_panoptic_stuffonly",) -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -SOLVER: - BASE_LR: 0.005 - STEPS: (30,) - MAX_ITER: 40 - IMS_PER_BATCH: 4 -DATALOADER: - NUM_WORKERS: 2 diff --git a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_training_acc_test.yaml b/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_training_acc_test.yaml deleted file mode 100644 index 1f78d775889b11e9e76743de5ddb8139198edf61..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/configs/quick_schedules/semantic_R_50_FPN_training_acc_test.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "../Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -DATASETS: - TRAIN: ("coco_2017_val_panoptic_stuffonly",) - TEST: ("coco_2017_val_panoptic_stuffonly",) -SOLVER: - BASE_LR: 0.01 - WARMUP_FACTOR: 0.001 - WARMUP_ITERS: 300 - STEPS: (5500,) - MAX_ITER: 7000 -TEST: - EXPECTED_RESULTS: [["sem_seg", "mIoU", 76.51, 1.0], ["sem_seg", "mACC", 83.25, 1.0]] -INPUT: - # no scale augmentation - MIN_SIZE_TRAIN: (800, ) diff --git a/preprocess/detectron2/datasets/README.md b/preprocess/detectron2/datasets/README.md deleted file mode 100644 index 0eb44cc3b23beeb1755ab8d12002d26f13434235..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/datasets/README.md +++ /dev/null @@ -1,140 +0,0 @@ -# Use Builtin Datasets - -A dataset can be used by accessing [DatasetCatalog](https://detectron2.readthedocs.io/modules/data.html#detectron2.data.DatasetCatalog) -for its data, or [MetadataCatalog](https://detectron2.readthedocs.io/modules/data.html#detectron2.data.MetadataCatalog) for its metadata (class names, etc). -This document explains how to setup the builtin datasets so they can be used by the above APIs. -[Use Custom Datasets](https://detectron2.readthedocs.io/tutorials/datasets.html) gives a deeper dive on how to use `DatasetCatalog` and `MetadataCatalog`, -and how to add new datasets to them. - -Detectron2 has builtin support for a few datasets. -The datasets are assumed to exist in a directory specified by the environment variable -`DETECTRON2_DATASETS`. -Under this directory, detectron2 will look for datasets in the structure described below, if needed. -``` -$DETECTRON2_DATASETS/ - coco/ - lvis/ - cityscapes/ - VOC20{07,12}/ -``` - -You can set the location for builtin datasets by `export DETECTRON2_DATASETS=/path/to/datasets`. -If left unset, the default is `./datasets` relative to your current working directory. - -The [model zoo](https://github.com/facebookresearch/detectron2/blob/master/MODEL_ZOO.md) -contains configs and models that use these builtin datasets. - -## Expected dataset structure for [COCO instance/keypoint detection](https://cocodataset.org/#download): - -``` -coco/ - annotations/ - instances_{train,val}2017.json - person_keypoints_{train,val}2017.json - {train,val}2017/ - # image files that are mentioned in the corresponding json -``` - -You can use the 2014 version of the dataset as well. - -Some of the builtin tests (`dev/run_*_tests.sh`) uses a tiny version of the COCO dataset, -which you can download with `./datasets/prepare_for_tests.sh`. - -## Expected dataset structure for PanopticFPN: - -Extract panoptic annotations from [COCO website](https://cocodataset.org/#download) -into the following structure: -``` -coco/ - annotations/ - panoptic_{train,val}2017.json - panoptic_{train,val}2017/ # png annotations - panoptic_stuff_{train,val}2017/ # generated by the script mentioned below -``` - -Install panopticapi by: -``` -pip install git+https://github.com/cocodataset/panopticapi.git -``` -Then, run `python datasets/prepare_panoptic_fpn.py`, to extract semantic annotations from panoptic annotations. - -## Expected dataset structure for [LVIS instance segmentation](https://www.lvisdataset.org/dataset): -``` -coco/ - {train,val,test}2017/ -lvis/ - lvis_v0.5_{train,val}.json - lvis_v0.5_image_info_test.json - lvis_v1_{train,val}.json - lvis_v1_image_info_test{,_challenge}.json -``` - -Install lvis-api by: -``` -pip install git+https://github.com/lvis-dataset/lvis-api.git -``` - -To evaluate models trained on the COCO dataset using LVIS annotations, -run `python datasets/prepare_cocofied_lvis.py` to prepare "cocofied" LVIS annotations. - -## Expected dataset structure for [cityscapes](https://www.cityscapes-dataset.com/downloads/): -``` -cityscapes/ - gtFine/ - train/ - aachen/ - color.png, instanceIds.png, labelIds.png, polygons.json, - labelTrainIds.png - ... - val/ - test/ - # below are generated Cityscapes panoptic annotation - cityscapes_panoptic_train.json - cityscapes_panoptic_train/ - cityscapes_panoptic_val.json - cityscapes_panoptic_val/ - cityscapes_panoptic_test.json - cityscapes_panoptic_test/ - leftImg8bit/ - train/ - val/ - test/ -``` -Install cityscapes scripts by: -``` -pip install git+https://github.com/mcordts/cityscapesScripts.git -``` - -Note: to create labelTrainIds.png, first prepare the above structure, then run cityscapesescript with: -``` -CITYSCAPES_DATASET=/path/to/abovementioned/cityscapes python cityscapesscripts/preparation/createTrainIdLabelImgs.py -``` -These files are not needed for instance segmentation. - -Note: to generate Cityscapes panoptic dataset, run cityscapesescript with: -``` -CITYSCAPES_DATASET=/path/to/abovementioned/cityscapes python cityscapesscripts/preparation/createPanopticImgs.py -``` -These files are not needed for semantic and instance segmentation. - -## Expected dataset structure for [Pascal VOC](http://host.robots.ox.ac.uk/pascal/VOC/index.html): -``` -VOC20{07,12}/ - Annotations/ - ImageSets/ - Main/ - trainval.txt - test.txt - # train.txt or val.txt, if you use these splits - JPEGImages/ -``` - -## Expected dataset structure for [ADE20k Scene Parsing](http://sceneparsing.csail.mit.edu/): -``` -ADEChallengeData2016/ - annotations/ - annotations_detectron2/ - images/ - objectInfo150.txt -``` -The directory `annotations_detectron2` is generated by running `python datasets/prepare_ade20k_sem_seg.py`. diff --git a/preprocess/detectron2/datasets/prepare_ade20k_sem_seg.py b/preprocess/detectron2/datasets/prepare_ade20k_sem_seg.py deleted file mode 100755 index 8b4a58d8f2877544498e328b6d269f23aa1eb59f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/datasets/prepare_ade20k_sem_seg.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import os -from pathlib import Path -import tqdm -from PIL import Image - - -def convert(input, output): - img = np.asarray(Image.open(input)) - assert img.dtype == np.uint8 - img = img - 1 # 0 (ignore) becomes 255. others are shifted by 1 - Image.fromarray(img).save(output) - - -if __name__ == "__main__": - dataset_dir = Path(os.getenv("DETECTRON2_DATASETS", "datasets")) / "ADEChallengeData2016" - for name in ["training", "validation"]: - annotation_dir = dataset_dir / "annotations" / name - output_dir = dataset_dir / "annotations_detectron2" / name - output_dir.mkdir(parents=True, exist_ok=True) - for file in tqdm.tqdm(list(annotation_dir.iterdir())): - output_file = output_dir / file.name - convert(file, output_file) diff --git a/preprocess/detectron2/datasets/prepare_cocofied_lvis.py b/preprocess/detectron2/datasets/prepare_cocofied_lvis.py deleted file mode 100755 index 245c88482a9e2405e5a912b5c560aed78a614a13..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/datasets/prepare_cocofied_lvis.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import copy -import json -import os -from collections import defaultdict - -# This mapping is extracted from the official LVIS mapping: -# https://github.com/lvis-dataset/lvis-api/blob/master/data/coco_to_synset.json -COCO_SYNSET_CATEGORIES = [ - {"synset": "person.n.01", "coco_cat_id": 1}, - {"synset": "bicycle.n.01", "coco_cat_id": 2}, - {"synset": "car.n.01", "coco_cat_id": 3}, - {"synset": "motorcycle.n.01", "coco_cat_id": 4}, - {"synset": "airplane.n.01", "coco_cat_id": 5}, - {"synset": "bus.n.01", "coco_cat_id": 6}, - {"synset": "train.n.01", "coco_cat_id": 7}, - {"synset": "truck.n.01", "coco_cat_id": 8}, - {"synset": "boat.n.01", "coco_cat_id": 9}, - {"synset": "traffic_light.n.01", "coco_cat_id": 10}, - {"synset": "fireplug.n.01", "coco_cat_id": 11}, - {"synset": "stop_sign.n.01", "coco_cat_id": 13}, - {"synset": "parking_meter.n.01", "coco_cat_id": 14}, - {"synset": "bench.n.01", "coco_cat_id": 15}, - {"synset": "bird.n.01", "coco_cat_id": 16}, - {"synset": "cat.n.01", "coco_cat_id": 17}, - {"synset": "dog.n.01", "coco_cat_id": 18}, - {"synset": "horse.n.01", "coco_cat_id": 19}, - {"synset": "sheep.n.01", "coco_cat_id": 20}, - {"synset": "beef.n.01", "coco_cat_id": 21}, - {"synset": "elephant.n.01", "coco_cat_id": 22}, - {"synset": "bear.n.01", "coco_cat_id": 23}, - {"synset": "zebra.n.01", "coco_cat_id": 24}, - {"synset": "giraffe.n.01", "coco_cat_id": 25}, - {"synset": "backpack.n.01", "coco_cat_id": 27}, - {"synset": "umbrella.n.01", "coco_cat_id": 28}, - {"synset": "bag.n.04", "coco_cat_id": 31}, - {"synset": "necktie.n.01", "coco_cat_id": 32}, - {"synset": "bag.n.06", "coco_cat_id": 33}, - {"synset": "frisbee.n.01", "coco_cat_id": 34}, - {"synset": "ski.n.01", "coco_cat_id": 35}, - {"synset": "snowboard.n.01", "coco_cat_id": 36}, - {"synset": "ball.n.06", "coco_cat_id": 37}, - {"synset": "kite.n.03", "coco_cat_id": 38}, - {"synset": "baseball_bat.n.01", "coco_cat_id": 39}, - {"synset": "baseball_glove.n.01", "coco_cat_id": 40}, - {"synset": "skateboard.n.01", "coco_cat_id": 41}, - {"synset": "surfboard.n.01", "coco_cat_id": 42}, - {"synset": "tennis_racket.n.01", "coco_cat_id": 43}, - {"synset": "bottle.n.01", "coco_cat_id": 44}, - {"synset": "wineglass.n.01", "coco_cat_id": 46}, - {"synset": "cup.n.01", "coco_cat_id": 47}, - {"synset": "fork.n.01", "coco_cat_id": 48}, - {"synset": "knife.n.01", "coco_cat_id": 49}, - {"synset": "spoon.n.01", "coco_cat_id": 50}, - {"synset": "bowl.n.03", "coco_cat_id": 51}, - {"synset": "banana.n.02", "coco_cat_id": 52}, - {"synset": "apple.n.01", "coco_cat_id": 53}, - {"synset": "sandwich.n.01", "coco_cat_id": 54}, - {"synset": "orange.n.01", "coco_cat_id": 55}, - {"synset": "broccoli.n.01", "coco_cat_id": 56}, - {"synset": "carrot.n.01", "coco_cat_id": 57}, - {"synset": "frank.n.02", "coco_cat_id": 58}, - {"synset": "pizza.n.01", "coco_cat_id": 59}, - {"synset": "doughnut.n.02", "coco_cat_id": 60}, - {"synset": "cake.n.03", "coco_cat_id": 61}, - {"synset": "chair.n.01", "coco_cat_id": 62}, - {"synset": "sofa.n.01", "coco_cat_id": 63}, - {"synset": "pot.n.04", "coco_cat_id": 64}, - {"synset": "bed.n.01", "coco_cat_id": 65}, - {"synset": "dining_table.n.01", "coco_cat_id": 67}, - {"synset": "toilet.n.02", "coco_cat_id": 70}, - {"synset": "television_receiver.n.01", "coco_cat_id": 72}, - {"synset": "laptop.n.01", "coco_cat_id": 73}, - {"synset": "mouse.n.04", "coco_cat_id": 74}, - {"synset": "remote_control.n.01", "coco_cat_id": 75}, - {"synset": "computer_keyboard.n.01", "coco_cat_id": 76}, - {"synset": "cellular_telephone.n.01", "coco_cat_id": 77}, - {"synset": "microwave.n.02", "coco_cat_id": 78}, - {"synset": "oven.n.01", "coco_cat_id": 79}, - {"synset": "toaster.n.02", "coco_cat_id": 80}, - {"synset": "sink.n.01", "coco_cat_id": 81}, - {"synset": "electric_refrigerator.n.01", "coco_cat_id": 82}, - {"synset": "book.n.01", "coco_cat_id": 84}, - {"synset": "clock.n.01", "coco_cat_id": 85}, - {"synset": "vase.n.01", "coco_cat_id": 86}, - {"synset": "scissors.n.01", "coco_cat_id": 87}, - {"synset": "teddy.n.01", "coco_cat_id": 88}, - {"synset": "hand_blower.n.01", "coco_cat_id": 89}, - {"synset": "toothbrush.n.01", "coco_cat_id": 90}, -] - - -def cocofy_lvis(input_filename, output_filename): - """ - Filter LVIS instance segmentation annotations to remove all categories that are not included in - COCO. The new json files can be used to evaluate COCO AP using `lvis-api`. The category ids in - the output json are the incontiguous COCO dataset ids. - - Args: - input_filename (str): path to the LVIS json file. - output_filename (str): path to the COCOfied json file. - """ - - with open(input_filename, "r") as f: - lvis_json = json.load(f) - - lvis_annos = lvis_json.pop("annotations") - cocofied_lvis = copy.deepcopy(lvis_json) - lvis_json["annotations"] = lvis_annos - - # Mapping from lvis cat id to coco cat id via synset - lvis_cat_id_to_synset = {cat["id"]: cat["synset"] for cat in lvis_json["categories"]} - synset_to_coco_cat_id = {x["synset"]: x["coco_cat_id"] for x in COCO_SYNSET_CATEGORIES} - # Synsets that we will keep in the dataset - synsets_to_keep = set(synset_to_coco_cat_id.keys()) - coco_cat_id_with_instances = defaultdict(int) - - new_annos = [] - ann_id = 1 - for ann in lvis_annos: - lvis_cat_id = ann["category_id"] - synset = lvis_cat_id_to_synset[lvis_cat_id] - if synset not in synsets_to_keep: - continue - coco_cat_id = synset_to_coco_cat_id[synset] - new_ann = copy.deepcopy(ann) - new_ann["category_id"] = coco_cat_id - new_ann["id"] = ann_id - ann_id += 1 - new_annos.append(new_ann) - coco_cat_id_with_instances[coco_cat_id] += 1 - cocofied_lvis["annotations"] = new_annos - - for image in cocofied_lvis["images"]: - for key in ["not_exhaustive_category_ids", "neg_category_ids"]: - new_category_list = [] - for lvis_cat_id in image[key]: - synset = lvis_cat_id_to_synset[lvis_cat_id] - if synset not in synsets_to_keep: - continue - coco_cat_id = synset_to_coco_cat_id[synset] - new_category_list.append(coco_cat_id) - coco_cat_id_with_instances[coco_cat_id] += 1 - image[key] = new_category_list - - coco_cat_id_with_instances = set(coco_cat_id_with_instances.keys()) - - new_categories = [] - for cat in lvis_json["categories"]: - synset = cat["synset"] - if synset not in synsets_to_keep: - continue - coco_cat_id = synset_to_coco_cat_id[synset] - if coco_cat_id not in coco_cat_id_with_instances: - continue - new_cat = copy.deepcopy(cat) - new_cat["id"] = coco_cat_id - new_categories.append(new_cat) - cocofied_lvis["categories"] = new_categories - - with open(output_filename, "w") as f: - json.dump(cocofied_lvis, f) - print("{} is COCOfied and stored in {}.".format(input_filename, output_filename)) - - -if __name__ == "__main__": - dataset_dir = os.path.join(os.getenv("DETECTRON2_DATASETS", "datasets"), "lvis") - for s in ["lvis_v0.5_train", "lvis_v0.5_val"]: - print("Start COCOfing {}.".format(s)) - cocofy_lvis( - os.path.join(dataset_dir, "{}.json".format(s)), - os.path.join(dataset_dir, "{}_cocofied.json".format(s)), - ) diff --git a/preprocess/detectron2/datasets/prepare_for_tests.sh b/preprocess/detectron2/datasets/prepare_for_tests.sh deleted file mode 100755 index 67e875a41da652b2fcae6631b76d94584935ddb9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/datasets/prepare_for_tests.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -# Download the mini dataset (coco val2017_100, with only 100 images) -# to be used in unittests & integration tests. - -cd "${0%/*}" - -BASE=https://dl.fbaipublicfiles.com/detectron2 -ROOT=${DETECTRON2_DATASETS:-./} -ROOT=${ROOT/#\~/$HOME} # expand ~ to HOME -mkdir -p $ROOT/coco/annotations - -for anno in instances_val2017_100 \ - person_keypoints_val2017_100 ; do - - dest=$ROOT/coco/annotations/$anno.json - [[ -s $dest ]] && { - echo "$dest exists. Skipping ..." - } || { - wget $BASE/annotations/coco/$anno.json -O $dest - } -done - -dest=$ROOT/coco/val2017_100.tgz -[[ -d $ROOT/coco/val2017 ]] && { - echo "$ROOT/coco/val2017 exists. Skipping ..." -} || { - wget $BASE/annotations/coco/val2017_100.tgz -O $dest - tar xzf $dest -C $ROOT/coco/ && rm -f $dest -} diff --git a/preprocess/detectron2/datasets/prepare_panoptic_fpn.py b/preprocess/detectron2/datasets/prepare_panoptic_fpn.py deleted file mode 100755 index 597d791afab1bcc0013203a66c7fba225065eebe..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/datasets/prepare_panoptic_fpn.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import functools -import json -import multiprocessing as mp -import numpy as np -import os -import time -from fvcore.common.download import download -from panopticapi.utils import rgb2id -from PIL import Image - -from detectron2.data.datasets.builtin_meta import COCO_CATEGORIES - - -def _process_panoptic_to_semantic(input_panoptic, output_semantic, segments, id_map): - panoptic = np.asarray(Image.open(input_panoptic), dtype=np.uint32) - panoptic = rgb2id(panoptic) - output = np.zeros_like(panoptic, dtype=np.uint8) + 255 - for seg in segments: - cat_id = seg["category_id"] - new_cat_id = id_map[cat_id] - output[panoptic == seg["id"]] = new_cat_id - Image.fromarray(output).save(output_semantic) - - -def separate_coco_semantic_from_panoptic(panoptic_json, panoptic_root, sem_seg_root, categories): - """ - Create semantic segmentation annotations from panoptic segmentation - annotations, to be used by PanopticFPN. - - It maps all thing categories to class 0, and maps all unlabeled pixels to class 255. - It maps all stuff categories to contiguous ids starting from 1. - - Args: - panoptic_json (str): path to the panoptic json file, in COCO's format. - panoptic_root (str): a directory with panoptic annotation files, in COCO's format. - sem_seg_root (str): a directory to output semantic annotation files - categories (list[dict]): category metadata. Each dict needs to have: - "id": corresponds to the "category_id" in the json annotations - "isthing": 0 or 1 - """ - os.makedirs(sem_seg_root, exist_ok=True) - - stuff_ids = [k["id"] for k in categories if k["isthing"] == 0] - thing_ids = [k["id"] for k in categories if k["isthing"] == 1] - id_map = {} # map from category id to id in the output semantic annotation - assert len(stuff_ids) <= 254 - for i, stuff_id in enumerate(stuff_ids): - id_map[stuff_id] = i + 1 - for thing_id in thing_ids: - id_map[thing_id] = 0 - id_map[0] = 255 - - with open(panoptic_json) as f: - obj = json.load(f) - - pool = mp.Pool(processes=max(mp.cpu_count() // 2, 4)) - - def iter_annotations(): - for anno in obj["annotations"]: - file_name = anno["file_name"] - segments = anno["segments_info"] - input = os.path.join(panoptic_root, file_name) - output = os.path.join(sem_seg_root, file_name) - yield input, output, segments - - print("Start writing to {} ...".format(sem_seg_root)) - start = time.time() - pool.starmap( - functools.partial(_process_panoptic_to_semantic, id_map=id_map), - iter_annotations(), - chunksize=100, - ) - print("Finished. time: {:.2f}s".format(time.time() - start)) - - -if __name__ == "__main__": - dataset_dir = os.path.join(os.getenv("DETECTRON2_DATASETS", "datasets"), "coco") - for s in ["val2017", "train2017"]: - separate_coco_semantic_from_panoptic( - os.path.join(dataset_dir, "annotations/panoptic_{}.json".format(s)), - os.path.join(dataset_dir, "panoptic_{}".format(s)), - os.path.join(dataset_dir, "panoptic_stuff_{}".format(s)), - COCO_CATEGORIES, - ) - - # Prepare val2017_100 for quick testing: - - dest_dir = os.path.join(dataset_dir, "annotations/") - URL_PREFIX = "https://dl.fbaipublicfiles.com/detectron2/" - download(URL_PREFIX + "annotations/coco/panoptic_val2017_100.json", dest_dir) - with open(os.path.join(dest_dir, "panoptic_val2017_100.json")) as f: - obj = json.load(f) - - def link_val100(dir_full, dir_100): - print("Creating " + dir_100 + " ...") - os.makedirs(dir_100, exist_ok=True) - for img in obj["images"]: - basename = os.path.splitext(img["file_name"])[0] - src = os.path.join(dir_full, basename + ".png") - dst = os.path.join(dir_100, basename + ".png") - src = os.path.relpath(src, start=dir_100) - os.symlink(src, dst) - - link_val100( - os.path.join(dataset_dir, "panoptic_val2017"), - os.path.join(dataset_dir, "panoptic_val2017_100"), - ) - - link_val100( - os.path.join(dataset_dir, "panoptic_stuff_val2017"), - os.path.join(dataset_dir, "panoptic_stuff_val2017_100"), - ) diff --git a/preprocess/detectron2/demo/README.md b/preprocess/detectron2/demo/README.md deleted file mode 100644 index 133d8d38e5e9f5f44aca92c59f73309e166d7132..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/demo/README.md +++ /dev/null @@ -1,8 +0,0 @@ - -## Detectron2 Demo - -We provide a command line tool to run a simple demo of builtin configs. -The usage is explained in [GETTING_STARTED.md](../GETTING_STARTED.md). - -See our [blog post](https://ai.facebook.com/blog/-detectron2-a-pytorch-based-modular-object-detection-library-) -for a high-quality demo generated with this tool. diff --git a/preprocess/detectron2/demo/demo.py b/preprocess/detectron2/demo/demo.py deleted file mode 100755 index 6bd5bd295a21d9e4f5cc79bcd7dafaef1cb298f0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/demo/demo.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import argparse -import glob -import multiprocessing as mp -import os -import tempfile -import time -import warnings - -import cv2 -import numpy as np -import tqdm - -from detectron2.config import get_cfg -from detectron2.data.detection_utils import read_image -from detectron2.utils.logger import setup_logger - -from predictor import VisualizationDemo - -# constants -WINDOW_NAME = "COCO detections" - - -def setup_cfg(args): - # load config from file and command-line arguments - cfg = get_cfg() - # To use demo for Panoptic-DeepLab, please uncomment the following two lines. - # from detectron2.projects.panoptic_deeplab import add_panoptic_deeplab_config # noqa - # add_panoptic_deeplab_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - # Set score_threshold for builtin models - cfg.MODEL.RETINANET.SCORE_THRESH_TEST = args.confidence_threshold - cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = args.confidence_threshold - cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = ( - args.confidence_threshold - ) - cfg.freeze() - return cfg - - -def get_parser(): - parser = argparse.ArgumentParser(description="Detectron2 demo for builtin configs") - parser.add_argument( - "--config-file", - default="configs/quick_schedules/mask_rcnn_R_50_FPN_inference_acc_test.yaml", - metavar="FILE", - help="path to config file", - ) - parser.add_argument( - "--webcam", action="store_true", help="Take inputs from webcam." - ) - parser.add_argument("--video-input", help="Path to video file.") - parser.add_argument( - "--input", - nargs="+", - help="A list of space separated input images; " - "or a single glob pattern such as 'directory/*.jpg'", - ) - parser.add_argument( - "--output", - help="A file or directory to save output visualizations. " - "If not given, will show output in an OpenCV window.", - ) - - parser.add_argument( - "--confidence-threshold", - type=float, - default=0.5, - help="Minimum score for instance predictions to be shown", - ) - parser.add_argument( - "--opts", - help="Modify config options using the command-line 'KEY VALUE' pairs", - default=[], - nargs=argparse.REMAINDER, - ) - return parser - - -def test_opencv_video_format(codec, file_ext): - with tempfile.TemporaryDirectory(prefix="video_format_test") as dir: - filename = os.path.join(dir, "test_file" + file_ext) - writer = cv2.VideoWriter( - filename=filename, - fourcc=cv2.VideoWriter_fourcc(*codec), - fps=float(30), - frameSize=(10, 10), - isColor=True, - ) - [writer.write(np.zeros((10, 10, 3), np.uint8)) for _ in range(30)] - writer.release() - if os.path.isfile(filename): - return True - return False - - -def main() -> None: - mp.set_start_method("spawn", force=True) - args = get_parser().parse_args() - setup_logger(name="fvcore") - logger = setup_logger() - logger.info("Arguments: " + str(args)) - - cfg = setup_cfg(args) - - demo = VisualizationDemo(cfg) - - if args.input: - if len(args.input) == 1: - args.input = glob.glob(os.path.expanduser(args.input[0])) - assert args.input, "The input path(s) was not found" - for path in tqdm.tqdm(args.input, disable=not args.output): - # use PIL, to be consistent with evaluation - img = read_image(path, format="BGR") - start_time = time.time() - predictions, visualized_output = demo.run_on_image(img) - logger.info( - "{}: {} in {:.2f}s".format( - path, - "detected {} instances".format(len(predictions["instances"])) - if "instances" in predictions - else "finished", - time.time() - start_time, - ) - ) - - if args.output: - if os.path.isdir(args.output): - assert os.path.isdir(args.output), args.output - out_filename = os.path.join(args.output, os.path.basename(path)) - else: - assert ( - len(args.input) == 1 - ), "Please specify a directory with args.output" - out_filename = args.output - visualized_output.save(out_filename) - else: - cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL) - cv2.imshow(WINDOW_NAME, visualized_output.get_image()[:, :, ::-1]) - if cv2.waitKey(0) == 27: - break # esc to quit - elif args.webcam: - assert args.input is None, "Cannot have both --input and --webcam!" - assert args.output is None, "output not yet supported with --webcam!" - cam = cv2.VideoCapture(0) - for vis in tqdm.tqdm(demo.run_on_video(cam)): - cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL) - cv2.imshow(WINDOW_NAME, vis) - if cv2.waitKey(1) == 27: - break # esc to quit - cam.release() - cv2.destroyAllWindows() - elif args.video_input: - video = cv2.VideoCapture(args.video_input) - width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) - height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) - frames_per_second = video.get(cv2.CAP_PROP_FPS) - num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) - basename = os.path.basename(args.video_input) - codec, file_ext = ( - ("x264", ".mkv") - if test_opencv_video_format("x264", ".mkv") - else ("mp4v", ".mp4") - ) - if codec == ".mp4v": - warnings.warn("x264 codec not available, switching to mp4v") - if args.output: - if os.path.isdir(args.output): - output_fname = os.path.join(args.output, basename) - output_fname = os.path.splitext(output_fname)[0] + file_ext - else: - output_fname = args.output - assert not os.path.isfile(output_fname), output_fname - output_file = cv2.VideoWriter( - filename=output_fname, - # some installation of opencv may not support x264 (due to its license), - # you can try other format (e.g. MPEG) - fourcc=cv2.VideoWriter_fourcc(*codec), - fps=float(frames_per_second), - frameSize=(width, height), - isColor=True, - ) - assert os.path.isfile(args.video_input) - for vis_frame in tqdm.tqdm(demo.run_on_video(video), total=num_frames): - if args.output: - output_file.write(vis_frame) - else: - cv2.namedWindow(basename, cv2.WINDOW_NORMAL) - cv2.imshow(basename, vis_frame) - if cv2.waitKey(1) == 27: - break # esc to quit - video.release() - if args.output: - output_file.release() - else: - cv2.destroyAllWindows() - - -if __name__ == "__main__": - main() # pragma: no cover diff --git a/preprocess/detectron2/demo/predictor.py b/preprocess/detectron2/demo/predictor.py deleted file mode 100644 index 1c589a18b49a0c36f82396918544f653923def1d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/demo/predictor.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import atexit -import bisect -import multiprocessing as mp -from collections import deque -import cv2 -import torch - -from detectron2.data import MetadataCatalog -from detectron2.engine.defaults import DefaultPredictor -from detectron2.utils.video_visualizer import VideoVisualizer -from detectron2.utils.visualizer import ColorMode, Visualizer - - -class VisualizationDemo: - def __init__(self, cfg, instance_mode=ColorMode.IMAGE, parallel=False): - """ - Args: - cfg (CfgNode): - instance_mode (ColorMode): - parallel (bool): whether to run the model in different processes from visualization. - Useful since the visualization logic can be slow. - """ - self.metadata = MetadataCatalog.get( - cfg.DATASETS.TEST[0] if len(cfg.DATASETS.TEST) else "__unused" - ) - self.cpu_device = torch.device("cpu") - self.instance_mode = instance_mode - - self.parallel = parallel - if parallel: - num_gpu = torch.cuda.device_count() - self.predictor = AsyncPredictor(cfg, num_gpus=num_gpu) - else: - self.predictor = DefaultPredictor(cfg) - - def run_on_image(self, image): - """ - Args: - image (np.ndarray): an image of shape (H, W, C) (in BGR order). - This is the format used by OpenCV. - - Returns: - predictions (dict): the output of the model. - vis_output (VisImage): the visualized image output. - """ - vis_output = None - predictions = self.predictor(image) - # Convert image from OpenCV BGR format to Matplotlib RGB format. - image = image[:, :, ::-1] - visualizer = Visualizer(image, self.metadata, instance_mode=self.instance_mode) - if "panoptic_seg" in predictions: - panoptic_seg, segments_info = predictions["panoptic_seg"] - vis_output = visualizer.draw_panoptic_seg_predictions( - panoptic_seg.to(self.cpu_device), segments_info - ) - else: - if "sem_seg" in predictions: - vis_output = visualizer.draw_sem_seg( - predictions["sem_seg"].argmax(dim=0).to(self.cpu_device) - ) - if "instances" in predictions: - instances = predictions["instances"].to(self.cpu_device) - vis_output = visualizer.draw_instance_predictions(predictions=instances) - - return predictions, vis_output - - def _frame_from_video(self, video): - while video.isOpened(): - success, frame = video.read() - if success: - yield frame - else: - break - - def run_on_video(self, video): - """ - Visualizes predictions on frames of the input video. - - Args: - video (cv2.VideoCapture): a :class:`VideoCapture` object, whose source can be - either a webcam or a video file. - - Yields: - ndarray: BGR visualizations of each video frame. - """ - video_visualizer = VideoVisualizer(self.metadata, self.instance_mode) - - def process_predictions(frame, predictions): - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - if "panoptic_seg" in predictions: - panoptic_seg, segments_info = predictions["panoptic_seg"] - vis_frame = video_visualizer.draw_panoptic_seg_predictions( - frame, panoptic_seg.to(self.cpu_device), segments_info - ) - elif "instances" in predictions: - predictions = predictions["instances"].to(self.cpu_device) - vis_frame = video_visualizer.draw_instance_predictions(frame, predictions) - elif "sem_seg" in predictions: - vis_frame = video_visualizer.draw_sem_seg( - frame, predictions["sem_seg"].argmax(dim=0).to(self.cpu_device) - ) - - # Converts Matplotlib RGB format to OpenCV BGR format - vis_frame = cv2.cvtColor(vis_frame.get_image(), cv2.COLOR_RGB2BGR) - return vis_frame - - frame_gen = self._frame_from_video(video) - if self.parallel: - buffer_size = self.predictor.default_buffer_size - - frame_data = deque() - - for cnt, frame in enumerate(frame_gen): - frame_data.append(frame) - self.predictor.put(frame) - - if cnt >= buffer_size: - frame = frame_data.popleft() - predictions = self.predictor.get() - yield process_predictions(frame, predictions) - - while len(frame_data): - frame = frame_data.popleft() - predictions = self.predictor.get() - yield process_predictions(frame, predictions) - else: - for frame in frame_gen: - yield process_predictions(frame, self.predictor(frame)) - - -class AsyncPredictor: - """ - A predictor that runs the model asynchronously, possibly on >1 GPUs. - Because rendering the visualization takes considerably amount of time, - this helps improve throughput a little bit when rendering videos. - """ - - class _StopToken: - pass - - class _PredictWorker(mp.Process): - def __init__(self, cfg, task_queue, result_queue): - self.cfg = cfg - self.task_queue = task_queue - self.result_queue = result_queue - super().__init__() - - def run(self): - predictor = DefaultPredictor(self.cfg) - - while True: - task = self.task_queue.get() - if isinstance(task, AsyncPredictor._StopToken): - break - idx, data = task - result = predictor(data) - self.result_queue.put((idx, result)) - - def __init__(self, cfg, num_gpus: int = 1): - """ - Args: - cfg (CfgNode): - num_gpus (int): if 0, will run on CPU - """ - num_workers = max(num_gpus, 1) - self.task_queue = mp.Queue(maxsize=num_workers * 3) - self.result_queue = mp.Queue(maxsize=num_workers * 3) - self.procs = [] - for gpuid in range(max(num_gpus, 1)): - cfg = cfg.clone() - cfg.defrost() - cfg.MODEL.DEVICE = "cuda:{}".format(gpuid) if num_gpus > 0 else "cpu" - self.procs.append( - AsyncPredictor._PredictWorker(cfg, self.task_queue, self.result_queue) - ) - - self.put_idx = 0 - self.get_idx = 0 - self.result_rank = [] - self.result_data = [] - - for p in self.procs: - p.start() - atexit.register(self.shutdown) - - def put(self, image): - self.put_idx += 1 - self.task_queue.put((self.put_idx, image)) - - def get(self): - self.get_idx += 1 # the index needed for this request - if len(self.result_rank) and self.result_rank[0] == self.get_idx: - res = self.result_data[0] - del self.result_data[0], self.result_rank[0] - return res - - while True: - # make sure the results are returned in the correct order - idx, res = self.result_queue.get() - if idx == self.get_idx: - return res - insert = bisect.bisect(self.result_rank, idx) - self.result_rank.insert(insert, idx) - self.result_data.insert(insert, res) - - def __len__(self): - return self.put_idx - self.get_idx - - def __call__(self, image): - self.put(image) - return self.get() - - def shutdown(self): - for _ in self.procs: - self.task_queue.put(AsyncPredictor._StopToken()) - - @property - def default_buffer_size(self): - return len(self.procs) * 5 diff --git a/preprocess/detectron2/dev/README.md b/preprocess/detectron2/dev/README.md deleted file mode 100644 index bec811ad002a016f2137d9d0ea61c27ee5e78992..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/README.md +++ /dev/null @@ -1,7 +0,0 @@ - -## Some scripts for developers to use, include: - -- `linter.sh`: lint the codebase before commit. -- `run_{inference,instant}_tests.sh`: run inference/training for a few iterations. - Note that these tests require 2 GPUs. -- `parse_results.sh`: parse results from a log file. diff --git a/preprocess/detectron2/dev/linter.sh b/preprocess/detectron2/dev/linter.sh deleted file mode 100755 index 55793e01819853987e81e6a14a5905ce0b40bf81..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/linter.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -# cd to detectron2 project root -cd "$(dirname "${BASH_SOURCE[0]}")/.." - -{ - black --version | grep -E "22\." > /dev/null -} || { - echo "Linter requires 'black==22.*' !" - exit 1 -} - -ISORT_VERSION=$(isort --version-number) -if [[ "$ISORT_VERSION" != 4.3* ]]; then - echo "Linter requires isort==4.3.21 !" - exit 1 -fi - -set -v - -echo "Running isort ..." -isort -y -sp . --atomic - -echo "Running black ..." -black -l 100 . - -echo "Running flake8 ..." -if [ -x "$(command -v flake8)" ]; then - flake8 . -else - python3 -m flake8 . -fi - -# echo "Running mypy ..." -# Pytorch does not have enough type annotations -# mypy detectron2/solver detectron2/structures detectron2/config - -echo "Running clang-format ..." -find . -regex ".*\.\(cpp\|c\|cc\|cu\|cxx\|h\|hh\|hpp\|hxx\|tcc\|mm\|m\)" -print0 | xargs -0 clang-format -i - -command -v arc > /dev/null && arc lint diff --git a/preprocess/detectron2/dev/packaging/README.md b/preprocess/detectron2/dev/packaging/README.md deleted file mode 100644 index 0174b7dd528efcaa0fe27d46f40a3866f03e7c41..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/packaging/README.md +++ /dev/null @@ -1,17 +0,0 @@ - -## To build a cu101 wheel for release: - -``` -$ nvidia-docker run -it --storage-opt "size=20GB" --name pt pytorch/manylinux-cuda101 -# inside the container: -# git clone https://github.com/facebookresearch/detectron2/ -# cd detectron2 -# export CU_VERSION=cu101 D2_VERSION_SUFFIX= PYTHON_VERSION=3.7 PYTORCH_VERSION=1.8 -# ./dev/packaging/build_wheel.sh -``` - -## To build all wheels for combinations of CUDA and Python -``` -./dev/packaging/build_all_wheels.sh -./dev/packaging/gen_wheel_index.sh /path/to/wheels -``` diff --git a/preprocess/detectron2/dev/packaging/build_all_wheels.sh b/preprocess/detectron2/dev/packaging/build_all_wheels.sh deleted file mode 100755 index 00f9de5e27867bf210438190c2951a571ac1f3fc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/packaging/build_all_wheels.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -[[ -d "dev/packaging" ]] || { - echo "Please run this script at detectron2 root!" - exit 1 -} - -build_one() { - cu=$1 - pytorch_ver=$2 - - case "$cu" in - cu*) - container_name=manylinux-cuda${cu/cu/} - ;; - cpu) - container_name=manylinux-cuda101 - ;; - *) - echo "Unrecognized cu=$cu" - exit 1 - ;; - esac - - echo "Launching container $container_name ..." - container_id="$container_name"_"$cu"_"$pytorch_ver" - - py_versions=(3.7 3.8 3.9) - - for py in "${py_versions[@]}"; do - docker run -itd \ - --name "$container_id" \ - --mount type=bind,source="$(pwd)",target=/detectron2 \ - pytorch/$container_name - - cat </dev/null 2>&1 && pwd )" -. "$script_dir/pkg_helpers.bash" - -echo "Build Settings:" -echo "CU_VERSION: $CU_VERSION" # e.g. cu101 -echo "D2_VERSION_SUFFIX: $D2_VERSION_SUFFIX" # e.g. +cu101 or "" -echo "PYTHON_VERSION: $PYTHON_VERSION" # e.g. 3.7 -echo "PYTORCH_VERSION: $PYTORCH_VERSION" # e.g. 1.4 - -setup_cuda -setup_wheel_python - -yum install ninja-build -y -ln -sv /usr/bin/ninja-build /usr/bin/ninja || true - -pip_install pip numpy -U -pip_install "torch==$PYTORCH_VERSION" \ - -f https://download.pytorch.org/whl/"$CU_VERSION"/torch_stable.html - -# use separate directories to allow parallel build -BASE_BUILD_DIR=build/$CU_VERSION-py$PYTHON_VERSION-pt$PYTORCH_VERSION -python setup.py \ - build -b "$BASE_BUILD_DIR" \ - bdist_wheel -b "$BASE_BUILD_DIR/build_dist" -d "wheels/$CU_VERSION/torch$PYTORCH_VERSION" -rm -rf "$BASE_BUILD_DIR" diff --git a/preprocess/detectron2/dev/packaging/gen_install_table.py b/preprocess/detectron2/dev/packaging/gen_install_table.py deleted file mode 100755 index b4c852dc53de613707b9668f748184c2b63b9dea..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/packaging/gen_install_table.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -# -*- coding: utf-8 -*- - -import argparse - -template = """
install
\
-python -m pip install detectron2{d2_version} -f \\
-  https://dl.fbaipublicfiles.com/detectron2/wheels/{cuda}/torch{torch}/index.html
-
""" -CUDA_SUFFIX = { - "11.3": "cu113", - "11.1": "cu111", - "11.0": "cu110", - "10.2": "cu102", - "10.1": "cu101", - "10.0": "cu100", - "9.2": "cu92", - "cpu": "cpu", -} - - -def gen_header(torch_versions): - return '' + "".join( - [ - ''.format(t) - for t in torch_versions - ] - ) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--d2-version", help="detectron2 version number, default to empty") - args = parser.parse_args() - d2_version = f"=={args.d2_version}" if args.d2_version else "" - - all_versions = ( - [("1.8", k) for k in ["11.1", "10.2", "10.1", "cpu"]] - + [("1.9", k) for k in ["11.1", "10.2", "cpu"]] - + [("1.10", k) for k in ["11.3", "11.1", "10.2", "cpu"]] - ) - - torch_versions = sorted( - {k[0] for k in all_versions}, key=lambda x: int(x.split(".")[1]), reverse=True - ) - cuda_versions = sorted( - {k[1] for k in all_versions}, key=lambda x: float(x) if x != "cpu" else 0, reverse=True - ) - - table = gen_header(torch_versions) - for cu in cuda_versions: - table += f""" """ - cu_suffix = CUDA_SUFFIX[cu] - for torch in torch_versions: - if (torch, cu) in all_versions: - cell = template.format(d2_version=d2_version, cuda=cu_suffix, torch=torch) - else: - cell = "" - table += f""" """ - table += "" - table += "
CUDA torch {}
{cu}{cell}
" - print(table) diff --git a/preprocess/detectron2/dev/packaging/gen_wheel_index.sh b/preprocess/detectron2/dev/packaging/gen_wheel_index.sh deleted file mode 100755 index ec96a27d809fe87ad963f3ffa7147ca4afbc1711..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/packaging/gen_wheel_index.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - - -root=$(readlink -f $1) -if [[ -z "$root" ]]; then - echo "Usage: ./gen_wheel_index.sh /absolute/path/to/wheels" - exit -fi - -export LC_ALL=C # reproducible sort -# NOTE: all sort in this script might not work when xx.10 is released - -index=$root/index.html - -cd "$root" -for cu in cpu cu92 cu100 cu101 cu102 cu110 cu111 cu113; do - mkdir -p "$root/$cu" - cd "$root/$cu" - echo "Creating $PWD/index.html ..." - # First sort by torch version, then stable sort by d2 version with unique. - # As a result, the latest torch version for each d2 version is kept. - for whl in $(find -type f -name '*.whl' -printf '%P\n' \ - | sort -k 1 -r | sort -t '/' -k 2 --stable -r --unique); do - echo "$whl
" - done > index.html - - - for torch in torch*; do - cd "$root/$cu/$torch" - - # list all whl for each cuda,torch version - echo "Creating $PWD/index.html ..." - for whl in $(find . -type f -name '*.whl' -printf '%P\n' | sort -r); do - echo "$whl
" - done > index.html - done -done - -cd "$root" -# Just list everything: -echo "Creating $index ..." -for whl in $(find . -type f -name '*.whl' -printf '%P\n' | sort -r); do - echo "$whl
" -done > "$index" - diff --git a/preprocess/detectron2/dev/packaging/pkg_helpers.bash b/preprocess/detectron2/dev/packaging/pkg_helpers.bash deleted file mode 100755 index 550bb6e5756d43da3d30c8cd9b602b3bd30a7e4a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/packaging/pkg_helpers.bash +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -# Function to retry functions that sometimes timeout or have flaky failures -retry () { - $* || (sleep 1 && $*) || (sleep 2 && $*) || (sleep 4 && $*) || (sleep 8 && $*) -} -# Install with pip a bit more robustly than the default -pip_install() { - retry pip install --progress-bar off "$@" -} - - -setup_cuda() { - # Now work out the CUDA settings - # Like other torch domain libraries, we choose common GPU architectures only. - # See https://github.com/pytorch/pytorch/blob/master/torch/utils/cpp_extension.py - # and https://github.com/pytorch/vision/blob/main/packaging/pkg_helpers.bash for reference. - export FORCE_CUDA=1 - case "$CU_VERSION" in - cu113) - export CUDA_HOME=/usr/local/cuda-11.3/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX;8.0;8.6+PTX" - ;; - cu112) - export CUDA_HOME=/usr/local/cuda-11.2/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX;8.0;8.6+PTX" - ;; - cu111) - export CUDA_HOME=/usr/local/cuda-11.1/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX;8.0;8.6+PTX" - ;; - cu110) - export CUDA_HOME=/usr/local/cuda-11.0/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX;8.0+PTX" - ;; - cu102) - export CUDA_HOME=/usr/local/cuda-10.2/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX" - ;; - cu101) - export CUDA_HOME=/usr/local/cuda-10.1/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX" - ;; - cu100) - export CUDA_HOME=/usr/local/cuda-10.0/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0;7.5+PTX" - ;; - cu92) - export CUDA_HOME=/usr/local/cuda-9.2/ - export TORCH_CUDA_ARCH_LIST="3.7;5.0;5.2;6.0;6.1+PTX;7.0+PTX" - ;; - cpu) - unset FORCE_CUDA - export CUDA_VISIBLE_DEVICES= - ;; - *) - echo "Unrecognized CU_VERSION=$CU_VERSION" - exit 1 - ;; - esac -} - -setup_wheel_python() { - case "$PYTHON_VERSION" in - 3.7) python_abi=cp37-cp37m ;; - 3.8) python_abi=cp38-cp38 ;; - 3.9) python_abi=cp39-cp39 ;; - *) - echo "Unrecognized PYTHON_VERSION=$PYTHON_VERSION" - exit 1 - ;; - esac - export PATH="/opt/python/$python_abi/bin:$PATH" -} diff --git a/preprocess/detectron2/dev/parse_results.sh b/preprocess/detectron2/dev/parse_results.sh deleted file mode 100755 index 80768a4005753447c49339790fe66c9b82a80aaf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/parse_results.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. - -# A shell script that parses metrics from the log file. -# Make it easier for developers to track performance of models. - -LOG="$1" - -if [[ -z "$LOG" ]]; then - echo "Usage: $0 /path/to/log/file" - exit 1 -fi - -# [12/15 11:47:32] trainer INFO: Total training time: 12:15:04.446477 (0.4900 s / it) -# [12/15 11:49:03] inference INFO: Total inference time: 0:01:25.326167 (0.13652186737060548 s / img per device, on 8 devices) -# [12/15 11:49:03] inference INFO: Total inference pure compute time: ..... - -# training time -trainspeed=$(grep -o 'Overall training.*' "$LOG" | grep -Eo '\(.*\)' | grep -o '[0-9\.]*') -echo "Training speed: $trainspeed s/it" - -# inference time: there could be multiple inference during training -inferencespeed=$(grep -o 'Total inference pure.*' "$LOG" | tail -n1 | grep -Eo '\(.*\)' | grep -o '[0-9\.]*' | head -n1) -echo "Inference speed: $inferencespeed s/it" - -# [12/15 11:47:18] trainer INFO: eta: 0:00:00 iter: 90000 loss: 0.5407 (0.7256) loss_classifier: 0.1744 (0.2446) loss_box_reg: 0.0838 (0.1160) loss_mask: 0.2159 (0.2722) loss_objectness: 0.0244 (0.0429) loss_rpn_box_reg: 0.0279 (0.0500) time: 0.4487 (0.4899) data: 0.0076 (0.0975) lr: 0.000200 max mem: 4161 -memory=$(grep -o 'max[_ ]mem: [0-9]*' "$LOG" | tail -n1 | grep -o '[0-9]*') -echo "Training memory: $memory MB" - -echo "Easy to copypaste:" -echo "$trainspeed","$inferencespeed","$memory" - -echo "------------------------------" - -# [12/26 17:26:32] engine.coco_evaluation: copypaste: Task: bbox -# [12/26 17:26:32] engine.coco_evaluation: copypaste: AP,AP50,AP75,APs,APm,APl -# [12/26 17:26:32] engine.coco_evaluation: copypaste: 0.0017,0.0024,0.0017,0.0005,0.0019,0.0011 -# [12/26 17:26:32] engine.coco_evaluation: copypaste: Task: segm -# [12/26 17:26:32] engine.coco_evaluation: copypaste: AP,AP50,AP75,APs,APm,APl -# [12/26 17:26:32] engine.coco_evaluation: copypaste: 0.0014,0.0021,0.0016,0.0005,0.0016,0.0011 - -echo "COCO Results:" -num_tasks=$(grep -o 'copypaste:.*Task.*' "$LOG" | sort -u | wc -l) -# each task has 3 lines -grep -o 'copypaste:.*' "$LOG" | cut -d ' ' -f 2- | tail -n $((num_tasks * 3)) diff --git a/preprocess/detectron2/dev/run_inference_tests.sh b/preprocess/detectron2/dev/run_inference_tests.sh deleted file mode 100755 index bc9dcc56f06f79fc5efa42c04ffdc07c2787e3ac..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/run_inference_tests.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -BIN="python tools/train_net.py" -OUTPUT="inference_test_output" -NUM_GPUS=2 - -CFG_LIST=( "${@:1}" ) - -if [ ${#CFG_LIST[@]} -eq 0 ]; then - CFG_LIST=( ./configs/quick_schedules/*inference_acc_test.yaml ) -fi - -echo "========================================================================" -echo "Configs to run:" -echo "${CFG_LIST[@]}" -echo "========================================================================" - - -for cfg in "${CFG_LIST[@]}"; do - echo "========================================================================" - echo "Running $cfg ..." - echo "========================================================================" - $BIN \ - --eval-only \ - --num-gpus $NUM_GPUS \ - --config-file "$cfg" \ - OUTPUT_DIR $OUTPUT - rm -rf $OUTPUT -done - - -echo "========================================================================" -echo "Running demo.py ..." -echo "========================================================================" -DEMO_BIN="python demo/demo.py" -COCO_DIR=datasets/coco/val2014 -mkdir -pv $OUTPUT - -set -v - -$DEMO_BIN --config-file ./configs/quick_schedules/panoptic_fpn_R_50_inference_acc_test.yaml \ - --input $COCO_DIR/COCO_val2014_0000001933* --output $OUTPUT -rm -rf $OUTPUT diff --git a/preprocess/detectron2/dev/run_instant_tests.sh b/preprocess/detectron2/dev/run_instant_tests.sh deleted file mode 100755 index 9fd9ba0c239d3e982c17711c9db872de3730decf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/dev/run_instant_tests.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -BIN="python tools/train_net.py" -OUTPUT="instant_test_output" -NUM_GPUS=2 - -CFG_LIST=( "${@:1}" ) -if [ ${#CFG_LIST[@]} -eq 0 ]; then - CFG_LIST=( ./configs/quick_schedules/*instant_test.yaml ) -fi - -echo "========================================================================" -echo "Configs to run:" -echo "${CFG_LIST[@]}" -echo "========================================================================" - -for cfg in "${CFG_LIST[@]}"; do - echo "========================================================================" - echo "Running $cfg ..." - echo "========================================================================" - $BIN --num-gpus $NUM_GPUS --config-file "$cfg" \ - SOLVER.IMS_PER_BATCH $(($NUM_GPUS * 2)) \ - OUTPUT_DIR "$OUTPUT" - rm -rf "$OUTPUT" -done - diff --git a/preprocess/detectron2/docker/Dockerfile b/preprocess/detectron2/docker/Dockerfile deleted file mode 100644 index fae0060b2b78b26e4cef9631a04e84db4eb2c567..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docker/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -FROM nvidia/cuda:11.1.1-cudnn8-devel-ubuntu18.04 -# use an older system (18.04) to avoid opencv incompatibility (issue#3524) - -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update && apt-get install -y \ - python3-opencv ca-certificates python3-dev git wget sudo ninja-build -RUN ln -sv /usr/bin/python3 /usr/bin/python - -# create a non-root user -ARG USER_ID=1000 -RUN useradd -m --no-log-init --system --uid ${USER_ID} appuser -g sudo -RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers -USER appuser -WORKDIR /home/appuser - -ENV PATH="/home/appuser/.local/bin:${PATH}" -RUN wget https://bootstrap.pypa.io/pip/3.6/get-pip.py && \ - python3 get-pip.py --user && \ - rm get-pip.py - -# install dependencies -# See https://pytorch.org/ for other options if you use a different version of CUDA -RUN pip install --user tensorboard cmake onnx # cmake from apt-get is too old -RUN pip install --user torch==1.10 torchvision==0.11.1 -f https://download.pytorch.org/whl/cu111/torch_stable.html - -RUN pip install --user 'git+https://github.com/facebookresearch/fvcore' -# install detectron2 -RUN git clone https://github.com/facebookresearch/detectron2 detectron2_repo -# set FORCE_CUDA because during `docker build` cuda is not accessible -ENV FORCE_CUDA="1" -# This will by default build detectron2 for all common cuda architectures and take a lot more time, -# because inside `docker build`, there is no way to tell which architecture will be used. -ARG TORCH_CUDA_ARCH_LIST="Kepler;Kepler+Tesla;Maxwell;Maxwell+Tegra;Pascal;Volta;Turing" -ENV TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST}" - -RUN pip install --user -e detectron2_repo - -# Set a fixed model cache directory. -ENV FVCORE_CACHE="/tmp" -WORKDIR /home/appuser/detectron2_repo - -# run detectron2 under user "appuser": -# wget http://images.cocodataset.org/val2017/000000439715.jpg -O input.jpg -# python3 demo/demo.py \ - #--config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ - #--input input.jpg --output outputs/ \ - #--opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl diff --git a/preprocess/detectron2/docker/README.md b/preprocess/detectron2/docker/README.md deleted file mode 100644 index ea709f33b007abd2de044a0338659ec003330725..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docker/README.md +++ /dev/null @@ -1,45 +0,0 @@ - -## Use the container (with docker ≥ 19.03) - -``` -cd docker/ -# Build: -docker build --build-arg USER_ID=$UID -t detectron2:v0 . -# Launch (require GPUs): -docker run --gpus all -it \ - --shm-size=8gb --env="DISPLAY" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ - --name=detectron2 detectron2:v0 - -# Grant docker access to host X server to show images -xhost +local:`docker inspect --format='{{ .Config.Hostname }}' detectron2` -``` - -## Use the container (with docker-compose ≥ 1.28.0) - -Install docker-compose and nvidia-docker-toolkit, then run: -``` -cd docker && USER_ID=$UID docker-compose run detectron2 -``` - -## Use the deployment container (to test C++ examples) -After building the base detectron2 container as above, do: -``` -# Build: -docker build -t detectron2-deploy:v0 -f deploy.Dockerfile . -# Launch: -docker run --gpus all -it detectron2-deploy:v0 -``` - -#### Using a persistent cache directory - -You can prevent models from being re-downloaded on every run, -by storing them in a cache directory. - -To do this, add `--volume=$HOME/.torch/fvcore_cache:/tmp:rw` in the run command. - -## Install new dependencies -Add the following to `Dockerfile` to make persistent changes. -``` -RUN sudo apt-get update && sudo apt-get install -y vim -``` -Or run them in the container to make temporary changes. diff --git a/preprocess/detectron2/docker/deploy.Dockerfile b/preprocess/detectron2/docker/deploy.Dockerfile deleted file mode 100644 index 30b4ed774368af89d654c9f01850d769e6cf9f52..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docker/deploy.Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# This file defines a container that compiles the C++ examples of detectron2. -# See docker/README.md for usage. - -# Depends on the image produced by "./Dockerfile" -FROM detectron2:v0 - -USER appuser -ENV HOME=/home/appuser -WORKDIR $HOME - -# Let torchvision find libtorch -ENV CMAKE_PREFIX_PATH=$HOME/.local/lib/python3.6/site-packages/torch/ - -RUN sudo apt-get update && sudo apt-get install libopencv-dev --yes - -# install libtorchvision -RUN git clone --branch v0.11.1 https://github.com/pytorch/vision/ -RUN mkdir vision/build && cd vision/build && \ - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_BUILD_TYPE=Release -DWITH_CUDA=on -DTORCH_CUDA_ARCH_LIST=$TORCH_CUDA_ARCH_LIST && \ - make -j && make install - -# make our installation take effect -ENV CPATH=$HOME/.local/include \ - LIBRARY_PATH=$HOME/.local/lib \ - LD_LIBRARY_PATH=$HOME/.local/lib - - -# build C++ examples of detectron2 -RUN cd detectron2_repo/tools/deploy && mkdir build && cd build && \ - cmake -DTORCH_CUDA_ARCH_LIST=$TORCH_CUDA_ARCH_LIST .. && make -# binaries will be available under tools/deploy/build diff --git a/preprocess/detectron2/docker/docker-compose.yml b/preprocess/detectron2/docker/docker-compose.yml deleted file mode 100644 index 6665ab4c4bd40cae9973417b5b8d4c0c1edd7fc7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docker/docker-compose.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: "2.3" -services: - detectron2: - build: - context: . - dockerfile: Dockerfile - args: - USER_ID: ${USER_ID:-1000} - deploy: - resources: - reservations: - devices: - - capabilities: - - gpu - shm_size: "8gb" - ulimits: - memlock: -1 - stack: 67108864 - volumes: - - /tmp/.X11-unix:/tmp/.X11-unix:ro - environment: - - DISPLAY=$DISPLAY - - NVIDIA_VISIBLE_DEVICES=all - # Uncomment with proper source to access webcam from docker - # devices: - # - /dev/video0:/dev/video0 diff --git a/preprocess/detectron2/docs/.gitignore b/preprocess/detectron2/docs/.gitignore deleted file mode 100644 index e35d8850c9688b1ce82711694692cc574a799396..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_build diff --git a/preprocess/detectron2/docs/Makefile b/preprocess/detectron2/docs/Makefile deleted file mode 100644 index 718eddce170fe13b67216baf9d4d25b20e860506..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Minimal makefile for Sphinx documentation -# Copyright (c) Facebook, Inc. and its affiliates. - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/preprocess/detectron2/docs/README.md b/preprocess/detectron2/docs/README.md deleted file mode 100644 index 8531cafd4d1aae0267f4fc5e7212f7db5ed90686..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Read the docs: - -The latest documentation built from this directory is available at [detectron2.readthedocs.io](https://detectron2.readthedocs.io/). -Documents in this directory are not meant to be read on github. - -# Build the docs: - -1. Install detectron2 according to [INSTALL.md](../INSTALL.md). -2. Install additional libraries required to build docs: - - docutils==0.16 - - Sphinx==3.2.0 - - recommonmark==0.6.0 - - sphinx_rtd_theme - -3. Run `make html` from this directory. diff --git a/preprocess/detectron2/docs/_static/css/custom.css b/preprocess/detectron2/docs/_static/css/custom.css deleted file mode 100644 index 6c511764cf4c1d55a227619a98e5ba6578619ad7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/_static/css/custom.css +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * some extra css to make markdown look similar between github/sphinx - */ - -/* - * Below is for install.md: - */ -.rst-content code { - white-space: pre; - border: 0px; -} - -.rst-content th { - border: 1px solid #e1e4e5; -} - -.rst-content th p { - /* otherwise will be default 24px for regular paragraph */ - margin-bottom: 0px; -} - -.rst-content .line-block { - /* otherwise will be 24px */ - margin-bottom: 0px; -} - -div.section > details { - padding-bottom: 1em; -} diff --git a/preprocess/detectron2/docs/conf.py b/preprocess/detectron2/docs/conf.py deleted file mode 100644 index 1fb3e30f97dcc02b497e7c6de6bcc9e47ea94885..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/conf.py +++ /dev/null @@ -1,395 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -# flake8: noqa - -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -from unittest import mock -from sphinx.domains import Domain -from typing import Dict, List, Tuple - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -import sphinx_rtd_theme - - -class GithubURLDomain(Domain): - """ - Resolve certain links in markdown files to github source. - """ - - name = "githuburl" - ROOT = "https://github.com/facebookresearch/detectron2/blob/main/" - LINKED_DOC = ["tutorials/install", "tutorials/getting_started"] - - def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode): - github_url = None - if not target.endswith("html") and target.startswith("../../"): - url = target.replace("../", "") - github_url = url - if fromdocname in self.LINKED_DOC: - # unresolved links in these docs are all github links - github_url = target - - if github_url is not None: - if github_url.endswith("MODEL_ZOO") or github_url.endswith("README"): - # bug of recommonmark. - # https://github.com/readthedocs/recommonmark/blob/ddd56e7717e9745f11300059e4268e204138a6b1/recommonmark/parser.py#L152-L155 - github_url += ".md" - print("Ref {} resolved to github:{}".format(target, github_url)) - contnode["refuri"] = self.ROOT + github_url - return [("githuburl:any", contnode)] - else: - return [] - - -# to support markdown -from recommonmark.parser import CommonMarkParser - -sys.path.insert(0, os.path.abspath("../")) -os.environ["_DOC_BUILDING"] = "True" -DEPLOY = os.environ.get("READTHEDOCS") == "True" - - -# -- Project information ----------------------------------------------------- - -# fmt: off -try: - import torch # noqa -except ImportError: - for m in [ - "torch", "torchvision", "torch.nn", "torch.nn.parallel", "torch.distributed", "torch.multiprocessing", "torch.autograd", - "torch.autograd.function", "torch.nn.modules", "torch.nn.modules.utils", "torch.utils", "torch.utils.data", "torch.onnx", - "torchvision", "torchvision.ops", - ]: - sys.modules[m] = mock.Mock(name=m) - sys.modules['torch'].__version__ = "1.7" # fake version - HAS_TORCH = False -else: - try: - torch.ops.detectron2 = mock.Mock(name="torch.ops.detectron2") - except: - pass - HAS_TORCH = True - -for m in [ - "cv2", "scipy", "portalocker", "detectron2._C", - "pycocotools", "pycocotools.mask", "pycocotools.coco", "pycocotools.cocoeval", - "google", "google.protobuf", "google.protobuf.internal", "onnx", - "caffe2", "caffe2.proto", "caffe2.python", "caffe2.python.utils", "caffe2.python.onnx", "caffe2.python.onnx.backend", -]: - sys.modules[m] = mock.Mock(name=m) -# fmt: on -sys.modules["cv2"].__version__ = "3.4" - -import detectron2 # isort: skip - -if HAS_TORCH: - from detectron2.utils.env import fixup_module_metadata - - fixup_module_metadata("torch.nn", torch.nn.__dict__) - fixup_module_metadata("torch.utils.data", torch.utils.data.__dict__) - - -project = "detectron2" -copyright = "2019-2020, detectron2 contributors" -author = "detectron2 contributors" - -# The short X.Y version -version = detectron2.__version__ -# The full version, including alpha/beta/rc tags -release = version - - -# -- General configuration --------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -needs_sphinx = "3.0" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "recommonmark", - "sphinx.ext.autodoc", - "sphinx.ext.napoleon", - "sphinx.ext.intersphinx", - "sphinx.ext.todo", - "sphinx.ext.coverage", - "sphinx.ext.mathjax", - "sphinx.ext.viewcode", - "sphinx.ext.githubpages", -] - -# -- Configurations for plugins ------------ -napoleon_google_docstring = True -napoleon_include_init_with_doc = True -napoleon_include_special_with_doc = True -napoleon_numpy_docstring = False -napoleon_use_rtype = False -autodoc_inherit_docstrings = False -autodoc_member_order = "bysource" - -if DEPLOY: - intersphinx_timeout = 10 -else: - # skip this when building locally - intersphinx_timeout = 0.5 -intersphinx_mapping = { - "python": ("https://docs.python.org/3.7", None), - "numpy": ("https://docs.scipy.org/doc/numpy/", None), - "torch": ("https://pytorch.org/docs/master/", None), -} -# ------------------------- - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -source_suffix = [".rst", ".md"] - -# The master toctree document. -master_doc = "index" - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "build", "README.md", "tutorials/README.md"] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - - -# -- Options for HTML output ------------------------------------------------- - -html_theme = "sphinx_rtd_theme" -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] -html_css_files = ["css/custom.css"] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = "detectron2doc" - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, "detectron2.tex", "detectron2 Documentation", "detectron2 contributors", "manual") -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "detectron2", "detectron2 Documentation", [author], 1)] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "detectron2", - "detectron2 Documentation", - author, - "detectron2", - "One line description of project.", - "Miscellaneous", - ) -] - - -# -- Options for todo extension ---------------------------------------------- - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -def autodoc_skip_member(app, what, name, obj, skip, options): - # we hide something deliberately - if getattr(obj, "__HIDE_SPHINX_DOC__", False): - return True - - # Hide some that are deprecated or not intended to be used - HIDDEN = { - "ResNetBlockBase", - "GroupedBatchSampler", - "build_transform_gen", - "apply_transform_gens", - "TransformGen", - "apply_augmentations", - "StandardAugInput", - "build_batch_data_loader", - "draw_panoptic_seg_predictions", - "WarmupCosineLR", - "WarmupMultiStepLR", - "downgrade_config", - "upgrade_config", - "add_export_config", - } - try: - if name in HIDDEN or ( - hasattr(obj, "__doc__") and obj.__doc__.lower().strip().startswith("deprecated") - ): - print("Skipping deprecated object: {}".format(name)) - return True - except: - pass - return skip - - -_PAPER_DATA = { - "resnet": ("1512.03385", "Deep Residual Learning for Image Recognition"), - "fpn": ("1612.03144", "Feature Pyramid Networks for Object Detection"), - "mask r-cnn": ("1703.06870", "Mask R-CNN"), - "faster r-cnn": ( - "1506.01497", - "Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks", - ), - "deformconv": ("1703.06211", "Deformable Convolutional Networks"), - "deformconv2": ("1811.11168", "Deformable ConvNets v2: More Deformable, Better Results"), - "panopticfpn": ("1901.02446", "Panoptic Feature Pyramid Networks"), - "retinanet": ("1708.02002", "Focal Loss for Dense Object Detection"), - "cascade r-cnn": ("1712.00726", "Cascade R-CNN: Delving into High Quality Object Detection"), - "lvis": ("1908.03195", "LVIS: A Dataset for Large Vocabulary Instance Segmentation"), - "rrpn": ("1703.01086", "Arbitrary-Oriented Scene Text Detection via Rotation Proposals"), - "imagenet in 1h": ("1706.02677", "Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour"), - "xception": ("1610.02357", "Xception: Deep Learning with Depthwise Separable Convolutions"), - "mobilenet": ( - "1704.04861", - "MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications", - ), - "deeplabv3+": ( - "1802.02611", - "Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation", - ), - "dds": ("2003.13678", "Designing Network Design Spaces"), - "scaling": ("2103.06877", "Fast and Accurate Model Scaling"), - "fcos": ("2006.09214", "FCOS: A Simple and Strong Anchor-free Object Detector"), - "rethinking-batchnorm": ("2105.07576", 'Rethinking "Batch" in BatchNorm'), - "vitdet": ("2203.16527", "Exploring Plain Vision Transformer Backbones for Object Detection"), - "mvitv2": ( - "2112.01526", - "MViTv2: Improved Multiscale Vision Transformers for Classification and Detection", - ), - "swin": ( - "2103.14030", - "Swin Transformer: Hierarchical Vision Transformer using Shifted Windows", - ), - "omni3d": ( - "2207.10660", - "Omni3D: A Large Benchmark and Model for 3D Object Detection in the Wild", - ), -} - - -def paper_ref_role( - typ: str, - rawtext: str, - text: str, - lineno: int, - inliner, - options: Dict = {}, - content: List[str] = [], -): - """ - Parse :paper:`xxx`. Similar to the "extlinks" sphinx extension. - """ - from docutils import nodes, utils - from sphinx.util.nodes import split_explicit_title - - text = utils.unescape(text) - has_explicit_title, title, link = split_explicit_title(text) - link = link.lower() - if link not in _PAPER_DATA: - inliner.reporter.warning("Cannot find paper " + link) - paper_url, paper_title = "#", link - else: - paper_url, paper_title = _PAPER_DATA[link] - if "/" not in paper_url: - paper_url = "https://arxiv.org/abs/" + paper_url - if not has_explicit_title: - title = paper_title - pnode = nodes.reference(title, title, internal=False, refuri=paper_url) - return [pnode], [] - - -def setup(app): - from recommonmark.transform import AutoStructify - - app.add_domain(GithubURLDomain) - app.connect("autodoc-skip-member", autodoc_skip_member) - app.add_role("paper", paper_ref_role) - app.add_config_value( - "recommonmark_config", - {"enable_math": True, "enable_inline_math": True, "enable_eval_rst": True}, - True, - ) - app.add_transform(AutoStructify) diff --git a/preprocess/detectron2/docs/index.rst b/preprocess/detectron2/docs/index.rst deleted file mode 100644 index 8634b7b12ab906c10a78d6053428029799282ffd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. detectron2 documentation master file, created by - sphinx-quickstart on Sat Sep 21 13:46:45 2019. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to detectron2's documentation! -====================================== - -.. toctree:: - :maxdepth: 2 - - tutorials/index - notes/index - modules/index diff --git a/preprocess/detectron2/docs/modules/checkpoint.rst b/preprocess/detectron2/docs/modules/checkpoint.rst deleted file mode 100644 index 449caaffd8a9d5e13040cb64aca073703c579a5d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/checkpoint.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.checkpoint -============================= - -.. automodule:: detectron2.checkpoint - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/config.rst b/preprocess/detectron2/docs/modules/config.rst deleted file mode 100644 index c76913d83e696dfb02a8c25e8cd38bb25ad121f9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/config.rst +++ /dev/null @@ -1,18 +0,0 @@ -detectron2.config -========================= - -Related tutorials: :doc:`../tutorials/configs`, :doc:`../tutorials/extend`. - -.. automodule:: detectron2.config - :members: - :undoc-members: - :show-inheritance: - - -Yaml Config References ------------------ - -.. literalinclude:: ../../detectron2/config/defaults.py - :language: python - :linenos: - :lines: 7- diff --git a/preprocess/detectron2/docs/modules/data.rst b/preprocess/detectron2/docs/modules/data.rst deleted file mode 100644 index 0d5bd89166fe6ad1d414c85055081f3fa9145764..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/data.rst +++ /dev/null @@ -1,37 +0,0 @@ -detectron2.data -======================= - -.. autodata:: detectron2.data.DatasetCatalog(dict) - :annotation: - -.. autodata:: detectron2.data.MetadataCatalog(dict) - :annotation: - -.. automodule:: detectron2.data - :members: - :undoc-members: - :show-inheritance: - -detectron2.data.detection\_utils module ---------------------------------------- - -.. automodule:: detectron2.data.detection_utils - :members: - :undoc-members: - :show-inheritance: - -detectron2.data.datasets module ---------------------------------------- - -.. automodule:: detectron2.data.datasets - :members: - :undoc-members: - :show-inheritance: - -detectron2.data.samplers module ---------------------------------------- - -.. automodule:: detectron2.data.samplers - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/data_transforms.rst b/preprocess/detectron2/docs/modules/data_transforms.rst deleted file mode 100644 index 1533a434bc1374a9825aa4fed0fab8abb2e8c02f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/data_transforms.rst +++ /dev/null @@ -1,10 +0,0 @@ -detectron2.data.transforms -==================================== - -Related tutorial: :doc:`../tutorials/augmentation`. - -.. automodule:: detectron2.data.transforms - :members: - :undoc-members: - :show-inheritance: - :imported-members: diff --git a/preprocess/detectron2/docs/modules/engine.rst b/preprocess/detectron2/docs/modules/engine.rst deleted file mode 100644 index 7e0d2b0762a601566772b97aaedb3c55b447fab5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/engine.rst +++ /dev/null @@ -1,26 +0,0 @@ -detectron2.engine -========================= - -Related tutorial: :doc:`../tutorials/training`. - -.. automodule:: detectron2.engine - :members: - :undoc-members: - :show-inheritance: - - -detectron2.engine.defaults module ---------------------------------- - -.. automodule:: detectron2.engine.defaults - :members: - :undoc-members: - :show-inheritance: - -detectron2.engine.hooks module ---------------------------------- - -.. automodule:: detectron2.engine.hooks - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/evaluation.rst b/preprocess/detectron2/docs/modules/evaluation.rst deleted file mode 100644 index 69bfc4b9ef52ed26c61ec3d3feb5aa9bfa28da26..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/evaluation.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.evaluation -============================= - -.. automodule:: detectron2.evaluation - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/export.rst b/preprocess/detectron2/docs/modules/export.rst deleted file mode 100644 index dcee14f869a7c0e60a1e861e07ecf1c49d272dac..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/export.rst +++ /dev/null @@ -1,9 +0,0 @@ -detectron2.export -========================= - -Related tutorial: :doc:`../tutorials/deployment`. - -.. automodule:: detectron2.export - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/fvcore.rst b/preprocess/detectron2/docs/modules/fvcore.rst deleted file mode 100644 index c8bf9f58aea97cfad6430dd3c30924603cecf7ce..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/fvcore.rst +++ /dev/null @@ -1,49 +0,0 @@ -fvcore documentation -==================== - -Detectron2 depends on utilities in -`fvcore `_. -We include part of fvcore documentation here for easier reference. - -fvcore.nn ------------------ - -.. automodule:: fvcore.nn - :members: - :inherited-members: - :undoc-members: - :show-inheritance: - -fvcore.common ---------------------- - -.. automodule:: fvcore.common.checkpoint - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: fvcore.common.config - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: fvcore.common.history_buffer - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: fvcore.common.param_scheduler - :members: - :inherited-members: - :undoc-members: - :show-inheritance: - -.. automodule:: fvcore.common.registry - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: fvcore.common.timer - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/index.rst b/preprocess/detectron2/docs/modules/index.rst deleted file mode 100644 index 14b754395bfbc581a181c7062acc47311103969d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -API Documentation -================== - -.. toctree:: - - checkpoint - config - data - data_transforms - engine - evaluation - layers - model_zoo - modeling - solver - structures - utils - export - fvcore diff --git a/preprocess/detectron2/docs/modules/layers.rst b/preprocess/detectron2/docs/modules/layers.rst deleted file mode 100644 index b43b42a7d9d01ec9fa8ef8a56019efa2bc494677..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/layers.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.layers -========================= - -.. automodule:: detectron2.layers - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/model_zoo.rst b/preprocess/detectron2/docs/modules/model_zoo.rst deleted file mode 100644 index 5abbad1ffe191480177e2173308cdc946159cf46..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/model_zoo.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.model_zoo -============================ - -.. automodule:: detectron2.model_zoo - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/modeling.rst b/preprocess/detectron2/docs/modules/modeling.rst deleted file mode 100644 index a22c7ed35f4b694264c49c854109eb2fa85c20ea..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/modeling.rst +++ /dev/null @@ -1,58 +0,0 @@ -detectron2.modeling -=========================== - -.. automodule:: detectron2.modeling - :members: - :undoc-members: - :show-inheritance: - - -detectron2.modeling.poolers module ---------------------------------------- - -.. automodule:: detectron2.modeling.poolers - :members: - :undoc-members: - :show-inheritance: - - -detectron2.modeling.sampling module ------------------------------------- - -.. automodule:: detectron2.modeling.sampling - :members: - :undoc-members: - :show-inheritance: - - -detectron2.modeling.box_regression module ------------------------------------------- - -.. automodule:: detectron2.modeling.box_regression - :members: - :undoc-members: - :show-inheritance: - - -Model Registries ------------------ - -These are different registries provided in modeling. -Each registry provide you the ability to replace it with your customized component, -without having to modify detectron2's code. - -Note that it is impossible to allow users to customize any line of code directly. -Even just to add one line at some place, -you'll likely need to find out the smallest registry which contains that line, -and register your component to that registry. - - -.. autodata:: detectron2.modeling.META_ARCH_REGISTRY -.. autodata:: detectron2.modeling.BACKBONE_REGISTRY -.. autodata:: detectron2.modeling.PROPOSAL_GENERATOR_REGISTRY -.. autodata:: detectron2.modeling.RPN_HEAD_REGISTRY -.. autodata:: detectron2.modeling.ANCHOR_GENERATOR_REGISTRY -.. autodata:: detectron2.modeling.ROI_HEADS_REGISTRY -.. autodata:: detectron2.modeling.ROI_BOX_HEAD_REGISTRY -.. autodata:: detectron2.modeling.ROI_MASK_HEAD_REGISTRY -.. autodata:: detectron2.modeling.ROI_KEYPOINT_HEAD_REGISTRY diff --git a/preprocess/detectron2/docs/modules/solver.rst b/preprocess/detectron2/docs/modules/solver.rst deleted file mode 100644 index 59d98c72cceca33831681b5392d8bbec53fe70ad..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/solver.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.solver -========================= - -.. automodule:: detectron2.solver - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/structures.rst b/preprocess/detectron2/docs/modules/structures.rst deleted file mode 100644 index 1369dc0882d387930cd4f571f80c3c3157af6de6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/structures.rst +++ /dev/null @@ -1,7 +0,0 @@ -detectron2.structures -============================= - -.. automodule:: detectron2.structures - :members: - :undoc-members: - :show-inheritance: diff --git a/preprocess/detectron2/docs/modules/utils.rst b/preprocess/detectron2/docs/modules/utils.rst deleted file mode 100644 index ab58f2caf26b3beb08f72dd93d06485af5ace5c0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/modules/utils.rst +++ /dev/null @@ -1,80 +0,0 @@ -detectron2.utils -======================== - -detectron2.utils.colormap module --------------------------------- - -.. automodule:: detectron2.utils.colormap - :members: - :undoc-members: - :show-inheritance: - -detectron2.utils.comm module ----------------------------- - -.. automodule:: detectron2.utils.comm - :members: - :undoc-members: - :show-inheritance: - - -detectron2.utils.events module ------------------------------- - -.. automodule:: detectron2.utils.events - :members: - :undoc-members: - :show-inheritance: - - -detectron2.utils.logger module ------------------------------- - -.. automodule:: detectron2.utils.logger - :members: - :undoc-members: - :show-inheritance: - - -detectron2.utils.registry module --------------------------------- - -.. automodule:: detectron2.utils.registry - :members: - :undoc-members: - :show-inheritance: - -detectron2.utils.memory module ----------------------------------- - -.. automodule:: detectron2.utils.memory - :members: - :undoc-members: - :show-inheritance: - - -detectron2.utils.analysis module ----------------------------------- - -.. automodule:: detectron2.utils.analysis - :members: - :undoc-members: - :show-inheritance: - - -detectron2.utils.visualizer module ----------------------------------- - -.. automodule:: detectron2.utils.visualizer - :members: - :undoc-members: - :show-inheritance: - -detectron2.utils.video\_visualizer module ------------------------------------------ - -.. automodule:: detectron2.utils.video_visualizer - :members: - :undoc-members: - :show-inheritance: - diff --git a/preprocess/detectron2/docs/notes/benchmarks.md b/preprocess/detectron2/docs/notes/benchmarks.md deleted file mode 100644 index b41588daf3a039b9034e80366c2710e90ba3e056..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/notes/benchmarks.md +++ /dev/null @@ -1,196 +0,0 @@ - -# Benchmarks - -Here we benchmark the training speed of a Mask R-CNN in detectron2, -with some other popular open source Mask R-CNN implementations. - - -### Settings - -* Hardware: 8 NVIDIA V100s with NVLink. -* Software: Python 3.7, CUDA 10.1, cuDNN 7.6.5, PyTorch 1.5, - TensorFlow 1.15.0rc2, Keras 2.2.5, MxNet 1.6.0b20190820. -* Model: an end-to-end R-50-FPN Mask-RCNN model, using the same hyperparameter as the - [Detectron baseline config](https://github.com/facebookresearch/Detectron/blob/master/configs/12_2017_baselines/e2e_mask_rcnn_R-50-FPN_1x.yaml) - (it does not have scale augmentation). -* Metrics: We use the average throughput in iterations 100-500 to skip GPU warmup time. - Note that for R-CNN-style models, the throughput of a model typically changes during training, because - it depends on the predictions of the model. Therefore this metric is not directly comparable with - "train speed" in model zoo, which is the average speed of the entire training run. - - -### Main Results - -```eval_rst -+-------------------------------+--------------------+ -| Implementation | Throughput (img/s) | -+===============================+====================+ -| |D2| |PT| | 62 | -+-------------------------------+--------------------+ -| mmdetection_ |PT| | 53 | -+-------------------------------+--------------------+ -| maskrcnn-benchmark_ |PT| | 53 | -+-------------------------------+--------------------+ -| tensorpack_ |TF| | 50 | -+-------------------------------+--------------------+ -| simpledet_ |mxnet| | 39 | -+-------------------------------+--------------------+ -| Detectron_ |C2| | 19 | -+-------------------------------+--------------------+ -| `matterport/Mask_RCNN`__ |TF| | 14 | -+-------------------------------+--------------------+ - -.. _maskrcnn-benchmark: https://github.com/facebookresearch/maskrcnn-benchmark/ -.. _tensorpack: https://github.com/tensorpack/tensorpack/tree/master/examples/FasterRCNN -.. _mmdetection: https://github.com/open-mmlab/mmdetection/ -.. _simpledet: https://github.com/TuSimple/simpledet/ -.. _Detectron: https://github.com/facebookresearch/Detectron -__ https://github.com/matterport/Mask_RCNN/ - -.. |D2| image:: https://github.com/facebookresearch/detectron2/raw/main/.github/Detectron2-Logo-Horz.svg?sanitize=true - :height: 15pt - :target: https://github.com/facebookresearch/detectron2/ -.. |PT| image:: https://pytorch.org/assets/images/logo-icon.svg - :width: 15pt - :height: 15pt - :target: https://pytorch.org -.. |TF| image:: https://static.nvidiagrid.net/ngc/containers/tensorflow.png - :width: 15pt - :height: 15pt - :target: https://tensorflow.org -.. |mxnet| image:: https://github.com/dmlc/web-data/raw/master/mxnet/image/mxnet_favicon.png - :width: 15pt - :height: 15pt - :target: https://mxnet.apache.org/ -.. |C2| image:: https://caffe2.ai/static/logo.svg - :width: 15pt - :height: 15pt - :target: https://caffe2.ai -``` - - -Details for each implementation: - -* __Detectron2__: with release v0.1.2, run: - ``` - python tools/train_net.py --config-file configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml --num-gpus 8 - ``` - -* __mmdetection__: at commit `b0d845f`, run - ``` - ./tools/dist_train.sh configs/mask_rcnn/mask_rcnn_r50_caffe_fpn_1x_coco.py 8 - ``` - -* __maskrcnn-benchmark__: use commit `0ce8f6f` with `sed -i 's/torch.uint8/torch.bool/g' **/*.py; sed -i 's/AT_CHECK/TORCH_CHECK/g' **/*.cu` - to make it compatible with PyTorch 1.5. Then, run training with - ``` - python -m torch.distributed.launch --nproc_per_node=8 tools/train_net.py --config-file configs/e2e_mask_rcnn_R_50_FPN_1x.yaml - ``` - The speed we observed is faster than its model zoo, likely due to different software versions. - -* __tensorpack__: at commit `caafda`, `export TF_CUDNN_USE_AUTOTUNE=0`, then run - ``` - mpirun -np 8 ./train.py --config DATA.BASEDIR=/data/coco TRAINER=horovod BACKBONE.STRIDE_1X1=True TRAIN.STEPS_PER_EPOCH=50 --load ImageNet-R50-AlignPadding.npz - ``` - -* __SimpleDet__: at commit `9187a1`, run - ``` - python detection_train.py --config config/mask_r50v1_fpn_1x.py - ``` - -* __Detectron__: run - ``` - python tools/train_net.py --cfg configs/12_2017_baselines/e2e_mask_rcnn_R-50-FPN_1x.yaml - ``` - Note that many of its ops run on CPUs, therefore the performance is limited. - -* __matterport/Mask_RCNN__: at commit `3deaec`, apply the following diff, `export TF_CUDNN_USE_AUTOTUNE=0`, then run - ``` - python coco.py train --dataset=/data/coco/ --model=imagenet - ``` - Note that many small details in this implementation might be different - from Detectron's standards. - -
- - (diff to make it use the same hyperparameters - click to expand) - - - ```diff - diff --git i/mrcnn/model.py w/mrcnn/model.py - index 62cb2b0..61d7779 100644 - --- i/mrcnn/model.py - +++ w/mrcnn/model.py - @@ -2367,8 +2367,8 @@ class MaskRCNN(): - epochs=epochs, - steps_per_epoch=self.config.STEPS_PER_EPOCH, - callbacks=callbacks, - - validation_data=val_generator, - - validation_steps=self.config.VALIDATION_STEPS, - + #validation_data=val_generator, - + #validation_steps=self.config.VALIDATION_STEPS, - max_queue_size=100, - workers=workers, - use_multiprocessing=True, - diff --git i/mrcnn/parallel_model.py w/mrcnn/parallel_model.py - index d2bf53b..060172a 100644 - --- i/mrcnn/parallel_model.py - +++ w/mrcnn/parallel_model.py - @@ -32,6 +32,7 @@ class ParallelModel(KM.Model): - keras_model: The Keras model to parallelize - gpu_count: Number of GPUs. Must be > 1 - """ - + super().__init__() - self.inner_model = keras_model - self.gpu_count = gpu_count - merged_outputs = self.make_parallel() - diff --git i/samples/coco/coco.py w/samples/coco/coco.py - index 5d172b5..239ed75 100644 - --- i/samples/coco/coco.py - +++ w/samples/coco/coco.py - @@ -81,7 +81,10 @@ class CocoConfig(Config): - IMAGES_PER_GPU = 2 - - # Uncomment to train on 8 GPUs (default is 1) - - # GPU_COUNT = 8 - + GPU_COUNT = 8 - + BACKBONE = "resnet50" - + STEPS_PER_EPOCH = 50 - + TRAIN_ROIS_PER_IMAGE = 512 - - # Number of classes (including background) - NUM_CLASSES = 1 + 80 # COCO has 80 classes - @@ -496,29 +499,10 @@ if __name__ == '__main__': - # *** This training schedule is an example. Update to your needs *** - - # Training - Stage 1 - - print("Training network heads") - model.train(dataset_train, dataset_val, - learning_rate=config.LEARNING_RATE, - epochs=40, - - layers='heads', - - augmentation=augmentation) - - - - # Training - Stage 2 - - # Finetune layers from ResNet stage 4 and up - - print("Fine tune Resnet stage 4 and up") - - model.train(dataset_train, dataset_val, - - learning_rate=config.LEARNING_RATE, - - epochs=120, - - layers='4+', - - augmentation=augmentation) - - - - # Training - Stage 3 - - # Fine tune all layers - - print("Fine tune all layers") - - model.train(dataset_train, dataset_val, - - learning_rate=config.LEARNING_RATE / 10, - - epochs=160, - - layers='all', - + layers='3+', - augmentation=augmentation) - - elif args.command == "evaluate": - ``` - -
diff --git a/preprocess/detectron2/docs/notes/changelog.md b/preprocess/detectron2/docs/notes/changelog.md deleted file mode 100644 index 000e9f8898dba53f54121a5325ba5165e45ddea2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/notes/changelog.md +++ /dev/null @@ -1,48 +0,0 @@ -# Change Log and Backward Compatibility - -### Releases -See release logs at -[https://github.com/facebookresearch/detectron2/releases](https://github.com/facebookresearch/detectron2/releases) -for new updates. - -### Backward Compatibility - -Due to the research nature of what the library does, there might be backward incompatible changes. -But we try to reduce users' disruption by the following ways: -* APIs listed in [API documentation](https://detectron2.readthedocs.io/modules/index.html), including - function/class names, their arguments, and documented class attributes, are considered *stable* unless - otherwise noted in the documentation. - They are less likely to be broken, but if needed, will trigger a deprecation warning for a reasonable period - before getting broken, and will be documented in release logs. -* Others functions/classses/attributes are considered internal, and are more likely to change. - However, we're aware that some of them may be already used by other projects, and in particular we may - use them for convenience among projects under `detectron2/projects`. - For such APIs, we may treat them as stable APIs and also apply the above strategies. - They may be promoted to stable when we're ready. -* Projects under "detectron2/projects" or imported with "detectron2.projects" are research projects - and are all considered experimental. -* Classes/functions that contain the word "default" or are explicitly documented to produce - "default behavior" may change their behaviors when new features are added. - -Despite of the possible breakage, if a third-party project would like to keep up with the latest updates -in detectron2, using it as a library will still be less disruptive than forking, because -the frequency and scope of API changes will be much smaller than code changes. - -To see such changes, search for "incompatible changes" in [release logs](https://github.com/facebookresearch/detectron2/releases). - -### Config Version Change Log - -Detectron2's config version has not been changed since open source. -There is no need for an open source user to worry about this. - -* v1: Rename `RPN_HEAD.NAME` to `RPN.HEAD_NAME`. -* v2: A batch of rename of many configurations before release. - -### Silent Regressions in Historical Versions: - -We list a few silent regressions, since they may silently produce incorrect results and will be hard to debug. - -* 04/01/2020 - 05/11/2020: Bad accuracy if `TRAIN_ON_PRED_BOXES` is set to True. -* 03/30/2020 - 04/01/2020: ResNets are not correctly built. -* 12/19/2019 - 12/26/2019: Using aspect ratio grouping causes a drop in accuracy. -* - 11/9/2019: Test time augmentation does not predict the last category. diff --git a/preprocess/detectron2/docs/notes/compatibility.md b/preprocess/detectron2/docs/notes/compatibility.md deleted file mode 100644 index 83d93f51c056c598c1209f9a21a4e04407b827f0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/notes/compatibility.md +++ /dev/null @@ -1,84 +0,0 @@ -# Compatibility with Other Libraries - -## Compatibility with Detectron (and maskrcnn-benchmark) - -Detectron2 addresses some legacy issues left in Detectron. As a result, their models -are not compatible: -running inference with the same model weights will produce different results in the two code bases. - -The major differences regarding inference are: - -- The height and width of a box with corners (x1, y1) and (x2, y2) is now computed more naturally as - width = x2 - x1 and height = y2 - y1; - In Detectron, a "+ 1" was added both height and width. - - Note that the relevant ops in Caffe2 have [adopted this change of convention](https://github.com/pytorch/pytorch/pull/20550) - with an extra option. - So it is still possible to run inference with a Detectron2-trained model in Caffe2. - - The change in height/width calculations most notably changes: - - encoding/decoding in bounding box regression. - - non-maximum suppression. The effect here is very negligible, though. - -- RPN now uses simpler anchors with fewer quantization artifacts. - - In Detectron, the anchors were quantized and - [do not have accurate areas](https://github.com/facebookresearch/Detectron/issues/227). - In Detectron2, the anchors are center-aligned to feature grid points and not quantized. - -- Classification layers have a different ordering of class labels. - - This involves any trainable parameter with shape (..., num_categories + 1, ...). - In Detectron2, integer labels [0, K-1] correspond to the K = num_categories object categories - and the label "K" corresponds to the special "background" category. - In Detectron, label "0" means background, and labels [1, K] correspond to the K categories. - -- ROIAlign is implemented differently. The new implementation is [available in Caffe2](https://github.com/pytorch/pytorch/pull/23706). - - 1. All the ROIs are shifted by half a pixel compared to Detectron in order to create better image-feature-map alignment. - See `layers/roi_align.py` for details. - To enable the old behavior, use `ROIAlign(aligned=False)`, or `POOLER_TYPE=ROIAlign` instead of - `ROIAlignV2` (the default). - - 1. The ROIs are not required to have a minimum size of 1. - This will lead to tiny differences in the output, but should be negligible. - -- Mask inference function is different. - - In Detectron2, the "paste_mask" function is different and should be more accurate than in Detectron. This change - can improve mask AP on COCO by ~0.5% absolute. - -There are some other differences in training as well, but they won't affect -model-level compatibility. The major ones are: - -- We fixed a [bug](https://github.com/facebookresearch/Detectron/issues/459) in - Detectron, by making `RPN.POST_NMS_TOPK_TRAIN` per-image, rather than per-batch. - The fix may lead to a small accuracy drop for a few models (e.g. keypoint - detection) and will require some parameter tuning to match the Detectron results. -- For simplicity, we change the default loss in bounding box regression to L1 loss, instead of smooth L1 loss. - We have observed that this tends to slightly decrease box AP50 while improving box AP for higher - overlap thresholds (and leading to a slight overall improvement in box AP). -- We interpret the coordinates in COCO bounding box and segmentation annotations - as coordinates in range `[0, width]` or `[0, height]`. The coordinates in - COCO keypoint annotations are interpreted as pixel indices in range `[0, width - 1]` or `[0, height - 1]`. - Note that this affects how flip augmentation is implemented. - - -[This article](https://ppwwyyxx.com/blog/2021/Where-are-Pixels/) -explains more details on the above mentioned issues -about pixels, coordinates, and "+1"s. - - -## Compatibility with Caffe2 - -As mentioned above, despite the incompatibilities with Detectron, the relevant -ops have been implemented in Caffe2. -Therefore, models trained with detectron2 can be converted in Caffe2. -See [Deployment](../tutorials/deployment.md) for the tutorial. - -## Compatibility with TensorFlow - -Most ops are available in TensorFlow, although some tiny differences in -the implementation of resize / ROIAlign / padding need to be addressed. -A working conversion script is provided by [tensorpack Faster R-CNN](https://github.com/tensorpack/tensorpack/tree/master/examples/FasterRCNN/convert_d2) -to run a standard detectron2 model in TensorFlow. diff --git a/preprocess/detectron2/docs/notes/contributing.md b/preprocess/detectron2/docs/notes/contributing.md deleted file mode 120000 index 95181235eaff1cb5cbb2dc554e8d4991b603d0e5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/notes/contributing.md +++ /dev/null @@ -1 +0,0 @@ -../../.github/CONTRIBUTING.md \ No newline at end of file diff --git a/preprocess/detectron2/docs/notes/index.rst b/preprocess/detectron2/docs/notes/index.rst deleted file mode 100644 index 63cf907be7bb15f5316af6d44a46df601755a86b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/notes/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -Notes -====================================== - -.. toctree:: - :maxdepth: 2 - - benchmarks - compatibility - contributing - changelog diff --git a/preprocess/detectron2/docs/requirements.txt b/preprocess/detectron2/docs/requirements.txt deleted file mode 100644 index 720a1b1193de23c3354c55cf7ec05cdc5974416a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/requirements.txt +++ /dev/null @@ -1,23 +0,0 @@ -docutils==0.16 -# https://github.com/sphinx-doc/sphinx/commit/7acd3ada3f38076af7b2b5c9f3b60bb9c2587a3d -sphinx==3.2.0 -recommonmark==0.6.0 -sphinx_rtd_theme -# Dependencies here are only those required by import -termcolor -numpy -tqdm -matplotlib -termcolor -yacs -tabulate -cloudpickle -Pillow -future -git+https://github.com/facebookresearch/fvcore.git -https://download.pytorch.org/whl/cpu/torch-1.8.1%2Bcpu-cp37-cp37m-linux_x86_64.whl -https://download.pytorch.org/whl/cpu/torchvision-0.9.1%2Bcpu-cp37-cp37m-linux_x86_64.whl -omegaconf>=2.1.0.dev24 -hydra-core>=1.1.0.dev5 -scipy -timm diff --git a/preprocess/detectron2/docs/tutorials/README.md b/preprocess/detectron2/docs/tutorials/README.md deleted file mode 100644 index 1ca9c94d042ef838143a45490fe6b4556c19f3c9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Read the docs: - -The latest documentation built from this directory is available at [detectron2.readthedocs.io](https://detectron2.readthedocs.io/). -Documents in this directory are not meant to be read on github. diff --git a/preprocess/detectron2/docs/tutorials/augmentation.md b/preprocess/detectron2/docs/tutorials/augmentation.md deleted file mode 100644 index 7601a082ceadf645e32468c2045dfe50c1216efc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/augmentation.md +++ /dev/null @@ -1,186 +0,0 @@ - -# Data Augmentation - -Augmentation is an important part of training. -Detectron2's data augmentation system aims at addressing the following goals: - -1. Allow augmenting multiple data types together - (e.g., images together with their bounding boxes and masks) -2. Allow applying a sequence of statically-declared augmentation -3. Allow adding custom new data types to augment (rotated bounding boxes, video clips, etc.) -4. Process and manipulate the __operations__ that are applied by augmentations - -The first two features cover most of the common use cases, and is also -available in other libraries such as [albumentations](https://medium.com/pytorch/multi-target-in-albumentations-16a777e9006e). -Supporting other features adds some overhead to detectron2's augmentation API, -which we'll explain in this tutorial. - -This tutorial focuses on how to use augmentations when writing new data loaders, -and how to write new augmentations. -If you use the default data loader in detectron2, it already supports taking a user-provided list of custom augmentations, -as explained in the [Dataloader tutorial](data_loading). - -## Basic Usage - -The basic usage of feature (1) and (2) is like the following: -```python -from detectron2.data import transforms as T -# Define a sequence of augmentations: -augs = T.AugmentationList([ - T.RandomBrightness(0.9, 1.1), - T.RandomFlip(prob=0.5), - T.RandomCrop("absolute", (640, 640)) -]) # type: T.Augmentation - -# Define the augmentation input ("image" required, others optional): -input = T.AugInput(image, boxes=boxes, sem_seg=sem_seg) -# Apply the augmentation: -transform = augs(input) # type: T.Transform -image_transformed = input.image # new image -sem_seg_transformed = input.sem_seg # new semantic segmentation - -# For any extra data that needs to be augmented together, use transform, e.g.: -image2_transformed = transform.apply_image(image2) -polygons_transformed = transform.apply_polygons(polygons) -``` - -Three basic concepts are involved here. They are: -* [T.Augmentation](../modules/data_transforms.html#detectron2.data.transforms.Augmentation) defines the __"policy"__ to modify inputs. - * its `__call__(AugInput) -> Transform` method augments the inputs in-place, and returns the operation that is applied -* [T.Transform](../modules/data_transforms.html#detectron2.data.transforms.Transform) - implements the actual __operations__ to transform data - * it has methods such as `apply_image`, `apply_coords` that define how to transform each data type -* [T.AugInput](../modules/data_transforms.html#detectron2.data.transforms.AugInput) - stores inputs needed by `T.Augmentation` and how they should be transformed. - This concept is needed for some advanced usage. - Using this class directly should be sufficient for all common use cases, - since extra data not in `T.AugInput` can be augmented using the returned - `transform`, as shown in the above example. - -## Write New Augmentations - -Most 2D augmentations only need to know about the input image. Such augmentation can be implemented easily like this: - -```python -class MyColorAugmentation(T.Augmentation): - def get_transform(self, image): - r = np.random.rand(2) - return T.ColorTransform(lambda x: x * r[0] + r[1] * 10) - -class MyCustomResize(T.Augmentation): - def get_transform(self, image): - old_h, old_w = image.shape[:2] - new_h, new_w = int(old_h * np.random.rand()), int(old_w * 1.5) - return T.ResizeTransform(old_h, old_w, new_h, new_w) - -augs = MyCustomResize() -transform = augs(input) -``` - -In addition to image, any attributes of the given `AugInput` can be used as long -as they are part of the function signature, e.g.: - -```python -class MyCustomCrop(T.Augmentation): - def get_transform(self, image, sem_seg): - # decide where to crop using both image and sem_seg - return T.CropTransform(...) - -augs = MyCustomCrop() -assert hasattr(input, "image") and hasattr(input, "sem_seg") -transform = augs(input) -``` - -New transform operation can also be added by subclassing -[T.Transform](../modules/data_transforms.html#detectron2.data.transforms.Transform). - -## Advanced Usage - -We give a few examples of advanced usages that -are enabled by our system. -These options can be interesting to new research, -although changing them is often not needed -for standard use cases. - -### Custom transform strategy - -Instead of only returning the augmented data, detectron2's `Augmentation` returns the __operations__ as `T.Transform`. -This allows users to apply custom transform strategy on their data. -We use keypoints data as an example. - -Keypoints are (x, y) coordinates, but they are not so trivial to augment due to the semantic meaning they carry. -Such meaning is only known to the users, therefore users may want to augment them manually -by looking at the returned `transform`. -For example, when an image is horizontally flipped, we'd like to swap the keypoint annotations for "left eye" and "right eye". -This can be done like this (included by default in detectron2's default data loader): -```python -# augs, input are defined as in previous examples -transform = augs(input) # type: T.Transform -keypoints_xy = transform.apply_coords(keypoints_xy) # transform the coordinates - -# get a list of all transforms that were applied -transforms = T.TransformList([transform]).transforms -# check if it is flipped for odd number of times -do_hflip = sum(isinstance(t, T.HFlipTransform) for t in transforms) % 2 == 1 -if do_hflip: - keypoints_xy = keypoints_xy[flip_indices_mapping] -``` - -As another example, keypoints annotations often have a "visibility" field. -A sequence of augmentations might augment a visible keypoint out of the image boundary (e.g. with cropping), -but then bring it back within the boundary afterwards (e.g. with image padding). -If users decide to label such keypoints "invisible", -then the visibility check has to happen after every transform step. -This can be achieved by: - -```python -transform = augs(input) # type: T.TransformList -assert isinstance(transform, T.TransformList) -for t in transform.transforms: - keypoints_xy = t.apply_coords(keypoints_xy) - visibility &= (keypoints_xy >= [0, 0] & keypoints_xy <= [W, H]).all(axis=1) - -# btw, detectron2's `transform_keypoint_annotations` function chooses to label such keypoints "visible": -# keypoints_xy = transform.apply_coords(keypoints_xy) -# visibility &= (keypoints_xy >= [0, 0] & keypoints_xy <= [W, H]).all(axis=1) -``` - - -### Geometrically invert the transform -If images are pre-processed by augmentations before inference, the predicted results -such as segmentation masks are localized on the augmented image. -We'd like to invert the applied augmentation with the [inverse()](../modules/data_transforms.html#detectron2.data.transforms.Transform.inverse) -API, to obtain results on the original image: -```python -transform = augs(input) -pred_mask = make_prediction(input.image) -inv_transform = transform.inverse() -pred_mask_orig = inv_transform.apply_segmentation(pred_mask) -``` - -### Add new data types - -[T.Transform](../modules/data_transforms.html#detectron2.data.transforms.Transform) -supports a few common data types to transform, including images, coordinates, masks, boxes, polygons. -It allows registering new data types, e.g.: -```python -@T.HFlipTransform.register_type("rotated_boxes") -def func(flip_transform: T.HFlipTransform, rotated_boxes: Any): - # do the work - return flipped_rotated_boxes - -t = HFlipTransform(width=800) -transformed_rotated_boxes = t.apply_rotated_boxes(rotated_boxes) # func will be called -``` - -### Extend T.AugInput - -An augmentation can only access attributes available in the given input. -[T.AugInput](../modules/data_transforms.html#detectron2.data.transforms.StandardAugInput) defines "image", "boxes", "sem_seg", -which are sufficient for common augmentation strategies to decide how to augment. -If not, a custom implementation is needed. - -By re-implement the "transform()" method in AugInput, it is also possible to -augment different fields in ways that are dependent on each other. -Such use case is uncommon (e.g. post-process bounding box based on augmented masks), but allowed by the system. - diff --git a/preprocess/detectron2/docs/tutorials/builtin_datasets.md b/preprocess/detectron2/docs/tutorials/builtin_datasets.md deleted file mode 120000 index 0ba82423ad498bdd86274ada56a201134a590d94..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/builtin_datasets.md +++ /dev/null @@ -1 +0,0 @@ -../../datasets/README.md \ No newline at end of file diff --git a/preprocess/detectron2/docs/tutorials/configs.md b/preprocess/detectron2/docs/tutorials/configs.md deleted file mode 100644 index 49538d0532994664584460560f4f809ff3a6e6df..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/configs.md +++ /dev/null @@ -1,62 +0,0 @@ -# Yacs Configs - -Detectron2 provides a key-value based config system that can be -used to obtain standard, common behaviors. - -This system uses YAML and [yacs](https://github.com/rbgirshick/yacs). -Yaml is a very limited language, -so we do not expect all features in detectron2 to be available through configs. -If you need something that's not available in the config space, -please write code using detectron2's API. - -With the introduction of a more powerful [LazyConfig system](lazyconfigs.md), -we no longer add functionality / new keys to the Yacs/Yaml-based config system. - -### Basic Usage - -Some basic usage of the `CfgNode` object is shown here. See more in [documentation](../modules/config.html#detectron2.config.CfgNode). -```python -from detectron2.config import get_cfg -cfg = get_cfg() # obtain detectron2's default config -cfg.xxx = yyy # add new configs for your own custom components -cfg.merge_from_file("my_cfg.yaml") # load values from a file - -cfg.merge_from_list(["MODEL.WEIGHTS", "weights.pth"]) # can also load values from a list of str -print(cfg.dump()) # print formatted configs -with open("output.yaml", "w") as f: - f.write(cfg.dump()) # save config to file -``` - -In addition to the basic Yaml syntax, the config file can -define a `_BASE_: base.yaml` field, which will load a base config file first. -Values in the base config will be overwritten in sub-configs, if there are any conflicts. -We provided several base configs for standard model architectures. - -Many builtin tools in detectron2 accept command line config overwrite: -Key-value pairs provided in the command line will overwrite the existing values in the config file. -For example, [demo.py](../../demo/demo.py) can be used with -```sh -./demo.py --config-file config.yaml [--other-options] \ - --opts MODEL.WEIGHTS /path/to/weights INPUT.MIN_SIZE_TEST 1000 -``` - -To see a list of available configs in detectron2 and what they mean, -check [Config References](../modules/config.html#config-references) - -### Configs in Projects - -A project that lives outside the detectron2 library may define its own configs, which will need to be added -for the project to be functional, e.g.: -```python -from detectron2.projects.point_rend import add_pointrend_config -cfg = get_cfg() # obtain detectron2's default config -add_pointrend_config(cfg) # add pointrend's default config -# ... ... -``` - -### Best Practice with Configs - -1. Treat the configs you write as "code": avoid copying them or duplicating them; use `_BASE_` - to share common parts between configs. - -2. Keep the configs you write simple: don't include keys that do not affect the experimental setting. diff --git a/preprocess/detectron2/docs/tutorials/data_loading.md b/preprocess/detectron2/docs/tutorials/data_loading.md deleted file mode 100644 index 1d2769fc513abb0981a140f3a6b6432538704261..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/data_loading.md +++ /dev/null @@ -1,95 +0,0 @@ - -# Dataloader - -Dataloader is the component that provides data to models. -A dataloader usually (but not necessarily) takes raw information from [datasets](./datasets.md), -and process them into a format needed by the model. - -## How the Existing Dataloader Works - -Detectron2 contains a builtin data loading pipeline. -It's good to understand how it works, in case you need to write a custom one. - -Detectron2 provides two functions -[build_detection_{train,test}_loader](../modules/data.html#detectron2.data.build_detection_train_loader) -that create a default data loader from a given config. -Here is how `build_detection_{train,test}_loader` work: - -1. It takes the name of a registered dataset (e.g., "coco_2017_train") and loads a `list[dict]` representing the dataset items - in a lightweight format. These dataset items are not yet ready to be used by the model (e.g., images are - not loaded into memory, random augmentations have not been applied, etc.). - Details about the dataset format and dataset registration can be found in - [datasets](./datasets.md). -2. Each dict in this list is mapped by a function ("mapper"): - * Users can customize this mapping function by specifying the "mapper" argument in - `build_detection_{train,test}_loader`. The default mapper is [DatasetMapper](../modules/data.html#detectron2.data.DatasetMapper). - * The output format of the mapper can be arbitrary, as long as it is accepted by the consumer of this data loader (usually the model). - The outputs of the default mapper, after batching, follow the default model input format documented in - [Use Models](./models.html#model-input-format). - * The role of the mapper is to transform the lightweight representation of a dataset item into a format - that is ready for the model to consume (including, e.g., read images, perform random data augmentation and convert to torch Tensors). - If you would like to perform custom transformations to data, you often want a custom mapper. -3. The outputs of the mapper are batched (simply into a list). -4. This batched data is the output of the data loader. Typically, it's also the input of - `model.forward()`. - - -## Write a Custom Dataloader - -Using a different "mapper" with `build_detection_{train,test}_loader(mapper=)` works for most use cases -of custom data loading. -For example, if you want to resize all images to a fixed size for training, use: - -```python -import detectron2.data.transforms as T -from detectron2.data import DatasetMapper # the default mapper -dataloader = build_detection_train_loader(cfg, - mapper=DatasetMapper(cfg, is_train=True, augmentations=[ - T.Resize((800, 800)) - ])) -# use this dataloader instead of the default -``` -If the arguments of the default [DatasetMapper](../modules/data.html#detectron2.data.DatasetMapper) -does not provide what you need, you may write a custom mapper function and use it instead, e.g.: - -```python -from detectron2.data import detection_utils as utils - # Show how to implement a minimal mapper, similar to the default DatasetMapper -def mapper(dataset_dict): - dataset_dict = copy.deepcopy(dataset_dict) # it will be modified by code below - # can use other ways to read image - image = utils.read_image(dataset_dict["file_name"], format="BGR") - # See "Data Augmentation" tutorial for details usage - auginput = T.AugInput(image) - transform = T.Resize((800, 800))(auginput) - image = torch.from_numpy(auginput.image.transpose(2, 0, 1)) - annos = [ - utils.transform_instance_annotations(annotation, [transform], image.shape[1:]) - for annotation in dataset_dict.pop("annotations") - ] - return { - # create the format that the model expects - "image": image, - "instances": utils.annotations_to_instances(annos, image.shape[1:]) - } -dataloader = build_detection_train_loader(cfg, mapper=mapper) -``` - -If you want to change not only the mapper (e.g., in order to implement different sampling or batching logic), -`build_detection_train_loader` won't work and you will need to write a different data loader. -The data loader is simply a -python iterator that produces [the format](./models.md) that the model accepts. -You can implement it using any tools you like. - -No matter what to implement, it's recommended to -check out [API documentation of detectron2.data](../modules/data) to learn more about the APIs of -these functions. - -## Use a Custom Dataloader - -If you use [DefaultTrainer](../modules/engine.html#detectron2.engine.defaults.DefaultTrainer), -you can overwrite its `build_{train,test}_loader` method to use your own dataloader. -See the [deeplab dataloader](../../projects/DeepLab/train_net.py) -for an example. - -If you write your own training loop, you can plug in your data loader easily. diff --git a/preprocess/detectron2/docs/tutorials/datasets.md b/preprocess/detectron2/docs/tutorials/datasets.md deleted file mode 100644 index 91103f64264aa6f3059611c5fe06ecd65bcb986f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/datasets.md +++ /dev/null @@ -1,290 +0,0 @@ -# Use Custom Datasets - -This document explains how the dataset APIs -([DatasetCatalog](../modules/data.html#detectron2.data.DatasetCatalog), [MetadataCatalog](../modules/data.html#detectron2.data.MetadataCatalog)) -work, and how to use them to add custom datasets. - -Datasets that have builtin support in detectron2 are listed in [builtin datasets](builtin_datasets.md). -If you want to use a custom dataset while also reusing detectron2's data loaders, -you will need to: - -1. __Register__ your dataset (i.e., tell detectron2 how to obtain your dataset). -2. Optionally, __register metadata__ for your dataset. - -Next, we explain the above two concepts in detail. - -The [Colab tutorial](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5) -has a live example of how to register and train on a dataset of custom formats. - -### Register a Dataset - -To let detectron2 know how to obtain a dataset named "my_dataset", users need to implement -a function that returns the items in your dataset and then tell detectron2 about this -function: -```python -def my_dataset_function(): - ... - return list[dict] in the following format - -from detectron2.data import DatasetCatalog -DatasetCatalog.register("my_dataset", my_dataset_function) -# later, to access the data: -data: List[Dict] = DatasetCatalog.get("my_dataset") -``` - -Here, the snippet associates a dataset named "my_dataset" with a function that returns the data. -The function must return the same data (with same order) if called multiple times. -The registration stays effective until the process exits. - -The function can do arbitrary things and should return the data in `list[dict]`, each dict in either -of the following formats: -1. Detectron2's standard dataset dict, described below. This will make it work with many other builtin - features in detectron2, so it's recommended to use it when it's sufficient. -2. Any custom format. You can also return arbitrary dicts in your own format, - such as adding extra keys for new tasks. - Then you will need to handle them properly downstream as well. - See below for more details. - -#### Standard Dataset Dicts - -For standard tasks -(instance detection, instance/semantic/panoptic segmentation, keypoint detection), -we load the original dataset into `list[dict]` with a specification similar to COCO's annotations. -This is our standard representation for a dataset. - -Each dict contains information about one image. -The dict may have the following fields, -and the required fields vary based on what the dataloader or the task needs (see more below). - -```eval_rst -.. list-table:: - :header-rows: 1 - - * - Task - - Fields - * - Common - - file_name, height, width, image_id - - * - Instance detection/segmentation - - annotations - - * - Semantic segmentation - - sem_seg_file_name - - * - Panoptic segmentation - - pan_seg_file_name, segments_info -``` - -+ `file_name`: the full path to the image file. -+ `height`, `width`: integer. The shape of the image. -+ `image_id` (str or int): a unique id that identifies this image. Required by many - evaluators to identify the images, but a dataset may use it for different purposes. -+ `annotations` (list[dict]): Required by __instance detection/segmentation or keypoint detection__ tasks. - Each dict corresponds to annotations of one instance in this image, and - may contain the following keys: - + `bbox` (list[float], required): list of 4 numbers representing the bounding box of the instance. - + `bbox_mode` (int, required): the format of bbox. It must be a member of - [structures.BoxMode](../modules/structures.html#detectron2.structures.BoxMode). - Currently supports: `BoxMode.XYXY_ABS`, `BoxMode.XYWH_ABS`. - + `category_id` (int, required): an integer in the range [0, num_categories-1] representing the category label. - The value num_categories is reserved to represent the "background" category, if applicable. - + `segmentation` (list[list[float]] or dict): the segmentation mask of the instance. - + If `list[list[float]]`, it represents a list of polygons, one for each connected component - of the object. Each `list[float]` is one simple polygon in the format of `[x1, y1, ..., xn, yn]` (n≥3). - The Xs and Ys are absolute coordinates in unit of pixels. - + If `dict`, it represents the per-pixel segmentation mask in COCO's compressed RLE format. - The dict should have keys "size" and "counts". You can convert a uint8 segmentation mask of 0s and - 1s into such dict by `pycocotools.mask.encode(np.asarray(mask, order="F"))`. - `cfg.INPUT.MASK_FORMAT` must be set to `bitmask` if using the default data loader with such format. - + `keypoints` (list[float]): in the format of [x1, y1, v1,..., xn, yn, vn]. - v[i] means the [visibility](http://cocodataset.org/#format-data) of this keypoint. - `n` must be equal to the number of keypoint categories. - The Xs and Ys are absolute real-value coordinates in range [0, W or H]. - - (Note that the keypoint coordinates in COCO format are integers in range [0, W-1 or H-1], which is different - from our standard format. Detectron2 adds 0.5 to COCO keypoint coordinates to convert them from discrete - pixel indices to floating point coordinates.) - + `iscrowd`: 0 (default) or 1. Whether this instance is labeled as COCO's "crowd - region". Don't include this field if you don't know what it means. - - If `annotations` is an empty list, it means the image is labeled to have no objects. - Such images will by default be removed from training, - but can be included using `DATALOADER.FILTER_EMPTY_ANNOTATIONS`. - -+ `sem_seg_file_name` (str): - The full path to the semantic segmentation ground truth file. - It should be a grayscale image whose pixel values are integer labels. -+ `pan_seg_file_name` (str): - The full path to panoptic segmentation ground truth file. - It should be an RGB image whose pixel values are integer ids encoded using the - [panopticapi.utils.id2rgb](https://github.com/cocodataset/panopticapi/) function. - The ids are defined by `segments_info`. - If an id does not appear in `segments_info`, the pixel is considered unlabeled - and is usually ignored in training & evaluation. -+ `segments_info` (list[dict]): defines the meaning of each id in panoptic segmentation ground truth. - Each dict has the following keys: - + `id` (int): integer that appears in the ground truth image. - + `category_id` (int): an integer in the range [0, num_categories-1] representing the category label. - + `iscrowd`: 0 (default) or 1. Whether this instance is labeled as COCO's "crowd region". - - -```eval_rst - -.. note:: - - The PanopticFPN model does not use the panoptic segmentation - format defined here, but a combination of both instance segmentation and semantic segmentation data - format. See :doc:`builtin_datasets` for instructions on COCO. - -``` - -Fast R-CNN (with pre-computed proposals) models are rarely used today. -To train a Fast R-CNN, the following extra keys are needed: - -+ `proposal_boxes` (array): 2D numpy array with shape (K, 4) representing K precomputed proposal boxes for this image. -+ `proposal_objectness_logits` (array): numpy array with shape (K, ), which corresponds to the objectness - logits of proposals in 'proposal_boxes'. -+ `proposal_bbox_mode` (int): the format of the precomputed proposal bbox. - It must be a member of - [structures.BoxMode](../modules/structures.html#detectron2.structures.BoxMode). - Default is `BoxMode.XYXY_ABS`. - - - -#### Custom Dataset Dicts for New Tasks - -In the `list[dict]` that your dataset function returns, the dictionary can also have __arbitrary custom data__. -This will be useful for a new task that needs extra information not covered -by the standard dataset dicts. In this case, you need to make sure the downstream code can handle your data -correctly. Usually this requires writing a new `mapper` for the dataloader (see [Use Custom Dataloaders](./data_loading.md)). - -When designing a custom format, note that all dicts are stored in memory -(sometimes serialized and with multiple copies). -To save memory, each dict is meant to contain __small__ but sufficient information -about each sample, such as file names and annotations. -Loading full samples typically happens in the data loader. - -For attributes shared among the entire dataset, use `Metadata` (see below). -To avoid extra memory, do not save such information inside each sample. - -### "Metadata" for Datasets - -Each dataset is associated with some metadata, accessible through -`MetadataCatalog.get(dataset_name).some_metadata`. -Metadata is a key-value mapping that contains information that's shared among -the entire dataset, and usually is used to interpret what's in the dataset, e.g., -names of classes, colors of classes, root of files, etc. -This information will be useful for augmentation, evaluation, visualization, logging, etc. -The structure of metadata depends on what is needed from the corresponding downstream code. - -If you register a new dataset through `DatasetCatalog.register`, -you may also want to add its corresponding metadata through -`MetadataCatalog.get(dataset_name).some_key = some_value`, to enable any features that need the metadata. -You can do it like this (using the metadata key "thing_classes" as an example): - -```python -from detectron2.data import MetadataCatalog -MetadataCatalog.get("my_dataset").thing_classes = ["person", "dog"] -``` - -Here is a list of metadata keys that are used by builtin features in detectron2. -If you add your own dataset without these metadata, some features may be -unavailable to you: - -* `thing_classes` (list[str]): Used by all instance detection/segmentation tasks. - A list of names for each instance/thing category. - If you load a COCO format dataset, it will be automatically set by the function `load_coco_json`. - -* `thing_colors` (list[tuple(r, g, b)]): Pre-defined color (in [0, 255]) for each thing category. - Used for visualization. If not given, random colors will be used. - -* `stuff_classes` (list[str]): Used by semantic and panoptic segmentation tasks. - A list of names for each stuff category. - -* `stuff_colors` (list[tuple(r, g, b)]): Pre-defined color (in [0, 255]) for each stuff category. - Used for visualization. If not given, random colors are used. - -* `ignore_label` (int): Used by semantic and panoptic segmentation tasks. Pixels in ground-truth - annotations with this category label should be ignored in evaluation. Typically these are "unlabeled" - pixels. - -* `keypoint_names` (list[str]): Used by keypoint detection. A list of names for each keypoint. - -* `keypoint_flip_map` (list[tuple[str]]): Used by keypoint detection. A list of pairs of names, - where each pair are the two keypoints that should be flipped if the image is - flipped horizontally during augmentation. -* `keypoint_connection_rules`: list[tuple(str, str, (r, g, b))]. Each tuple specifies a pair of keypoints - that are connected and the color (in [0, 255]) to use for the line between them when visualized. - -Some additional metadata that are specific to the evaluation of certain datasets (e.g. COCO): - -* `thing_dataset_id_to_contiguous_id` (dict[int->int]): Used by all instance detection/segmentation tasks in the COCO format. - A mapping from instance class ids in the dataset to contiguous ids in range [0, #class). - Will be automatically set by the function `load_coco_json`. - -* `stuff_dataset_id_to_contiguous_id` (dict[int->int]): Used when generating prediction json files for - semantic/panoptic segmentation. - A mapping from semantic segmentation class ids in the dataset - to contiguous ids in [0, num_categories). It is useful for evaluation only. - -* `json_file`: The COCO annotation json file. Used by COCO evaluation for COCO-format datasets. -* `panoptic_root`, `panoptic_json`: Used by COCO-format panoptic evaluation. -* `evaluator_type`: Used by the builtin main training script to select - evaluator. Don't use it in a new training script. - You can just provide the [DatasetEvaluator](../modules/evaluation.html#detectron2.evaluation.DatasetEvaluator) - for your dataset directly in your main script. - -```eval_rst -.. note:: - - In recognition, sometimes we use the term "thing" for instance-level tasks, - and "stuff" for semantic segmentation tasks. - Both are used in panoptic segmentation tasks. - For background on the concept of "thing" and "stuff", see - `On Seeing Stuff: The Perception of Materials by Humans and Machines - `_. -``` - -### Register a COCO Format Dataset - -If your instance-level (detection, segmentation, keypoint) dataset is already a json file in the COCO format, -the dataset and its associated metadata can be registered easily with: -```python -from detectron2.data.datasets import register_coco_instances -register_coco_instances("my_dataset", {}, "json_annotation.json", "path/to/image/dir") -``` - -If your dataset is in COCO format but need to be further processed, or has extra custom per-instance annotations, -the [load_coco_json](../modules/data.html#detectron2.data.datasets.load_coco_json) -function might be useful. - -### Update the Config for New Datasets - -Once you've registered the dataset, you can use the name of the dataset (e.g., "my_dataset" in -example above) in `cfg.DATASETS.{TRAIN,TEST}`. -There are other configs you might want to change to train or evaluate on new datasets: - -* `MODEL.ROI_HEADS.NUM_CLASSES` and `MODEL.RETINANET.NUM_CLASSES` are the number of thing classes - for R-CNN and RetinaNet models, respectively. -* `MODEL.ROI_KEYPOINT_HEAD.NUM_KEYPOINTS` sets the number of keypoints for Keypoint R-CNN. - You'll also need to set [Keypoint OKS](http://cocodataset.org/#keypoints-eval) - with `TEST.KEYPOINT_OKS_SIGMAS` for evaluation. -* `MODEL.SEM_SEG_HEAD.NUM_CLASSES` sets the number of stuff classes for Semantic FPN & Panoptic FPN. -* `TEST.DETECTIONS_PER_IMAGE` controls the maximum number of objects to be detected. - Set it to a larger number if test images may contain >100 objects. -* If you're training Fast R-CNN (with precomputed proposals), `DATASETS.PROPOSAL_FILES_{TRAIN,TEST}` - need to match the datasets. The format of proposal files are documented - [here](../modules/data.html#detectron2.data.load_proposals_into_dataset). - -New models -(e.g. [TensorMask](../../projects/TensorMask), -[PointRend](../../projects/PointRend)) -often have similar configs of their own that need to be changed as well. - -```eval_rst -.. tip:: - - After changing the number of classes, certain layers in a pre-trained model will become incompatible - and therefore cannot be loaded to the new model. - This is expected, and loading such pre-trained models will produce warnings about such layers. -``` diff --git a/preprocess/detectron2/docs/tutorials/deployment.md b/preprocess/detectron2/docs/tutorials/deployment.md deleted file mode 100644 index f7598880a9946402848301123d2889cfec2359e5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/deployment.md +++ /dev/null @@ -1,137 +0,0 @@ -# Deployment - -Models written in Python need to go through an export process to become a deployable artifact. -A few basic concepts about this process: - -__"Export method"__ is how a Python model is fully serialized to a deployable format. -We support the following export methods: - -* `tracing`: see [pytorch documentation](https://pytorch.org/tutorials/beginner/Intro_to_TorchScript_tutorial.html) to learn about it -* `scripting`: see [pytorch documentation](https://pytorch.org/tutorials/beginner/Intro_to_TorchScript_tutorial.html) to learn about it -* `caffe2_tracing`: replace parts of the model by caffe2 operators, then use tracing. - -__"Format"__ is how a serialized model is described in a file, e.g. -TorchScript, Caffe2 protobuf, ONNX format. -__"Runtime"__ is an engine that loads a serialized model and executes it, -e.g., PyTorch, Caffe2, TensorFlow, onnxruntime, TensorRT, etc. -A runtime is often tied to a specific format -(e.g. PyTorch needs TorchScript format, Caffe2 needs protobuf format). -We currently support the following combination and each has some limitations: - -```eval_rst -+----------------------------+-------------+-------------+-----------------------------+ -| Export Method | tracing | scripting | caffe2_tracing | -+============================+=============+=============+=============================+ -| **Formats** | TorchScript | TorchScript | Caffe2, TorchScript, ONNX | -+----------------------------+-------------+-------------+-----------------------------+ -| **Runtime** | PyTorch | PyTorch | Caffe2, PyTorch | -+----------------------------+-------------+-------------+-----------------------------+ -| C++/Python inference | ✅ | ✅ | ✅ | -+----------------------------+-------------+-------------+-----------------------------+ -| Dynamic resolution | ✅ | ✅ | ✅ | -+----------------------------+-------------+-------------+-----------------------------+ -| Batch size requirement | Constant | Dynamic | Batch inference unsupported | -+----------------------------+-------------+-------------+-----------------------------+ -| Extra runtime deps | torchvision | torchvision | Caffe2 ops (usually already | -| | | | | -| | | | included in PyTorch) | -+----------------------------+-------------+-------------+-----------------------------+ -| Faster/Mask/Keypoint R-CNN | ✅ | ✅ | ✅ | -+----------------------------+-------------+-------------+-----------------------------+ -| RetinaNet | ✅ | ✅ | ✅ | -+----------------------------+-------------+-------------+-----------------------------+ -| PointRend R-CNN | ✅ | ❌ | ❌ | -+----------------------------+-------------+-------------+-----------------------------+ -| Cascade R-CNN | ✅ | ❌ | ❌ | -+----------------------------+-------------+-------------+-----------------------------+ - -``` - -`caffe2_tracing` is going to be deprecated. -We don't plan to work on additional support for other formats/runtime, but contributions are welcome. - - -## Deployment with Tracing or Scripting - -Models can be exported to TorchScript format, by either -[tracing or scripting](https://pytorch.org/tutorials/beginner/Intro_to_TorchScript_tutorial.html). -The output model file can be loaded without detectron2 dependency in either Python or C++. -The exported model often requires torchvision (or its C++ library) dependency for some custom ops. - -This feature requires PyTorch ≥ 1.8. - -### Coverage -Most official models under the meta architectures `GeneralizedRCNN` and `RetinaNet` -are supported in both tracing and scripting mode. -Cascade R-CNN and PointRend are currently supported in tracing. -Users' custom extensions are supported if they are also scriptable or traceable. - -For models exported with tracing, dynamic input resolution is allowed, but batch size -(number of input images) must be fixed. -Scripting can support dynamic batch size. - -### Usage - -The main export APIs for tracing and scripting are [TracingAdapter](../modules/export.html#detectron2.export.TracingAdapter) -and [scripting_with_instances](../modules/export.html#detectron2.export.scripting_with_instances). -Their usage is currently demonstrated in [test_export_torchscript.py](../../tests/test_export_torchscript.py) -(see `TestScripting` and `TestTracing`) -as well as the [deployment example](../../tools/deploy). -Please check that these examples can run, and then modify for your use cases. -The usage now requires some user effort and necessary knowledge for each model to workaround the limitation of scripting and tracing. -In the future we plan to wrap these under simpler APIs to lower the bar to use them. - -## Deployment with Caffe2-tracing -We provide [Caffe2Tracer](../modules/export.html#detectron2.export.Caffe2Tracer) -that performs the export logic. -It replaces parts of the model with Caffe2 operators, -and then export the model into Caffe2, TorchScript or ONNX format. - -The converted model is able to run in either Python or C++ without detectron2/torchvision dependency, on CPU or GPUs. -It has a runtime optimized for CPU & mobile inference, but not optimized for GPU inference. - -This feature requires ONNX ≥ 1.6. - -### Coverage - -Most official models under these 3 common meta architectures: `GeneralizedRCNN`, `RetinaNet`, `PanopticFPN` -are supported. Cascade R-CNN is not supported. Batch inference is not supported. - -Users' custom extensions under these architectures (added through registration) are supported -as long as they do not contain control flow or operators not available in Caffe2 (e.g. deformable convolution). -For example, custom backbones and heads are often supported out of the box. - -### Usage - -The APIs are listed at [the API documentation](../modules/export). -We provide [export_model.py](../../tools/deploy/) as an example that uses -these APIs to convert a standard model. For custom models/datasets, you can add them to this script. - -### Use the model in C++/Python - -The model can be loaded in C++ and deployed with -either Caffe2 or Pytorch runtime.. [C++ examples](../../tools/deploy/) for Mask R-CNN -are given as a reference. Note that: - -* Models exported with `caffe2_tracing` method take a special input format - described in [documentation](../modules/export.html#detectron2.export.Caffe2Tracer). - This was taken care of in the C++ example. - -* The converted models do not contain post-processing operations that - transform raw layer outputs into formatted predictions. - For example, the C++ examples only produce raw outputs (28x28 masks) from the final - layers that are not post-processed, because in actual deployment, an application often needs - its custom lightweight post-processing, so this step is left for users. - -To help use the Caffe2-format model in python, -we provide a python wrapper around the converted model, in the -[Caffe2Model.\_\_call\_\_](../modules/export.html#detectron2.export.Caffe2Model.__call__) method. -This method has an interface that's identical to the [pytorch versions of models](./models.md), -and it internally applies pre/post-processing code to match the formats. -This wrapper can serve as a reference for how to use Caffe2's python API, -or for how to implement pre/post-processing in actual deployment. - -## Conversion to TensorFlow -[tensorpack Faster R-CNN](https://github.com/tensorpack/tensorpack/tree/master/examples/FasterRCNN/convert_d2) -provides scripts to convert a few standard detectron2 R-CNN models to TensorFlow's pb format. -It works by translating configs and weights, therefore only support a few models. diff --git a/preprocess/detectron2/docs/tutorials/evaluation.md b/preprocess/detectron2/docs/tutorials/evaluation.md deleted file mode 100644 index 2ef94faa38cae1c5f4e49eed4887ebbcd147513c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/evaluation.md +++ /dev/null @@ -1,68 +0,0 @@ - -# Evaluation - -Evaluation is a process that takes a number of inputs/outputs pairs and aggregate them. -You can always [use the model](./models.md) directly and just parse its inputs/outputs manually to perform -evaluation. -Alternatively, evaluation is implemented in detectron2 using the [DatasetEvaluator](../modules/evaluation.html#detectron2.evaluation.DatasetEvaluator) -interface. - -Detectron2 includes a few `DatasetEvaluator` that computes metrics using standard dataset-specific -APIs (e.g., COCO, LVIS). -You can also implement your own `DatasetEvaluator` that performs some other jobs -using the inputs/outputs pairs. -For example, to count how many instances are detected on the validation set: - -```python -class Counter(DatasetEvaluator): - def reset(self): - self.count = 0 - def process(self, inputs, outputs): - for output in outputs: - self.count += len(output["instances"]) - def evaluate(self): - # save self.count somewhere, or print it, or return it. - return {"count": self.count} -``` - -## Use evaluators - -To evaluate using the methods of evaluators manually: -```python -def get_all_inputs_outputs(): - for data in data_loader: - yield data, model(data) - -evaluator.reset() -for inputs, outputs in get_all_inputs_outputs(): - evaluator.process(inputs, outputs) -eval_results = evaluator.evaluate() -``` - -Evaluators can also be used with [inference_on_dataset](../modules/evaluation.html#detectron2.evaluation.inference_on_dataset). -For example, - -```python -eval_results = inference_on_dataset( - model, - data_loader, - DatasetEvaluators([COCOEvaluator(...), Counter()])) -``` -This will execute `model` on all inputs from `data_loader`, and call evaluator to process them. - -Compared to running the evaluation manually using the model, the benefit of this function is that -evaluators can be merged together using [DatasetEvaluators](../modules/evaluation.html#detectron2.evaluation.DatasetEvaluators), -and all the evaluation can finish in one forward pass over the dataset. -This function also provides accurate speed benchmarks for the given model and dataset. - -## Evaluators for custom dataset - -Many evaluators in detectron2 are made for specific datasets, -in order to obtain scores using each dataset's official API. -In addition to that, two evaluators are able to evaluate any generic dataset -that follows detectron2's [standard dataset format](./datasets.md), so they -can be used to evaluate custom datasets: - -* [COCOEvaluator](../modules/evaluation.html#detectron2.evaluation.COCOEvaluator) is able to evaluate AP (Average Precision) for box detection, - instance segmentation, keypoint detection on any custom dataset. -* [SemSegEvaluator](../modules/evaluation.html#detectron2.evaluation.SemSegEvaluator) is able to evaluate semantic segmentation metrics on any custom dataset. diff --git a/preprocess/detectron2/docs/tutorials/extend.md b/preprocess/detectron2/docs/tutorials/extend.md deleted file mode 100644 index a6af550fdb2aa79c818cef54b009f2fe816d46a9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/extend.md +++ /dev/null @@ -1,141 +0,0 @@ -# Extend Detectron2's Defaults - -__Research is about doing things in new ways__. -This brings a tension in how to create abstractions in code, -which is a challenge for any research engineering project of a significant size: - -1. On one hand, it needs to have very thin abstractions to allow for the possibility of doing - everything in new ways. It should be reasonably easy to break existing - abstractions and replace them with new ones. - -2. On the other hand, such a project also needs reasonably high-level - abstractions, so that users can easily do things in standard ways, - without worrying too much about the details that only certain researchers care about. - -In detectron2, there are two types of interfaces that address this tension together: - -1. Functions and classes that take a config (`cfg`) argument - created from a yaml file - (sometimes with few extra arguments). - - Such functions and classes implement - the "standard default" behavior: it will read what it needs from a given - config and do the "standard" thing. - Users only need to load an expert-made config and pass it around, without having to worry about - which arguments are used and what they all mean. - - See [Yacs Configs](configs.md) for a detailed tutorial. - -2. Functions and classes that have well-defined explicit arguments. - - Each of these is a small building block of the entire system. - They require users' expertise to understand what each argument should be, - and require more effort to stitch together to a larger system. - But they can be stitched together in more flexible ways. - - When you need to implement something not supported by the "standard defaults" - included in detectron2, these well-defined components can be reused. - - The [LazyConfig system](lazyconfigs.md) relies on such functions and classes. - -3. A few functions and classes are implemented with the - [@configurable](../modules/config.html#detectron2.config.configurable) - decorator - they can be called with either a config, or with explicit arguments, or a mixture of both. - Their explicit argument interfaces are currently experimental. - - As an example, a Mask R-CNN model can be built in the following ways: - - 1. Config-only: - ```python - # load proper yaml config file, then - model = build_model(cfg) - ``` - - 2. Mixture of config and additional argument overrides: - ```python - model = GeneralizedRCNN( - cfg, - roi_heads=StandardROIHeads(cfg, batch_size_per_image=666), - pixel_std=[57.0, 57.0, 57.0]) - ``` - - 3. Full explicit arguments: -
- - (click to expand) - - - ```python - model = GeneralizedRCNN( - backbone=FPN( - ResNet( - BasicStem(3, 64, norm="FrozenBN"), - ResNet.make_default_stages(50, stride_in_1x1=True, norm="FrozenBN"), - out_features=["res2", "res3", "res4", "res5"], - ).freeze(2), - ["res2", "res3", "res4", "res5"], - 256, - top_block=LastLevelMaxPool(), - ), - proposal_generator=RPN( - in_features=["p2", "p3", "p4", "p5", "p6"], - head=StandardRPNHead(in_channels=256, num_anchors=3), - anchor_generator=DefaultAnchorGenerator( - sizes=[[32], [64], [128], [256], [512]], - aspect_ratios=[0.5, 1.0, 2.0], - strides=[4, 8, 16, 32, 64], - offset=0.0, - ), - anchor_matcher=Matcher([0.3, 0.7], [0, -1, 1], allow_low_quality_matches=True), - box2box_transform=Box2BoxTransform([1.0, 1.0, 1.0, 1.0]), - batch_size_per_image=256, - positive_fraction=0.5, - pre_nms_topk=(2000, 1000), - post_nms_topk=(1000, 1000), - nms_thresh=0.7, - ), - roi_heads=StandardROIHeads( - num_classes=80, - batch_size_per_image=512, - positive_fraction=0.25, - proposal_matcher=Matcher([0.5], [0, 1], allow_low_quality_matches=False), - box_in_features=["p2", "p3", "p4", "p5"], - box_pooler=ROIPooler(7, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"), - box_head=FastRCNNConvFCHead( - ShapeSpec(channels=256, height=7, width=7), conv_dims=[], fc_dims=[1024, 1024] - ), - box_predictor=FastRCNNOutputLayers( - ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=Box2BoxTransform((10, 10, 5, 5)), - num_classes=80, - ), - mask_in_features=["p2", "p3", "p4", "p5"], - mask_pooler=ROIPooler(14, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"), - mask_head=MaskRCNNConvUpsampleHead( - ShapeSpec(channels=256, width=14, height=14), - num_classes=80, - conv_dims=[256, 256, 256, 256, 256], - ), - ), - pixel_mean=[103.530, 116.280, 123.675], - pixel_std=[1.0, 1.0, 1.0], - input_format="BGR", - ) - ``` - -
- - -If you only need the standard behavior, the [Beginner's Tutorial](./getting_started.md) -should suffice. If you need to extend detectron2 to your own needs, -see the following tutorials for more details: - -* Detectron2 includes a few standard datasets. To use custom ones, see - [Use Custom Datasets](./datasets.md). -* Detectron2 contains the standard logic that creates a data loader for training/testing from a - dataset, but you can write your own as well. See [Use Custom Data Loaders](./data_loading.md). -* Detectron2 implements many standard detection models, and provide ways for you - to overwrite their behaviors. See [Use Models](./models.md) and [Write Models](./write-models.md). -* Detectron2 provides a default training loop that is good for common training tasks. - You can customize it with hooks, or write your own loop instead. See [training](./training.md). diff --git a/preprocess/detectron2/docs/tutorials/getting_started.md b/preprocess/detectron2/docs/tutorials/getting_started.md deleted file mode 120000 index e90bde77a3197b77f4cfdce86ca8f96491650acd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/getting_started.md +++ /dev/null @@ -1 +0,0 @@ -../../GETTING_STARTED.md \ No newline at end of file diff --git a/preprocess/detectron2/docs/tutorials/index.rst b/preprocess/detectron2/docs/tutorials/index.rst deleted file mode 100644 index 850b95cfa873ffa0ba2d6f6e4263ad0895c08be8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -Tutorials -====================================== - -.. toctree:: - :maxdepth: 2 - - install - getting_started - builtin_datasets - extend - datasets - data_loading - augmentation - models - write-models - training - evaluation - configs - lazyconfigs - deployment diff --git a/preprocess/detectron2/docs/tutorials/install.md b/preprocess/detectron2/docs/tutorials/install.md deleted file mode 120000 index 5f52b2be3c9650cfc3e16ffb8fa374d3fcbad371..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/install.md +++ /dev/null @@ -1 +0,0 @@ -../../INSTALL.md \ No newline at end of file diff --git a/preprocess/detectron2/docs/tutorials/lazyconfigs.md b/preprocess/detectron2/docs/tutorials/lazyconfigs.md deleted file mode 100644 index a01101ae40ec12d25d5a3d96892b60ef32dca21e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/lazyconfigs.md +++ /dev/null @@ -1,170 +0,0 @@ -# Lazy Configs - -The traditional yacs-based config system provides basic, standard functionalities. -However, it does not offer enough flexibility for many new projects. -We develop an alternative, non-intrusive config system that can be used with -detectron2 or potentially any other complex projects. - -## Python Syntax - -Our config objects are still dictionaries. Instead of using Yaml to define dictionaries, -we create dictionaries in Python directly. This gives users the following power that -doesn't exist in Yaml: - -* Easily manipulate the dictionary (addition & deletion) using Python. -* Write simple arithmetics or call simple functions. -* Use more data types / objects. -* Import / compose other config files, using the familiar Python import syntax. - -A Python config file can be loaded like this: -```python -# config.py: -a = dict(x=1, y=2, z=dict(xx=1)) -b = dict(x=3, y=4) - -# my_code.py: -from detectron2.config import LazyConfig -cfg = LazyConfig.load("path/to/config.py") # an omegaconf dictionary -assert cfg.a.z.xx == 1 -``` - -After [LazyConfig.load](../modules/config.html#detectron2.config.LazyConfig.load), `cfg` will be a dictionary that contains all dictionaries -defined in the global scope of the config file. Note that: -* All dictionaries are turned to an [omegaconf](https://omegaconf.readthedocs.io/) - config object during loading. This enables access to omegaconf features, - such as its [access syntax](https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#access-and-manipulation) - and [interpolation](https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#variable-interpolation). -* Absolute imports in `config.py` works the same as in regular Python. -* Relative imports can only import dictionaries from config files. - They are simply a syntax sugar for [LazyConfig.load_rel](../modules/config.html#detectron2.config.LazyConfig.load_rel). - They can load Python files at relative path without requiring `__init__.py`. - -[LazyConfig.save](../modules/config.html#detectron2.config.LazyConfig.save) can save a config object to yaml. -Note that this is not always successful if non-serializable objects appear in the config file (e.g. lambdas). -It is up to users whether to sacrifice the ability to save in exchange for flexibility. - -## Recursive Instantiation - -The LazyConfig system heavily uses recursive instantiation, which is a pattern that -uses a dictionary to describe a -call to a function/class. The dictionary consists of: - -1. A "\_target\_" key which contains path to the callable, such as "module.submodule.class_name". -2. Other keys that represent arguments to pass to the callable. Arguments themselves can be defined - using recursive instantiation. - -We provide a helper function [LazyCall](../modules/config.html#detectron2.config.LazyCall) that helps create such dictionaries. -The following code using `LazyCall` -```python -from detectron2.config import LazyCall as L -from my_app import Trainer, Optimizer -cfg = L(Trainer)( - optimizer=L(Optimizer)( - lr=0.01, - algo="SGD" - ) -) -``` -creates a dictionary like this: -```python -cfg = { - "_target_": "my_app.Trainer", - "optimizer": { - "_target_": "my_app.Optimizer", - "lr": 0.01, "algo": "SGD" - } -} -``` - -By representing objects using such dictionaries, a general -[instantiate](../modules/config.html#detectron2.config.instantiate) -function can turn them into actual objects, i.e.: -```python -from detectron2.config import instantiate -trainer = instantiate(cfg) -# equivalent to: -# from my_app import Trainer, Optimizer -# trainer = Trainer(optimizer=Optimizer(lr=0.01, algo="SGD")) -``` - -This pattern is powerful enough to describe very complex objects, e.g.: - -
- -A Full Mask R-CNN described in recursive instantiation (click to expand) - - -```eval_rst -.. literalinclude:: ../../configs/common/models/mask_rcnn_fpn.py - :language: python - :linenos: -``` - -
- -There are also objects or logic that cannot be described simply by a dictionary, -such as reused objects or method calls. They may require some refactoring -to work with recursive instantiation. - -## Using Model Zoo LazyConfigs - -We provide some configs in the model zoo using the LazyConfig system, for example: - -* [common baselines](../../configs/common/). -* [new Mask R-CNN baselines](../../configs/new_baselines/) - -After installing detectron2, they can be loaded by the model zoo API -[model_zoo.get_config](../modules/model_zoo.html#detectron2.model_zoo.get_config). - -Using these as references, you're free to define custom config structure / fields for your own -project, as long as your training script can understand them. -Despite of this, our model zoo configs still follow some simple conventions for consistency, e.g. -`cfg.model` defines a model object, `cfg.dataloader.{train,test}` defines dataloader objects, -and `cfg.train` contains training options in key-value form. -In addition to `print()`, a better way to view the structure of a config is like this: -```python -from detectron2.model_zoo import get_config -from detectron2.config import LazyConfig -print(LazyConfig.to_py(get_config("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.py"))) -``` -From the output it's easier to find relevant options to change, e.g. -`dataloader.train.total_batch_size` for the batch size, or `optimizer.lr` for base learning rate. - -We provide a reference training script -[tools/lazyconfig_train_net.py](../../tools/lazyconfig_train_net.py), -that can train/eval our model zoo configs. -It also shows how to support command line value overrides. - -To demonstrate the power and flexibility of the new system, we show that -[a simple config file](../../configs/Misc/torchvision_imagenet_R_50.py) -can let detectron2 train an ImageNet classification model from torchvision, even though -detectron2 contains no features about ImageNet classification. -This can serve as a reference for using detectron2 in other deep learning tasks. - -## Summary - -By using recursive instantiation to create objects, -we avoid passing a giant config to many places, because `cfg` is only passed to `instantiate`. -This has the following benefits: - -* It's __non-intrusive__: objects to be constructed are config-agnostic, regular Python - functions/classes. - They can even live in other libraries. For example, - `{"_target_": "torch.nn.Conv2d", "in_channels": 10, "out_channels": 10, "kernel_size": 1}` - defines a conv layer. -* __Clarity__ of what function/classes will be called, and what arguments they use. -* `cfg` doesn't need pre-defined keys and structures. It's valid as long as it translates to valid - code. This gives a lot more __flexibility__. -* You can still pass huge dictionaries as arguments, just like the old way. - -Recursive instantiation and Python syntax are orthogonal: you can use one without the other. -But by putting them together, the config file looks a lot like the code that will be executed: - -![img](./lazyconfig.jpg) - -However, the config file just defines dictionaries, which can be easily manipulated further -by composition or overrides. -The corresponding code will only be executed -later when `instantiate` is called. In some way, -in config files we're writing "editable code" that will be "lazily executed" later when needed. -That's why we call this system "LazyConfig". diff --git a/preprocess/detectron2/docs/tutorials/models.md b/preprocess/detectron2/docs/tutorials/models.md deleted file mode 100644 index a2def5c715ac793e6269cbb84ef4792f91a774c1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/models.md +++ /dev/null @@ -1,180 +0,0 @@ -# Use Models - -## Build Models from Yacs Config -From a yacs config object, -models (and their sub-models) can be built by -functions such as `build_model`, `build_backbone`, `build_roi_heads`: -```python -from detectron2.modeling import build_model -model = build_model(cfg) # returns a torch.nn.Module -``` - -`build_model` only builds the model structure and fills it with random parameters. -See below for how to load an existing checkpoint to the model and how to use the `model` object. - -### Load/Save a Checkpoint -```python -from detectron2.checkpoint import DetectionCheckpointer -DetectionCheckpointer(model).load(file_path_or_url) # load a file, usually from cfg.MODEL.WEIGHTS - -checkpointer = DetectionCheckpointer(model, save_dir="output") -checkpointer.save("model_999") # save to output/model_999.pth -``` - -Detectron2's checkpointer recognizes models in pytorch's `.pth` format, as well as the `.pkl` files -in our model zoo. -See [API doc](../modules/checkpoint.html#detectron2.checkpoint.DetectionCheckpointer) -for more details about its usage. - -The model files can be arbitrarily manipulated using `torch.{load,save}` for `.pth` files or -`pickle.{dump,load}` for `.pkl` files. - -### Use a Model - -A model can be called by `outputs = model(inputs)`, where `inputs` is a `list[dict]`. -Each dict corresponds to one image and the required keys -depend on the type of model, and whether the model is in training or evaluation mode. -For example, in order to do inference, -all existing models expect the "image" key, and optionally "height" and "width". -The detailed format of inputs and outputs of existing models are explained below. - -__Training__: When in training mode, all models are required to be used under an `EventStorage`. -The training statistics will be put into the storage: -```python -from detectron2.utils.events import EventStorage -with EventStorage() as storage: - losses = model(inputs) -``` - -__Inference__: If you only want to do simple inference using an existing model, -[DefaultPredictor](../modules/engine.html#detectron2.engine.defaults.DefaultPredictor) -is a wrapper around model that provides such basic functionality. -It includes default behavior including model loading, preprocessing, -and operates on single image rather than batches. See its documentation for usage. - -You can also run inference directly like this: -```python -model.eval() -with torch.no_grad(): - outputs = model(inputs) -``` - -### Model Input Format - -Users can implement custom models that support any arbitrary input format. -Here we describe the standard input format that all builtin models support in detectron2. -They all take a `list[dict]` as the inputs. Each dict -corresponds to information about one image. - -The dict may contain the following keys: - -* "image": `Tensor` in (C, H, W) format. The meaning of channels are defined by `cfg.INPUT.FORMAT`. - Image normalization, if any, will be performed inside the model using - `cfg.MODEL.PIXEL_{MEAN,STD}`. -* "height", "width": the **desired** output height and width **in inference**, which is not necessarily the same - as the height or width of the `image` field. - For example, the `image` field contains the resized image, if resize is used as a preprocessing step. - But you may want the outputs to be in **original** resolution. - If provided, the model will produce output in this resolution, - rather than in the resolution of the `image` as input into the model. This is more efficient and accurate. -* "instances": an [Instances](../modules/structures.html#detectron2.structures.Instances) - object for training, with the following fields: - + "gt_boxes": a [Boxes](../modules/structures.html#detectron2.structures.Boxes) object storing N boxes, one for each instance. - + "gt_classes": `Tensor` of long type, a vector of N labels, in range [0, num_categories). - + "gt_masks": a [PolygonMasks](../modules/structures.html#detectron2.structures.PolygonMasks) - or [BitMasks](../modules/structures.html#detectron2.structures.BitMasks) object storing N masks, one for each instance. - + "gt_keypoints": a [Keypoints](../modules/structures.html#detectron2.structures.Keypoints) - object storing N keypoint sets, one for each instance. -* "sem_seg": `Tensor[int]` in (H, W) format. The semantic segmentation ground truth for training. - Values represent category labels starting from 0. -* "proposals": an [Instances](../modules/structures.html#detectron2.structures.Instances) - object used only in Fast R-CNN style models, with the following fields: - + "proposal_boxes": a [Boxes](../modules/structures.html#detectron2.structures.Boxes) object storing P proposal boxes. - + "objectness_logits": `Tensor`, a vector of P scores, one for each proposal. - -For inference of builtin models, only "image" key is required, and "width/height" are optional. - -We currently don't define standard input format for panoptic segmentation training, -because models now use custom formats produced by custom data loaders. - -#### How it connects to data loader: - -The output of the default [DatasetMapper]( ../modules/data.html#detectron2.data.DatasetMapper) is a dict -that follows the above format. -After the data loader performs batching, it becomes `list[dict]` which the builtin models support. - - -### Model Output Format - -When in training mode, the builtin models output a `dict[str->ScalarTensor]` with all the losses. - -When in inference mode, the builtin models output a `list[dict]`, one dict for each image. -Based on the tasks the model is doing, each dict may contain the following fields: - -* "instances": [Instances](../modules/structures.html#detectron2.structures.Instances) - object with the following fields: - * "pred_boxes": [Boxes](../modules/structures.html#detectron2.structures.Boxes) object storing N boxes, one for each detected instance. - * "scores": `Tensor`, a vector of N confidence scores. - * "pred_classes": `Tensor`, a vector of N labels in range [0, num_categories). - + "pred_masks": a `Tensor` of shape (N, H, W), masks for each detected instance. - + "pred_keypoints": a `Tensor` of shape (N, num_keypoint, 3). - Each row in the last dimension is (x, y, score). Confidence scores are larger than 0. -* "sem_seg": `Tensor` of (num_categories, H, W), the semantic segmentation prediction. -* "proposals": [Instances](../modules/structures.html#detectron2.structures.Instances) - object with the following fields: - * "proposal_boxes": [Boxes](../modules/structures.html#detectron2.structures.Boxes) - object storing N boxes. - * "objectness_logits": a torch vector of N confidence scores. -* "panoptic_seg": A tuple of `(pred: Tensor, segments_info: Optional[list[dict]])`. - The `pred` tensor has shape (H, W), containing the segment id of each pixel. - - * If `segments_info` exists, each dict describes one segment id in `pred` and has the following fields: - - * "id": the segment id - * "isthing": whether the segment is a thing or stuff - * "category_id": the category id of this segment. - - If a pixel's id does not exist in `segments_info`, it is considered to be void label - defined in [Panoptic Segmentation](https://arxiv.org/abs/1801.00868). - - * If `segments_info` is None, all pixel values in `pred` must be ≥ -1. - Pixels with value -1 are assigned void labels. - Otherwise, the category id of each pixel is obtained by - `category_id = pixel // metadata.label_divisor`. - - -### Partially execute a model: - -Sometimes you may want to obtain an intermediate tensor inside a model, -such as the input of certain layer, the output before post-processing. -Since there are typically hundreds of intermediate tensors, there isn't an API that provides you -the intermediate result you need. -You have the following options: - -1. Write a (sub)model. Following the [tutorial](./write-models.md), you can - rewrite a model component (e.g. a head of a model), such that it - does the same thing as the existing component, but returns the output - you need. -2. Partially execute a model. You can create the model as usual, - but use custom code to execute it instead of its `forward()`. For example, - the following code obtains mask features before mask head. - - ```python - images = ImageList.from_tensors(...) # preprocessed input tensor - model = build_model(cfg) - model.eval() - features = model.backbone(images.tensor) - proposals, _ = model.proposal_generator(images, features) - instances, _ = model.roi_heads(images, features, proposals) - mask_features = [features[f] for f in model.roi_heads.in_features] - mask_features = model.roi_heads.mask_pooler(mask_features, [x.pred_boxes for x in instances]) - ``` - -3. Use [forward hooks](https://pytorch.org/tutorials/beginner/former_torchies/nnft_tutorial.html#forward-and-backward-function-hooks). - Forward hooks can help you obtain inputs or outputs of a certain module. - If they are not exactly what you want, they can at least be used together with partial execution - to obtain other tensors. - -All options require you to read documentation and sometimes code -of the existing models to understand the internal logic, -in order to write code to obtain the internal tensors. diff --git a/preprocess/detectron2/docs/tutorials/training.md b/preprocess/detectron2/docs/tutorials/training.md deleted file mode 100644 index 83a6cb0a8e38ca06bbf96201ac2595d2116523c3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/training.md +++ /dev/null @@ -1,67 +0,0 @@ -# Training - -From the previous tutorials, you may now have a custom model and a data loader. -To run training, users typically have a preference in one of the following two styles: - -### Custom Training Loop - -With a model and a data loader ready, everything else needed to write a training loop can -be found in PyTorch, and you are free to write the training loop yourself. -This style allows researchers to manage the entire training logic more clearly and have full control. -One such example is provided in [tools/plain_train_net.py](../../tools/plain_train_net.py). - -Any customization on the training logic is then easily controlled by the user. - -### Trainer Abstraction - -We also provide a standardized "trainer" abstraction with a -hook system that helps simplify the standard training behavior. -It includes the following two instantiations: - -* [SimpleTrainer](../modules/engine.html#detectron2.engine.SimpleTrainer) - provides a minimal training loop for single-cost single-optimizer single-data-source training, with nothing else. - Other tasks (checkpointing, logging, etc) can be implemented using - [the hook system](../modules/engine.html#detectron2.engine.HookBase). -* [DefaultTrainer](../modules/engine.html#detectron2.engine.defaults.DefaultTrainer) is a `SimpleTrainer` initialized from a - yacs config, used by - [tools/train_net.py](../../tools/train_net.py) and many scripts. - It includes more standard default behaviors that one might want to opt in, - including default configurations for optimizer, learning rate schedule, - logging, evaluation, checkpointing etc. - -To customize a `DefaultTrainer`: - -1. For simple customizations (e.g. change optimizer, evaluator, LR scheduler, data loader, etc.), overwrite [its methods](../modules/engine.html#detectron2.engine.defaults.DefaultTrainer) in a subclass, just like [tools/train_net.py](../../tools/train_net.py). -2. For extra tasks during training, check the - [hook system](../modules/engine.html#detectron2.engine.HookBase) to see if it's supported. - - As an example, to print hello during training: - ```python - class HelloHook(HookBase): - def after_step(self): - if self.trainer.iter % 100 == 0: - print(f"Hello at iteration {self.trainer.iter}!") - ``` -3. Using a trainer+hook system means there will always be some non-standard behaviors that cannot be supported, especially in research. - For this reason, we intentionally keep the trainer & hook system minimal, rather than powerful. - If anything cannot be achieved by such a system, it's easier to start from [tools/plain_train_net.py](../../tools/plain_train_net.py) to implement custom training logic manually. - -### Logging of Metrics - -During training, detectron2 models and trainer put metrics to a centralized [EventStorage](../modules/utils.html#detectron2.utils.events.EventStorage). -You can use the following code to access it and log metrics to it: -```python -from detectron2.utils.events import get_event_storage - -# inside the model: -if self.training: - value = # compute the value from inputs - storage = get_event_storage() - storage.put_scalar("some_accuracy", value) -``` - -Refer to its documentation for more details. - -Metrics are then written to various destinations with [EventWriter](../modules/utils.html#module-detectron2.utils.events). -DefaultTrainer enables a few `EventWriter` with default configurations. -See above for how to customize them. diff --git a/preprocess/detectron2/docs/tutorials/write-models.md b/preprocess/detectron2/docs/tutorials/write-models.md deleted file mode 100644 index 967d126503c71b419bca94615cb1090e1a79cb49..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/docs/tutorials/write-models.md +++ /dev/null @@ -1,90 +0,0 @@ -# Write Models - -If you are trying to do something completely new, you may wish to implement -a model entirely from scratch. However, in many situations you may -be interested in modifying or extending some components of an existing model. -Therefore, we also provide mechanisms that let users override the -behavior of certain internal components of standard models. - - -## Register New Components - -For common concepts that users often want to customize, such as "backbone feature extractor", "box head", -we provide a registration mechanism for users to inject custom implementation that -will be immediately available to use in config files. - -For example, to add a new backbone, import this code in your code: -```python -from detectron2.modeling import BACKBONE_REGISTRY, Backbone, ShapeSpec - -@BACKBONE_REGISTRY.register() -class ToyBackbone(Backbone): - def __init__(self, cfg, input_shape): - super().__init__() - # create your own backbone - self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=16, padding=3) - - def forward(self, image): - return {"conv1": self.conv1(image)} - - def output_shape(self): - return {"conv1": ShapeSpec(channels=64, stride=16)} -``` - -In this code, we implement a new backbone following the interface of the -[Backbone](../modules/modeling.html#detectron2.modeling.Backbone) class, -and register it into the [BACKBONE_REGISTRY](../modules/modeling.html#detectron2.modeling.BACKBONE_REGISTRY) -which requires subclasses of `Backbone`. -After importing this code, detectron2 can link the name of the class to its implementation. Therefore you can write the following code: - -```python -cfg = ... # read a config -cfg.MODEL.BACKBONE.NAME = 'ToyBackbone' # or set it in the config file -model = build_model(cfg) # it will find `ToyBackbone` defined above -``` - -As another example, to add new abilities to the ROI heads in the Generalized R-CNN meta-architecture, -you can implement a new -[ROIHeads](../modules/modeling.html#detectron2.modeling.ROIHeads) subclass and put it in the `ROI_HEADS_REGISTRY`. -[DensePose](../../projects/DensePose) -and [MeshRCNN](https://github.com/facebookresearch/meshrcnn) -are two examples that implement new ROIHeads to perform new tasks. -And [projects/](../../projects/) -contains more examples that implement different architectures. - -A complete list of registries can be found in [API documentation](../modules/modeling.html#model-registries). -You can register components in these registries to customize different parts of a model, or the -entire model. - -## Construct Models with Explicit Arguments - -Registry is a bridge to connect names in config files to the actual code. -They are meant to cover a few main components that users frequently need to replace. -However, the capability of a text-based config file is sometimes limited and -some deeper customization may be available only through writing code. - -Most model components in detectron2 have a clear `__init__` interface that documents -what input arguments it needs. Calling them with custom arguments will give you a custom variant -of the model. - -As an example, to use __custom loss function__ in the box head of a Faster R-CNN, we can do the following: - -1. Losses are currently computed in [FastRCNNOutputLayers](../modules/modeling.html#detectron2.modeling.FastRCNNOutputLayers). - We need to implement a variant or a subclass of it, with custom loss functions, named `MyRCNNOutput`. -2. Call `StandardROIHeads` with `box_predictor=MyRCNNOutput()` argument instead of the builtin `FastRCNNOutputLayers`. - If all other arguments should stay unchanged, this can be easily achieved by using the [configurable `__init__`](../modules/config.html#detectron2.config.configurable) mechanism: - - ```python - roi_heads = StandardROIHeads( - cfg, backbone.output_shape(), - box_predictor=MyRCNNOutput(...) - ) - ``` -3. (optional) If we want to enable this new model from a config file, registration is needed: - ```python - @ROI_HEADS_REGISTRY.register() - class MyStandardROIHeads(StandardROIHeads): - def __init__(self, cfg, input_shape): - super().__init__(cfg, input_shape, - box_predictor=MyRCNNOutput(...)) - ``` diff --git a/preprocess/detectron2/projects/DeepLab/README.md b/preprocess/detectron2/projects/DeepLab/README.md deleted file mode 100644 index bd03cf1c41f7b0358fb6988d6a387effbb328a50..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# DeepLab in Detectron2 - -In this repository, we implement DeepLabV3 and DeepLabV3+ in Detectron2. - -## Installation -Install Detectron2 following [the instructions](https://detectron2.readthedocs.io/tutorials/install.html). - -## Training - -To train a model with 8 GPUs run: -```bash -cd /path/to/detectron2/projects/DeepLab -python train_net.py --config-file configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly: -```bash -cd /path/to/detectron2/projects/DeepLab -python train_net.py --config-file configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint -``` - -## Cityscapes Semantic Segmentation -Cityscapes models are trained with ImageNet pretraining. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodBackboneOutput
resolution
mIoUmodel iddownload
DeepLabV3R101-DC51024×2048 76.7 - -  |  -
DeepLabV3R103-DC51024×2048 78.5 28041665 model | metrics
DeepLabV3+R101-DC51024×2048 78.1 - -  |  -
DeepLabV3+R103-DC51024×2048 80.0 28054032model | metrics
- -Note: -- [R103](https://dl.fbaipublicfiles.com/detectron2/DeepLab/R-103.pkl): a ResNet-101 with its first 7x7 convolution replaced by 3 3x3 convolutions. -This modification has been used in most semantic segmentation papers. We pre-train this backbone on ImageNet using the default recipe of [pytorch examples](https://github.com/pytorch/examples/tree/master/imagenet). -- DC5 means using dilated convolution in `res5`. - -## Citing DeepLab - -If you use DeepLab, please use the following BibTeX entry. - -* DeepLabv3+: - -``` -@inproceedings{deeplabv3plus2018, - title={Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation}, - author={Liang-Chieh Chen and Yukun Zhu and George Papandreou and Florian Schroff and Hartwig Adam}, - booktitle={ECCV}, - year={2018} -} -``` - -* DeepLabv3: - -``` -@article{deeplabv32018, - title={Rethinking atrous convolution for semantic image segmentation}, - author={Chen, Liang-Chieh and Papandreou, George and Schroff, Florian and Adam, Hartwig}, - journal={arXiv:1706.05587}, - year={2017} -} -``` diff --git a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/Base-DeepLabV3-OS16-Semantic.yaml b/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/Base-DeepLabV3-OS16-Semantic.yaml deleted file mode 100644 index fa6edb5dcd0e1d866058474e6627abb2674e6a34..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/Base-DeepLabV3-OS16-Semantic.yaml +++ /dev/null @@ -1,36 +0,0 @@ -_BASE_: "../../../../configs/Base-RCNN-DilatedC5.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - BACKBONE: - FREEZE_AT: 0 - SEM_SEG_HEAD: - NAME: "DeepLabV3Head" - IN_FEATURES: ["res5"] - ASPP_CHANNELS: 256 - ASPP_DILATIONS: [6, 12, 18] - ASPP_DROPOUT: 0.1 - CONVS_DIM: 256 - COMMON_STRIDE: 16 - NUM_CLASSES: 19 - LOSS_TYPE: "hard_pixel_mining" -DATASETS: - TRAIN: ("cityscapes_fine_sem_seg_train",) - TEST: ("cityscapes_fine_sem_seg_val",) -SOLVER: - BASE_LR: 0.01 - MAX_ITER: 90000 - LR_SCHEDULER_NAME: "WarmupPolyLR" - IMS_PER_BATCH: 16 -INPUT: - MIN_SIZE_TRAIN: (512, 768, 1024, 1280, 1536, 1792, 2048) - MIN_SIZE_TRAIN_SAMPLING: "choice" - MIN_SIZE_TEST: 1024 - MAX_SIZE_TRAIN: 4096 - MAX_SIZE_TEST: 2048 - CROP: - ENABLED: True - TYPE: "absolute" - SIZE: (512, 1024) - SINGLE_CATEGORY_MAX_AREA: 1.0 -DATALOADER: - NUM_WORKERS: 10 diff --git a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_R_103_os16_mg124_poly_90k_bs16.yaml b/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_R_103_os16_mg124_poly_90k_bs16.yaml deleted file mode 100644 index a2f5a54140189c099c39b4b737e92decb5fbe569..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_R_103_os16_mg124_poly_90k_bs16.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: Base-DeepLabV3-OS16-Semantic.yaml -MODEL: - WEIGHTS: "detectron2://DeepLab/R-103.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - BACKBONE: - NAME: "build_resnet_deeplab_backbone" - RESNETS: - DEPTH: 101 - NORM: "SyncBN" - RES5_MULTI_GRID: [1, 2, 4] - STEM_TYPE: "deeplab" - STEM_OUT_CHANNELS: 128 - STRIDE_IN_1X1: False - SEM_SEG_HEAD: - NAME: "DeepLabV3Head" - NORM: "SyncBN" -INPUT: - FORMAT: "RGB" diff --git a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml b/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml deleted file mode 100644 index c03a72d83dd813a94ab1d1d59f875c2428eca890..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/configs/Cityscapes-SemanticSegmentation/deeplab_v3_plus_R_103_os16_mg124_poly_90k_bs16.yaml +++ /dev/null @@ -1,24 +0,0 @@ -_BASE_: Base-DeepLabV3-OS16-Semantic.yaml -MODEL: - WEIGHTS: "detectron2://DeepLab/R-103.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - BACKBONE: - NAME: "build_resnet_deeplab_backbone" - RESNETS: - DEPTH: 101 - NORM: "SyncBN" - OUT_FEATURES: ["res2", "res5"] - RES5_MULTI_GRID: [1, 2, 4] - STEM_TYPE: "deeplab" - STEM_OUT_CHANNELS: 128 - STRIDE_IN_1X1: False - SEM_SEG_HEAD: - NAME: "DeepLabV3PlusHead" - IN_FEATURES: ["res2", "res5"] - PROJECT_FEATURES: ["res2"] - PROJECT_CHANNELS: [48] - NORM: "SyncBN" - COMMON_STRIDE: 4 -INPUT: - FORMAT: "RGB" diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/__init__.py b/preprocess/detectron2/projects/DeepLab/deeplab/__init__.py deleted file mode 100644 index dcd88ff0c09d630577e3ac9f8afb5324a80a7be4..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .build_solver import build_lr_scheduler -from .config import add_deeplab_config -from .resnet import build_resnet_deeplab_backbone -from .semantic_seg import DeepLabV3Head, DeepLabV3PlusHead diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/build_solver.py b/preprocess/detectron2/projects/DeepLab/deeplab/build_solver.py deleted file mode 100644 index a1d359c2c35baf75a835879bb4b4f902be235179..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/build_solver.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import torch - -from detectron2.config import CfgNode -from detectron2.solver import LRScheduler -from detectron2.solver import build_lr_scheduler as build_d2_lr_scheduler - -from .lr_scheduler import WarmupPolyLR - - -def build_lr_scheduler(cfg: CfgNode, optimizer: torch.optim.Optimizer) -> LRScheduler: - """ - Build a LR scheduler from config. - """ - name = cfg.SOLVER.LR_SCHEDULER_NAME - if name == "WarmupPolyLR": - return WarmupPolyLR( - optimizer, - cfg.SOLVER.MAX_ITER, - warmup_factor=cfg.SOLVER.WARMUP_FACTOR, - warmup_iters=cfg.SOLVER.WARMUP_ITERS, - warmup_method=cfg.SOLVER.WARMUP_METHOD, - power=cfg.SOLVER.POLY_LR_POWER, - constant_ending=cfg.SOLVER.POLY_LR_CONSTANT_ENDING, - ) - else: - return build_d2_lr_scheduler(cfg, optimizer) diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/config.py b/preprocess/detectron2/projects/DeepLab/deeplab/config.py deleted file mode 100644 index 5f5e45a9124e61c12d90cfc5032b268496891a4a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/config.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - - -def add_deeplab_config(cfg): - """ - Add config for DeepLab. - """ - # We retry random cropping until no single category in semantic segmentation GT occupies more - # than `SINGLE_CATEGORY_MAX_AREA` part of the crop. - cfg.INPUT.CROP.SINGLE_CATEGORY_MAX_AREA = 1.0 - # Used for `poly` learning rate schedule. - cfg.SOLVER.POLY_LR_POWER = 0.9 - cfg.SOLVER.POLY_LR_CONSTANT_ENDING = 0.0 - # Loss type, choose from `cross_entropy`, `hard_pixel_mining`. - cfg.MODEL.SEM_SEG_HEAD.LOSS_TYPE = "hard_pixel_mining" - # DeepLab settings - cfg.MODEL.SEM_SEG_HEAD.PROJECT_FEATURES = ["res2"] - cfg.MODEL.SEM_SEG_HEAD.PROJECT_CHANNELS = [48] - cfg.MODEL.SEM_SEG_HEAD.ASPP_CHANNELS = 256 - cfg.MODEL.SEM_SEG_HEAD.ASPP_DILATIONS = [6, 12, 18] - cfg.MODEL.SEM_SEG_HEAD.ASPP_DROPOUT = 0.1 - cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV = False - # Backbone new configs - cfg.MODEL.RESNETS.RES4_DILATION = 1 - cfg.MODEL.RESNETS.RES5_MULTI_GRID = [1, 2, 4] - # ResNet stem type from: `basic`, `deeplab` - cfg.MODEL.RESNETS.STEM_TYPE = "deeplab" diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/loss.py b/preprocess/detectron2/projects/DeepLab/deeplab/loss.py deleted file mode 100644 index 3a43087b7c1a2b4d2b249fad117724dbd0f14fdd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/loss.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import torch -import torch.nn as nn - - -class DeepLabCE(nn.Module): - """ - Hard pixel mining with cross entropy loss, for semantic segmentation. - This is used in TensorFlow DeepLab frameworks. - Paper: DeeperLab: Single-Shot Image Parser - Reference: https://github.com/tensorflow/models/blob/bd488858d610e44df69da6f89277e9de8a03722c/research/deeplab/utils/train_utils.py#L33 # noqa - Arguments: - ignore_label: Integer, label to ignore. - top_k_percent_pixels: Float, the value lies in [0.0, 1.0]. When its - value < 1.0, only compute the loss for the top k percent pixels - (e.g., the top 20% pixels). This is useful for hard pixel mining. - weight: Tensor, a manual rescaling weight given to each class. - """ - - def __init__(self, ignore_label=-1, top_k_percent_pixels=1.0, weight=None): - super(DeepLabCE, self).__init__() - self.top_k_percent_pixels = top_k_percent_pixels - self.ignore_label = ignore_label - self.criterion = nn.CrossEntropyLoss( - weight=weight, ignore_index=ignore_label, reduction="none" - ) - - def forward(self, logits, labels, weights=None): - if weights is None: - pixel_losses = self.criterion(logits, labels).contiguous().view(-1) - else: - # Apply per-pixel loss weights. - pixel_losses = self.criterion(logits, labels) * weights - pixel_losses = pixel_losses.contiguous().view(-1) - if self.top_k_percent_pixels == 1.0: - return pixel_losses.mean() - - top_k_pixels = int(self.top_k_percent_pixels * pixel_losses.numel()) - pixel_losses, _ = torch.topk(pixel_losses, top_k_pixels) - return pixel_losses.mean() diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/lr_scheduler.py b/preprocess/detectron2/projects/DeepLab/deeplab/lr_scheduler.py deleted file mode 100644 index b754b59750ed7fea1e2d24d40f019d26bd562bf5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/lr_scheduler.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import math -from typing import List -import torch - -from detectron2.solver.lr_scheduler import LRScheduler, _get_warmup_factor_at_iter - -# NOTE: PyTorch's LR scheduler interface uses names that assume the LR changes -# only on epoch boundaries. We typically use iteration based schedules instead. -# As a result, "epoch" (e.g., as in self.last_epoch) should be understood to mean -# "iteration" instead. - -# FIXME: ideally this would be achieved with a CombinedLRScheduler, separating -# MultiStepLR with WarmupLR but the current LRScheduler design doesn't allow it. - - -class WarmupPolyLR(LRScheduler): - """ - Poly learning rate schedule used to train DeepLab. - Paper: DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, - Atrous Convolution, and Fully Connected CRFs. - Reference: https://github.com/tensorflow/models/blob/21b73d22f3ed05b650e85ac50849408dd36de32e/research/deeplab/utils/train_utils.py#L337 # noqa - """ - - def __init__( - self, - optimizer: torch.optim.Optimizer, - max_iters: int, - warmup_factor: float = 0.001, - warmup_iters: int = 1000, - warmup_method: str = "linear", - last_epoch: int = -1, - power: float = 0.9, - constant_ending: float = 0.0, - ): - self.max_iters = max_iters - self.warmup_factor = warmup_factor - self.warmup_iters = warmup_iters - self.warmup_method = warmup_method - self.power = power - self.constant_ending = constant_ending - super().__init__(optimizer, last_epoch) - - def get_lr(self) -> List[float]: - warmup_factor = _get_warmup_factor_at_iter( - self.warmup_method, self.last_epoch, self.warmup_iters, self.warmup_factor - ) - if self.constant_ending > 0 and warmup_factor == 1.0: - # Constant ending lr. - if ( - math.pow((1.0 - self.last_epoch / self.max_iters), self.power) - < self.constant_ending - ): - return [base_lr * self.constant_ending for base_lr in self.base_lrs] - return [ - base_lr * warmup_factor * math.pow((1.0 - self.last_epoch / self.max_iters), self.power) - for base_lr in self.base_lrs - ] - - def _compute_values(self) -> List[float]: - # The new interface - return self.get_lr() diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/resnet.py b/preprocess/detectron2/projects/DeepLab/deeplab/resnet.py deleted file mode 100644 index 2cc277b24630a9425f4c37e1abc3352b49e1a031..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/resnet.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import fvcore.nn.weight_init as weight_init -import torch.nn.functional as F - -from detectron2.layers import CNNBlockBase, Conv2d, get_norm -from detectron2.modeling import BACKBONE_REGISTRY -from detectron2.modeling.backbone.resnet import ( - BasicStem, - BottleneckBlock, - DeformBottleneckBlock, - ResNet, -) - - -class DeepLabStem(CNNBlockBase): - """ - The DeepLab ResNet stem (layers before the first residual block). - """ - - def __init__(self, in_channels=3, out_channels=128, norm="BN"): - """ - Args: - norm (str or callable): norm after the first conv layer. - See :func:`layers.get_norm` for supported format. - """ - super().__init__(in_channels, out_channels, 4) - self.in_channels = in_channels - self.conv1 = Conv2d( - in_channels, - out_channels // 2, - kernel_size=3, - stride=2, - padding=1, - bias=False, - norm=get_norm(norm, out_channels // 2), - ) - self.conv2 = Conv2d( - out_channels // 2, - out_channels // 2, - kernel_size=3, - stride=1, - padding=1, - bias=False, - norm=get_norm(norm, out_channels // 2), - ) - self.conv3 = Conv2d( - out_channels // 2, - out_channels, - kernel_size=3, - stride=1, - padding=1, - bias=False, - norm=get_norm(norm, out_channels), - ) - weight_init.c2_msra_fill(self.conv1) - weight_init.c2_msra_fill(self.conv2) - weight_init.c2_msra_fill(self.conv3) - - def forward(self, x): - x = self.conv1(x) - x = F.relu_(x) - x = self.conv2(x) - x = F.relu_(x) - x = self.conv3(x) - x = F.relu_(x) - x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1) - return x - - -@BACKBONE_REGISTRY.register() -def build_resnet_deeplab_backbone(cfg, input_shape): - """ - Create a ResNet instance from config. - Returns: - ResNet: a :class:`ResNet` instance. - """ - # need registration of new blocks/stems? - norm = cfg.MODEL.RESNETS.NORM - if cfg.MODEL.RESNETS.STEM_TYPE == "basic": - stem = BasicStem( - in_channels=input_shape.channels, - out_channels=cfg.MODEL.RESNETS.STEM_OUT_CHANNELS, - norm=norm, - ) - elif cfg.MODEL.RESNETS.STEM_TYPE == "deeplab": - stem = DeepLabStem( - in_channels=input_shape.channels, - out_channels=cfg.MODEL.RESNETS.STEM_OUT_CHANNELS, - norm=norm, - ) - else: - raise ValueError("Unknown stem type: {}".format(cfg.MODEL.RESNETS.STEM_TYPE)) - - # fmt: off - freeze_at = cfg.MODEL.BACKBONE.FREEZE_AT - out_features = cfg.MODEL.RESNETS.OUT_FEATURES - depth = cfg.MODEL.RESNETS.DEPTH - num_groups = cfg.MODEL.RESNETS.NUM_GROUPS - width_per_group = cfg.MODEL.RESNETS.WIDTH_PER_GROUP - bottleneck_channels = num_groups * width_per_group - in_channels = cfg.MODEL.RESNETS.STEM_OUT_CHANNELS - out_channels = cfg.MODEL.RESNETS.RES2_OUT_CHANNELS - stride_in_1x1 = cfg.MODEL.RESNETS.STRIDE_IN_1X1 - res4_dilation = cfg.MODEL.RESNETS.RES4_DILATION - res5_dilation = cfg.MODEL.RESNETS.RES5_DILATION - deform_on_per_stage = cfg.MODEL.RESNETS.DEFORM_ON_PER_STAGE - deform_modulated = cfg.MODEL.RESNETS.DEFORM_MODULATED - deform_num_groups = cfg.MODEL.RESNETS.DEFORM_NUM_GROUPS - res5_multi_grid = cfg.MODEL.RESNETS.RES5_MULTI_GRID - # fmt: on - assert res4_dilation in {1, 2}, "res4_dilation cannot be {}.".format(res4_dilation) - assert res5_dilation in {1, 2, 4}, "res5_dilation cannot be {}.".format(res5_dilation) - if res4_dilation == 2: - # Always dilate res5 if res4 is dilated. - assert res5_dilation == 4 - - num_blocks_per_stage = {50: [3, 4, 6, 3], 101: [3, 4, 23, 3], 152: [3, 8, 36, 3]}[depth] - - stages = [] - - # Avoid creating variables without gradients - # It consumes extra memory and may cause allreduce to fail - out_stage_idx = [{"res2": 2, "res3": 3, "res4": 4, "res5": 5}[f] for f in out_features] - max_stage_idx = max(out_stage_idx) - for idx, stage_idx in enumerate(range(2, max_stage_idx + 1)): - if stage_idx == 4: - dilation = res4_dilation - elif stage_idx == 5: - dilation = res5_dilation - else: - dilation = 1 - first_stride = 1 if idx == 0 or dilation > 1 else 2 - stage_kargs = { - "num_blocks": num_blocks_per_stage[idx], - "stride_per_block": [first_stride] + [1] * (num_blocks_per_stage[idx] - 1), - "in_channels": in_channels, - "out_channels": out_channels, - "norm": norm, - } - stage_kargs["bottleneck_channels"] = bottleneck_channels - stage_kargs["stride_in_1x1"] = stride_in_1x1 - stage_kargs["dilation"] = dilation - stage_kargs["num_groups"] = num_groups - if deform_on_per_stage[idx]: - stage_kargs["block_class"] = DeformBottleneckBlock - stage_kargs["deform_modulated"] = deform_modulated - stage_kargs["deform_num_groups"] = deform_num_groups - else: - stage_kargs["block_class"] = BottleneckBlock - if stage_idx == 5: - stage_kargs.pop("dilation") - stage_kargs["dilation_per_block"] = [dilation * mg for mg in res5_multi_grid] - blocks = ResNet.make_stage(**stage_kargs) - in_channels = out_channels - out_channels *= 2 - bottleneck_channels *= 2 - stages.append(blocks) - return ResNet(stem, stages, out_features=out_features).freeze(freeze_at) diff --git a/preprocess/detectron2/projects/DeepLab/deeplab/semantic_seg.py b/preprocess/detectron2/projects/DeepLab/deeplab/semantic_seg.py deleted file mode 100644 index d4625c52d96b2a700d828112c2a2ea80f5028330..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/deeplab/semantic_seg.py +++ /dev/null @@ -1,348 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from typing import Callable, Dict, List, Optional, Tuple, Union -import fvcore.nn.weight_init as weight_init -import torch -from torch import nn -from torch.nn import functional as F - -from detectron2.config import configurable -from detectron2.layers import ASPP, Conv2d, DepthwiseSeparableConv2d, ShapeSpec, get_norm -from detectron2.modeling import SEM_SEG_HEADS_REGISTRY - -from .loss import DeepLabCE - - -@SEM_SEG_HEADS_REGISTRY.register() -class DeepLabV3PlusHead(nn.Module): - """ - A semantic segmentation head described in :paper:`DeepLabV3+`. - """ - - @configurable - def __init__( - self, - input_shape: Dict[str, ShapeSpec], - *, - project_channels: List[int], - aspp_dilations: List[int], - aspp_dropout: float, - decoder_channels: List[int], - common_stride: int, - norm: Union[str, Callable], - train_size: Optional[Tuple], - loss_weight: float = 1.0, - loss_type: str = "cross_entropy", - ignore_value: int = -1, - num_classes: Optional[int] = None, - use_depthwise_separable_conv: bool = False, - ): - """ - NOTE: this interface is experimental. - - Args: - input_shape: shape of the input features. They will be ordered by stride - and the last one (with largest stride) is used as the input to the - decoder (i.e. the ASPP module); the rest are low-level feature for - the intermediate levels of decoder. - project_channels (list[int]): a list of low-level feature channels. - The length should be len(in_features) - 1. - aspp_dilations (list(int)): a list of 3 dilations in ASPP. - aspp_dropout (float): apply dropout on the output of ASPP. - decoder_channels (list[int]): a list of output channels of each - decoder stage. It should have the same length as "in_features" - (each element in "in_features" corresponds to one decoder stage). - common_stride (int): output stride of decoder. - norm (str or callable): normalization for all conv layers. - train_size (tuple): (height, width) of training images. - loss_weight (float): loss weight. - loss_type (str): type of loss function, 2 opptions: - (1) "cross_entropy" is the standard cross entropy loss. - (2) "hard_pixel_mining" is the loss in DeepLab that samples - top k% hardest pixels. - ignore_value (int): category to be ignored during training. - num_classes (int): number of classes, if set to None, the decoder - will not construct a predictor. - use_depthwise_separable_conv (bool): use DepthwiseSeparableConv2d - in ASPP and decoder. - """ - super().__init__() - input_shape = sorted(input_shape.items(), key=lambda x: x[1].stride) - - # fmt: off - self.in_features = [k for k, v in input_shape] # starting from "res2" to "res5" - in_channels = [x[1].channels for x in input_shape] - in_strides = [x[1].stride for x in input_shape] - aspp_channels = decoder_channels[-1] - self.ignore_value = ignore_value - self.common_stride = common_stride # output stride - self.loss_weight = loss_weight - self.loss_type = loss_type - self.decoder_only = num_classes is None - self.use_depthwise_separable_conv = use_depthwise_separable_conv - # fmt: on - - assert ( - len(project_channels) == len(self.in_features) - 1 - ), "Expected {} project_channels, got {}".format( - len(self.in_features) - 1, len(project_channels) - ) - assert len(decoder_channels) == len( - self.in_features - ), "Expected {} decoder_channels, got {}".format( - len(self.in_features), len(decoder_channels) - ) - self.decoder = nn.ModuleDict() - - use_bias = norm == "" - for idx, in_channel in enumerate(in_channels): - decoder_stage = nn.ModuleDict() - - if idx == len(self.in_features) - 1: - # ASPP module - if train_size is not None: - train_h, train_w = train_size - encoder_stride = in_strides[-1] - if train_h % encoder_stride or train_w % encoder_stride: - raise ValueError("Crop size need to be divisible by encoder stride.") - pool_h = train_h // encoder_stride - pool_w = train_w // encoder_stride - pool_kernel_size = (pool_h, pool_w) - else: - pool_kernel_size = None - project_conv = ASPP( - in_channel, - aspp_channels, - aspp_dilations, - norm=norm, - activation=F.relu, - pool_kernel_size=pool_kernel_size, - dropout=aspp_dropout, - use_depthwise_separable_conv=use_depthwise_separable_conv, - ) - fuse_conv = None - else: - project_conv = Conv2d( - in_channel, - project_channels[idx], - kernel_size=1, - bias=use_bias, - norm=get_norm(norm, project_channels[idx]), - activation=F.relu, - ) - weight_init.c2_xavier_fill(project_conv) - if use_depthwise_separable_conv: - # We use a single 5x5 DepthwiseSeparableConv2d to replace - # 2 3x3 Conv2d since they have the same receptive field, - # proposed in :paper:`Panoptic-DeepLab`. - fuse_conv = DepthwiseSeparableConv2d( - project_channels[idx] + decoder_channels[idx + 1], - decoder_channels[idx], - kernel_size=5, - padding=2, - norm1=norm, - activation1=F.relu, - norm2=norm, - activation2=F.relu, - ) - else: - fuse_conv = nn.Sequential( - Conv2d( - project_channels[idx] + decoder_channels[idx + 1], - decoder_channels[idx], - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, decoder_channels[idx]), - activation=F.relu, - ), - Conv2d( - decoder_channels[idx], - decoder_channels[idx], - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, decoder_channels[idx]), - activation=F.relu, - ), - ) - weight_init.c2_xavier_fill(fuse_conv[0]) - weight_init.c2_xavier_fill(fuse_conv[1]) - - decoder_stage["project_conv"] = project_conv - decoder_stage["fuse_conv"] = fuse_conv - - self.decoder[self.in_features[idx]] = decoder_stage - - if not self.decoder_only: - self.predictor = Conv2d( - decoder_channels[0], num_classes, kernel_size=1, stride=1, padding=0 - ) - nn.init.normal_(self.predictor.weight, 0, 0.001) - nn.init.constant_(self.predictor.bias, 0) - - if self.loss_type == "cross_entropy": - self.loss = nn.CrossEntropyLoss(reduction="mean", ignore_index=self.ignore_value) - elif self.loss_type == "hard_pixel_mining": - self.loss = DeepLabCE(ignore_label=self.ignore_value, top_k_percent_pixels=0.2) - else: - raise ValueError("Unexpected loss type: %s" % self.loss_type) - - @classmethod - def from_config(cls, cfg, input_shape): - if cfg.INPUT.CROP.ENABLED: - assert cfg.INPUT.CROP.TYPE == "absolute" - train_size = cfg.INPUT.CROP.SIZE - else: - train_size = None - decoder_channels = [cfg.MODEL.SEM_SEG_HEAD.CONVS_DIM] * ( - len(cfg.MODEL.SEM_SEG_HEAD.IN_FEATURES) - 1 - ) + [cfg.MODEL.SEM_SEG_HEAD.ASPP_CHANNELS] - ret = dict( - input_shape={ - k: v for k, v in input_shape.items() if k in cfg.MODEL.SEM_SEG_HEAD.IN_FEATURES - }, - project_channels=cfg.MODEL.SEM_SEG_HEAD.PROJECT_CHANNELS, - aspp_dilations=cfg.MODEL.SEM_SEG_HEAD.ASPP_DILATIONS, - aspp_dropout=cfg.MODEL.SEM_SEG_HEAD.ASPP_DROPOUT, - decoder_channels=decoder_channels, - common_stride=cfg.MODEL.SEM_SEG_HEAD.COMMON_STRIDE, - norm=cfg.MODEL.SEM_SEG_HEAD.NORM, - train_size=train_size, - loss_weight=cfg.MODEL.SEM_SEG_HEAD.LOSS_WEIGHT, - loss_type=cfg.MODEL.SEM_SEG_HEAD.LOSS_TYPE, - ignore_value=cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE, - num_classes=cfg.MODEL.SEM_SEG_HEAD.NUM_CLASSES, - use_depthwise_separable_conv=cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV, - ) - return ret - - def forward(self, features, targets=None): - """ - Returns: - In training, returns (None, dict of losses) - In inference, returns (CxHxW logits, {}) - """ - y = self.layers(features) - if self.decoder_only: - # Output from self.layers() only contains decoder feature. - return y - if self.training: - return None, self.losses(y, targets) - else: - y = F.interpolate( - y, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - return y, {} - - def layers(self, features): - # Reverse feature maps into top-down order (from low to high resolution) - for f in self.in_features[::-1]: - x = features[f] - proj_x = self.decoder[f]["project_conv"](x) - if self.decoder[f]["fuse_conv"] is None: - # This is aspp module - y = proj_x - else: - # Upsample y - y = F.interpolate(y, size=proj_x.size()[2:], mode="bilinear", align_corners=False) - y = torch.cat([proj_x, y], dim=1) - y = self.decoder[f]["fuse_conv"](y) - if not self.decoder_only: - y = self.predictor(y) - return y - - def losses(self, predictions, targets): - predictions = F.interpolate( - predictions, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - loss = self.loss(predictions, targets) - losses = {"loss_sem_seg": loss * self.loss_weight} - return losses - - -@SEM_SEG_HEADS_REGISTRY.register() -class DeepLabV3Head(nn.Module): - """ - A semantic segmentation head described in :paper:`DeepLabV3`. - """ - - def __init__(self, cfg, input_shape: Dict[str, ShapeSpec]): - super().__init__() - - # fmt: off - self.in_features = cfg.MODEL.SEM_SEG_HEAD.IN_FEATURES - in_channels = [input_shape[f].channels for f in self.in_features] - aspp_channels = cfg.MODEL.SEM_SEG_HEAD.ASPP_CHANNELS - aspp_dilations = cfg.MODEL.SEM_SEG_HEAD.ASPP_DILATIONS - self.ignore_value = cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE - num_classes = cfg.MODEL.SEM_SEG_HEAD.NUM_CLASSES - conv_dims = cfg.MODEL.SEM_SEG_HEAD.CONVS_DIM - self.common_stride = cfg.MODEL.SEM_SEG_HEAD.COMMON_STRIDE # output stride - norm = cfg.MODEL.SEM_SEG_HEAD.NORM - self.loss_weight = cfg.MODEL.SEM_SEG_HEAD.LOSS_WEIGHT - self.loss_type = cfg.MODEL.SEM_SEG_HEAD.LOSS_TYPE - train_crop_size = cfg.INPUT.CROP.SIZE - aspp_dropout = cfg.MODEL.SEM_SEG_HEAD.ASPP_DROPOUT - use_depthwise_separable_conv = cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV - # fmt: on - - assert len(self.in_features) == 1 - assert len(in_channels) == 1 - - # ASPP module - if cfg.INPUT.CROP.ENABLED: - assert cfg.INPUT.CROP.TYPE == "absolute" - train_crop_h, train_crop_w = train_crop_size - if train_crop_h % self.common_stride or train_crop_w % self.common_stride: - raise ValueError("Crop size need to be divisible by output stride.") - pool_h = train_crop_h // self.common_stride - pool_w = train_crop_w // self.common_stride - pool_kernel_size = (pool_h, pool_w) - else: - pool_kernel_size = None - self.aspp = ASPP( - in_channels[0], - aspp_channels, - aspp_dilations, - norm=norm, - activation=F.relu, - pool_kernel_size=pool_kernel_size, - dropout=aspp_dropout, - use_depthwise_separable_conv=use_depthwise_separable_conv, - ) - - self.predictor = Conv2d(conv_dims, num_classes, kernel_size=1, stride=1, padding=0) - nn.init.normal_(self.predictor.weight, 0, 0.001) - nn.init.constant_(self.predictor.bias, 0) - - if self.loss_type == "cross_entropy": - self.loss = nn.CrossEntropyLoss(reduction="mean", ignore_index=self.ignore_value) - elif self.loss_type == "hard_pixel_mining": - self.loss = DeepLabCE(ignore_label=self.ignore_value, top_k_percent_pixels=0.2) - else: - raise ValueError("Unexpected loss type: %s" % self.loss_type) - - def forward(self, features, targets=None): - """ - Returns: - In training, returns (None, dict of losses) - In inference, returns (CxHxW logits, {}) - """ - x = features[self.in_features[0]] - x = self.aspp(x) - x = self.predictor(x) - if self.training: - return None, self.losses(x, targets) - else: - x = F.interpolate( - x, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - return x, {} - - def losses(self, predictions, targets): - predictions = F.interpolate( - predictions, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - loss = self.loss(predictions, targets) - losses = {"loss_sem_seg": loss * self.loss_weight} - return losses diff --git a/preprocess/detectron2/projects/DeepLab/train_net.py b/preprocess/detectron2/projects/DeepLab/train_net.py deleted file mode 100755 index b3f514ea57bc06bb4390c174f141156060408e97..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DeepLab/train_net.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -DeepLab Training Script. - -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -import detectron2.data.transforms as T -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_train_loader, DatasetMapper, MetadataCatalog -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import ( - CityscapesSemSegEvaluator, - DatasetEvaluators, - SemSegEvaluator, -) -from detectron2.projects.deeplab import add_deeplab_config, build_lr_scheduler - - -def build_sem_seg_train_aug(cfg): - augs = [ - T.ResizeShortestEdge( - cfg.INPUT.MIN_SIZE_TRAIN, - cfg.INPUT.MAX_SIZE_TRAIN, - cfg.INPUT.MIN_SIZE_TRAIN_SAMPLING, - ) - ] - if cfg.INPUT.CROP.ENABLED: - augs.append( - T.RandomCrop_CategoryAreaConstraint( - cfg.INPUT.CROP.TYPE, - cfg.INPUT.CROP.SIZE, - cfg.INPUT.CROP.SINGLE_CATEGORY_MAX_AREA, - cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE, - ) - ) - augs.append(T.RandomFlip()) - return augs - - -class Trainer(DefaultTrainer): - """ - We use the "DefaultTrainer" which contains a number pre-defined logic for - standard training workflow. They may not work for you, especially if you - are working on a new research project. In that case you can use the cleaner - "SimpleTrainer", or write your own training loop. - """ - - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type == "sem_seg": - return SemSegEvaluator( - dataset_name, - distributed=True, - output_dir=output_folder, - ) - if evaluator_type == "cityscapes_sem_seg": - return CityscapesSemSegEvaluator(dataset_name) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - if len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - @classmethod - def build_train_loader(cls, cfg): - if "SemanticSegmentor" in cfg.MODEL.META_ARCHITECTURE: - mapper = DatasetMapper( - cfg, is_train=True, augmentations=build_sem_seg_train_aug(cfg) - ) - else: - mapper = None - return build_detection_train_loader(cfg, mapper=mapper) - - @classmethod - def build_lr_scheduler(cls, cfg, optimizer): - """ - It now calls :func:`detectron2.solver.build_lr_scheduler`. - Overwrite it if you'd like a different scheduler. - """ - return build_lr_scheduler(cfg, optimizer) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_deeplab_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/DensePose/README.md b/preprocess/detectron2/projects/DensePose/README.md deleted file mode 100644 index 38f4f834adfcd5490a790a715b24c9ad26ab4dde..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# DensePose in Detectron2 - -DensePose aims at learning and establishing dense correspondences between image pixels -and 3D object geometry for deformable objects, such as humans or animals. -In this repository, we provide the code to train and evaluate DensePose R-CNN and -various tools to visualize DensePose annotations and results. - -There are two main paradigms that are used within DensePose project. - -## [Chart-based Dense Pose Estimation for Humans and Animals](doc/DENSEPOSE_IUV.md) - -
- -
- -For chart-based estimation, 3D object mesh is split into charts and -for each pixel the model estimates chart index `I` and local chart coordinates `(U, V)`. -Please follow the link above to find a [detailed overview](doc/DENSEPOSE_IUV.md#Overview) -of the method, links to trained models along with their performance evaluation in the -[Model Zoo](doc/DENSEPOSE_IUV.md#ModelZoo) and -[references](doc/DENSEPOSE_IUV.md#References) to the corresponding papers. - -## [Continuous Surface Embeddings for Dense Pose Estimation for Humans and Animals](doc/DENSEPOSE_CSE.md) - -
- -
- -To establish continuous surface embeddings, the model simultaneously learns -descriptors for mesh vertices and for image pixels. -The embeddings are put into correspondence, thus the location -of each pixel on the 3D model is derived. -Please follow the link above to find a [detailed overview](doc/DENSEPOSE_CSE.md#Overview) -of the method, links to trained models along with their performance evaluation in the -[Model Zoo](doc/DENSEPOSE_CSE.md#ModelZoo) and -[references](doc/DENSEPOSE_CSE.md#References) to the corresponding papers. - -# Quick Start - -See [ Getting Started ](doc/GETTING_STARTED.md) - -# Model Zoo - -Please check the dedicated pages -for [chart-based model zoo](doc/DENSEPOSE_IUV.md#ModelZoo) -and for [continuous surface embeddings model zoo](doc/DENSEPOSE_CSE.md#ModelZoo). - -# What's New - -* June 2021: [DensePose CSE with Cycle Losses](doc/RELEASE_2021_06.md) -* March 2021: [DensePose CSE (a framework to extend DensePose to various categories using 3D models) - and DensePose Evolution (a framework to bootstrap DensePose on unlabeled data) released](doc/RELEASE_2021_03.md) -* April 2020: [DensePose Confidence Estimation and Model Zoo Improvements](doc/RELEASE_2020_04.md) - -# License - -Detectron2 is released under the [Apache 2.0 license](../../LICENSE) - -## Citing DensePose - -If you use DensePose, please refer to the BibTeX entries -for [chart-based models](doc/DENSEPOSE_IUV.md#References) -and for [continuous surface embeddings](doc/DENSEPOSE_CSE.md#References). - diff --git a/preprocess/detectron2/projects/DensePose/apply_net_gradio.py b/preprocess/detectron2/projects/DensePose/apply_net_gradio.py deleted file mode 100644 index 259942e721a382e6626e007e355c96812bac122f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/apply_net_gradio.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -from typing import List - -import cv2 -import numpy as np -import torch -from densepose import add_densepose_config -from densepose.structures import DensePoseChartPredictorOutput, DensePoseEmbeddingPredictorOutput -from densepose.vis.extractor import DensePoseOutputsExtractor, DensePoseResultExtractor -from detectron2.config import get_cfg -from detectron2.engine.defaults import DefaultPredictor -from detectron2.structures.instances import Instances -from PIL import Image - - -class DensePose4Gradio: - def __init__(self, cfg, model) -> None: - cfg = self.setup_config(cfg, model, []) - self.predictor = DefaultPredictor(cfg) - - def setup_config( - self, config_fpath: str, model_fpath: str, opts: List[str] - ): - cfg = get_cfg() - add_densepose_config(cfg) - cfg.merge_from_file(config_fpath) - if opts: - cfg.merge_from_list(opts) - cfg.MODEL.WEIGHTS = model_fpath - cfg.freeze() - return cfg - - def execute(self, image: Image.Image): - img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) - with torch.no_grad(): - outputs = self.predictor(img)["instances"] - return self.execute_on_outputs(img, outputs) - - def execute_on_outputs(self, image: np.ndarray, outputs: Instances): - result = {} - if outputs.has("scores"): - result["scores"] = outputs.get("scores").cpu() - if outputs.has("pred_boxes"): - result["pred_boxes_XYXY"] = outputs.get("pred_boxes").tensor.cpu() - if outputs.has("pred_densepose"): - if isinstance(outputs.pred_densepose, DensePoseChartPredictorOutput): - extractor = DensePoseResultExtractor() - elif isinstance(outputs.pred_densepose, DensePoseEmbeddingPredictorOutput): - extractor = DensePoseOutputsExtractor() - result["pred_densepose"] = extractor(outputs)[0] - - H, W, _ = image.shape - - i = result['pred_densepose'][0].labels.cpu().numpy() - i_scale = (i.astype(np.float32) * 255 / 24).astype(np.uint8) - i_color = cv2.applyColorMap(i_scale, cv2.COLORMAP_PARULA) - i_color = cv2.cvtColor(i_color, cv2.COLOR_RGB2BGR) - i_color[i == 0] = [0, 0, 0] - - box = result["pred_boxes_XYXY"][0] - box[2] = box[2] - box[0] - box[3] = box[3] - box[1] - x, y, w, h = [int(v) for v in box] - - bg = np.zeros((H, W, 3)) - bg[y:y + h, x:x + w, :] = i_color - - bg_img = Image.fromarray(np.uint8(bg), "RGB") - - return bg_img diff --git a/preprocess/detectron2/projects/DensePose/configs/Base-DensePose-RCNN-FPN.yaml b/preprocess/detectron2/projects/DensePose/configs/Base-DensePose-RCNN-FPN.yaml deleted file mode 100644 index 1579187a7004e716eb3a86dbbfebb092d7aca84b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/Base-DensePose-RCNN-FPN.yaml +++ /dev/null @@ -1,48 +0,0 @@ -VERSION: 2 -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - BACKBONE: - NAME: "build_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res2", "res3", "res4", "res5"] - FPN: - IN_FEATURES: ["res2", "res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: [[32], [64], [128], [256], [512]] # One size for each in feature map - ASPECT_RATIOS: [[0.5, 1.0, 2.0]] # Three aspect ratios (same for all in feature maps) - RPN: - IN_FEATURES: ["p2", "p3", "p4", "p5", "p6"] - PRE_NMS_TOPK_TRAIN: 2000 # Per FPN level - PRE_NMS_TOPK_TEST: 1000 # Per FPN level - # Detectron1 uses 2000 proposals per-batch, - # (See "modeling/rpn/rpn_outputs.py" for details of this legacy issue) - # which is approximately 1000 proposals per-image since the default batch size for FPN is 2. - POST_NMS_TOPK_TRAIN: 1000 - POST_NMS_TOPK_TEST: 1000 - - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_FC: 2 - POOLER_RESOLUTION: 7 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 -DATASETS: - TRAIN: ("densepose_coco_2014_train", "densepose_coco_2014_valminusminival") - TEST: ("densepose_coco_2014_minival",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.01 - STEPS: (60000, 80000) - MAX_ITER: 90000 - WARMUP_FACTOR: 0.1 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) diff --git a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w32_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w32_s1x.yaml deleted file mode 100644 index 36eabfed984b360907f5782d4e8b0232784f8a40..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w32_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://1drv.ms/u/s!Aus8VCZ_C_33dYBMemi9xOUFR0w" - BACKBONE: - NAME: "build_hrfpn_backbone" - RPN: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] - ROI_HEADS: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: "norm" - BASE_LR: 0.03 diff --git a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w40_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w40_s1x.yaml deleted file mode 100644 index 0ca8085e154c40a5b0f42a17575d2d48328619f0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w40_s1x.yaml +++ /dev/null @@ -1,23 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://1drv.ms/u/s!Aus8VCZ_C_33ck0gvo5jfoWBOPo" - BACKBONE: - NAME: "build_hrfpn_backbone" - RPN: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] - ROI_HEADS: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] - HRNET: - STAGE2: - NUM_CHANNELS: [40, 80] - STAGE3: - NUM_CHANNELS: [40, 80, 160] - STAGE4: - NUM_CHANNELS: [40, 80, 160, 320] -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: "norm" - BASE_LR: 0.03 diff --git a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w48_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w48_s1x.yaml deleted file mode 100644 index a3f437ab57ae0ff48cd4a97cbda987346f9a5a24..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/HRNet/densepose_rcnn_HRFPN_HRNet_w48_s1x.yaml +++ /dev/null @@ -1,23 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://1drv.ms/u/s!Aus8VCZ_C_33dKvqI6pBZlifgJk" - BACKBONE: - NAME: "build_hrfpn_backbone" - RPN: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] - ROI_HEADS: - IN_FEATURES: ['p1', 'p2', 'p3', 'p4', 'p5'] - HRNET: - STAGE2: - NUM_CHANNELS: [48, 96] - STAGE3: - NUM_CHANNELS: [48, 96, 192] - STAGE4: - NUM_CHANNELS: [48, 96, 192, 384] -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: "norm" - BASE_LR: 0.03 diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN-Human.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN-Human.yaml deleted file mode 100644 index e92340ee0cdba2abd0a35114cbf3e78b04435dfe..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN-Human.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - ROI_DENSEPOSE_HEAD: - CSE: - EMBEDDERS: - "smpl_27554": - TYPE: vertex_feature - NUM_VERTICES: 27554 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_smpl_27554_256.pkl" -DATASETS: - TRAIN: - - "densepose_coco_2014_train_cse" - - "densepose_coco_2014_valminusminival_cse" - TEST: - - "densepose_coco_2014_minival_cse" - CLASS_TO_MESH_NAME_MAPPING: - "0": "smpl_27554" diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN.yaml deleted file mode 100644 index de3b26009bdee95666248f99cd243fe37e7fd8bd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/Base-DensePose-RCNN-FPN.yaml +++ /dev/null @@ -1,60 +0,0 @@ -VERSION: 2 -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - BACKBONE: - NAME: "build_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res2", "res3", "res4", "res5"] - FPN: - IN_FEATURES: ["res2", "res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: [[32], [64], [128], [256], [512]] # One size for each in feature map - ASPECT_RATIOS: [[0.5, 1.0, 2.0]] # Three aspect ratios (same for all in feature maps) - RPN: - IN_FEATURES: ["p2", "p3", "p4", "p5", "p6"] - PRE_NMS_TOPK_TRAIN: 2000 # Per FPN level - PRE_NMS_TOPK_TEST: 1000 # Per FPN level - # Detectron1 uses 2000 proposals per-batch, - # (See "modeling/rpn/rpn_outputs.py" for details of this legacy issue) - # which is approximately 1000 proposals per-image since the default batch size for FPN is 2. - POST_NMS_TOPK_TRAIN: 1000 - POST_NMS_TOPK_TEST: 1000 - - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_FC: 2 - POOLER_RESOLUTION: 7 - POOLER_SAMPLING_RATIO: 2 - POOLER_TYPE: "ROIAlign" - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - PREDICTOR_NAME: "DensePoseEmbeddingPredictor" - LOSS_NAME: "DensePoseCseLoss" - CSE: - # embedding loss, possible values: - # - "EmbeddingLoss" - # - "SoftEmbeddingLoss" - EMBED_LOSS_NAME: "EmbeddingLoss" -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.01 - STEPS: (60000, 80000) - MAX_ITER: 90000 - WARMUP_FACTOR: 0.1 - CLIP_GRADIENTS: - CLIP_TYPE: norm - CLIP_VALUE: 1.0 - ENABLED: true - NORM_TYPE: 2.0 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -DENSEPOSE_EVALUATION: - TYPE: cse - STORAGE: file diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_s1x.yaml deleted file mode 100644 index 69d858902671e683b884b32c3c1448a44dc3995e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - CSE: - EMBED_LOSS_NAME: "EmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_soft_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_soft_s1x.yaml deleted file mode 100644 index 141657cdab24a2f591eeef763aef29543c43108e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_DL_soft_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_s1x.yaml deleted file mode 100644 index d2eea1e2c3cecc7bba1bfd6f2332227bd3d0f5ed..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "EmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_soft_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_soft_s1x.yaml deleted file mode 100644 index 1c362e1f9e93f9b9b458532f5318518396404d9f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_101_FPN_soft_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_s1x.yaml deleted file mode 100644 index 26684deaa9c72aab1408dbe3abb6ac3a9b6a17ac..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - CSE: - EMBED_LOSS_NAME: "EmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_soft_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_soft_s1x.yaml deleted file mode 100644 index b53501d29b84e9ff4088ce98bc83688e89e546ed..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_DL_soft_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml deleted file mode 100644 index c186625a86cc76441b9edeefeabd7caf44af7755..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "EmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_16k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_16k.yaml deleted file mode 100644 index 69ab22669e2176b6ec661fc982be7412abb5e0e8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_16k.yaml +++ /dev/null @@ -1,133 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CATEGORY_MAPS: - "densepose_lvis_v1_ds2_train_v1": - "1202": 943 # zebra -> sheep - "569": 943 # horse -> sheep - "496": 943 # giraffe -> sheep - "422": 943 # elephant -> sheep - "80": 943 # cow -> sheep - "76": 943 # bear -> sheep - "225": 943 # cat -> sheep - "378": 943 # dog -> sheep - "densepose_lvis_v1_ds2_val_v1": - "1202": 943 # zebra -> sheep - "569": 943 # horse -> sheep - "496": 943 # giraffe -> sheep - "422": 943 # elephant -> sheep - "80": 943 # cow -> sheep - "76": 943 # bear -> sheep - "225": 943 # cat -> sheep - "378": 943 # dog -> sheep - CLASS_TO_MESH_NAME_MAPPING: - # Note: different classes are mapped to a single class - # mesh is chosen based on GT data, so this is just some - # value which has no particular meaning - "0": "sheep_5004" -SOLVER: - MAX_ITER: 16000 - STEPS: (12000, 14000) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_4k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_4k.yaml deleted file mode 100644 index 921a9c125d9da982fb88172acc7825ba3c583370..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_CA_finetune_4k.yaml +++ /dev/null @@ -1,133 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_5001": - TYPE: vertex_feature - NUM_VERTICES: 5001 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_5001_256.pkl" - "dog_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_5002_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds1_train_v1" - TEST: - - "densepose_lvis_v1_ds1_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds1_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds1_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CATEGORY_MAPS: - "densepose_lvis_v1_ds1_train_v1": - "1202": 943 # zebra -> sheep - "569": 943 # horse -> sheep - "496": 943 # giraffe -> sheep - "422": 943 # elephant -> sheep - "80": 943 # cow -> sheep - "76": 943 # bear -> sheep - "225": 943 # cat -> sheep - "378": 943 # dog -> sheep - "densepose_lvis_v1_ds1_val_v1": - "1202": 943 # zebra -> sheep - "569": 943 # horse -> sheep - "496": 943 # giraffe -> sheep - "422": 943 # elephant -> sheep - "80": 943 # cow -> sheep - "76": 943 # bear -> sheep - "225": 943 # cat -> sheep - "378": 943 # dog -> sheep - CLASS_TO_MESH_NAME_MAPPING: - # Note: different classes are mapped to a single class - # mesh is chosen based on GT data, so this is just some - # value which has no particular meaning - "0": "sheep_5004" -SOLVER: - MAX_ITER: 4000 - STEPS: (3000, 3500) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_16k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_16k.yaml deleted file mode 100644 index 1b5a098d171e508fcb9dd8088ecc1799c3068efc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_16k.yaml +++ /dev/null @@ -1,119 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k/270668502/model_final_21b1d2.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_7466" - "3": "dog_7466" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 16000 - STEPS: (12000, 14000) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_i2m_16k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_i2m_16k.yaml deleted file mode 100644 index 18d6dacf4b62e609aa85735a87daa8d2506000d7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_i2m_16k.yaml +++ /dev/null @@ -1,121 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k/270668502/model_final_21b1d2.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - PIX_TO_SHAPE_CYCLE_LOSS: - ENABLED: True - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_7466" - "3": "dog_7466" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 16000 - STEPS: (12000, 14000) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_m2m_16k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_m2m_16k.yaml deleted file mode 100644 index 6b798ae21204b9310adae33040c870253edc68ee..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_I0_finetune_m2m_16k.yaml +++ /dev/null @@ -1,138 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k/267687159/model_final_354e61.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - SHAPE_TO_SHAPE_CYCLE_LOSS: - ENABLED: True - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" - "smpl_27554": - TYPE: vertex_feature - NUM_VERTICES: 27554 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_smpl_27554_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_7466" - "3": "dog_7466" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 16000 - STEPS: (12000, 14000) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True - MESH_ALIGNMENT_MESH_NAMES: - - bear_4936 - - cow_5002 - - cat_7466 - - dog_7466 - - elephant_5002 - - giraffe_5002 - - horse_5004 - - sheep_5004 - - zebra_5002 diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_16k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_16k.yaml deleted file mode 100644 index b1462e374377fbf448e176951794face175b5002..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_16k.yaml +++ /dev/null @@ -1,119 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_7466" - "3": "dog_7466" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 16000 - STEPS: (12000, 14000) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_4k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_4k.yaml deleted file mode 100644 index ba4b81dde2ef53749b096f137ac658563fdad857..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_4k.yaml +++ /dev/null @@ -1,119 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_5001": - TYPE: vertex_feature - NUM_VERTICES: 5001 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_5001_256.pkl" - "dog_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_5002_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds1_train_v1" - TEST: - - "densepose_lvis_v1_ds1_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds1_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds1_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_5001" - "3": "dog_5002" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 4000 - STEPS: (3000, 3500) -DENSEPOSE_EVALUATION: - EVALUATE_MESH_ALIGNMENT: True diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k.yaml deleted file mode 100644 index bb6136e274ca64aa2285698664d3243519d1979f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_maskonly_24k.yaml +++ /dev/null @@ -1,118 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - COARSE_SEGM_TRAINED_BY_MASKS: True - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBED_LOSS_WEIGHT: 0.0 - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_7466_256.pkl" - "dog_7466": - TYPE: vertex_feature - NUM_VERTICES: 7466 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_7466_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_ds2_train_v1" - TEST: - - "densepose_lvis_v1_ds2_val_v1" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_ds2_train_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_ds2_val_v1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_7466" - "3": "dog_7466" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 24000 - STEPS: (20000, 22000) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_chimps_finetune_4k.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_chimps_finetune_4k.yaml deleted file mode 100644 index 3bccb7837a2e4b905b4e3c7af465c3be3a44452d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_chimps_finetune_4k.yaml +++ /dev/null @@ -1,29 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_soft_s1x/250533982/model_final_2c4512.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - GEODESIC_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "chimp_5029": - TYPE: vertex_feature - NUM_VERTICES: 5029 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_chimp_5029_256.pkl" -DATASETS: - TRAIN: - - "densepose_chimps_cse_train" - TEST: - - "densepose_chimps_cse_val" - CLASS_TO_MESH_NAME_MAPPING: - "0": "chimp_5029" -SOLVER: - MAX_ITER: 4000 - STEPS: (3000, 3500) diff --git a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_s1x.yaml deleted file mode 100644 index 9662fb8f8a4e9f7b01f41ddb79a3469ecab7032b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/cse/densepose_rcnn_R_50_FPN_soft_s1x.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN-Human.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1M_s1x.yaml deleted file mode 100644 index 3c16763c532499c1a0c62fb8c81a2ab97be3a1ec..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1_s1x.yaml deleted file mode 100644 index 15475b1ac3bb7272a7ebc0061a55119ffd2591b9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC1_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2M_s1x.yaml deleted file mode 100644 index 0cbe07f3bb0027bb7ecdc86f96d60790382b477b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2_s1x.yaml deleted file mode 100644 index 7546b967ab89129c9a276f19b1cf2d6b59f1a462..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_WC2_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_s1x.yaml deleted file mode 100644 index 045f7f02f1b4eb0c0ef1733c3ac65e3aa70168de..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_DL_s1x.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1M_s1x.yaml deleted file mode 100644 index 9334e18655d4451457a58c6ce945e01855f95105..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1_s1x.yaml deleted file mode 100644 index ace62094fbc4ce2024810333c11c7a955d8eeb22..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC1_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2M_s1x.yaml deleted file mode 100644 index 90f0be2805cd04e83c25d041d35ae66c90ce2b95..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2_s1x.yaml deleted file mode 100644 index 766c098f6dcdd1fb3f67957d7d1d982b37747b96..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_WC2_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x.yaml deleted file mode 100644 index af44fb767edf9bf093463e62f93e070d0d019c5a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x_legacy.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x_legacy.yaml deleted file mode 100644 index 8e79a1b9549cf19ed4a43cf9caf3dc88f6133310..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_101_FPN_s1x_legacy.yaml +++ /dev/null @@ -1,17 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - RESNETS: - DEPTH: 101 - ROI_DENSEPOSE_HEAD: - NUM_COARSE_SEGM_CHANNELS: 15 - POOLER_RESOLUTION: 14 - HEATMAP_SIZE: 56 - INDEX_WEIGHTS: 2.0 - PART_WEIGHTS: 0.3 - POINT_REGRESSION_WEIGHTS: 0.1 - DECODER_ON: False -SOLVER: - BASE_LR: 0.002 - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1M_s1x.yaml deleted file mode 100644 index 18a417a9a76d388810d46d1ee738d8b19abf0db0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1_s1x.yaml deleted file mode 100644 index f3720eff56ce042a68da6c99f484b963cae2c7d9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC1_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2M_s1x.yaml deleted file mode 100644 index 8a413d2a0d1549702fb45a2e50056fe0abde941f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2_s1x.yaml deleted file mode 100644 index 5a47cc05e6e9dc882778c6b502d93cbcec88fb88..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_WC2_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_s1x.yaml deleted file mode 100644 index 52a170b4a28289ad943314f77256e34800d23121..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_DL_s1x.yaml +++ /dev/null @@ -1,10 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1M_s1x.yaml deleted file mode 100644 index 8a81f2a143cbfcd2dbc92f0fc5c86f951b9b7adf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1M_s1x.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: norm - CLIP_VALUE: 100.0 - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1_s1x.yaml deleted file mode 100644 index d36e54256ac22f1b01604e54430da24972f06eeb..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC1_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2M_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2M_s1x.yaml deleted file mode 100644 index 5cf29eacd57626c676ed4c960a3e97e552b6dbdf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2M_s1x.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2_s1x.yaml deleted file mode 100644 index e880d469564a3757ba3f4d708054074cefda49b6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_WC2_s1x.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - POINT_REGRESSION_WEIGHTS: 0.0005 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 130000 - STEPS: (100000, 120000) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x.yaml deleted file mode 100644 index d2dd14c6f92f3850b99e6f1c828c0fcee52120e1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -SOLVER: - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x_legacy.yaml b/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x_legacy.yaml deleted file mode 100644 index 6c5391f3b3c3d437312a290d29b0656cb3804b25..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/densepose_rcnn_R_50_FPN_s1x_legacy.yaml +++ /dev/null @@ -1,17 +0,0 @@ -_BASE_: "Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - NUM_COARSE_SEGM_CHANNELS: 15 - POOLER_RESOLUTION: 14 - HEATMAP_SIZE: 56 - INDEX_WEIGHTS: 2.0 - PART_WEIGHTS: 0.3 - POINT_REGRESSION_WEIGHTS: 0.1 - DECODER_ON: False -SOLVER: - BASE_LR: 0.002 - MAX_ITER: 130000 - STEPS: (100000, 120000) diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml deleted file mode 100644 index f09d723f3cb9eef94223c5926dbb7731397304c9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml +++ /dev/null @@ -1,91 +0,0 @@ -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - BACKBONE: - NAME: "build_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res2", "res3", "res4", "res5"] - FPN: - IN_FEATURES: ["res2", "res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: [[32], [64], [128], [256], [512]] # One size for each in feature map - ASPECT_RATIOS: [[0.5, 1.0, 2.0]] # Three aspect ratios (same for all in feature maps) - RPN: - IN_FEATURES: ["p2", "p3", "p4", "p5", "p6"] - PRE_NMS_TOPK_TRAIN: 2000 # Per FPN level - PRE_NMS_TOPK_TEST: 1000 # Per FPN level - # Detectron1 uses 2000 proposals per-batch, - # (See "modeling/rpn/rpn_outputs.py" for details of this legacy issue) - # which is approximately 1000 proposals per-image since the default batch size for FPN is 2. - POST_NMS_TOPK_TRAIN: 1000 - POST_NMS_TOPK_TEST: 1000 - ROI_HEADS: - NAME: "StandardROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_BOX_HEAD: - NAME: "FastRCNNConvFCHead" - NUM_FC: 2 - POOLER_RESOLUTION: 7 - ROI_MASK_HEAD: - NAME: "MaskRCNNConvUpsampleHead" - NUM_CONV: 4 - POOLER_RESOLUTION: 14 -DATASETS: - TRAIN: ("base_coco_2017_train", "densepose_coco_2014_train") - TEST: ("densepose_chimps",) - CATEGORY_MAPS: - "base_coco_2017_train": - "16": 1 # bird -> person - "17": 1 # cat -> person - "18": 1 # dog -> person - "19": 1 # horse -> person - "20": 1 # sheep -> person - "21": 1 # cow -> person - "22": 1 # elephant -> person - "23": 1 # bear -> person - "24": 1 # zebra -> person - "25": 1 # girafe -> person - "base_coco_2017_val": - "16": 1 # bird -> person - "17": 1 # cat -> person - "18": 1 # dog -> person - "19": 1 # horse -> person - "20": 1 # sheep -> person - "21": 1 # cow -> person - "22": 1 # elephant -> person - "23": 1 # bear -> person - "24": 1 # zebra -> person - "25": 1 # girafe -> person - WHITELISTED_CATEGORIES: - "base_coco_2017_train": - - 1 # person - - 16 # bird - - 17 # cat - - 18 # dog - - 19 # horse - - 20 # sheep - - 21 # cow - - 22 # elephant - - 23 # bear - - 24 # zebra - - 25 # girafe - "base_coco_2017_val": - - 1 # person - - 16 # bird - - 17 # cat - - 18 # dog - - 19 # horse - - 20 # sheep - - 21 # cow - - 22 # elephant - - 23 # bear - - 24 # zebra - - 25 # girafe -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA.yaml deleted file mode 100644 index 6296692d5ff15da24f87adb6327a62d9f4a34892..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA.yaml +++ /dev/null @@ -1,28 +0,0 @@ -_BASE_: "Base-RCNN-FPN-Atop10P_CA.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - COARSE_SEGM_TRAINED_BY_MASKS: True - INDEX_WEIGHTS: 1.0 -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - WARMUP_FACTOR: 0.025 - MAX_ITER: 270000 - STEPS: (210000, 250000) diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_coarsesegm.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_coarsesegm.yaml deleted file mode 100644 index 033918e0daec8c225306dafac3a5fe9923189e53..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_coarsesegm.yaml +++ /dev/null @@ -1,56 +0,0 @@ -_BASE_: "Base-RCNN-FPN-Atop10P_CA.yaml" -MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl - RESNETS: - DEPTH: 50 - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - COARSE_SEGM_TRAINED_BY_MASKS: True -BOOTSTRAP_DATASETS: - - DATASET: "chimpnsee" - RATIO: 1.0 - IMAGE_LOADER: - TYPE: "video_keyframe" - SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 - TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 - BATCH_SIZE: 8 - NUM_WORKERS: 1 - INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 - DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_coarse_segm_confidence" - COUNT_PER_CLASS: 8 - FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -BOOTSTRAP_MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 270000 - STEPS: (210000, 250000) diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_finesegm.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_finesegm.yaml deleted file mode 100644 index 5814a4a01fd772674fa40c0cba34666aed87b33a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_finesegm.yaml +++ /dev/null @@ -1,56 +0,0 @@ -_BASE_: "Base-RCNN-FPN-Atop10P_CA.yaml" -MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl - RESNETS: - DEPTH: 50 - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - COARSE_SEGM_TRAINED_BY_MASKS: True -BOOTSTRAP_DATASETS: - - DATASET: "chimpnsee" - RATIO: 1.0 - IMAGE_LOADER: - TYPE: "video_keyframe" - SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 - TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 - BATCH_SIZE: 8 - NUM_WORKERS: 1 - INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 - DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_fine_segm_confidence" - COUNT_PER_CLASS: 8 - FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -BOOTSTRAP_MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 270000 - STEPS: (210000, 250000) diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform.yaml deleted file mode 100644 index d591ea6e22282f43fff0b44131e0913aa7261276..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform.yaml +++ /dev/null @@ -1,56 +0,0 @@ -_BASE_: "Base-RCNN-FPN-Atop10P_CA.yaml" -MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl - RESNETS: - DEPTH: 50 - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - COARSE_SEGM_TRAINED_BY_MASKS: True -BOOTSTRAP_DATASETS: - - DATASET: "chimpnsee" - RATIO: 1.0 - IMAGE_LOADER: - TYPE: "video_keyframe" - SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 - TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 - BATCH_SIZE: 8 - NUM_WORKERS: 1 - INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 - DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_uniform" - COUNT_PER_CLASS: 8 - FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -BOOTSTRAP_MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 270000 - STEPS: (210000, 250000) diff --git a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uv.yaml b/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uv.yaml deleted file mode 100644 index 110acff5a54247abb7b344672038b71e24167f33..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uv.yaml +++ /dev/null @@ -1,56 +0,0 @@ -_BASE_: "Base-RCNN-FPN-Atop10P_CA.yaml" -MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl - RESNETS: - DEPTH: 50 - DENSEPOSE_ON: True - ROI_HEADS: - NAME: "DensePoseROIHeads" - IN_FEATURES: ["p2", "p3", "p4", "p5"] - NUM_CLASSES: 1 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - SEGM_CONFIDENCE: - ENABLED: True - POINT_REGRESSION_WEIGHTS: 0.0005 - POOLER_TYPE: "ROIAlign" - NUM_COARSE_SEGM_CHANNELS: 2 - COARSE_SEGM_TRAINED_BY_MASKS: True -BOOTSTRAP_DATASETS: - - DATASET: "chimpnsee" - RATIO: 1.0 - IMAGE_LOADER: - TYPE: "video_keyframe" - SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 - TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 - BATCH_SIZE: 8 - NUM_WORKERS: 1 - INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 - DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_UV_confidence" - COUNT_PER_CLASS: 8 - FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -BOOTSTRAP_MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 270000 - STEPS: (210000, 250000) diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_DL_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_DL_instant_test.yaml deleted file mode 100644 index 3b43f75da549a9e5148c8528b5d375317680d738..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_DL_instant_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../../cse/Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100_cse",) - TEST: ("densepose_coco_2014_minival_100_cse",) -SOLVER: - MAX_ITER: 40 - STEPS: (30,) diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_instant_test.yaml deleted file mode 100644 index a2c49a2d14e5665af117972d126e25422e37b2b9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/cse/densepose_rcnn_R_50_FPN_soft_animals_finetune_instant_test.yaml +++ /dev/null @@ -1,126 +0,0 @@ -_BASE_: "../../cse/Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 9 - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseV1ConvXHead" - CSE: - EMBED_LOSS_NAME: "SoftEmbeddingLoss" - EMBEDDING_DIST_GAUSS_SIGMA: 0.1 - EMBEDDERS: - "cat_5001": - TYPE: vertex_feature - NUM_VERTICES: 5001 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cat_5001_256.pkl" - "dog_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_dog_5002_256.pkl" - "sheep_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_sheep_5004_256.pkl" - "horse_5004": - TYPE: vertex_feature - NUM_VERTICES: 5004 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_horse_5004_256.pkl" - "zebra_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_zebra_5002_256.pkl" - "giraffe_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_giraffe_5002_256.pkl" - "elephant_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_elephant_5002_256.pkl" - "cow_5002": - TYPE: vertex_feature - NUM_VERTICES: 5002 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_cow_5002_256.pkl" - "bear_4936": - TYPE: vertex_feature - NUM_VERTICES: 4936 - FEATURE_DIM: 256 - FEATURES_TRAINABLE: False - IS_TRAINABLE: True - INIT_FILE: "https://dl.fbaipublicfiles.com/densepose/data/cse/lbo/phi_bear_4936_256.pkl" -DATASETS: - TRAIN: - - "densepose_lvis_v1_train1" - - "densepose_lvis_v1_train2" - TEST: - - "densepose_lvis_v1_val_animals_100" - WHITELISTED_CATEGORIES: - "densepose_lvis_v1_train1": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_train2": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - "densepose_lvis_v1_val_animals_100": - - 943 # sheep - - 1202 # zebra - - 569 # horse - - 496 # giraffe - - 422 # elephant - - 80 # cow - - 76 # bear - - 225 # cat - - 378 # dog - CLASS_TO_MESH_NAME_MAPPING: - "0": "bear_4936" - "1": "cow_5002" - "2": "cat_5001" - "3": "dog_5002" - "4": "elephant_5002" - "5": "giraffe_5002" - "6": "horse_5004" - "7": "sheep_5004" - "8": "zebra_5002" -SOLVER: - MAX_ITER: 40 - STEPS: (30,) diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_HRFPN_HRNet_w32_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_HRFPN_HRNet_w32_instant_test.yaml deleted file mode 100644 index 95677ce9a7ff426a9051737876e7424908b1423f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_HRFPN_HRNet_w32_instant_test.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "../HRNet/densepose_rcnn_HRFPN_HRNet_w32_s1x.yaml" -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100",) - TEST: ("densepose_coco_2014_minival_100",) -SOLVER: - MAX_ITER: 40 - STEPS: (30,) - IMS_PER_BATCH: 2 diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_DL_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_DL_instant_test.yaml deleted file mode 100644 index b90989eef81e27d23119d2cd4627e8cea211ac51..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_DL_instant_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - ROI_DENSEPOSE_HEAD: - NAME: "DensePoseDeepLabHead" -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100",) - TEST: ("densepose_coco_2014_minival_100",) -SOLVER: - MAX_ITER: 40 - STEPS: (30,) diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_TTA_inference_acc_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_TTA_inference_acc_test.yaml deleted file mode 100644 index b124da19140f564258b583ec109eeeeaff8fd78a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_TTA_inference_acc_test.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_BASE_: "../densepose_rcnn_R_50_FPN_s1x.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl" -DATASETS: - TRAIN: () - TEST: ("densepose_coco_2014_minival_100",) -TEST: - AUG: - ENABLED: True - MIN_SIZES: (400, 500, 600, 700, 800, 900, 1000, 1100, 1200) - MAX_SIZE: 4000 - FLIP: True - EXPECTED_RESULTS: [["bbox_TTA", "AP", 61.74, 0.03], ["densepose_gps_TTA", "AP", 60.22, 0.03], ["densepose_gpsm_TTA", "AP", 63.59, 0.03]] diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC1_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC1_instant_test.yaml deleted file mode 100644 index f0fe61151adf255baba717f3e65ff6fab52829a6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC1_instant_test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "iid_iso" - POINT_REGRESSION_WEIGHTS: 0.0005 -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100",) - TEST: ("densepose_coco_2014_minival_100",) -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 40 - STEPS: (30,) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC2_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC2_instant_test.yaml deleted file mode 100644 index f0d9358c8846452314697a19b5e2ea9e075ddaeb..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_WC2_instant_test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 - ROI_DENSEPOSE_HEAD: - UV_CONFIDENCE: - ENABLED: True - TYPE: "indep_aniso" - POINT_REGRESSION_WEIGHTS: 0.0005 -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100",) - TEST: ("densepose_coco_2014_minival_100",) -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - MAX_ITER: 40 - STEPS: (30,) - WARMUP_FACTOR: 0.025 diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_inference_acc_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_inference_acc_test.yaml deleted file mode 100644 index d607c98813d045c1e19875bdfe45fbc1c3fdb292..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_inference_acc_test.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "../densepose_rcnn_R_50_FPN_s1x.yaml" -MODEL: - WEIGHTS: "https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl" -DATASETS: - TRAIN: () - TEST: ("densepose_coco_2014_minival_100",) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 59.27, 0.025], ["densepose_gps", "AP", 60.11, 0.02], ["densepose_gpsm", "AP", 64.09, 0.02]] diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_instant_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_instant_test.yaml deleted file mode 100644 index 057c8768186e8a818228aa2f028ba3007374c571..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_instant_test.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -DATASETS: - TRAIN: ("densepose_coco_2014_minival_100",) - TEST: ("densepose_coco_2014_minival_100",) -SOLVER: - MAX_ITER: 40 - STEPS: (30,) diff --git a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_training_acc_test.yaml b/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_training_acc_test.yaml deleted file mode 100644 index 0053c9d7d41af0ee7262804838d8edcde10ed40d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/configs/quick_schedules/densepose_rcnn_R_50_FPN_training_acc_test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -_BASE_: "../Base-DensePose-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - ROI_HEADS: - NUM_CLASSES: 1 -DATASETS: - TRAIN: ("densepose_coco_2014_minival",) - TEST: ("densepose_coco_2014_minival",) -SOLVER: - CLIP_GRADIENTS: - ENABLED: True - CLIP_TYPE: norm - CLIP_VALUE: 1.0 - MAX_ITER: 6000 - STEPS: (5500, 5800) -TEST: - EXPECTED_RESULTS: [["bbox", "AP", 76.2477, 1.0], ["densepose_gps", "AP", 79.6090, 1.5], ["densepose_gpsm", "AP", 80.0061, 1.5]] - diff --git a/preprocess/detectron2/projects/DensePose/dev/README.md b/preprocess/detectron2/projects/DensePose/dev/README.md deleted file mode 100644 index e3a94b67ed4b4d0c2934f074802cd00f3660f9a9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/dev/README.md +++ /dev/null @@ -1,7 +0,0 @@ - -## Some scripts for developers to use, include: - -- `run_instant_tests.sh`: run training for a few iterations. -- `run_inference_tests.sh`: run inference on a small dataset. -- `../../dev/linter.sh`: lint the codebase before commit -- `../../dev/parse_results.sh`: parse results from log file. diff --git a/preprocess/detectron2/projects/DensePose/dev/run_inference_tests.sh b/preprocess/detectron2/projects/DensePose/dev/run_inference_tests.sh deleted file mode 100755 index 46556b80a3ee793bdf6a79f5de2ec88cac902189..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/dev/run_inference_tests.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -BIN="python train_net.py" -OUTPUT="inference_test_output" -NUM_GPUS=2 -IMS_PER_GPU=2 -IMS_PER_BATCH=$(( NUM_GPUS * IMS_PER_GPU )) - -CFG_LIST=( "${@:1}" ) - -if [ ${#CFG_LIST[@]} -eq 0 ]; then - CFG_LIST=( ./configs/quick_schedules/*inference_acc_test.yaml ) -fi - -echo "========================================================================" -echo "Configs to run:" -echo "${CFG_LIST[@]}" -echo "========================================================================" - -for cfg in "${CFG_LIST[@]}"; do - echo "========================================================================" - echo "Running $cfg ..." - echo "========================================================================" - $BIN \ - --eval-only \ - --num-gpus $NUM_GPUS \ - --config-file "$cfg" \ - OUTPUT_DIR "$OUTPUT" \ - SOLVER.IMS_PER_BATCH $IMS_PER_BATCH - rm -rf $OUTPUT -done - diff --git a/preprocess/detectron2/projects/DensePose/dev/run_instant_tests.sh b/preprocess/detectron2/projects/DensePose/dev/run_instant_tests.sh deleted file mode 100755 index 23a9c67cefe3cfca790181c90b27f2471d8a7771..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/dev/run_instant_tests.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -e -# Copyright (c) Facebook, Inc. and its affiliates. - -BIN="python train_net.py" -OUTPUT="instant_test_output" -NUM_GPUS=2 -SOLVER_IMS_PER_BATCH=$((NUM_GPUS * 2)) - -CFG_LIST=( "${@:1}" ) -if [ ${#CFG_LIST[@]} -eq 0 ]; then - CFG_LIST=( ./configs/quick_schedules/*instant_test.yaml ) -fi - -echo "========================================================================" -echo "Configs to run:" -echo "${CFG_LIST[@]}" -echo "========================================================================" - -for cfg in "${CFG_LIST[@]}"; do - echo "========================================================================" - echo "Running $cfg ..." - echo "========================================================================" - $BIN --num-gpus $NUM_GPUS --config-file "$cfg" \ - SOLVER.IMS_PER_BATCH $SOLVER_IMS_PER_BATCH \ - OUTPUT_DIR "$OUTPUT" - rm -rf "$OUTPUT" -done - diff --git a/preprocess/detectron2/projects/DensePose/doc/BOOTSTRAPPING_PIPELINE.md b/preprocess/detectron2/projects/DensePose/doc/BOOTSTRAPPING_PIPELINE.md deleted file mode 100644 index a1326862abe5479140269f5e6af50b68e7c2d0aa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/BOOTSTRAPPING_PIPELINE.md +++ /dev/null @@ -1,197 +0,0 @@ -# Bootstrapping Pipeline - -Bootstrapping pipeline for DensePose was proposed in -[Sanakoyeu et al., 2020](https://arxiv.org/pdf/2003.00080.pdf) -to extend DensePose from humans to proximal animal classes -(chimpanzees). Currently, the pipeline is only implemented for -[chart-based models](DENSEPOSE_IUV.md). -Bootstrapping proceeds in two steps. - -## Master Model Training - -Master model is trained on data from source domain (humans) -and supporting domain (animals). Instances from the source domain -contain full DensePose annotations (`S`, `I`, `U` and `V`) and -instances from the supporting domain have segmentation annotations only. -To ensure segmentation quality in the target domain, only a subset of -supporting domain classes is included into the training. This is achieved -through category filters, e.g. -(see [configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml](../configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml)): - -``` - WHITELISTED_CATEGORIES: - "base_coco_2017_train": - - 1 # person - - 16 # bird - - 17 # cat - - 18 # dog - - 19 # horse - - 20 # sheep - - 21 # cow - - 22 # elephant - - 23 # bear - - 24 # zebra - - 25 # girafe -``` -The acronym `Atop10P` in config file names indicates that categories are filtered to -only contain top 10 animals and person. - -The training is performed in a *class-agnostic* manner: all instances -are mapped into the same class (person), e.g. -(see [configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml](../configs/evolution/Base-RCNN-FPN-Atop10P_CA.yaml)): - -``` - CATEGORY_MAPS: - "base_coco_2017_train": - "16": 1 # bird -> person - "17": 1 # cat -> person - "18": 1 # dog -> person - "19": 1 # horse -> person - "20": 1 # sheep -> person - "21": 1 # cow -> person - "22": 1 # elephant -> person - "23": 1 # bear -> person - "24": 1 # zebra -> person - "25": 1 # girafe -> person -``` -The acronym `CA` in config file names indicates that the training is class-agnostic. - -## Student Model Training - -Student model is trained on data from source domain (humans), -supporting domain (animals) and target domain (chimpanzees). -Annotations in source and supporting domains are similar to the ones -used for the master model training. -Annotations in target domain are obtained by applying the master model -to images that contain instances from the target category and sampling -sparse annotations from dense results. This process is called *bootstrapping*. -Below we give details on how the bootstrapping pipeline is implemented. - -### Data Loaders - -The central components that enable bootstrapping are -[`InferenceBasedLoader`](../densepose/data/inference_based_loader.py) and -[`CombinedDataLoader`](../densepose/data/combined_loader.py). - -`InferenceBasedLoader` takes images from a data loader, applies a model -to the images, filters the model outputs based on the selected criteria and -samples the filtered outputs to produce annotations. - -`CombinedDataLoader` combines data obtained from the loaders based on specified -ratios. The standard data loader has the default ratio of 1.0, -ratios for bootstrap datasets are specified in the configuration file. -The higher the ratio the higher the probability to include samples from the -particular data loader into a batch. - -Here is an example of the bootstrapping configuration taken from -[`configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform.yaml`](../configs/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform.yaml): -``` -BOOTSTRAP_DATASETS: - - DATASET: "chimpnsee" - RATIO: 1.0 - IMAGE_LOADER: - TYPE: "video_keyframe" - SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 - TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 - BATCH_SIZE: 8 - NUM_WORKERS: 1 - INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 - DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_uniform" - COUNT_PER_CLASS: 8 - FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -BOOTSTRAP_MODEL: - WEIGHTS: https://dl.fbaipublicfiles.com/densepose/evolution/densepose_R_50_FPN_DL_WC1M_3x_Atop10P_CA/217578784/model_final_9fe1cc.pkl -``` - -The above example has one bootstrap dataset (`chimpnsee`). This dataset is registered as -a [VIDEO_LIST](../densepose/data/datasets/chimpnsee.py) dataset, which means that -it consists of a number of videos specified in a text file. For videos there can be -different strategies to sample individual images. Here we use `video_keyframe` strategy -which considers only keyframes; this ensures temporal offset between sampled images and -faster seek operations. We select at most 4 random keyframes in each video: - -``` -SELECT: - STRATEGY: "random_k" - NUM_IMAGES: 4 -``` - -The frames are then resized - -``` -TRANSFORM: - TYPE: "resize" - MIN_SIZE: 800 - MAX_SIZE: 1333 -``` - -and batched using the standard -[PyTorch DataLoader](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader): - -``` -BATCH_SIZE: 8 -NUM_WORKERS: 1 -``` - -`InferenceBasedLoader` decomposes those batches into batches of size `INPUT_BATCH_SIZE` -and applies the master model specified by `BOOTSTRAP_MODEL`. Models outputs are filtered -by detection score: - -``` -FILTER: - TYPE: "detection_score" - MIN_VALUE: 0.8 -``` - -and sampled using the specified sampling strategy: - -``` -DATA_SAMPLER: - # supported types: - # densepose_uniform - # densepose_UV_confidence - # densepose_fine_segm_confidence - # densepose_coarse_segm_confidence - TYPE: "densepose_uniform" - COUNT_PER_CLASS: 8 -``` - -The current implementation supports -[uniform sampling](../densepose/data/samplers/densepose_uniform.py) and -[confidence-based sampling](../densepose/data/samplers/densepose_confidence_based.py) -to obtain sparse annotations from dense results. For confidence-based -sampling one needs to use the master model which produces confidence estimates. -The `WC1M` master model used in the example above produces all three types of confidence -estimates. - -Finally, sampled data is grouped into batches of size `OUTPUT_BATCH_SIZE`: - -``` -INFERENCE: - INPUT_BATCH_SIZE: 1 - OUTPUT_BATCH_SIZE: 1 -``` - -The proportion of data from annotated datasets and bootstrapped dataset can be tracked -in the logs, e.g.: - -``` -[... densepose.engine.trainer]: batch/ 1.8, batch/base_coco_2017_train 6.4, batch/densepose_coco_2014_train 3.85 -``` - -which means that over the last 20 iterations, on average for 1.8 bootstrapped data samples there were 6.4 samples from `base_coco_2017_train` and 3.85 samples from `densepose_coco_2014_train`. diff --git a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_CSE.md b/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_CSE.md deleted file mode 100644 index d5761ef989bdfb441a2a61f4e508cc826f93d2d1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_CSE.md +++ /dev/null @@ -1,336 +0,0 @@ -# Continuous Surface Embeddings for Dense Pose Estimation for Humans and Animals - -## Overview - -
- -
- -The pipeline uses [Faster R-CNN](https://arxiv.org/abs/1506.01497) -with [Feature Pyramid Network](https://arxiv.org/abs/1612.03144) meta architecture -outlined in Figure 1. For each detected object, the model predicts -its coarse segmentation `S` (2 channels: foreground / background) -and the embedding `E` (16 channels). At the same time, the embedder produces vertex -embeddings `Ê` for the corresponding mesh. Universal positional embeddings `E` -and vertex embeddings `Ê` are matched to derive for each pixel its continuous -surface embedding. - -
- -
-

Figure 1. DensePose continuous surface embeddings architecture based on Faster R-CNN with Feature Pyramid Network (FPN).

- -### Datasets - -For more details on datasets used for training and validation of -continuous surface embeddings models, -please refer to the [DensePose Datasets](DENSEPOSE_DATASETS.md) page. - -## Model Zoo and Baselines - -### Human CSE Models - -Continuous surface embeddings models for humans trained using the protocols from [Neverova et al, 2020](https://arxiv.org/abs/2011.12438). - -Models trained with hard assignment loss ℒ: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_s1xs1x0.3490.0606.361.167.164.465.7251155172model | metrics
R_101_FPN_s1xs1x0.4610.0717.462.367.264.765.8251155500model | metrics
R_50_FPN_DL_s1xs1x0.3990.0617.060.867.865.566.4251156349model | metrics
R_101_FPN_DL_s1xs1x0.5040.0748.361.568.065.666.6251156606model | metrics
- -Models trained with soft assignment loss ℒσ: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_soft_s1xs1x0.3570.0579.761.366.964.365.4250533982model | metrics
R_101_FPN_soft_s1xs1x0.4640.07110.562.167.364.566.0250712522model | metrics
R_50_FPN_DL_soft_s1xs1x0.4270.06211.360.868.066.166.7250713703model | metrics
R_101_FPN_DL_soft_s1xs1x0.4830.07112.261.568.266.267.1250713061model | metrics
- -### Animal CSE Models - -Models obtained by finetuning human CSE models on animals data from `ds1_train` -(see the [DensePose LVIS](DENSEPOSE_DATASETS.md#continuous-surface-embeddings-annotations-3) -section for more details on the datasets) with soft assignment loss ℒσ: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_soft_chimps_finetune_4k4K0.5690.0514.762.059.032.239.6253146869model | metrics
R_50_FPN_soft_animals_finetune_4k4K0.3810.0617.344.955.521.328.8253145793model | metrics
R_50_FPN_soft_animals_CA_finetune_4k4K0.4120.0597.153.459.525.433.4253498611model | metrics
- -Acronyms: - -`CA`: class agnostic training, where all annotated instances are mapped into a single category - - -Models obtained by finetuning human CSE models on animals data from `ds2_train` dataset -with soft assignment loss ℒσ and, for some schedules, cycle losses. -Please refer to [DensePose LVIS](DENSEPOSE_DATASETS.md#continuous-surface-embeddings-annotations-3) -section for details on the dataset and to [Neverova et al, 2021]() for details on cycle losses. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
GErrGPSmodel iddownload
R_50_FPN_soft_animals_I0_finetune_16k16k0.3860.0588.454.267.029.038.613.285.4270727112model | metrics
R_50_FPN_soft_animals_I0_finetune_m2m_16k16k0.5080.05612.254.167.328.638.412.587.6270982215model | metrics
R_50_FPN_soft_animals_I0_finetune_i2m_16k16k0.4830.0569.754.066.628.938.311.088.9270727461model | metrics
- -## References - -If you use DensePose methods based on continuous surface embeddings, please take the -references from the following BibTeX entries: - -Continuous surface embeddings: -``` -@InProceedings{Neverova2020ContinuousSurfaceEmbeddings, - title = {Continuous Surface Embeddings}, - author = {Neverova, Natalia and Novotny, David and Khalidov, Vasil and Szafraniec, Marc and Labatut, Patrick and Vedaldi, Andrea}, - journal = {Advances in Neural Information Processing Systems}, - year = {2020}, -} -``` - -Cycle Losses: -``` -@InProceedings{Neverova2021UniversalCanonicalMaps, - title = {Discovering Relationships between Object Categories via Universal Canonical Maps}, - author = {Neverova, Natalia and Sanakoyeu, Artsiom and Novotny, David and Labatut, Patrick and Vedaldi, Andrea}, - journal = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, - year = {2021}, -} -``` diff --git a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_DATASETS.md b/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_DATASETS.md deleted file mode 100644 index 6943741e104310e7ec1837951e602e9c79061b10..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_DATASETS.md +++ /dev/null @@ -1,513 +0,0 @@ -# DensePose Datasets - -We summarize the datasets used in various DensePose training -schedules and describe different available annotation types. - -## Table of Contents - -[General Information](#general-information) - -[DensePose COCO](#densepose-coco) - -[DensePose PoseTrack](#densepose-posetrack) - -[DensePose Chimps](#densepose-chimps) - -[DensePose LVIS](#densepose-lvis) - -## General Information - -DensePose annotations are typically stored in JSON files. Their -structure follows the [COCO Data Format](https://cocodataset.org/#format-data), -the basic data structure is outlined below: - -``` -{ - "info": info, - "images": [image], - "annotations": [annotation], - "licenses": [license], -} - -info{ - "year": int, - "version": str, - "description": str, - "contributor": str, - "url": str, - "date_created": datetime, -} - -image{ - "id": int, - "width": int, - "height": int, - "file_name": str, - "license": int, - "flickr_url": str, - "coco_url": str, - "date_captured": datetime, -} - -license{ - "id": int, "name": str, "url": str, -} -``` - -DensePose annotations can be of two types: -*chart-based annotations* or *continuous surface embeddings annotations*. -We give more details on each of the two annotation types below. - -### Chart-based Annotations - -These annotations assume a single 3D model which corresponds to -all the instances in a given dataset. -3D model is assumed to be split into *charts*. Each chart has its own -2D parametrization through inner coordinates `U` and `V`, typically -taking values in `[0, 1]`. - -Chart-based annotations consist of *point-based annotations* and -*segmentation annotations*. Point-based annotations specify, for a given -image point, which model part it belongs to and what are its coordinates -in the corresponding chart. Segmentation annotations specify regions -in an image that are occupied by a given part. In some cases, charts -associated with point annotations are more detailed than the ones -associated with segmentation annotations. In this case we distinguish -*fine segmentation* (associated with points) and *coarse segmentation* -(associated with masks). - -**Point-based annotations**: - -`dp_x` and `dp_y`: image coordinates of the annotated points along -the horizontal and vertical axes respectively. The coordinates are defined -with respect to the top-left corner of the annotated bounding box and are -normalized assuming the bounding box size to be `256x256`; - -`dp_I`: for each point specifies the index of the fine segmentation chart -it belongs to; - -`dp_U` and `dp_V`: point coordinates on the corresponding chart. -Each fine segmentation part has its own parametrization in terms of chart -coordinates. - -**Segmentation annotations**: - -`dp_masks`: RLE encoded dense masks (`dict` containing keys `counts` and `size`). -The masks are typically of size `256x256`, they define segmentation within the -bounding box. - -### Continuous Surface Embeddings Annotations - -Continuous surface embeddings annotations also consist of *point-based annotations* -and *segmentation annotations*. Point-based annotations establish correspondence -between image points and 3D model vertices. Segmentation annotations specify -foreground regions for a given instane. - -**Point-based annotations**: - -`dp_x` and `dp_y` specify image point coordinates the same way as for chart-based -annotations; - -`dp_vertex` gives indices of 3D model vertices, which the annotated image points -correspond to; - -`ref_model` specifies 3D model name. - -**Segmentation annotations**: - -Segmentations can either be given by `dp_masks` field or by `segmentation` field. - -`dp_masks`: RLE encoded dense masks (`dict` containing keys `counts` and `size`). -The masks are typically of size `256x256`, they define segmentation within the -bounding box. - -`segmentation`: polygon-based masks stored as a 2D list -`[[x1 y1 x2 y2...],[x1 y1 ...],...]` of polygon vertex coordinates in a given -image. - -## DensePose COCO - -
- -
-

- Figure 1. Annotation examples from the DensePose COCO dataset. -

- -DensePose COCO dataset contains about 50K annotated persons on images from the -[COCO dataset](https://cocodataset.org/#home) -The images are available for download from the -[COCO Dataset download page](https://cocodataset.org/#download): -[train2014](http://images.cocodataset.org/zips/train2014.zip), -[val2014](http://images.cocodataset.org/zips/val2014.zip). -The details on available annotations and their download links are given below. - -### Chart-based Annotations - -Chart-based DensePose COCO annotations are available for the instances of category -`person` and correspond to the model shown in Figure 2. -They include `dp_x`, `dp_y`, `dp_I`, `dp_U` and `dp_V` fields for annotated points -(~100 points per annotated instance) and `dp_masks` field, which encodes -coarse segmentation into 14 parts in the following order: -`Torso`, `Right Hand`, `Left Hand`, `Left Foot`, `Right Foot`, -`Upper Leg Right`, `Upper Leg Left`, `Lower Leg Right`, `Lower Leg Left`, -`Upper Arm Left`, `Upper Arm Right`, `Lower Arm Left`, `Lower Arm Right`, -`Head`. - -
- -
-

- Figure 2. Human body charts (fine segmentation) - and the associated 14 body parts depicted with rounded rectangles - (coarse segmentation). -

- -The dataset splits used in the training schedules are -`train2014`, `valminusminival2014` and `minival2014`. -`train2014` and `valminusminival2014` are used for training, -and `minival2014` is used for validation. -The table with annotation download links, which summarizes the number of annotated -instances and images for each of the dataset splits is given below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name# inst# imagesfile sizedownload
densepose_train20143921026437526Mdensepose_train2014.json
densepose_valminusminival201472975984105Mdensepose_valminusminival2014.json
densepose_minival20142243150831Mdensepose_minival2014.json
- -### Continuous Surface Embeddings Annotations - -DensePose COCO continuous surface embeddings annotations are available for the instances -of category `person`. The annotations correspond to the 3D model shown in Figure 2, -and include `dp_x`, `dp_y` and `dp_vertex` and `ref_model` fields. -All chart-based annotations were also kept for convenience. - -As with chart-based annotations, the dataset splits used in the training schedules are -`train2014`, `valminusminival2014` and `minival2014`. -`train2014` and `valminusminival2014` are used for training, -and `minival2014` is used for validation. -The table with annotation download links, which summarizes the number of annotated -instances and images for each of the dataset splits is given below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name# inst# imagesfile sizedownload
densepose_train2014_cse3921026437554Mdensepose_train2014_cse.json
densepose_valminusminival2014_cse72975984110Mdensepose_valminusminival2014_cse.json
densepose_minival2014_cse2243150832Mdensepose_minival2014_cse.json
- -## DensePose PoseTrack - -
- -
-

- Figure 3. Annotation examples from the PoseTrack dataset. -

- -DensePose PoseTrack dataset contains annotated image sequences. -To download the images for this dataset, please follow the instructions -from the [PoseTrack Download Page](https://posetrack.net/users/download.php). - -### Chart-based Annotations - -Chart-based DensePose PoseTrack annotations are available for the instances with category -`person` and correspond to the model shown in Figure 2. -They include `dp_x`, `dp_y`, `dp_I`, `dp_U` and `dp_V` fields for annotated points -(~100 points per annotated instance) and `dp_masks` field, which encodes -coarse segmentation into the same 14 parts as in DensePose COCO. - -The dataset splits used in the training schedules are -`posetrack_train2017` (train set) and `posetrack_val2017` (validation set). -The table with annotation download links, which summarizes the number of annotated -instances, instance tracks and images for the dataset splits is given below: - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name# inst# images# tracksfile sizedownload
densepose_posetrack_train20178274168036118Mdensepose_posetrack_train2017.json
densepose_posetrack_val201747537824659Mdensepose_posetrack_val2017.json
- -## DensePose Chimps - -
- -
-

- Figure 4. Example images from the DensePose Chimps dataset. -

- -DensePose Chimps dataset contains annotated images of chimpanzees. -To download the images for this dataset, please use the URL specified in -`image_url` field in the annotations. - -### Chart-based Annotations - -Chart-based DensePose Chimps annotations correspond to the human model shown in Figure 2, -the instances are thus annotated to belong to the `person` category. -They include `dp_x`, `dp_y`, `dp_I`, `dp_U` and `dp_V` fields for annotated points -(~3 points per annotated instance) and `dp_masks` field, which encodes -foreground mask in RLE format. - -Chart-base DensePose Chimps annotations are used for validation only. -The table with annotation download link, which summarizes the number of annotated -instances and images is given below: - - - - - - - - - - - - - - - - - -
Name# inst# imagesfile sizedownload
densepose_chimps9306546Mdensepose_chimps_full_v2.json
- -### Continuous Surface Embeddings Annotations - -Continuous surface embeddings annotations for DensePose Chimps -include `dp_x`, `dp_y` and `dp_vertex` point-based annotations -(~3 points per annotated instance), `dp_masks` field with the same -contents as for chart-based annotations and `ref_model` field -which refers to a chimpanzee 3D model `chimp_5029`. - -The dataset is split into training and validation subsets. -The table with annotation download links, which summarizes the number of annotated -instances and images for each of the dataset splits is given below: - -The table below outlines the dataset splits: - - - - - - - - - - - - - - - - - - - - - - - -
Name# inst# imagesfile sizedownload
densepose_chimps_cse_train5003503Mdensepose_chimps_cse_train.json
densepose_chimps_cse_val4303043Mdensepose_chimps_cse_val.json
- -## DensePose LVIS - -
- -
-

- Figure 5. Example images from the DensePose LVIS dataset. -

- -DensePose LVIS dataset contains segmentation and DensePose annotations for animals -on images from the [LVIS dataset](https://www.lvisdataset.org/dataset). -The images are available for download through the links: -[train2017](http://images.cocodataset.org/zips/train2017.zip), -[val2017](http://images.cocodataset.org/zips/val2017.zip). - -### Continuous Surface Embeddings Annotations - -Continuous surface embeddings (CSE) annotations for DensePose LVIS -include `dp_x`, `dp_y` and `dp_vertex` point-based annotations -(~3 points per annotated instance) and a `ref_model` field -which refers to a 3D model that corresponds to the instance. -Instances from 9 animal categories were annotated with CSE DensePose data: -bear, cow, cat, dog, elephant, giraffe, horse, sheep and zebra. - -Foreground masks are available from instance segmentation annotations -(`segmentation` field) in polygon format, they are stored as a 2D list -`[[x1 y1 x2 y2...],[x1 y1 ...],...]`. - -We used two datasets, each constising of one training (`train`) -and validation (`val`) subsets: the first one (`ds1`) -was used in [Neverova et al, 2020](https://arxiv.org/abs/2011.12438). -The second one (`ds2`), was used in [Neverova et al, 2021](). - -The summary of the available datasets is given below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
All DataSelected Animals
(9 categories)
File
Name# cat# img# segm# img# segm# dpsizedownload
ds1_train55641412398541419472518446Mdensepose_lvis_v1_ds1_train_v1.json
ds1_val2515713281571153710365Mdensepose_lvis_v1_ds1_val_v1.json
ds2_train12039938812701411374646964189321051Mdensepose_lvis_v1_ds2_train_v1.json
ds2_val92690915526909155360424Mdensepose_lvis_v1_ds2_val_v1.json
- -Legend: - -`#cat` - number of categories in the dataset for which annotations are available; - -`#img` - number of images with annotations in the dataset; - -`#segm` - number of segmentation annotations; - -`#dp` - number of DensePose annotations. - - -Important Notes: - -1. The reference models used for `ds1_train` and `ds1_val` are -`bear_4936`, `cow_5002`, `cat_5001`, `dog_5002`, `elephant_5002`, `giraffe_5002`, -`horse_5004`, `sheep_5004` and `zebra_5002`. The reference models used for -`ds2_train` and `ds2_val` are `bear_4936`, `cow_5002`, `cat_7466`, -`dog_7466`, `elephant_5002`, `giraffe_5002`, `horse_5004`, `sheep_5004` and `zebra_5002`. -So reference models for categories `cat` aind `dog` are different for `ds1` and `ds2`. - -2. Some annotations from `ds1_train` are reused in `ds2_train` (4538 DensePose annotations -and 21275 segmentation annotations). The ones for cat and dog categories were remapped -from `cat_5001` and `dog_5002` reference models used in `ds1` to `cat_7466` and `dog_7466` -used in `ds2`. - -3. All annotations from `ds1_val` are included into `ds2_val` after the remapping -procedure mentioned in note 2. - -4. Some annotations from `ds1_train` are part of `ds2_val` (646 DensePose annotations and -1225 segmentation annotations). Thus one should not train on `ds1_train` if evaluating on `ds2_val`. diff --git a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_IUV.md b/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_IUV.md deleted file mode 100644 index de158e0eea0c287507b701376abc9307ce92c0f1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/DENSEPOSE_IUV.md +++ /dev/null @@ -1,627 +0,0 @@ -# Chart-based Dense Pose Estimation for Humans and Animals - -## Overview - -The goal of chart-based DensePose methods is to establish dense correspondences -between image pixels and 3D object mesh by splitting the latter into charts and estimating -for each pixel the corresponding chart index `I` and local chart coordinates `(U, V)`. - -
- -
- -The charts used for human DensePose estimation are shown in Figure 1. -The human body is split into 24 parts, each part is parametrized by `U` and `V` -coordinates, each taking values in `[0, 1]`. - -
- -
-

Figure 1. Partitioning and parametrization of human body surface.

- -The pipeline uses [Faster R-CNN](https://arxiv.org/abs/1506.01497) -with [Feature Pyramid Network](https://arxiv.org/abs/1612.03144) meta architecture -outlined in Figure 2. For each detected object, the model predicts -its coarse segmentation `S` (2 or 15 channels: foreground / background or -background + 14 predefined body parts), fine segmentation `I` (25 channels: -background + 24 predefined body parts) and local chart coordinates `U` and `V`. - -
- -
-

Figure 2. DensePose chart-based architecture based on Faster R-CNN with Feature Pyramid Network (FPN).

- -### Bootstrapping Chart-Based Models - -[Sanakoyeu et al., 2020](https://arxiv.org/pdf/2003.00080.pdf) introduced a pipeline -to transfer DensePose models trained on humans to proximal animal classes (chimpanzees), -which is summarized in Figure 3. The training proceeds in two stages: - -First, a *master* model is trained on data from source domain (humans with full -DensePose annotation `S`, `I`, `U` and `V`) -and supporting domain (animals with segmentation annotation only). -Only selected animal classes are chosen from the supporting -domain through *category filters* to guarantee the quality of target domain results. -The training is done in *class-agnostic manner*: all selected categories are mapped -to a single category (human). - -Second, a *student* model is trained on data from source and supporting domains, -as well as data from target domain obtained by applying the master model, selecting -high-confidence detections and sampling the results. - -
- -
-

Figure 3. Domain adaptation: master model is trained on data from source and -supporting domains to produce predictions in target domain; student model combines data from source and -supporting domains, as well as sampled predictions from the master model on target domain to improve -target domain predictions quality.

- -Examples of pretrained master and student models are available in the [Model Zoo](#ModelZooBootstrap). -For more details on the bootstrapping pipeline, please see [Bootstrapping Pipeline](BOOTSTRAPPING_PIPELINE.md). - -### Datasets - -For more details on datasets used for chart-based model training and validation, -please refer to the [DensePose Datasets](DENSEPOSE_DATASETS.md) page. - -## Model Zoo and Baselines - -### Legacy Models - -Baselines trained using schedules from [Güler et al, 2018](https://arxiv.org/pdf/1802.00434.pdf) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_s1x_legacys1x0.3070.0513.258.158.252.154.9164832157model | metrics
R_101_FPN_s1x_legacys1x0.3900.0634.359.559.353.256.0164832182model | metrics
- -### Improved Baselines, Original Fully Convolutional Head - -These models use an improved training schedule and Panoptic FPN head from [Kirillov et al, 2019](https://arxiv.org/abs/1901.02446). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_s1xs1x0.3590.0664.561.267.263.765.3165712039model | metrics
R_101_FPN_s1xs1x0.4280.0795.862.367.864.566.2165712084model | metrics
- -### Improved Baselines, DeepLabV3 Head - -These models use an improved training schedule, Panoptic FPN head from [Kirillov et al, 2019](https://arxiv.org/abs/1901.02446) and DeepLabV3 head from [Chen et al, 2017](https://arxiv.org/abs/1706.05587). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_DL_s1xs1x0.3920.0706.761.168.365.666.7165712097model | metrics
R_101_FPN_DL_s1xs1x0.4780.0837.062.368.766.367.6165712116model | metrics
- -###
Baselines with Confidence Estimation - -These models perform additional estimation of confidence in regressed UV coodrinates, along the lines of [Neverova et al., 2019](https://papers.nips.cc/paper/8378-correlated-uncertainty-for-learning-dense-correspondences-from-noisy-labels). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_WC1_s1xs1x0.3530.0644.660.567.064.265.4173862049model | metrics
R_50_FPN_WC2_s1xs1x0.3640.0664.860.766.964.265.7173861455model | metrics
R_50_FPN_DL_WC1_s1xs1x0.3970.0686.761.168.165.867.0173067973model | metrics
R_50_FPN_DL_WC2_s1xs1x0.4100.0706.860.867.965.666.7173859335model | metrics
R_101_FPN_WC1_s1xs1x0.4350.0765.762.567.664.966.3171402969model | metrics
R_101_FPN_WC2_s1xs1x0.4500.0785.762.367.664.866.4173860702model | metrics
R_101_FPN_DL_WC1_s1xs1x0.4790.0817.962.068.466.267.2173858525model | metrics
R_101_FPN_DL_WC2_s1xs1x0.4910.0827.661.768.365.967.2173294801model | metrics
- -Acronyms: - -`WC1`: with confidence estimation model type 1 for `U` and `V` - -`WC2`: with confidence estimation model type 2 for `U` and `V` - -###
Baselines with Mask Confidence Estimation - -Models that perform estimation of confidence in regressed UV coodrinates -as well as confidences associated with coarse and fine segmentation, -see [Sanakoyeu et al., 2020](https://arxiv.org/pdf/2003.00080.pdf) for details. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_WC1M_s1xs1x0.3810.0664.860.666.764.065.4217144516model | metrics
R_50_FPN_WC2M_s1xs1x0.3420.0685.060.766.964.265.5216245640model | metrics
R_50_FPN_DL_WC1M_s1xs1x0.3710.0686.060.768.065.266.7216245703model | metrics
R_50_FPN_DL_WC2M_s1xs1x0.3850.0716.160.868.165.066.4216245758model | metrics
R_101_FPN_WC1M_s1xs1x0.4230.0795.962.067.364.866.0216453687model | metrics
R_101_FPN_WC2M_s1xs1x0.4360.0805.962.567.464.566.0216245682model | metrics
R_101_FPN_DL_WC1M_s1xs1x0.4530.0796.862.068.166.467.1216245771model | metrics
R_101_FPN_DL_WC2M_s1xs1x0.4640.0806.961.968.266.167.1216245790model | metrics
- -Acronyms: - -`WC1M`: with confidence estimation model type 1 for `U` and `V` and mask confidence estimation - -`WC2M`: with confidence estimation model type 2 for `U` and `V` and mask confidence estimation - -###
Bootstrapping Baselines - -Master and student models trained using the bootstrapping pipeline with chimpanzee as the target category, -see [Sanakoyeu et al., 2020](https://arxiv.org/pdf/2003.00080.pdf) -and [Bootstrapping Pipeline](BOOTSTRAPPING_PIPELINE.md) for details. -Evaluation is performed on [DensePose Chimps](DENSEPOSE_DATASETS.md#densepose-chimps) dataset. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namelr
sched
train
time
(s/iter)
inference
time
(s/im)
train
mem
(GB)
box
AP
segm
AP
dp. APex
GPS
dp. AP
GPS
dp. AP
GPSm
model iddownload
R_50_FPN_DL_WC1M_3x_Atop10P_CA3x0.5220.0739.761.359.136.220.030.2217578784model | metrics
R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uniform3x1.9390.07210.160.958.537.221.531.0256453729model | metrics
R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_uv3x1.9850.0729.661.458.938.322.232.1256452095model | metrics
R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_finesegm3x2.0470.07210.360.958.536.720.730.7256452819model | metrics
R_50_FPN_DL_WC1M_3x_Atop10P_CA_B_coarsesegm3x1.8300.0709.661.359.237.921.531.6256455697model | metrics
- -Acronyms: - -`WC1M`: with confidence estimation model type 1 for `U` and `V` and mask confidence estimation - -`Atop10P`: humans and animals from the 10 best suitable categories are used for training - -`CA`: class agnostic training, where all annotated instances are mapped into a single category - -`B_<...>`: schedule with bootstrapping with the specified results sampling strategy - -Note: - -The relaxed `dp. APex GPS` metric was used in -[Sanakoyeu et al., 2020](https://arxiv.org/pdf/2003.00080.pdf) to evaluate DensePose -results. This metric considers matches at thresholds 0.2, 0.3 and 0.4 additionally -to the standard ones used in the evaluation protocol. The minimum threshold is -controlled by `DENSEPOSE_EVALUATION.MIN_IOU_THRESHOLD` config option. - -### License - -All models available for download are licensed under the -[Creative Commons Attribution-ShareAlike 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/) - -## References - -If you use chart-based DensePose methods, please take the references from the following -BibTeX entries: - -DensePose bootstrapping pipeline: -``` -@InProceedings{Sanakoyeu2020TransferringDensePose, - title = {Transferring Dense Pose to Proximal Animal Classes}, - author = {Artsiom Sanakoyeu and Vasil Khalidov and Maureen S. McCarthy and Andrea Vedaldi and Natalia Neverova}, - journal = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, - year = {2020}, -} -``` - -DensePose with confidence estimation: -``` -@InProceedings{Neverova2019DensePoseConfidences, - title = {Correlated Uncertainty for Learning Dense Correspondences from Noisy Labels}, - author = {Neverova, Natalia and Novotny, David and Vedaldi, Andrea}, - journal = {Advances in Neural Information Processing Systems}, - year = {2019}, -} -``` - -Original DensePose: -``` -@InProceedings{Guler2018DensePose, - title={DensePose: Dense Human Pose Estimation In The Wild}, - author={R\{i}za Alp G\"uler, Natalia Neverova, Iasonas Kokkinos}, - journal={The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, - year={2018} -} -``` diff --git a/preprocess/detectron2/projects/DensePose/doc/GETTING_STARTED.md b/preprocess/detectron2/projects/DensePose/doc/GETTING_STARTED.md deleted file mode 100644 index a5c86f3ab5e66dc3dee4f7836aa79bd5d41b68f2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/GETTING_STARTED.md +++ /dev/null @@ -1,76 +0,0 @@ -# Getting Started with DensePose - -## Inference with Pre-trained Models - -1. Pick a model and its config file from [Model Zoo(IUV)](DENSEPOSE_IUV.md#ModelZoo), [Model Zoo(CSE)](DENSEPOSE_CSE.md#ModelZoo), for example [densepose_rcnn_R_50_FPN_s1x.yaml](../configs/densepose_rcnn_R_50_FPN_s1x.yaml) -2. Run the [Apply Net](TOOL_APPLY_NET.md) tool to visualize the results or save the to disk. For example, to use contour visualization for DensePose, one can run: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml densepose_rcnn_R_50_FPN_s1x.pkl image.jpg dp_contour,bbox --output image_densepose_contour.png -``` -Please see [Apply Net](TOOL_APPLY_NET.md) for more details on the tool. - -## Training - -First, prepare the [dataset](http://densepose.org/#dataset) into the following structure under the directory you'll run training scripts: -
-datasets/coco/
-  annotations/
-    densepose_{train,minival,valminusminival}2014.json
-    densepose_minival2014_100.json   (optional, for testing only)
-  {train,val}2014/
-    # image files that are mentioned in the corresponding json
-
- -To train a model one can use the [train_net.py](../train_net.py) script. -This script was used to train all DensePose models in [Model Zoo(IUV)](DENSEPOSE_IUV.md#ModelZoo), [Model Zoo(CSE)](DENSEPOSE_CSE.md#ModelZoo). -For example, to launch end-to-end DensePose-RCNN training with ResNet-50 FPN backbone -on 8 GPUs following the s1x schedule, one can run -```bash -python train_net.py --config-file configs/densepose_rcnn_R_50_FPN_s1x.yaml --num-gpus 8 -``` -The configs are made for 8-GPU training. To train on 1 GPU, one can apply the -[linear learning rate scaling rule](https://arxiv.org/abs/1706.02677): -```bash -python train_net.py --config-file configs/densepose_rcnn_R_50_FPN_s1x.yaml \ - SOLVER.IMS_PER_BATCH 2 SOLVER.BASE_LR 0.0025 -``` - -## Evaluation - -Model testing can be done in the same way as training, except for an additional flag `--eval-only` and -model location specification through `MODEL.WEIGHTS model.pth` in the command line -```bash -python train_net.py --config-file configs/densepose_rcnn_R_50_FPN_s1x.yaml \ - --eval-only MODEL.WEIGHTS model.pth -``` - -## Tools - -We provide tools which allow one to: - - easily view DensePose annotated data in a dataset; - - perform DensePose inference on a set of images; - - visualize DensePose model results; - -`query_db` is a tool to print or visualize DensePose data in a dataset. -Please refer to [Query DB](TOOL_QUERY_DB.md) for more details on this tool - -`apply_net` is a tool to print or visualize DensePose results. -Please refer to [Apply Net](TOOL_APPLY_NET.md) for more details on this tool - - -## Installation as a package - -DensePose can also be installed as a Python package for integration with other software. - -The following dependencies are needed: -- Python >= 3.7 -- [PyTorch](https://pytorch.org/get-started/locally/#start-locally) >= 1.7 (to match [detectron2 requirements](https://detectron2.readthedocs.io/en/latest/tutorials/install.html#requirements)) -- [torchvision](https://pytorch.org/vision/stable/) version [compatible with your version of PyTorch](https://github.com/pytorch/vision#installation) - -DensePose can then be installed from this repository with: - -``` -pip install git+https://github.com/facebookresearch/detectron2@main#subdirectory=projects/DensePose -``` - -After installation, the package will be importable as `densepose`. diff --git a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2020_04.md b/preprocess/detectron2/projects/DensePose/doc/RELEASE_2020_04.md deleted file mode 100644 index 2fab6ae78e887c630ad94e71aa6e946115c61593..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2020_04.md +++ /dev/null @@ -1,6 +0,0 @@ -# DensePose Confidence Estimation and Model Zoo Improvements - -* [DensePose models with confidence estimation](doc/DENSEPOSE_IUV.md#ModelZooConfidence) -* [Panoptic FPN and DeepLabV3 head implementation](doc/DENSEPOSE_IUV.md#ModelZooDeepLabV3) -* Test time augmentations for DensePose -* New evaluation metric (GPSm) that yields more reliable scores diff --git a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_03.md b/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_03.md deleted file mode 100644 index eb908a67f7e48d1d3aba51f946c0ca884cfcfe79..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_03.md +++ /dev/null @@ -1,45 +0,0 @@ -# DensePose CSE and DensePose Evolution - -* [DensePose Evolution pipeline](DENSEPOSE_IUV.md#ModelZooBootstrap), a framework to bootstrap - DensePose on unlabeled data - * [`InferenceBasedLoader`](../densepose/data/inference_based_loader.py) - with data samplers to use inference results from one model - to train another model (bootstrap); - * [`VideoKeyframeDataset`](../densepose/data/video/video_keyframe_dataset.py) - to efficiently load images from video keyframes; - * Category maps and filters to combine annotations from different categories - and train in a class-agnostic manner; - * [Pretrained models](DENSEPOSE_IUV.md#ModelZooBootstrap) for DensePose estimation on chimpanzees; - * DensePose head training from partial data (segmentation only); - * [DensePose models with mask confidence estimation](DENSEPOSE_IUV.md#ModelZooMaskConfidence); - * [DensePose Chimps]() dataset for IUV evaluation -* [DensePose Continuous Surface Embeddings](DENSEPOSE_CSE.md), a framework to extend DensePose - to various categories using 3D models - * [Hard embedding](../densepose/modeling/losses/embed.py) and - [soft embedding](../densepose/modeling/losses/soft_embed.py) - losses to train universal positional embeddings; - * [Embedder](../(densepose/modeling/cse/embedder.py) to handle - mesh vertex embeddings; - * [Storage](../densepose/evaluation/tensor_storage.py) for evaluation with high volumes of data; - * [Pretrained models](DENSEPOSE_CSE.md#ModelZoo) for DensePose CSE estimation on humans and animals; - * [DensePose Chimps](DENSEPOSE_DATASETS.md#densepose-chimps) and - [DensePose LVIS](DENSEPOSE_DATASETS.md#densepose-lvis) datasets for CSE finetuning and evaluation; - * [Vertex and texture mapping visualizers](../densepose/vis/densepose_outputs_vertex.py); -* Refactoring of all major components: losses, predictors, model outputs, model results, visualizers; - * Dedicated structures for [chart outputs](../densepose/structures/chart.py), - [chart outputs with confidences](../densepose/structures/chart_confidence.py), - [chart results](../densepose/structures/chart_result.py), - [CSE outputs](../densepose/structures/cse.py); - * Dedicated predictors for - [chart-based estimation](../densepose/modeling/predictors/chart.py), - [confidence estimation](../densepose/modeling/predictors/chart_confidence.py) - and [CSE estimation](../densepose/modeling/predictors/cse.py); - * Generic handling of various [conversions](../densepose/converters) (e.g. from outputs to results); - * Better organization of various [losses](../densepose/modeling/losses); - * Segregation of loss data accumulators for - [IUV setting](../densepose/modeling/losses/utils.py) - and [CSE setting](../densepose/modeling/losses/embed_utils.py); - * Splitting visualizers into separate modules; -* [HRNet](../densepose/modeling/hrnet.py) and [HRFPN](../densepose/modeling/hrfpn.py) backbones; -* [PoseTrack](DENSEPOSE_DATASETS.md#densepose-posetrack) dataset; -* [IUV texture visualizer](../densepose/vis/densepose_results_textures.py) diff --git a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_06.md b/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_06.md deleted file mode 100644 index fb5ff4facdfaf5559d7be26c49852f4f6bc5495e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/RELEASE_2021_06.md +++ /dev/null @@ -1,12 +0,0 @@ -# DensePose CSE with Cycle Losses - -This release follows the paper [Neverova et al, 2021]() and -adds CSE datasets with more annotations, better CSE animal models -to the model zoo, losses to ensure cycle consistency for models and mesh -alignment evaluator. In particular: - -* [Pixel to shape](../densepose/modeling/losses/cycle_pix2shape.py) and [shape to shape](../densepose/modeling/losses/cycle_shape2shape.py) cycle consistency losses; -* Mesh alignment [evaluator](../densepose/evaluation/mesh_alignment_evaluator.py); -* Existing CSE datasets renamed to [ds1_train](https://dl.fbaipublicfiles.com/densepose/annotations/lvis/densepose_lvis_v1_ds1_train_v1.json) and [ds1_val](https://dl.fbaipublicfiles.com/densepose/annotations/lvis/densepose_lvis_v1_ds1_val_v1.json); -* New CSE datasets [ds2_train](https://dl.fbaipublicfiles.com/densepose/annotations/lvis/densepose_lvis_v1_ds2_train_v1.json) and [ds2_val](https://dl.fbaipublicfiles.com/densepose/annotations/lvis/densepose_lvis_v1_ds2_val_v1.json) added; -* Better CSE animal models trained with the 16k schedule added to the [model zoo](DENSEPOSE_CSE.md#animal-cse-models). diff --git a/preprocess/detectron2/projects/DensePose/doc/TOOL_APPLY_NET.md b/preprocess/detectron2/projects/DensePose/doc/TOOL_APPLY_NET.md deleted file mode 100644 index ca8e1ddafc7b1003ba98cce2826157ab995a2443..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/TOOL_APPLY_NET.md +++ /dev/null @@ -1,203 +0,0 @@ -# Apply Net - -`apply_net` is a tool to print or visualize DensePose results on a set of images. -It has two modes: `dump` to save DensePose model results to a pickle file -and `show` to visualize them on images. - -The `image.jpg` file that is used as an example in this doc can be found [here](http://images.cocodataset.org/train2017/000000117508.jpg) - -## Dump Mode - -The general command form is: -```bash -python apply_net.py dump [-h] [-v] [--output ] -``` - -There are three mandatory arguments: - - ``, configuration file for a given model; - - ``, model file with trained parameters - - ``, input image file name, pattern or folder - -One can additionally provide `--output` argument to define the output file name, -which defaults to `output.pkl`. - - -Examples: - -1. Dump results of the [R_50_FPN_s1x](https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl) DensePose model for images in a folder `images` to file `dump.pkl`: -```bash -python apply_net.py dump configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -images --output dump.pkl -v -``` - -2. Dump results of the [R_50_FPN_s1x](https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl) DensePose model for images with file name matching a pattern `image*.jpg` to file `results.pkl`: -```bash -python apply_net.py dump configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -"image*.jpg" --output results.pkl -v -``` - -If you want to load the pickle file generated by the above command: -``` -# make sure DensePose is in your PYTHONPATH, or use the following line to add it: -sys.path.append("/your_detectron2_path/detectron2_repo/projects/DensePose/") - -f = open('/your_result_path/results.pkl', 'rb') -data = pickle.load(f) -``` - -The file `results.pkl` contains the list of results per image, for each image the result is a dictionary. - -**If you use a [IUV model](DENSEPOSE_IUV.md#-model-zoo-and-baselines)**, the dumped data will have the following format: - -``` -data: [{'file_name': '/your_path/image1.jpg', - 'scores': tensor([0.9884]), - 'pred_boxes_XYXY': tensor([[ 69.6114, 0.0000, 706.9797, 706.0000]]), - 'pred_densepose': [DensePoseChartResultWithConfidences(labels=tensor(...), uv=tensor(...), sigma_1=None, - sigma_2=None, kappa_u=None, kappa_v=None, fine_segm_confidence=None, coarse_segm_confidence=None), - DensePoseChartResultWithConfidences, ...] - } - {'file_name': '/your_path/image2.jpg', - 'scores': tensor([0.9999, 0.5373, 0.3991]), - 'pred_boxes_XYXY': tensor([[ 59.5734, 7.7535, 579.9311, 932.3619], - [612.9418, 686.1254, 612.9999, 704.6053], - [164.5081, 407.4034, 598.3944, 920.4266]]), - 'pred_densepose': [DensePoseChartResultWithConfidences(labels=tensor(...), uv=tensor(...), sigma_1=None, - sigma_2=None, kappa_u=None, kappa_v=None, fine_segm_confidence=None, coarse_segm_confidence=None), - DensePoseChartResultWithConfidences, ...] - }] -``` - -`DensePoseChartResultWithConfidences` contains the following fields: -- `labels` - a tensor of size `[H, W]` of type `torch.long` which contains fine segmentation labels (previously called `I`) -- `uv` - a tensor of size `[2, H, W]` of type `torch.float` which contains `U` and `V` coordinates -- various optional confidence-related fields (`sigma_1`, `sigma_2`, `kappa_u`, `kappa_v`, `fine_segm_confidence`, `coarse_segm_confidence`) - - -**If you use a [CSE model](DENSEPOSE_CSE.md#-model-zoo-and-baselines)**, the dumped data will have the following format: -``` -data: [{'file_name': '/your_path/image1.jpg', - 'scores': tensor([0.9984, 0.9961]), - 'pred_boxes_XYXY': tensor([[480.0093, 461.0796, 698.3614, 696.1011], - [78.1589, 168.6614, 307.1287, 653.8522]]), - 'pred_densepose': DensePoseEmbeddingPredictorOutput(embedding=tensor(...), coarse_segm=tensor(...))} - {'file_name': '/your_path/image2.jpg', - 'scores': tensor([0.9189, 0.9491]), - 'pred_boxes_XYXY': tensor([[734.9685, 534.2003, 287.3923, 254.8859], - [434.2853, 765.1219, 132.1029, 867.9283]]), - 'pred_densepose': DensePoseEmbeddingPredictorOutput(embedding=tensor(...), coarse_segm=tensor(...))}] -``` - -`DensePoseEmbeddingPredictorOutput` contains the following fields: -- `embedding` - a tensor of size `[N, D, sz, sz]` of type `torch.float`, which contains embeddings of size `D` of the `N` detections in the image -- `coarse_segm` - a tensor of size `[N, 2, sz, sz]` of type `torch.float` which contains segmentation scores of the `N` detections in the image; e.g. a mask can be obtained by `coarse_segm.argmax(dim=1)` - -`sz` is a fixed size for the tensors; you can resize them to the size of the bounding box, if needed - -We can use the following code, to parse the outputs of the first -detected instance on the first image (IUV model). -``` -img_id, instance_id = 0, 0 # Look at the first image and the first detected instance -bbox_xyxy = data[img_id]['pred_boxes_XYXY'][instance_id] -result = data[img_id]['pred_densepose'][instance_id] -uv = result.uv -``` -The array `bbox_xyxy` contains (x0, y0, x1, y1) of the bounding box. - - -## Visualization Mode - -The general command form is: -```bash -python apply_net.py show [-h] [-v] [--min_score ] [--nms_thresh ] [--output ] -``` - -There are four mandatory arguments: - - ``, configuration file for a given model; - - ``, model file with trained parameters - - ``, input image file name, pattern or folder - - ``, visualizations specifier; currently available visualizations are: - * `bbox` - bounding boxes of detected persons; - * `dp_segm` - segmentation masks for detected persons; - * `dp_u` - each body part is colored according to the estimated values of the - U coordinate in part parameterization; - * `dp_v` - each body part is colored according to the estimated values of the - V coordinate in part parameterization; - * `dp_contour` - plots contours with color-coded U and V coordinates; - * `dp_iuv_texture` - transfers the texture from a given texture image file to detected instances, in IUV mode; - * `dp_vertex` - plots the rainbow visualization of the closest vertices prediction for a given mesh, in CSE mode; - * `dp_cse_texture` - transfers the texture from a given list of texture image files (one from each human or animal mesh) to detected instances, in CSE mode - - -One can additionally provide the following optional arguments: - - `--min_score` to only show detections with sufficient scores that are not lower than provided value - - `--nms_thresh` to additionally apply non-maximum suppression to detections at a given threshold - - `--output` to define visualization file name template, which defaults to `output.png`. - To distinguish output file names for different images, the tool appends 1-based entry index, - e.g. output.0001.png, output.0002.png, etc... -- `--texture_atlas` to define the texture atlas image for IUV texture transfer -- `--texture_atlases_map` to define the texture atlas images map (a dictionary `{mesh name: texture atlas image}`) for CSE texture transfer - - -The following examples show how to output results of a DensePose model -with ResNet-50 FPN backbone using different visualizations for image `image.jpg`: - -1. Show bounding box and segmentation: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -image.jpg bbox,dp_segm -v -``` -![Bounding Box + Segmentation Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_segm.jpg) - -2. Show bounding box and estimated U coordinates for body parts: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -image.jpg bbox,dp_u -v -``` -![Bounding Box + U Coordinate Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_u.jpg) - -3. Show bounding box and estimated V coordinates for body parts: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -image.jpg bbox,dp_v -v -``` -![Bounding Box + V Coordinate Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_v.jpg) - -4. Show bounding box and estimated U and V coordinates via contour plots: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -image.jpg dp_contour,bbox -v -``` -![Bounding Box + Contour Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_contour.jpg) - -5. Show bounding box and texture transfer: -```bash -python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ -image.jpg dp_iuv_texture,bbox --texture_atlas texture_from_SURREAL.jpg -v -``` -![Bounding Box + IUV Texture Transfer Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_iuv_texture.jpg) - -6. Show bounding box and CSE rainbow visualization: -```bash -python apply_net.py show configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_s1x/251155172/model_final_c4ea5f.pkl \ -image.jpg dp_vertex,bbox -v -``` -![Bounding Box + CSE Rainbow Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_vertex.jpg) - -7. Show bounding box and CSE texture transfer: -```bash -python apply_net.py show configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml \ -https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_s1x/251155172/model_final_c4ea5f.pkl \ -image.jpg dp_cse_texture,bbox --texture_atlases_map '{"smpl_27554": "smpl_uvSnapshot_colors.jpg"}' -v -``` -![Bounding Box + CSE Texture Transfer Visualization](https://dl.fbaipublicfiles.com/densepose/web/apply_net/res_bbox_dp_cse_texture.jpg) - -The texture files can be found in the `doc/images` folder diff --git a/preprocess/detectron2/projects/DensePose/doc/TOOL_QUERY_DB.md b/preprocess/detectron2/projects/DensePose/doc/TOOL_QUERY_DB.md deleted file mode 100644 index b0a764b8740597c6af634127b80b53d28913726f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/doc/TOOL_QUERY_DB.md +++ /dev/null @@ -1,105 +0,0 @@ - -# Query Dataset - -`query_db` is a tool to print or visualize DensePose data from a dataset. -It has two modes: `print` and `show` to output dataset entries to standard -output or to visualize them on images. - -## Print Mode - -The general command form is: -```bash -python query_db.py print [-h] [-v] [--max-entries N] -``` - -There are two mandatory arguments: - - ``, DensePose dataset specification, from which to select - the entries (e.g. `densepose_coco_2014_train`). - - ``, dataset entry selector which can be a single specification, - or a comma-separated list of specifications of the form - `field[:type]=value` for exact match with the value - or `field[:type]=min-max` for a range of values - -One can additionally limit the maximum number of entries to output -by providing `--max-entries` argument. - -Examples: - -1. Output at most 10 first entries from the `densepose_coco_2014_train` dataset: -```bash -python query_db.py print densepose_coco_2014_train \* --max-entries 10 -v -``` - -2. Output all entries with `file_name` equal to `COCO_train2014_000000000036.jpg`: -```bash -python query_db.py print densepose_coco_2014_train file_name=COCO_train2014_000000000036.jpg -v -``` - -3. Output all entries with `image_id` between 36 and 156: -```bash -python query_db.py print densepose_coco_2014_train image_id:int=36-156 -v -``` - -## Visualization Mode - -The general command form is: -```bash -python query_db.py show [-h] [-v] [--max-entries N] [--output ] -``` - -There are three mandatory arguments: - - ``, DensePose dataset specification, from which to select - the entries (e.g. `densepose_coco_2014_train`). - - ``, dataset entry selector which can be a single specification, - or a comma-separated list of specifications of the form - `field[:type]=value` for exact match with the value - or `field[:type]=min-max` for a range of values - - ``, visualizations specifier; currently available visualizations are: - * `bbox` - bounding boxes of annotated persons; - * `dp_i` - annotated points colored according to the containing part; - * `dp_pts` - annotated points in green color; - * `dp_segm` - segmentation masks for annotated persons; - * `dp_u` - annotated points colored according to their U coordinate in part parameterization; - * `dp_v` - annotated points colored according to their V coordinate in part parameterization; - -One can additionally provide one of the two optional arguments: - - `--max_entries` to limit the maximum number of entries to visualize - - `--output` to provide visualization file name template, which defaults - to `output.png`. To distinguish file names for different dataset - entries, the tool appends 1-based entry index to the output file name, - e.g. output.0001.png, output.0002.png, etc. - -The following examples show how to output different visualizations for image with `id = 322` -from `densepose_coco_2014_train` dataset: - -1. Show bounding box and segmentation: -```bash -python query_db.py show densepose_coco_2014_train image_id:int=322 bbox,dp_segm -v -``` -![Bounding Box + Segmentation Visualization](images/vis_bbox_dp_segm.jpg) - -2. Show bounding box and points colored according to the containing part: -```bash -python query_db.py show densepose_coco_2014_train image_id:int=322 bbox,dp_i -v -``` -![Bounding Box + Point Label Visualization](images/vis_bbox_dp_i.jpg) - -3. Show bounding box and annotated points in green color: -```bash -python query_db.py show densepose_coco_2014_train image_id:int=322 bbox,dp_segm -v -``` -![Bounding Box + Point Visualization](images/vis_bbox_dp_pts.jpg) - -4. Show bounding box and annotated points colored according to their U coordinate in part parameterization: -```bash -python query_db.py show densepose_coco_2014_train image_id:int=322 bbox,dp_u -v -``` -![Bounding Box + Point U Visualization](images/vis_bbox_dp_u.jpg) - -5. Show bounding box and annotated points colored according to their V coordinate in part parameterization: -```bash -python query_db.py show densepose_coco_2014_train image_id:int=322 bbox,dp_v -v -``` -![Bounding Box + Point V Visualization](images/vis_bbox_dp_v.jpg) - - diff --git a/preprocess/detectron2/projects/DensePose/query_db.py b/preprocess/detectron2/projects/DensePose/query_db.py deleted file mode 100755 index 997eba3e6c264213b364a9444755cb15580e82ee..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/query_db.py +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -import argparse -import logging -import os -import sys -from timeit import default_timer as timer -from typing import Any, ClassVar, Dict, List -import torch - -from detectron2.data.catalog import DatasetCatalog -from detectron2.utils.file_io import PathManager -from detectron2.utils.logger import setup_logger - -from densepose.structures import DensePoseDataRelative -from densepose.utils.dbhelper import EntrySelector -from densepose.utils.logger import verbosity_to_level -from densepose.vis.base import CompoundVisualizer -from densepose.vis.bounding_box import BoundingBoxVisualizer -from densepose.vis.densepose_data_points import ( - DensePoseDataCoarseSegmentationVisualizer, - DensePoseDataPointsIVisualizer, - DensePoseDataPointsUVisualizer, - DensePoseDataPointsVisualizer, - DensePoseDataPointsVVisualizer, -) - -DOC = """Query DB - a tool to print / visualize data from a database -""" - -LOGGER_NAME = "query_db" - -logger = logging.getLogger(LOGGER_NAME) - -_ACTION_REGISTRY: Dict[str, "Action"] = {} - - -class Action: - @classmethod - def add_arguments(cls: type, parser: argparse.ArgumentParser): - parser.add_argument( - "-v", - "--verbosity", - action="count", - help="Verbose mode. Multiple -v options increase the verbosity.", - ) - - -def register_action(cls: type): - """ - Decorator for action classes to automate action registration - """ - global _ACTION_REGISTRY - _ACTION_REGISTRY[cls.COMMAND] = cls - return cls - - -class EntrywiseAction(Action): - @classmethod - def add_arguments(cls: type, parser: argparse.ArgumentParser): - super(EntrywiseAction, cls).add_arguments(parser) - parser.add_argument( - "dataset", metavar="", help="Dataset name (e.g. densepose_coco_2014_train)" - ) - parser.add_argument( - "selector", - metavar="", - help="Dataset entry selector in the form field1[:type]=value1[," - "field2[:type]=value_min-value_max...] which selects all " - "entries from the dataset that satisfy the constraints", - ) - parser.add_argument( - "--max-entries", metavar="N", help="Maximum number of entries to process", type=int - ) - - @classmethod - def execute(cls: type, args: argparse.Namespace): - dataset = setup_dataset(args.dataset) - entry_selector = EntrySelector.from_string(args.selector) - context = cls.create_context(args) - if args.max_entries is not None: - for _, entry in zip(range(args.max_entries), dataset): - if entry_selector(entry): - cls.execute_on_entry(entry, context) - else: - for entry in dataset: - if entry_selector(entry): - cls.execute_on_entry(entry, context) - - @classmethod - def create_context(cls: type, args: argparse.Namespace) -> Dict[str, Any]: - context = {} - return context - - -@register_action -class PrintAction(EntrywiseAction): - """ - Print action that outputs selected entries to stdout - """ - - COMMAND: ClassVar[str] = "print" - - @classmethod - def add_parser(cls: type, subparsers: argparse._SubParsersAction): - parser = subparsers.add_parser(cls.COMMAND, help="Output selected entries to stdout. ") - cls.add_arguments(parser) - parser.set_defaults(func=cls.execute) - - @classmethod - def add_arguments(cls: type, parser: argparse.ArgumentParser): - super(PrintAction, cls).add_arguments(parser) - - @classmethod - def execute_on_entry(cls: type, entry: Dict[str, Any], context: Dict[str, Any]): - import pprint - - printer = pprint.PrettyPrinter(indent=2, width=200, compact=True) - printer.pprint(entry) - - -@register_action -class ShowAction(EntrywiseAction): - """ - Show action that visualizes selected entries on an image - """ - - COMMAND: ClassVar[str] = "show" - VISUALIZERS: ClassVar[Dict[str, object]] = { - "dp_segm": DensePoseDataCoarseSegmentationVisualizer(), - "dp_i": DensePoseDataPointsIVisualizer(), - "dp_u": DensePoseDataPointsUVisualizer(), - "dp_v": DensePoseDataPointsVVisualizer(), - "dp_pts": DensePoseDataPointsVisualizer(), - "bbox": BoundingBoxVisualizer(), - } - - @classmethod - def add_parser(cls: type, subparsers: argparse._SubParsersAction): - parser = subparsers.add_parser(cls.COMMAND, help="Visualize selected entries") - cls.add_arguments(parser) - parser.set_defaults(func=cls.execute) - - @classmethod - def add_arguments(cls: type, parser: argparse.ArgumentParser): - super(ShowAction, cls).add_arguments(parser) - parser.add_argument( - "visualizations", - metavar="", - help="Comma separated list of visualizations, possible values: " - "[{}]".format(",".join(sorted(cls.VISUALIZERS.keys()))), - ) - parser.add_argument( - "--output", - metavar="", - default="output.png", - help="File name to save output to", - ) - - @classmethod - def execute_on_entry(cls: type, entry: Dict[str, Any], context: Dict[str, Any]): - import cv2 - import numpy as np - - image_fpath = PathManager.get_local_path(entry["file_name"]) - image = cv2.imread(image_fpath, cv2.IMREAD_GRAYSCALE) - image = np.tile(image[:, :, np.newaxis], [1, 1, 3]) - datas = cls._extract_data_for_visualizers_from_entry(context["vis_specs"], entry) - visualizer = context["visualizer"] - image_vis = visualizer.visualize(image, datas) - entry_idx = context["entry_idx"] + 1 - out_fname = cls._get_out_fname(entry_idx, context["out_fname"]) - cv2.imwrite(out_fname, image_vis) - logger.info(f"Output saved to {out_fname}") - context["entry_idx"] += 1 - - @classmethod - def _get_out_fname(cls: type, entry_idx: int, fname_base: str): - base, ext = os.path.splitext(fname_base) - return base + ".{0:04d}".format(entry_idx) + ext - - @classmethod - def create_context(cls: type, args: argparse.Namespace) -> Dict[str, Any]: - vis_specs = args.visualizations.split(",") - visualizers = [] - for vis_spec in vis_specs: - vis = cls.VISUALIZERS[vis_spec] - visualizers.append(vis) - context = { - "vis_specs": vis_specs, - "visualizer": CompoundVisualizer(visualizers), - "out_fname": args.output, - "entry_idx": 0, - } - return context - - @classmethod - def _extract_data_for_visualizers_from_entry( - cls: type, vis_specs: List[str], entry: Dict[str, Any] - ): - dp_list = [] - bbox_list = [] - for annotation in entry["annotations"]: - is_valid, _ = DensePoseDataRelative.validate_annotation(annotation) - if not is_valid: - continue - bbox = torch.as_tensor(annotation["bbox"]) - bbox_list.append(bbox) - dp_data = DensePoseDataRelative(annotation) - dp_list.append(dp_data) - datas = [] - for vis_spec in vis_specs: - datas.append(bbox_list if "bbox" == vis_spec else (bbox_list, dp_list)) - return datas - - -def setup_dataset(dataset_name): - logger.info("Loading dataset {}".format(dataset_name)) - start = timer() - dataset = DatasetCatalog.get(dataset_name) - stop = timer() - logger.info("Loaded dataset {} in {:.3f}s".format(dataset_name, stop - start)) - return dataset - - -def create_argument_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - description=DOC, - formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=120), - ) - parser.set_defaults(func=lambda _: parser.print_help(sys.stdout)) - subparsers = parser.add_subparsers(title="Actions") - for _, action in _ACTION_REGISTRY.items(): - action.add_parser(subparsers) - return parser - - -def main(): - parser = create_argument_parser() - args = parser.parse_args() - verbosity = getattr(args, "verbosity", None) - global logger - logger = setup_logger(name=LOGGER_NAME) - logger.setLevel(verbosity_to_level(verbosity)) - args.func(args) - - -if __name__ == "__main__": - main() diff --git a/preprocess/detectron2/projects/DensePose/setup.py b/preprocess/detectron2/projects/DensePose/setup.py deleted file mode 100644 index 29f7bb3bfabee9835257e6b3625de37e13e460e8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -import re -from pathlib import Path -from setuptools import find_packages, setup - -try: - import torch # noqa: F401 -except ImportError as e: - raise Exception( - """ -You must install PyTorch prior to installing DensePose: -pip install torch - -For more information: - https://pytorch.org/get-started/locally/ - """ - ) from e - - -def get_detectron2_current_version(): - """Version is not available for import through Python since it is - above the top level of the package. Instead, we parse it from the - file with a regex.""" - # Get version info from detectron2 __init__.py - version_source = (Path(__file__).parents[2] / "detectron2" / "__init__.py").read_text() - version_number = re.findall(r'__version__ = "([0-9\.]+)"', version_source)[0] - return version_number - - -setup( - name="detectron2-densepose", - author="FAIR", - version=get_detectron2_current_version(), - url="https://github.com/facebookresearch/detectron2/tree/main/projects/DensePose", - packages=find_packages(), - python_requires=">=3.7", - install_requires=[ - "av>=8.0.3", - # "detectron2@git+https://github.com/facebookresearch/detectron2.git", - "opencv-python-headless>=4.5.3.56", - "scipy>=1.5.4", - ], -) diff --git a/preprocess/detectron2/projects/DensePose/tests/common.py b/preprocess/detectron2/projects/DensePose/tests/common.py deleted file mode 100644 index ff22b9ab6eceb7c9de0f769c3cbd3197ecd51222..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/common.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import os -import torch - -from detectron2.config import get_cfg -from detectron2.engine import default_setup -from detectron2.modeling import build_model - -from densepose import add_densepose_config - -_BASE_CONFIG_DIR = "configs" -_EVOLUTION_CONFIG_SUB_DIR = "evolution" -_HRNET_CONFIG_SUB_DIR = "HRNet" -_QUICK_SCHEDULES_CONFIG_SUB_DIR = "quick_schedules" -_BASE_CONFIG_FILE_PREFIX = "Base-" -_CONFIG_FILE_EXT = ".yaml" - - -def _get_base_config_dir(): - """ - Return the base directory for configurations - """ - return os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", _BASE_CONFIG_DIR) - - -def _get_evolution_config_dir(): - """ - Return the base directory for evolution configurations - """ - return os.path.join(_get_base_config_dir(), _EVOLUTION_CONFIG_SUB_DIR) - - -def _get_hrnet_config_dir(): - """ - Return the base directory for HRNet configurations - """ - return os.path.join(_get_base_config_dir(), _HRNET_CONFIG_SUB_DIR) - - -def _get_quick_schedules_config_dir(): - """ - Return the base directory for quick schedules configurations - """ - return os.path.join(_get_base_config_dir(), _QUICK_SCHEDULES_CONFIG_SUB_DIR) - - -def _collect_config_files(config_dir): - """ - Collect all configuration files (i.e. densepose_*.yaml) directly in the specified directory - """ - start = _get_base_config_dir() - results = [] - for entry in os.listdir(config_dir): - path = os.path.join(config_dir, entry) - if not os.path.isfile(path): - continue - _, ext = os.path.splitext(entry) - if ext != _CONFIG_FILE_EXT: - continue - if entry.startswith(_BASE_CONFIG_FILE_PREFIX): - continue - config_file = os.path.relpath(path, start) - results.append(config_file) - return results - - -def get_config_files(): - """ - Get all the configuration files (relative to the base configuration directory) - """ - return _collect_config_files(_get_base_config_dir()) - - -def get_evolution_config_files(): - """ - Get all the evolution configuration files (relative to the base configuration directory) - """ - return _collect_config_files(_get_evolution_config_dir()) - - -def get_hrnet_config_files(): - """ - Get all the HRNet configuration files (relative to the base configuration directory) - """ - return _collect_config_files(_get_hrnet_config_dir()) - - -def get_quick_schedules_config_files(): - """ - Get all the quick schedules configuration files (relative to the base configuration directory) - """ - return _collect_config_files(_get_quick_schedules_config_dir()) - - -def get_model_config(config_file): - """ - Load and return the configuration from the specified file (relative to the base configuration - directory) - """ - cfg = get_cfg() - add_densepose_config(cfg) - path = os.path.join(_get_base_config_dir(), config_file) - cfg.merge_from_file(path) - if not torch.cuda.is_available(): - cfg.MODEL.DEVICE = "cpu" - return cfg - - -def get_model(config_file): - """ - Get the model from the specified file (relative to the base configuration directory) - """ - cfg = get_model_config(config_file) - return build_model(cfg) - - -def setup(config_file): - """ - Setup the configuration from the specified file (relative to the base configuration directory) - """ - cfg = get_model_config(config_file) - cfg.freeze() - default_setup(cfg, {}) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_chart_based_annotations_accumulator.py b/preprocess/detectron2/projects/DensePose/tests/test_chart_based_annotations_accumulator.py deleted file mode 100644 index a1c4f8565a3c55b79b6ed96b03635e6c2932958d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_chart_based_annotations_accumulator.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -import torch - -from detectron2.structures import Boxes, BoxMode, Instances - -from densepose.modeling.losses.utils import ChartBasedAnnotationsAccumulator -from densepose.structures import DensePoseDataRelative, DensePoseList - -image_shape = (100, 100) -instances = Instances(image_shape) -n_instances = 3 -instances.proposal_boxes = Boxes(torch.rand(n_instances, 4)) -instances.gt_boxes = Boxes(torch.rand(n_instances, 4)) - - -# instances.gt_densepose = None cannot happen because instances attributes need a length -class TestChartBasedAnnotationsAccumulator(unittest.TestCase): - def test_chart_based_annotations_accumulator_no_gt_densepose(self): - accumulator = ChartBasedAnnotationsAccumulator() - accumulator.accumulate(instances) - expected_values = {"nxt_bbox_with_dp_index": 0, "nxt_bbox_index": n_instances} - for key in accumulator.__dict__: - self.assertEqual(getattr(accumulator, key), expected_values.get(key, [])) - - def test_chart_based_annotations_accumulator_gt_densepose_none(self): - instances.gt_densepose = [None] * n_instances - accumulator = ChartBasedAnnotationsAccumulator() - accumulator.accumulate(instances) - expected_values = {"nxt_bbox_with_dp_index": 0, "nxt_bbox_index": n_instances} - for key in accumulator.__dict__: - self.assertEqual(getattr(accumulator, key), expected_values.get(key, [])) - - def test_chart_based_annotations_accumulator_gt_densepose(self): - data_relative_keys = [ - DensePoseDataRelative.X_KEY, - DensePoseDataRelative.Y_KEY, - DensePoseDataRelative.I_KEY, - DensePoseDataRelative.U_KEY, - DensePoseDataRelative.V_KEY, - DensePoseDataRelative.S_KEY, - ] - annotations = [DensePoseDataRelative({k: [0] for k in data_relative_keys})] * n_instances - instances.gt_densepose = DensePoseList(annotations, instances.gt_boxes, image_shape) - accumulator = ChartBasedAnnotationsAccumulator() - accumulator.accumulate(instances) - bbox_xywh_est = BoxMode.convert( - instances.proposal_boxes.tensor.clone(), BoxMode.XYXY_ABS, BoxMode.XYWH_ABS - ) - bbox_xywh_gt = BoxMode.convert( - instances.gt_boxes.tensor.clone(), BoxMode.XYXY_ABS, BoxMode.XYWH_ABS - ) - expected_values = { - "s_gt": [ - torch.zeros((3, DensePoseDataRelative.MASK_SIZE, DensePoseDataRelative.MASK_SIZE)) - ] - * n_instances, - "bbox_xywh_est": bbox_xywh_est.split(1), - "bbox_xywh_gt": bbox_xywh_gt.split(1), - "point_bbox_with_dp_indices": [torch.tensor([i]) for i in range(n_instances)], - "point_bbox_indices": [torch.tensor([i]) for i in range(n_instances)], - "bbox_indices": list(range(n_instances)), - "nxt_bbox_with_dp_index": n_instances, - "nxt_bbox_index": n_instances, - } - default_value = [torch.tensor([0])] * 3 - for key in accumulator.__dict__: - to_test = getattr(accumulator, key) - gt_value = expected_values.get(key, default_value) - if key in ["nxt_bbox_with_dp_index", "nxt_bbox_index"]: - self.assertEqual(to_test, gt_value) - elif key == "bbox_indices": - self.assertListEqual(to_test, gt_value) - else: - self.assertTrue(torch.allclose(torch.stack(to_test), torch.stack(gt_value))) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_combine_data_loader.py b/preprocess/detectron2/projects/DensePose/tests/test_combine_data_loader.py deleted file mode 100644 index 832903a8e133b124669830b378af582c3b58b3dc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_combine_data_loader.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import random -import unittest -from typing import Any, Iterable, Iterator, Tuple - -from densepose.data import CombinedDataLoader - - -def _grouper(iterable: Iterable[Any], n: int, fillvalue=None) -> Iterator[Tuple[Any]]: - """ - Group elements of an iterable by chunks of size `n`, e.g. - grouper(range(9), 4) -> - (0, 1, 2, 3), (4, 5, 6, 7), (8, None, None, None) - """ - it = iter(iterable) - while True: - values = [] - for _ in range(n): - try: - value = next(it) - except StopIteration: - values.extend([fillvalue] * (n - len(values))) - yield tuple(values) - return - values.append(value) - yield tuple(values) - - -class TestCombinedDataLoader(unittest.TestCase): - def test_combine_loaders_1(self): - loader1 = _grouper([f"1_{i}" for i in range(10)], 2) - loader2 = _grouper([f"2_{i}" for i in range(11)], 3) - batch_size = 4 - ratios = (0.1, 0.9) - random.seed(43) - combined = CombinedDataLoader((loader1, loader2), batch_size, ratios) - BATCHES_GT = [ - ["1_0", "1_1", "2_0", "2_1"], - ["2_2", "2_3", "2_4", "2_5"], - ["1_2", "1_3", "2_6", "2_7"], - ["2_8", "2_9", "2_10", None], - ] - for i, batch in enumerate(combined): - self.assertEqual(len(batch), batch_size) - self.assertEqual(batch, BATCHES_GT[i]) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_cse_annotations_accumulator.py b/preprocess/detectron2/projects/DensePose/tests/test_cse_annotations_accumulator.py deleted file mode 100644 index a22dce9ce00532d60dc3f4edbef4cea26b006b92..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_cse_annotations_accumulator.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -import unittest -import torch - -from detectron2.structures import Boxes, BoxMode, Instances - -from densepose.modeling.losses.embed_utils import CseAnnotationsAccumulator -from densepose.structures import DensePoseDataRelative, DensePoseList - - -class TestCseAnnotationsAccumulator(unittest.TestCase): - def test_cse_annotations_accumulator_nodp(self): - instances_lst = [ - self._create_instances_nodp(), - ] - self._test_template(instances_lst) - - def test_cse_annotations_accumulator_sparsedp(self): - instances_lst = [ - self._create_instances_sparsedp(), - ] - self._test_template(instances_lst) - - def test_cse_annotations_accumulator_fulldp(self): - instances_lst = [ - self._create_instances_fulldp(), - ] - self._test_template(instances_lst) - - def test_cse_annotations_accumulator_combined(self): - instances_lst = [ - self._create_instances_nodp(), - self._create_instances_sparsedp(), - self._create_instances_fulldp(), - ] - self._test_template(instances_lst) - - def _test_template(self, instances_lst): - acc = CseAnnotationsAccumulator() - for instances in instances_lst: - acc.accumulate(instances) - packed_anns = acc.pack() - self._check_correspondence(packed_anns, instances_lst) - - def _create_instances_nodp(self): - image_shape = (480, 640) - instances = Instances(image_shape) - instances.gt_boxes = Boxes( - torch.as_tensor( - [ - [40.0, 40.0, 140.0, 140.0], - [160.0, 160.0, 270.0, 270.0], - [40.0, 160.0, 160.0, 280.0], - ] - ) - ) - instances.proposal_boxes = Boxes( - torch.as_tensor( - [ - [41.0, 39.0, 142.0, 138.0], - [161.0, 159.0, 272.0, 268.0], - [41.0, 159.0, 162.0, 278.0], - ] - ) - ) - # do not add gt_densepose - return instances - - def _create_instances_sparsedp(self): - image_shape = (540, 720) - instances = Instances(image_shape) - instances.gt_boxes = Boxes( - torch.as_tensor( - [ - [50.0, 50.0, 130.0, 130.0], - [150.0, 150.0, 240.0, 240.0], - [50.0, 150.0, 230.0, 330.0], - ] - ) - ) - instances.proposal_boxes = Boxes( - torch.as_tensor( - [ - [49.0, 51.0, 131.0, 129.0], - [151.0, 149.0, 241.0, 239.0], - [51.0, 149.0, 232.0, 329.0], - ] - ) - ) - instances.gt_densepose = DensePoseList( - [ - None, - self._create_dp_data( - { - "dp_x": [81.69, 153.47, 151.00], - "dp_y": [162.24, 128.71, 113.81], - "dp_vertex": [0, 1, 2], - "ref_model": "zebra_5002", - "dp_masks": [], - }, - {"c": (166, 133), "r": 64}, - ), - None, - ], - instances.gt_boxes, - image_shape, - ) - return instances - - def _create_instances_fulldp(self): - image_shape = (680, 840) - instances = Instances(image_shape) - instances.gt_boxes = Boxes( - torch.as_tensor( - [ - [65.0, 55.0, 165.0, 155.0], - [170.0, 175.0, 275.0, 280.0], - [55.0, 165.0, 165.0, 275.0], - ] - ) - ) - instances.proposal_boxes = Boxes( - torch.as_tensor( - [ - [66.0, 54.0, 166.0, 154.0], - [171.0, 174.0, 276.0, 279.0], - [56.0, 164.0, 166.0, 274.0], - ] - ) - ) - instances.gt_densepose = DensePoseList( - [ - self._create_dp_data( - { - "dp_x": [149.99, 198.62, 157.59], - "dp_y": [170.74, 197.73, 123.12], - "dp_vertex": [3, 4, 5], - "ref_model": "cat_5001", - "dp_masks": [], - }, - {"c": (100, 100), "r": 50}, - ), - self._create_dp_data( - { - "dp_x": [234.53, 116.72, 71.66], - "dp_y": [107.53, 11.31, 142.32], - "dp_vertex": [6, 7, 8], - "ref_model": "dog_5002", - "dp_masks": [], - }, - {"c": (200, 150), "r": 40}, - ), - self._create_dp_data( - { - "dp_x": [225.54, 202.61, 135.90], - "dp_y": [167.46, 181.00, 211.47], - "dp_vertex": [9, 10, 11], - "ref_model": "elephant_5002", - "dp_masks": [], - }, - {"c": (100, 200), "r": 45}, - ), - ], - instances.gt_boxes, - image_shape, - ) - return instances - - def _create_dp_data(self, anns, blob_def=None): - dp_data = DensePoseDataRelative(anns) - if blob_def is not None: - dp_data.segm[ - blob_def["c"][0] - blob_def["r"] : blob_def["c"][0] + blob_def["r"], - blob_def["c"][1] - blob_def["r"] : blob_def["c"][1] + blob_def["r"], - ] = 1 - return dp_data - - def _check_correspondence(self, packed_anns, instances_lst): - instance_idx = 0 - data_idx = 0 - pt_offset = 0 - if packed_anns is not None: - bbox_xyxy_gt = BoxMode.convert( - packed_anns.bbox_xywh_gt.clone(), BoxMode.XYWH_ABS, BoxMode.XYXY_ABS - ) - bbox_xyxy_est = BoxMode.convert( - packed_anns.bbox_xywh_est.clone(), BoxMode.XYWH_ABS, BoxMode.XYXY_ABS - ) - for instances in instances_lst: - if not hasattr(instances, "gt_densepose"): - instance_idx += len(instances) - continue - for i, dp_data in enumerate(instances.gt_densepose): - if dp_data is None: - instance_idx += 1 - continue - n_pts = len(dp_data.x) - self.assertTrue( - torch.allclose(dp_data.x, packed_anns.x_gt[pt_offset : pt_offset + n_pts]) - ) - self.assertTrue( - torch.allclose(dp_data.y, packed_anns.y_gt[pt_offset : pt_offset + n_pts]) - ) - self.assertTrue(torch.allclose(dp_data.segm, packed_anns.coarse_segm_gt[data_idx])) - self.assertTrue( - torch.allclose( - torch.ones(n_pts, dtype=torch.long) * dp_data.mesh_id, - packed_anns.vertex_mesh_ids_gt[pt_offset : pt_offset + n_pts], - ) - ) - self.assertTrue( - torch.allclose( - dp_data.vertex_ids, packed_anns.vertex_ids_gt[pt_offset : pt_offset + n_pts] - ) - ) - self.assertTrue( - torch.allclose(instances.gt_boxes.tensor[i], bbox_xyxy_gt[data_idx]) - ) - self.assertTrue( - torch.allclose(instances.proposal_boxes.tensor[i], bbox_xyxy_est[data_idx]) - ) - self.assertTrue( - torch.allclose( - torch.ones(n_pts, dtype=torch.long) * data_idx, - packed_anns.point_bbox_with_dp_indices[pt_offset : pt_offset + n_pts], - ) - ) - self.assertTrue( - torch.allclose( - torch.ones(n_pts, dtype=torch.long) * instance_idx, - packed_anns.point_bbox_indices[pt_offset : pt_offset + n_pts], - ) - ) - self.assertEqual(instance_idx, packed_anns.bbox_indices[data_idx]) - pt_offset += n_pts - instance_idx += 1 - data_idx += 1 - if data_idx == 0: - self.assertIsNone(packed_anns) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_dataset_loaded_annotations.py b/preprocess/detectron2/projects/DensePose/tests/test_dataset_loaded_annotations.py deleted file mode 100644 index cf8035b87c6477221a113ba9fcb794495c04af7c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_dataset_loaded_annotations.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -import unittest - -from densepose.data.datasets.builtin import COCO_DATASETS, DENSEPOSE_ANNOTATIONS_DIR, LVIS_DATASETS -from densepose.data.datasets.coco import load_coco_json -from densepose.data.datasets.lvis import load_lvis_json -from densepose.data.utils import maybe_prepend_base_path -from densepose.structures import DensePoseDataRelative - - -class TestDatasetLoadedAnnotations(unittest.TestCase): - COCO_DATASET_DATA = { - "densepose_coco_2014_train": {"n_instances": 39210}, - "densepose_coco_2014_minival": {"n_instances": 2243}, - "densepose_coco_2014_minival_100": {"n_instances": 164}, - "densepose_coco_2014_valminusminival": {"n_instances": 7297}, - "densepose_coco_2014_train_cse": {"n_instances": 39210}, - "densepose_coco_2014_minival_cse": {"n_instances": 2243}, - "densepose_coco_2014_minival_100_cse": {"n_instances": 164}, - "densepose_coco_2014_valminusminival_cse": {"n_instances": 7297}, - "densepose_chimps": {"n_instances": 930}, - "posetrack2017_train": {"n_instances": 8274}, - "posetrack2017_val": {"n_instances": 4753}, - "lvis_v05_train": {"n_instances": 5186}, - "lvis_v05_val": {"n_instances": 1037}, - } - - LVIS_DATASET_DATA = { - "densepose_lvis_v1_train1": {"n_instances": 3394}, - "densepose_lvis_v1_train2": {"n_instances": 1800}, - "densepose_lvis_v1_val": {"n_instances": 1037}, - "densepose_lvis_v1_val_animals_100": {"n_instances": 89}, - } - - def generic_coco_test(self, dataset_info): - if dataset_info.name not in self.COCO_DATASET_DATA: - return - n_inst = self.COCO_DATASET_DATA[dataset_info.name]["n_instances"] - self.generic_test(dataset_info, n_inst, load_coco_json) - - def generic_lvis_test(self, dataset_info): - if dataset_info.name not in self.LVIS_DATASET_DATA: - return - n_inst = self.LVIS_DATASET_DATA[dataset_info.name]["n_instances"] - self.generic_test(dataset_info, n_inst, load_lvis_json) - - def generic_test(self, dataset_info, n_inst, loader_fun): - datasets_root = DENSEPOSE_ANNOTATIONS_DIR - annotations_fpath = maybe_prepend_base_path(datasets_root, dataset_info.annotations_fpath) - images_root = maybe_prepend_base_path(datasets_root, dataset_info.images_root) - image_annotation_dicts = loader_fun( - annotations_json_file=annotations_fpath, - image_root=images_root, - dataset_name=dataset_info.name, - ) - num_valid = sum( - 1 - for image_annotation_dict in image_annotation_dicts - for ann in image_annotation_dict["annotations"] - if DensePoseDataRelative.validate_annotation(ann)[0] - ) - self.assertEqual(num_valid, n_inst) - - -def coco_test_fun(dataset_info): - return lambda self: self.generic_coco_test(dataset_info) - - -for dataset_info in COCO_DATASETS: - setattr( - TestDatasetLoadedAnnotations, - f"test_coco_builtin_loaded_annotations_{dataset_info.name}", - coco_test_fun(dataset_info), - ) - - -def lvis_test_fun(dataset_info): - return lambda self: self.generic_lvis_test(dataset_info) - - -for dataset_info in LVIS_DATASETS: - setattr( - TestDatasetLoadedAnnotations, - f"test_lvis_builtin_loaded_annotations_{dataset_info.name}", - lvis_test_fun(dataset_info), - ) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_frame_selector.py b/preprocess/detectron2/projects/DensePose/tests/test_frame_selector.py deleted file mode 100644 index 65f05f55c78d4ab24950e5335818b3e1f981aa0d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_frame_selector.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import random -import unittest - -from densepose.data.video import FirstKFramesSelector, LastKFramesSelector, RandomKFramesSelector - - -class TestFrameSelector(unittest.TestCase): - def test_frame_selector_random_k_1(self): - _SEED = 43 - _K = 4 - random.seed(_SEED) - selector = RandomKFramesSelector(_K) - frame_tss = list(range(0, 20, 2)) - _SELECTED_GT = [0, 8, 4, 6] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) - - def test_frame_selector_random_k_2(self): - _SEED = 43 - _K = 10 - random.seed(_SEED) - selector = RandomKFramesSelector(_K) - frame_tss = list(range(0, 6, 2)) - _SELECTED_GT = [0, 2, 4] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) - - def test_frame_selector_first_k_1(self): - _K = 4 - selector = FirstKFramesSelector(_K) - frame_tss = list(range(0, 20, 2)) - _SELECTED_GT = frame_tss[:_K] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) - - def test_frame_selector_first_k_2(self): - _K = 10 - selector = FirstKFramesSelector(_K) - frame_tss = list(range(0, 6, 2)) - _SELECTED_GT = frame_tss[:_K] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) - - def test_frame_selector_last_k_1(self): - _K = 4 - selector = LastKFramesSelector(_K) - frame_tss = list(range(0, 20, 2)) - _SELECTED_GT = frame_tss[-_K:] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) - - def test_frame_selector_last_k_2(self): - _K = 10 - selector = LastKFramesSelector(_K) - frame_tss = list(range(0, 6, 2)) - _SELECTED_GT = frame_tss[-_K:] - selected = selector(frame_tss) - self.assertEqual(_SELECTED_GT, selected) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_image_list_dataset.py b/preprocess/detectron2/projects/DensePose/tests/test_image_list_dataset.py deleted file mode 100644 index 7932602448b49b9be4fcea9645fe7a9c4d53c00e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_image_list_dataset.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import contextlib -import os -import tempfile -import unittest -import torch -from torchvision.utils import save_image - -from densepose.data.image_list_dataset import ImageListDataset -from densepose.data.transform import ImageResizeTransform - - -@contextlib.contextmanager -def temp_image(height, width): - random_image = torch.rand(height, width) - with tempfile.NamedTemporaryFile(suffix=".jpg") as f: - f.close() - save_image(random_image, f.name) - yield f.name - os.unlink(f.name) - - -class TestImageListDataset(unittest.TestCase): - def test_image_list_dataset(self): - height, width = 720, 1280 - with temp_image(height, width) as image_fpath: - image_list = [image_fpath] - category_list = [None] - dataset = ImageListDataset(image_list, category_list) - self.assertEqual(len(dataset), 1) - data1, categories1 = dataset[0]["images"], dataset[0]["categories"] - self.assertEqual(data1.shape, torch.Size((1, 3, height, width))) - self.assertEqual(data1.dtype, torch.float32) - self.assertIsNone(categories1[0]) - - def test_image_list_dataset_with_transform(self): - height, width = 720, 1280 - with temp_image(height, width) as image_fpath: - image_list = [image_fpath] - category_list = [None] - transform = ImageResizeTransform() - dataset = ImageListDataset(image_list, category_list, transform) - self.assertEqual(len(dataset), 1) - data1, categories1 = dataset[0]["images"], dataset[0]["categories"] - self.assertEqual(data1.shape, torch.Size((1, 3, 749, 1333))) - self.assertEqual(data1.dtype, torch.float32) - self.assertIsNone(categories1[0]) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_image_resize_transform.py b/preprocess/detectron2/projects/DensePose/tests/test_image_resize_transform.py deleted file mode 100644 index 01c3373b64ee243198af682928939781a15f929a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_image_resize_transform.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -import torch - -from densepose.data.transform import ImageResizeTransform - - -class TestImageResizeTransform(unittest.TestCase): - def test_image_resize_1(self): - images_batch = torch.ones((3, 3, 100, 100), dtype=torch.uint8) * 100 - transform = ImageResizeTransform() - images_transformed = transform(images_batch) - IMAGES_GT = torch.ones((3, 3, 800, 800), dtype=torch.float) * 100 - self.assertEqual(images_transformed.size(), IMAGES_GT.size()) - self.assertAlmostEqual(torch.abs(IMAGES_GT - images_transformed).max().item(), 0.0) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_model_e2e.py b/preprocess/detectron2/projects/DensePose/tests/test_model_e2e.py deleted file mode 100644 index 055fadfd781adcdfd661795edbc621d5eca763fe..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_model_e2e.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -import torch - -from detectron2.structures import BitMasks, Boxes, Instances - -from .common import get_model - - -# TODO(plabatut): Modularize detectron2 tests and re-use -def make_model_inputs(image, instances=None): - if instances is None: - return {"image": image} - - return {"image": image, "instances": instances} - - -def make_empty_instances(h, w): - instances = Instances((h, w)) - instances.gt_boxes = Boxes(torch.rand(0, 4)) - instances.gt_classes = torch.tensor([]).to(dtype=torch.int64) - instances.gt_masks = BitMasks(torch.rand(0, h, w)) - return instances - - -class ModelE2ETest(unittest.TestCase): - CONFIG_PATH = "" - - def setUp(self): - self.model = get_model(self.CONFIG_PATH) - - def _test_eval(self, sizes): - inputs = [make_model_inputs(torch.rand(3, size[0], size[1])) for size in sizes] - self.model.eval() - self.model(inputs) - - -class DensePoseRCNNE2ETest(ModelE2ETest): - CONFIG_PATH = "densepose_rcnn_R_101_FPN_s1x.yaml" - - def test_empty_data(self): - self._test_eval([(200, 250), (200, 249)]) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_setup.py b/preprocess/detectron2/projects/DensePose/tests/test_setup.py deleted file mode 100644 index 165a1b9a7b64aa8a0fbe5b862ebfb6594e77c256..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_setup.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest - -from .common import ( - get_config_files, - get_evolution_config_files, - get_hrnet_config_files, - get_quick_schedules_config_files, - setup, -) - - -class TestSetup(unittest.TestCase): - def _test_setup(self, config_file): - setup(config_file) - - def test_setup_configs(self): - config_files = get_config_files() - for config_file in config_files: - self._test_setup(config_file) - - def test_setup_evolution_configs(self): - config_files = get_evolution_config_files() - for config_file in config_files: - self._test_setup(config_file) - - def test_setup_hrnet_configs(self): - config_files = get_hrnet_config_files() - for config_file in config_files: - self._test_setup(config_file) - - def test_setup_quick_schedules_configs(self): - config_files = get_quick_schedules_config_files() - for config_file in config_files: - self._test_setup(config_file) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_structures.py b/preprocess/detectron2/projects/DensePose/tests/test_structures.py deleted file mode 100644 index 54082d3abf119bf2fdba7206124893f35b4b4ae1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_structures.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest - -from densepose.structures import normalized_coords_transform - - -class TestStructures(unittest.TestCase): - def test_normalized_coords_transform(self): - bbox = (32, 24, 288, 216) - x0, y0, w, h = bbox - xmin, ymin, xmax, ymax = x0, y0, x0 + w, y0 + h - f = normalized_coords_transform(*bbox) - # Top-left - expected_p, actual_p = (-1, -1), f((xmin, ymin)) - self.assertEqual(expected_p, actual_p) - # Top-right - expected_p, actual_p = (1, -1), f((xmax, ymin)) - self.assertEqual(expected_p, actual_p) - # Bottom-left - expected_p, actual_p = (-1, 1), f((xmin, ymax)) - self.assertEqual(expected_p, actual_p) - # Bottom-right - expected_p, actual_p = (1, 1), f((xmax, ymax)) - self.assertEqual(expected_p, actual_p) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_tensor_storage.py b/preprocess/detectron2/projects/DensePose/tests/test_tensor_storage.py deleted file mode 100644 index aeeeffae4675f8d607d0471250dadb2ece5361a0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_tensor_storage.py +++ /dev/null @@ -1,256 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import io -import tempfile -import unittest -from contextlib import ExitStack -import torch -import torch.distributed as dist -import torch.multiprocessing as mp - -from detectron2.utils import comm - -from densepose.evaluation.tensor_storage import ( - SingleProcessFileTensorStorage, - SingleProcessRamTensorStorage, - SizeData, - storage_gather, -) - - -class TestSingleProcessRamTensorStorage(unittest.TestCase): - def test_read_write_1(self): - schema = { - "tf": SizeData(dtype="float32", shape=(112, 112)), - "ti": SizeData(dtype="int32", shape=(4, 64, 64)), - } - # generate data which corresponds to the schema - data_elts = [] - torch.manual_seed(23) - for _i in range(3): - data_elt = { - "tf": torch.rand((112, 112), dtype=torch.float32), - "ti": (torch.rand(4, 64, 64) * 1000).to(dtype=torch.int32), - } - data_elts.append(data_elt) - storage = SingleProcessRamTensorStorage(schema, io.BytesIO()) - # write data to the storage - for i in range(3): - record_id = storage.put(data_elts[i]) - self.assertEqual(record_id, i) - # read data from the storage - for i in range(3): - record = storage.get(i) - self.assertEqual(len(record), len(schema)) - for field_name in schema: - self.assertTrue(field_name in record) - self.assertEqual(data_elts[i][field_name].shape, record[field_name].shape) - self.assertEqual(data_elts[i][field_name].dtype, record[field_name].dtype) - self.assertTrue(torch.allclose(data_elts[i][field_name], record[field_name])) - - -class TestSingleProcessFileTensorStorage(unittest.TestCase): - def test_read_write_1(self): - schema = { - "tf": SizeData(dtype="float32", shape=(112, 112)), - "ti": SizeData(dtype="int32", shape=(4, 64, 64)), - } - # generate data which corresponds to the schema - data_elts = [] - torch.manual_seed(23) - for _i in range(3): - data_elt = { - "tf": torch.rand((112, 112), dtype=torch.float32), - "ti": (torch.rand(4, 64, 64) * 1000).to(dtype=torch.int32), - } - data_elts.append(data_elt) - # WARNING: opens the file several times! may not work on all platforms - with tempfile.NamedTemporaryFile() as hFile: - storage = SingleProcessFileTensorStorage(schema, hFile.name, "wb") - # write data to the storage - for i in range(3): - record_id = storage.put(data_elts[i]) - self.assertEqual(record_id, i) - hFile.seek(0) - storage = SingleProcessFileTensorStorage(schema, hFile.name, "rb") - # read data from the storage - for i in range(3): - record = storage.get(i) - self.assertEqual(len(record), len(schema)) - for field_name in schema: - self.assertTrue(field_name in record) - self.assertEqual(data_elts[i][field_name].shape, record[field_name].shape) - self.assertEqual(data_elts[i][field_name].dtype, record[field_name].dtype) - self.assertTrue(torch.allclose(data_elts[i][field_name], record[field_name])) - - -def _find_free_port(): - """ - Copied from detectron2/engine/launch.py - """ - import socket - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # Binding to port 0 will cause the OS to find an available port for us - sock.bind(("", 0)) - port = sock.getsockname()[1] - sock.close() - # NOTE: there is still a chance the port could be taken by other processes. - return port - - -def launch(main_func, nprocs, args=()): - port = _find_free_port() - dist_url = f"tcp://127.0.0.1:{port}" - # dist_url = "env://" - mp.spawn( - distributed_worker, nprocs=nprocs, args=(main_func, nprocs, dist_url, args), daemon=False - ) - - -def distributed_worker(local_rank, main_func, nprocs, dist_url, args): - dist.init_process_group( - backend="gloo", init_method=dist_url, world_size=nprocs, rank=local_rank - ) - comm.synchronize() - assert comm._LOCAL_PROCESS_GROUP is None - pg = dist.new_group(list(range(nprocs))) - comm._LOCAL_PROCESS_GROUP = pg - main_func(*args) - - -def ram_read_write_worker(): - schema = { - "tf": SizeData(dtype="float32", shape=(112, 112)), - "ti": SizeData(dtype="int32", shape=(4, 64, 64)), - } - storage = SingleProcessRamTensorStorage(schema, io.BytesIO()) - world_size = comm.get_world_size() - rank = comm.get_rank() - data_elts = [] - # prepare different number of tensors in different processes - for i in range(rank + 1): - data_elt = { - "tf": torch.ones((112, 112), dtype=torch.float32) * (rank + i * world_size), - "ti": torch.ones((4, 64, 64), dtype=torch.int32) * (rank + i * world_size), - } - data_elts.append(data_elt) - # write data to the single process storage - for i in range(rank + 1): - record_id = storage.put(data_elts[i]) - assert record_id == i, f"Process {rank}: record ID {record_id}, expected {i}" - comm.synchronize() - # gather all data in process rank 0 - multi_storage = storage_gather(storage) - if rank != 0: - return - # read and check data from the multiprocess storage - for j in range(world_size): - for i in range(j): - record = multi_storage.get(j, i) - record_gt = { - "tf": torch.ones((112, 112), dtype=torch.float32) * (j + i * world_size), - "ti": torch.ones((4, 64, 64), dtype=torch.int32) * (j + i * world_size), - } - assert len(record) == len(schema), ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"expected {len(schema)} fields in the record, got {len(record)}" - ) - for field_name in schema: - assert field_name in record, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name} not in the record" - ) - - assert record_gt[field_name].shape == record[field_name].shape, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, expected shape {record_gt[field_name].shape} " - f"got {record[field_name].shape}" - ) - assert record_gt[field_name].dtype == record[field_name].dtype, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, expected dtype {record_gt[field_name].dtype} " - f"got {record[field_name].dtype}" - ) - assert torch.allclose(record_gt[field_name], record[field_name]), ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, tensors are not close enough:" - f"L-inf {(record_gt[field_name]-record[field_name]).abs_().max()} " - f"L1 {(record_gt[field_name]-record[field_name]).abs_().sum()} " - ) - - -def file_read_write_worker(rank_to_fpath): - schema = { - "tf": SizeData(dtype="float32", shape=(112, 112)), - "ti": SizeData(dtype="int32", shape=(4, 64, 64)), - } - world_size = comm.get_world_size() - rank = comm.get_rank() - storage = SingleProcessFileTensorStorage(schema, rank_to_fpath[rank], "wb") - data_elts = [] - # prepare different number of tensors in different processes - for i in range(rank + 1): - data_elt = { - "tf": torch.ones((112, 112), dtype=torch.float32) * (rank + i * world_size), - "ti": torch.ones((4, 64, 64), dtype=torch.int32) * (rank + i * world_size), - } - data_elts.append(data_elt) - # write data to the single process storage - for i in range(rank + 1): - record_id = storage.put(data_elts[i]) - assert record_id == i, f"Process {rank}: record ID {record_id}, expected {i}" - comm.synchronize() - # gather all data in process rank 0 - multi_storage = storage_gather(storage) - if rank != 0: - return - # read and check data from the multiprocess storage - for j in range(world_size): - for i in range(j): - record = multi_storage.get(j, i) - record_gt = { - "tf": torch.ones((112, 112), dtype=torch.float32) * (j + i * world_size), - "ti": torch.ones((4, 64, 64), dtype=torch.int32) * (j + i * world_size), - } - assert len(record) == len(schema), ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"expected {len(schema)} fields in the record, got {len(record)}" - ) - for field_name in schema: - assert field_name in record, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name} not in the record" - ) - - assert record_gt[field_name].shape == record[field_name].shape, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, expected shape {record_gt[field_name].shape} " - f"got {record[field_name].shape}" - ) - assert record_gt[field_name].dtype == record[field_name].dtype, ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, expected dtype {record_gt[field_name].dtype} " - f"got {record[field_name].dtype}" - ) - assert torch.allclose(record_gt[field_name], record[field_name]), ( - f"Process {rank}: multi storage record, rank {j}, id {i}: " - f"field {field_name}, tensors are not close enough:" - f"L-inf {(record_gt[field_name]-record[field_name]).abs_().max()} " - f"L1 {(record_gt[field_name]-record[field_name]).abs_().sum()} " - ) - - -class TestMultiProcessRamTensorStorage(unittest.TestCase): - def test_read_write_1(self): - launch(ram_read_write_worker, 8) - - -class TestMultiProcessFileTensorStorage(unittest.TestCase): - def test_read_write_1(self): - with ExitStack() as stack: - # WARNING: opens the files several times! may not work on all platforms - rank_to_fpath = { - i: stack.enter_context(tempfile.NamedTemporaryFile()).name for i in range(8) - } - launch(file_read_write_worker, 8, (rank_to_fpath,)) diff --git a/preprocess/detectron2/projects/DensePose/tests/test_video_keyframe_dataset.py b/preprocess/detectron2/projects/DensePose/tests/test_video_keyframe_dataset.py deleted file mode 100644 index 988e1616cdd30757157b479990050d1ca494ce7b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/tests/test_video_keyframe_dataset.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import contextlib -import os -import random -import tempfile -import unittest -import torch -import torchvision.io as io - -from densepose.data.transform import ImageResizeTransform -from densepose.data.video import RandomKFramesSelector, VideoKeyframeDataset - -try: - import av -except ImportError: - av = None - - -# copied from torchvision test/test_io.py -def _create_video_frames(num_frames, height, width): - y, x = torch.meshgrid(torch.linspace(-2, 2, height), torch.linspace(-2, 2, width)) - data = [] - for i in range(num_frames): - xc = float(i) / num_frames - yc = 1 - float(i) / (2 * num_frames) - d = torch.exp(-((x - xc) ** 2 + (y - yc) ** 2) / 2) * 255 - data.append(d.unsqueeze(2).repeat(1, 1, 3).byte()) - return torch.stack(data, 0) - - -# adapted from torchvision test/test_io.py -@contextlib.contextmanager -def temp_video(num_frames, height, width, fps, lossless=False, video_codec=None, options=None): - if lossless: - if video_codec is not None: - raise ValueError("video_codec can't be specified together with lossless") - if options is not None: - raise ValueError("options can't be specified together with lossless") - video_codec = "libx264rgb" - options = {"crf": "0"} - if video_codec is None: - video_codec = "libx264" - if options is None: - options = {} - data = _create_video_frames(num_frames, height, width) - with tempfile.NamedTemporaryFile(suffix=".mp4") as f: - f.close() - io.write_video(f.name, data, fps=fps, video_codec=video_codec, options=options) - yield f.name, data - os.unlink(f.name) - - -@unittest.skipIf(av is None, "PyAV unavailable") -class TestVideoKeyframeDataset(unittest.TestCase): - def test_read_keyframes_all(self): - with temp_video(60, 300, 300, 5, video_codec="mpeg4") as (fname, data): - video_list = [fname] - category_list = [None] - dataset = VideoKeyframeDataset(video_list, category_list) - self.assertEqual(len(dataset), 1) - data1, categories1 = dataset[0]["images"], dataset[0]["categories"] - self.assertEqual(data1.shape, torch.Size((5, 3, 300, 300))) - self.assertEqual(data1.dtype, torch.float32) - self.assertIsNone(categories1[0]) - return - self.assertTrue(False) - - def test_read_keyframes_with_selector(self): - with temp_video(60, 300, 300, 5, video_codec="mpeg4") as (fname, data): - video_list = [fname] - category_list = [None] - random.seed(0) - frame_selector = RandomKFramesSelector(3) - dataset = VideoKeyframeDataset(video_list, category_list, frame_selector) - self.assertEqual(len(dataset), 1) - data1, categories1 = dataset[0]["images"], dataset[0]["categories"] - self.assertEqual(data1.shape, torch.Size((3, 3, 300, 300))) - self.assertEqual(data1.dtype, torch.float32) - self.assertIsNone(categories1[0]) - return - self.assertTrue(False) - - def test_read_keyframes_with_selector_with_transform(self): - with temp_video(60, 300, 300, 5, video_codec="mpeg4") as (fname, data): - video_list = [fname] - category_list = [None] - random.seed(0) - frame_selector = RandomKFramesSelector(1) - transform = ImageResizeTransform() - dataset = VideoKeyframeDataset(video_list, category_list, frame_selector, transform) - data1, categories1 = dataset[0]["images"], dataset[0]["categories"] - self.assertEqual(len(dataset), 1) - self.assertEqual(data1.shape, torch.Size((1, 3, 800, 800))) - self.assertEqual(data1.dtype, torch.float32) - self.assertIsNone(categories1[0]) - return - self.assertTrue(False) diff --git a/preprocess/detectron2/projects/DensePose/train_net.py b/preprocess/detectron2/projects/DensePose/train_net.py deleted file mode 100755 index fbefc9b03b193da5604ce234d20fb2aeabbdebf7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/DensePose/train_net.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -DensePose Training Script. - -This script is similar to the training script in detectron2/tools. - -It is an example of how a user might use detectron2 for a new project. -""" - -from datetime import timedelta - -import detectron2.utils.comm as comm - -from densepose import add_densepose_config -from densepose.engine import Trainer -from densepose.modeling.densepose_checkpoint import DensePoseCheckpointer -from detectron2.config import get_cfg -from detectron2.engine import ( - default_argument_parser, - default_setup, - DEFAULT_TIMEOUT, - hooks, - launch, -) -from detectron2.evaluation import verify_results -from detectron2.utils.file_io import PathManager -from detectron2.utils.logger import setup_logger - - -def setup(args): - cfg = get_cfg() - add_densepose_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - # Setup logger for "densepose" module - setup_logger( - output=cfg.OUTPUT_DIR, distributed_rank=comm.get_rank(), name="densepose" - ) - return cfg - - -def main(args): - cfg = setup(args) - # disable strict kwargs checking: allow one to specify path handle - # hints through kwargs, like timeout in DP evaluation - PathManager.set_strict_kwargs_checking(False) - - if args.eval_only: - model = Trainer.build_model(cfg) - DensePoseCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - if cfg.TEST.AUG.ENABLED: - res.update(Trainer.test_with_TTA(cfg, model)) - if comm.is_main_process(): - verify_results(cfg, res) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - if cfg.TEST.AUG.ENABLED: - trainer.register_hooks( - [hooks.EvalHook(0, lambda: trainer.test_with_TTA(cfg, trainer.model))] - ) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - cfg = setup(args) - timeout = ( - DEFAULT_TIMEOUT - if cfg.DENSEPOSE_EVALUATION.DISTRIBUTED_INFERENCE - else timedelta(hours=4) - ) - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - timeout=timeout, - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/MViTv2/README.md b/preprocess/detectron2/projects/MViTv2/README.md deleted file mode 100644 index 64afd79cac8d83de5518b57199fd618eebe83645..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/README.md +++ /dev/null @@ -1,142 +0,0 @@ -# MViTv2: Improved Multiscale Vision Transformers for Classification and Detection - -Yanghao Li*, Chao-Yuan Wu*, Haoqi Fan, Karttikeya Mangalam, Bo Xiong, Jitendra Malik, Christoph Feichtenhofer* - -[[`arXiv`](https://arxiv.org/abs/2112.01526)] [[`BibTeX`](#CitingMViTv2)] - -In this repository, we provide detection configs and models for MViTv2 (CVPR 2022) in Detectron2. For image classification tasks, please refer to [MViTv2 repo](https://github.com/facebookresearch/mvit). - -## Results and Pretrained Models - -### COCO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namepre-trainMethodepochsbox
AP
mask
AP
#paramsFLOPSmodel iddownload
MViTV2-TIN1KMask R-CNN3648.343.844M279G307611773model
MViTV2-TIN1KCascade Mask R-CNN3652.245.076M701G308344828model
MViTV2-SIN1KCascade Mask R-CNN3653.246.087M748G308344647model
MViTV2-BIN1KCascade Mask R-CNN3654.146.7103M814G308109448model
MViTV2-BIN21KCascade Mask R-CNN3654.947.4103M814G309003202model
MViTV2-LIN21KCascade Mask R-CNN5055.848.3270M1519G308099658model
MViTV2-HIN21KCascade Mask R-CNN3656.148.5718M3084G309013744model
- -Note that the above models were trained and measured on 8-node with 64 NVIDIA A100 GPUs in total. The ImageNet pre-trained model weights are obtained from [MViTv2 repo](https://github.com/facebookresearch/mvit). - -## Training -All configs can be trained with: - -``` -../../tools/lazyconfig_train_net.py --config-file configs/path/to/config.py -``` -By default, we use 64 GPUs with batch size as 64 for training. - -## Evaluation -Model evaluation can be done similarly: -``` -../../tools/lazyconfig_train_net.py --config-file configs/path/to/config.py --eval-only train.init_checkpoint=/path/to/model_checkpoint -``` - - - -## Citing MViTv2 - -If you use MViTv2, please use the following BibTeX entry. - -```BibTeX -@inproceedings{li2021improved, - title={MViTv2: Improved multiscale vision transformers for classification and detection}, - author={Li, Yanghao and Wu, Chao-Yuan and Fan, Haoqi and Mangalam, Karttikeya and Xiong, Bo and Malik, Jitendra and Feichtenhofer, Christoph}, - booktitle={CVPR}, - year={2022} -} -``` diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_3x.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_3x.py deleted file mode 100644 index 61366bf11477136e8950b81dd24a1a7af9b37f8b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_3x.py +++ /dev/null @@ -1,8 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_t_3x import model, dataloader, optimizer, lr_multiplier, train - - -model.backbone.bottom_up.depth = 24 -model.backbone.bottom_up.last_block_indexes = (1, 4, 20, 23) -model.backbone.bottom_up.drop_path_rate = 0.4 - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_B_in1k.pyth" diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_in21k_3x.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_in21k_3x.py deleted file mode 100644 index 7c3bdce0a2206b3afd1a33245a193292f0cd2a35..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_b_in21k_3x.py +++ /dev/null @@ -1,3 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_b_3x import model, dataloader, optimizer, lr_multiplier, train - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_B_in21k.pyth" diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_h_in21k_lsj_3x.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_h_in21k_lsj_3x.py deleted file mode 100644 index 6fee5e99b7d5d611d27dca62a7db7d88808f87da..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_h_in21k_lsj_3x.py +++ /dev/null @@ -1,12 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_b_3x import model, optimizer, train, lr_multiplier -from .common.coco_loader_lsj import dataloader - - -model.backbone.bottom_up.embed_dim = 192 -model.backbone.bottom_up.depth = 80 -model.backbone.bottom_up.num_heads = 3 -model.backbone.bottom_up.last_block_indexes = (3, 11, 71, 79) -model.backbone.bottom_up.drop_path_rate = 0.6 -model.backbone.bottom_up.use_act_checkpoint = True - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_H_in21k.pyth" diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_l_in21k_lsj_50ep.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_l_in21k_lsj_50ep.py deleted file mode 100644 index 38da8958e0174d378555887d72a9956f4b3f8e58..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_l_in21k_lsj_50ep.py +++ /dev/null @@ -1,31 +0,0 @@ -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler - -from .cascade_mask_rcnn_mvitv2_b_3x import model, optimizer, train -from .common.coco_loader_lsj import dataloader - - -model.backbone.bottom_up.embed_dim = 144 -model.backbone.bottom_up.depth = 48 -model.backbone.bottom_up.num_heads = 2 -model.backbone.bottom_up.last_block_indexes = (1, 7, 43, 47) -model.backbone.bottom_up.drop_path_rate = 0.5 - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_L_in21k.pyth" - -# Schedule -# 50ep = 184375 // 2 iters * 64 images/iter / 118000 images/ep -train.max_iter = 184375 // 2 -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[163889 // 2, 177546 // 2], - num_updates=train.max_iter, - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) - -optimizer.lr = 1e-4 diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_s_3x.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_s_3x.py deleted file mode 100644 index ad8eeb4df25476893c5a966a669ecceaec2a6dbc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_s_3x.py +++ /dev/null @@ -1,7 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_t_3x import model, dataloader, optimizer, lr_multiplier, train - - -model.backbone.bottom_up.depth = 16 -model.backbone.bottom_up.last_block_indexes = (0, 2, 13, 15) - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_S_in1k.pyth" diff --git a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_t_3x.py b/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_t_3x.py deleted file mode 100644 index 51327dd9379b011c2d6cdc8299515b6df8112f4e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/cascade_mask_rcnn_mvitv2_t_3x.py +++ /dev/null @@ -1,48 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import FastRCNNOutputLayers, FastRCNNConvFCHead, CascadeROIHeads -from detectron2.layers.batch_norm import NaiveSyncBatchNorm - -from .mask_rcnn_mvitv2_t_3x import model, dataloader, optimizer, lr_multiplier, train - - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm=lambda c: NaiveSyncBatchNorm(c, stats_mode="N"), - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - cls_agnostic_bbox_reg=True, - num_classes="${...num_classes}", - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) - -# Using NaiveSyncBatchNorm becase heads may have empty input. That is not supported by -# torch.nn.SyncBatchNorm. We can remove this after -# https://github.com/pytorch/pytorch/issues/36530 is fixed. -model.roi_heads.mask_head.conv_norm = lambda c: NaiveSyncBatchNorm(c, stats_mode="N") - -# 2conv in RPN: -# https://github.com/tensorflow/tpu/blob/b24729de804fdb751b06467d3dce0637fa652060/models/official/detection/modeling/architecture/heads.py#L95-L97 # noqa: E501, B950 -model.proposal_generator.head.conv_dims = [-1, -1] diff --git a/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader.py b/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader.py deleted file mode 100644 index 923878b8d4cdda9292738550f1c6aa18e38d5757..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader.py +++ /dev/null @@ -1,59 +0,0 @@ -from omegaconf import OmegaConf - -import detectron2.data.transforms as T -from detectron2.config import LazyCall as L -from detectron2.data import ( - DatasetMapper, - build_detection_test_loader, - build_detection_train_loader, - get_detection_dataset_dicts, -) -from detectron2.evaluation import COCOEvaluator - -dataloader = OmegaConf.create() - -dataloader.train = L(build_detection_train_loader)( - dataset=L(get_detection_dataset_dicts)(names="coco_2017_train"), - mapper=L(DatasetMapper)( - is_train=True, - augmentations=[ - L(T.RandomApply)( - tfm_or_aug=L(T.AugmentationList)( - augs=[ - L(T.ResizeShortestEdge)( - short_edge_length=[400, 500, 600], sample_style="choice" - ), - L(T.RandomCrop)(crop_type="absolute_range", crop_size=(384, 600)), - ] - ), - prob=0.5, - ), - L(T.ResizeShortestEdge)( - short_edge_length=(480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800), - sample_style="choice", - max_size=1333, - ), - L(T.RandomFlip)(horizontal=True), - ], - image_format="RGB", - use_instance_mask=True, - ), - total_batch_size=16, - num_workers=4, -) - -dataloader.test = L(build_detection_test_loader)( - dataset=L(get_detection_dataset_dicts)(names="coco_2017_val", filter_empty=False), - mapper=L(DatasetMapper)( - is_train=False, - augmentations=[ - L(T.ResizeShortestEdge)(short_edge_length=800, max_size=1333), - ], - image_format="${...train.mapper.image_format}", - ), - num_workers=4, -) - -dataloader.evaluator = L(COCOEvaluator)( - dataset_name="${..test.dataset.names}", -) diff --git a/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader_lsj.py b/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader_lsj.py deleted file mode 100644 index 019b21fb23299542f757459da12a56df1c538e2b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/common/coco_loader_lsj.py +++ /dev/null @@ -1,19 +0,0 @@ -import detectron2.data.transforms as T -from detectron2 import model_zoo -from detectron2.config import LazyCall as L - -from .coco_loader import dataloader - -# Data using LSJ -image_size = 1024 -dataloader.train.mapper.augmentations = [ - L(T.RandomFlip)(horizontal=True), # flip first - L(T.ResizeScale)( - min_scale=0.1, max_scale=2.0, target_height=image_size, target_width=image_size - ), - L(T.FixedSizeCrop)(crop_size=(image_size, image_size)), -] -dataloader.train.mapper.image_format = "RGB" -dataloader.train.total_batch_size = 64 -# recompute boxes due to cropping -dataloader.train.mapper.recompute_boxes = True diff --git a/preprocess/detectron2/projects/MViTv2/configs/mask_rcnn_mvitv2_t_3x.py b/preprocess/detectron2/projects/MViTv2/configs/mask_rcnn_mvitv2_t_3x.py deleted file mode 100644 index ba4bdfecf2fc996f3e06480a2f02781c71b5aa44..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/MViTv2/configs/mask_rcnn_mvitv2_t_3x.py +++ /dev/null @@ -1,55 +0,0 @@ -from functools import partial -import torch.nn as nn -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2 import model_zoo -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler -from detectron2.modeling import MViT - -from .common.coco_loader import dataloader - -model = model_zoo.get_config("common/models/mask_rcnn_fpn.py").model -constants = model_zoo.get_config("common/data/constants.py").constants -model.pixel_mean = constants.imagenet_rgb256_mean -model.pixel_std = constants.imagenet_rgb256_std -model.input_format = "RGB" -model.backbone.bottom_up = L(MViT)( - embed_dim=96, - depth=10, - num_heads=1, - last_block_indexes=(0, 2, 7, 9), - residual_pooling=True, - drop_path_rate=0.2, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - out_features=("scale2", "scale3", "scale4", "scale5"), -) -model.backbone.in_features = "${.bottom_up.out_features}" - - -# Initialization and trainer settings -train = model_zoo.get_config("common/train.py").train -train.amp.enabled = True -train.ddp.fp16_compression = True -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_T_in1k.pyth" - -dataloader.train.total_batch_size = 64 - -# 36 epochs -train.max_iter = 67500 -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[52500, 62500, 67500], - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) - -optimizer = model_zoo.get_config("common/optim.py").AdamW -optimizer.params.overrides = { - "pos_embed": {"weight_decay": 0.0}, - "rel_pos_h": {"weight_decay": 0.0}, - "rel_pos_w": {"weight_decay": 0.0}, -} -optimizer.lr = 1.6e-4 diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/README.md b/preprocess/detectron2/projects/Panoptic-DeepLab/README.md deleted file mode 100644 index 86b6d42ba059d7da602b95cfdf3fe7d37ea7d4ec..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/README.md +++ /dev/null @@ -1,175 +0,0 @@ -# Panoptic-DeepLab: A Simple, Strong, and Fast Baseline for Bottom-Up Panoptic Segmentation - -Bowen Cheng, Maxwell D. Collins, Yukun Zhu, Ting Liu, Thomas S. Huang, Hartwig Adam, Liang-Chieh Chen - -[[`arXiv`](https://arxiv.org/abs/1911.10194)] [[`BibTeX`](#CitingPanopticDeepLab)] [[`Reference implementation`](https://github.com/bowenc0221/panoptic-deeplab)] - -
- -

- -## Installation -Install Detectron2 following [the instructions](https://detectron2.readthedocs.io/tutorials/install.html). -To use cityscapes, prepare data follow the [tutorial](https://detectron2.readthedocs.io/tutorials/builtin_datasets.html#expected-dataset-structure-for-cityscapes). - -## Training - -To train a model with 8 GPUs run: -```bash -cd /path/to/detectron2/projects/Panoptic-DeepLab -python train_net.py --config-file configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly: -```bash -cd /path/to/detectron2/projects/Panoptic-DeepLab -python train_net.py --config-file configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint -``` - -## Benchmark network speed - -If you want to benchmark the network speed without post-processing, you can run the evaluation script with `MODEL.PANOPTIC_DEEPLAB.BENCHMARK_NETWORK_SPEED True`: -```bash -cd /path/to/detectron2/projects/Panoptic-DeepLab -python train_net.py --config-file configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint MODEL.PANOPTIC_DEEPLAB.BENCHMARK_NETWORK_SPEED True -``` - -## Cityscapes Panoptic Segmentation -Cityscapes models are trained with ImageNet pretraining. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodBackboneOutput
resolution
PQSQRQmIoUAPMemory (M)model iddownload
Panoptic-DeepLabR50-DC51024×2048 58.6 80.9 71.2 75.9 29.8 8668 - model | metrics
Panoptic-DeepLabR52-DC51024×2048 60.3 81.5 72.9 78.2 33.2 9682 30841561 model | metrics
Panoptic-DeepLab (DSConv)R52-DC51024×2048 60.3 81.0 73.2 78.7 32.1 10466 33148034 model | metrics
- -Note: -- [R52](https://dl.fbaipublicfiles.com/detectron2/DeepLab/R-52.pkl): a ResNet-50 with its first 7x7 convolution replaced by 3 3x3 convolutions. This modification has been used in most semantic segmentation papers. We pre-train this backbone on ImageNet using the default recipe of [pytorch examples](https://github.com/pytorch/examples/tree/master/imagenet). -- DC5 means using dilated convolution in `res5`. -- We use a smaller training crop size (512x1024) than the original paper (1025x2049), we find using larger crop size (1024x2048) could further improve PQ by 1.5% but also degrades AP by 3%. -- The implementation with regular Conv2d in ASPP and head is much heavier head than the original paper. -- This implementation does not include optimized post-processing code needed for deployment. Post-processing the network - outputs now takes similar amount of time to the network itself. Please refer to speed in the - original paper for comparison. -- DSConv refers to using DepthwiseSeparableConv2d in ASPP and decoder. The implementation with DSConv is identical to the original paper. - -## COCO Panoptic Segmentation -COCO models are trained with ImageNet pretraining on 16 V100s. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodBackboneOutput
resolution
PQSQRQBox APMask APMemory (M)model iddownload
Panoptic-DeepLab (DSConv)R52-DC5640×640 35.5 77.3 44.7 18.6 19.7 246448865 model | metrics
- -Note: -- [R52](https://dl.fbaipublicfiles.com/detectron2/DeepLab/R-52.pkl): a ResNet-50 with its first 7x7 convolution replaced by 3 3x3 convolutions. This modification has been used in most semantic segmentation papers. We pre-train this backbone on ImageNet using the default recipe of [pytorch examples](https://github.com/pytorch/examples/tree/master/imagenet). -- DC5 means using dilated convolution in `res5`. -- This reproduced number matches the original paper (35.5 vs. 35.1 PQ). -- This implementation does not include optimized post-processing code needed for deployment. Post-processing the network - outputs now takes more time than the network itself. Please refer to speed in the original paper for comparison. -- DSConv refers to using DepthwiseSeparableConv2d in ASPP and decoder. - -## Citing Panoptic-DeepLab - -If you use Panoptic-DeepLab, please use the following BibTeX entry. - -* CVPR 2020 paper: - -``` -@inproceedings{cheng2020panoptic, - title={Panoptic-DeepLab: A Simple, Strong, and Fast Baseline for Bottom-Up Panoptic Segmentation}, - author={Cheng, Bowen and Collins, Maxwell D and Zhu, Yukun and Liu, Ting and Huang, Thomas S and Adam, Hartwig and Chen, Liang-Chieh}, - booktitle={CVPR}, - year={2020} -} -``` - -* ICCV 2019 COCO-Mapillary workshp challenge report: - -``` -@inproceedings{cheng2019panoptic, - title={Panoptic-DeepLab}, - author={Cheng, Bowen and Collins, Maxwell D and Zhu, Yukun and Liu, Ting and Huang, Thomas S and Adam, Hartwig and Chen, Liang-Chieh}, - booktitle={ICCV COCO + Mapillary Joint Recognition Challenge Workshop}, - year={2019} -} -``` diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/COCO-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_200k_bs64_crop_640_640_coco_dsconv.yaml b/preprocess/detectron2/projects/Panoptic-DeepLab/configs/COCO-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_200k_bs64_crop_640_640_coco_dsconv.yaml deleted file mode 100644 index 6944c6fdf3dcaafdc0a740188610fe604cb7d3be..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/COCO-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_200k_bs64_crop_640_640_coco_dsconv.yaml +++ /dev/null @@ -1,42 +0,0 @@ -_BASE_: ../Cityscapes-PanopticSegmentation/Base-PanopticDeepLab-OS16.yaml -MODEL: - WEIGHTS: "detectron2://DeepLab/R-52.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - BACKBONE: - NAME: "build_resnet_deeplab_backbone" - RESNETS: - DEPTH: 50 - NORM: "SyncBN" - RES5_MULTI_GRID: [1, 2, 4] - STEM_TYPE: "deeplab" - STEM_OUT_CHANNELS: 128 - STRIDE_IN_1X1: False - SEM_SEG_HEAD: - NUM_CLASSES: 133 - LOSS_TOP_K: 1.0 - USE_DEPTHWISE_SEPARABLE_CONV: True - PANOPTIC_DEEPLAB: - STUFF_AREA: 4096 - NMS_KERNEL: 41 - SIZE_DIVISIBILITY: 640 - USE_DEPTHWISE_SEPARABLE_CONV: True -DATASETS: - TRAIN: ("coco_2017_train_panoptic",) - TEST: ("coco_2017_val_panoptic",) -SOLVER: - BASE_LR: 0.0005 - MAX_ITER: 200000 - IMS_PER_BATCH: 64 -INPUT: - FORMAT: "RGB" - GAUSSIAN_SIGMA: 8 - MIN_SIZE_TRAIN: !!python/object/apply:eval ["[int(x * 0.1 * 640) for x in range(5, 16)]"] - MIN_SIZE_TRAIN_SAMPLING: "choice" - MIN_SIZE_TEST: 640 - MAX_SIZE_TRAIN: 960 - MAX_SIZE_TEST: 640 - CROP: - ENABLED: True - TYPE: "absolute" - SIZE: (640, 640) diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/Base-PanopticDeepLab-OS16.yaml b/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/Base-PanopticDeepLab-OS16.yaml deleted file mode 100644 index b7379980fdace160f385f0647e95325830b6bfd7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/Base-PanopticDeepLab-OS16.yaml +++ /dev/null @@ -1,65 +0,0 @@ -MODEL: - META_ARCHITECTURE: "PanopticDeepLab" - BACKBONE: - FREEZE_AT: 0 - RESNETS: - OUT_FEATURES: ["res2", "res3", "res5"] - RES5_DILATION: 2 - SEM_SEG_HEAD: - NAME: "PanopticDeepLabSemSegHead" - IN_FEATURES: ["res2", "res3", "res5"] - PROJECT_FEATURES: ["res2", "res3"] - PROJECT_CHANNELS: [32, 64] - ASPP_CHANNELS: 256 - ASPP_DILATIONS: [6, 12, 18] - ASPP_DROPOUT: 0.1 - HEAD_CHANNELS: 256 - CONVS_DIM: 256 - COMMON_STRIDE: 4 - NUM_CLASSES: 19 - LOSS_TYPE: "hard_pixel_mining" - NORM: "SyncBN" - INS_EMBED_HEAD: - NAME: "PanopticDeepLabInsEmbedHead" - IN_FEATURES: ["res2", "res3", "res5"] - PROJECT_FEATURES: ["res2", "res3"] - PROJECT_CHANNELS: [32, 64] - ASPP_CHANNELS: 256 - ASPP_DILATIONS: [6, 12, 18] - ASPP_DROPOUT: 0.1 - HEAD_CHANNELS: 32 - CONVS_DIM: 128 - COMMON_STRIDE: 4 - NORM: "SyncBN" - CENTER_LOSS_WEIGHT: 200.0 - OFFSET_LOSS_WEIGHT: 0.01 - PANOPTIC_DEEPLAB: - STUFF_AREA: 2048 - CENTER_THRESHOLD: 0.1 - NMS_KERNEL: 7 - TOP_K_INSTANCE: 200 -DATASETS: - TRAIN: ("cityscapes_fine_panoptic_train",) - TEST: ("cityscapes_fine_panoptic_val",) -SOLVER: - OPTIMIZER: "ADAM" - BASE_LR: 0.001 - WEIGHT_DECAY: 0.0 - WEIGHT_DECAY_NORM: 0.0 - WEIGHT_DECAY_BIAS: 0.0 - MAX_ITER: 60000 - LR_SCHEDULER_NAME: "WarmupPolyLR" - IMS_PER_BATCH: 32 -INPUT: - MIN_SIZE_TRAIN: (512, 640, 704, 832, 896, 1024, 1152, 1216, 1344, 1408, 1536, 1664, 1728, 1856, 1920, 2048) - MIN_SIZE_TRAIN_SAMPLING: "choice" - MIN_SIZE_TEST: 1024 - MAX_SIZE_TRAIN: 4096 - MAX_SIZE_TEST: 2048 - CROP: - ENABLED: True - TYPE: "absolute" - SIZE: (1024, 2048) -DATALOADER: - NUM_WORKERS: 10 -VERSION: 2 diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024.yaml b/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024.yaml deleted file mode 100644 index fde902bb2a87ccaf2c6fea4e79be4144ca44e239..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: Base-PanopticDeepLab-OS16.yaml -MODEL: - WEIGHTS: "detectron2://DeepLab/R-52.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - BACKBONE: - NAME: "build_resnet_deeplab_backbone" - RESNETS: - DEPTH: 50 - NORM: "SyncBN" - RES5_MULTI_GRID: [1, 2, 4] - STEM_TYPE: "deeplab" - STEM_OUT_CHANNELS: 128 - STRIDE_IN_1X1: False -SOLVER: - MAX_ITER: 90000 -INPUT: - FORMAT: "RGB" - CROP: - SIZE: (512, 1024) diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml b/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml deleted file mode 100644 index 8e314204c9b464993d92d3b4d95e2aa9b287b938..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/configs/Cityscapes-PanopticSegmentation/panoptic_deeplab_R_52_os16_mg124_poly_90k_bs32_crop_512_1024_dsconv.yaml +++ /dev/null @@ -1,24 +0,0 @@ -_BASE_: Base-PanopticDeepLab-OS16.yaml -MODEL: - WEIGHTS: "detectron2://DeepLab/R-52.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - BACKBONE: - NAME: "build_resnet_deeplab_backbone" - RESNETS: - DEPTH: 50 - NORM: "SyncBN" - RES5_MULTI_GRID: [1, 2, 4] - STEM_TYPE: "deeplab" - STEM_OUT_CHANNELS: 128 - STRIDE_IN_1X1: False - PANOPTIC_DEEPLAB: - USE_DEPTHWISE_SEPARABLE_CONV: True - SEM_SEG_HEAD: - USE_DEPTHWISE_SEPARABLE_CONV: True -SOLVER: - MAX_ITER: 90000 -INPUT: - FORMAT: "RGB" - CROP: - SIZE: (512, 1024) diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/__init__.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/__init__.py deleted file mode 100644 index 8d3c980643bbd385594850bfbffa84cd1412c162..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .config import add_panoptic_deeplab_config -from .dataset_mapper import PanopticDeeplabDatasetMapper -from .panoptic_seg import ( - PanopticDeepLab, - INS_EMBED_BRANCHES_REGISTRY, - build_ins_embed_branch, - PanopticDeepLabSemSegHead, - PanopticDeepLabInsEmbedHead, -) diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/config.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/config.py deleted file mode 100644 index 5aa2d280c66dbccc9ff8c3ccf39ccfbfc1eaa430..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/config.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -from detectron2.config import CfgNode as CN -from detectron2.projects.deeplab import add_deeplab_config - - -def add_panoptic_deeplab_config(cfg): - """ - Add config for Panoptic-DeepLab. - """ - # Reuse DeepLab config. - add_deeplab_config(cfg) - # Target generation parameters. - cfg.INPUT.GAUSSIAN_SIGMA = 10 - cfg.INPUT.IGNORE_STUFF_IN_OFFSET = True - cfg.INPUT.SMALL_INSTANCE_AREA = 4096 - cfg.INPUT.SMALL_INSTANCE_WEIGHT = 3 - cfg.INPUT.IGNORE_CROWD_IN_SEMANTIC = False - # Optimizer type. - cfg.SOLVER.OPTIMIZER = "ADAM" - # Panoptic-DeepLab semantic segmentation head. - # We add an extra convolution before predictor. - cfg.MODEL.SEM_SEG_HEAD.HEAD_CHANNELS = 256 - cfg.MODEL.SEM_SEG_HEAD.LOSS_TOP_K = 0.2 - # Panoptic-DeepLab instance segmentation head. - cfg.MODEL.INS_EMBED_HEAD = CN() - cfg.MODEL.INS_EMBED_HEAD.NAME = "PanopticDeepLabInsEmbedHead" - cfg.MODEL.INS_EMBED_HEAD.IN_FEATURES = ["res2", "res3", "res5"] - cfg.MODEL.INS_EMBED_HEAD.PROJECT_FEATURES = ["res2", "res3"] - cfg.MODEL.INS_EMBED_HEAD.PROJECT_CHANNELS = [32, 64] - cfg.MODEL.INS_EMBED_HEAD.ASPP_CHANNELS = 256 - cfg.MODEL.INS_EMBED_HEAD.ASPP_DILATIONS = [6, 12, 18] - cfg.MODEL.INS_EMBED_HEAD.ASPP_DROPOUT = 0.1 - # We add an extra convolution before predictor. - cfg.MODEL.INS_EMBED_HEAD.HEAD_CHANNELS = 32 - cfg.MODEL.INS_EMBED_HEAD.CONVS_DIM = 128 - cfg.MODEL.INS_EMBED_HEAD.COMMON_STRIDE = 4 - cfg.MODEL.INS_EMBED_HEAD.NORM = "SyncBN" - cfg.MODEL.INS_EMBED_HEAD.CENTER_LOSS_WEIGHT = 200.0 - cfg.MODEL.INS_EMBED_HEAD.OFFSET_LOSS_WEIGHT = 0.01 - # Panoptic-DeepLab post-processing setting. - cfg.MODEL.PANOPTIC_DEEPLAB = CN() - # Stuff area limit, ignore stuff region below this number. - cfg.MODEL.PANOPTIC_DEEPLAB.STUFF_AREA = 2048 - cfg.MODEL.PANOPTIC_DEEPLAB.CENTER_THRESHOLD = 0.1 - cfg.MODEL.PANOPTIC_DEEPLAB.NMS_KERNEL = 7 - cfg.MODEL.PANOPTIC_DEEPLAB.TOP_K_INSTANCE = 200 - # If set to False, Panoptic-DeepLab will not evaluate instance segmentation. - cfg.MODEL.PANOPTIC_DEEPLAB.PREDICT_INSTANCES = True - cfg.MODEL.PANOPTIC_DEEPLAB.USE_DEPTHWISE_SEPARABLE_CONV = False - # This is the padding parameter for images with various sizes. ASPP layers - # requires input images to be divisible by the average pooling size and we - # can use `MODEL.PANOPTIC_DEEPLAB.SIZE_DIVISIBILITY` to pad all images to - # a fixed resolution (e.g. 640x640 for COCO) to avoid having a image size - # that is not divisible by ASPP average pooling size. - cfg.MODEL.PANOPTIC_DEEPLAB.SIZE_DIVISIBILITY = -1 - # Only evaluates network speed (ignores post-processing). - cfg.MODEL.PANOPTIC_DEEPLAB.BENCHMARK_NETWORK_SPEED = False diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/dataset_mapper.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/dataset_mapper.py deleted file mode 100644 index 53272c726af810efc248f2428dda7ca7271fcd00..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/dataset_mapper.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import copy -import logging -import numpy as np -from typing import Callable, List, Union -import torch -from panopticapi.utils import rgb2id - -from detectron2.config import configurable -from detectron2.data import MetadataCatalog -from detectron2.data import detection_utils as utils -from detectron2.data import transforms as T - -from .target_generator import PanopticDeepLabTargetGenerator - -__all__ = ["PanopticDeeplabDatasetMapper"] - - -class PanopticDeeplabDatasetMapper: - """ - The callable currently does the following: - - 1. Read the image from "file_name" and label from "pan_seg_file_name" - 2. Applies random scale, crop and flip transforms to image and label - 3. Prepare data to Tensor and generate training targets from label - """ - - @configurable - def __init__( - self, - *, - augmentations: List[Union[T.Augmentation, T.Transform]], - image_format: str, - panoptic_target_generator: Callable, - ): - """ - NOTE: this interface is experimental. - - Args: - augmentations: a list of augmentations or deterministic transforms to apply - image_format: an image format supported by :func:`detection_utils.read_image`. - panoptic_target_generator: a callable that takes "panoptic_seg" and - "segments_info" to generate training targets for the model. - """ - # fmt: off - self.augmentations = T.AugmentationList(augmentations) - self.image_format = image_format - # fmt: on - logger = logging.getLogger(__name__) - logger.info("Augmentations used in training: " + str(augmentations)) - - self.panoptic_target_generator = panoptic_target_generator - - @classmethod - def from_config(cls, cfg): - augs = [ - T.ResizeShortestEdge( - cfg.INPUT.MIN_SIZE_TRAIN, - cfg.INPUT.MAX_SIZE_TRAIN, - cfg.INPUT.MIN_SIZE_TRAIN_SAMPLING, - ) - ] - if cfg.INPUT.CROP.ENABLED: - augs.append(T.RandomCrop(cfg.INPUT.CROP.TYPE, cfg.INPUT.CROP.SIZE)) - augs.append(T.RandomFlip()) - - # Assume always applies to the training set. - dataset_names = cfg.DATASETS.TRAIN - meta = MetadataCatalog.get(dataset_names[0]) - panoptic_target_generator = PanopticDeepLabTargetGenerator( - ignore_label=meta.ignore_label, - thing_ids=list(meta.thing_dataset_id_to_contiguous_id.values()), - sigma=cfg.INPUT.GAUSSIAN_SIGMA, - ignore_stuff_in_offset=cfg.INPUT.IGNORE_STUFF_IN_OFFSET, - small_instance_area=cfg.INPUT.SMALL_INSTANCE_AREA, - small_instance_weight=cfg.INPUT.SMALL_INSTANCE_WEIGHT, - ignore_crowd_in_semantic=cfg.INPUT.IGNORE_CROWD_IN_SEMANTIC, - ) - - ret = { - "augmentations": augs, - "image_format": cfg.INPUT.FORMAT, - "panoptic_target_generator": panoptic_target_generator, - } - return ret - - def __call__(self, dataset_dict): - """ - Args: - dataset_dict (dict): Metadata of one image, in Detectron2 Dataset format. - - Returns: - dict: a format that builtin models in detectron2 accept - """ - dataset_dict = copy.deepcopy(dataset_dict) # it will be modified by code below - # Load image. - image = utils.read_image(dataset_dict["file_name"], format=self.image_format) - utils.check_image_size(dataset_dict, image) - # Panoptic label is encoded in RGB image. - pan_seg_gt = utils.read_image(dataset_dict.pop("pan_seg_file_name"), "RGB") - - # Reuses semantic transform for panoptic labels. - aug_input = T.AugInput(image, sem_seg=pan_seg_gt) - _ = self.augmentations(aug_input) - image, pan_seg_gt = aug_input.image, aug_input.sem_seg - - # Pytorch's dataloader is efficient on torch.Tensor due to shared-memory, - # but not efficient on large generic data structures due to the use of pickle & mp.Queue. - # Therefore it's important to use torch.Tensor. - dataset_dict["image"] = torch.as_tensor(np.ascontiguousarray(image.transpose(2, 0, 1))) - - # Generates training targets for Panoptic-DeepLab. - targets = self.panoptic_target_generator(rgb2id(pan_seg_gt), dataset_dict["segments_info"]) - dataset_dict.update(targets) - - return dataset_dict diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/panoptic_seg.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/panoptic_seg.py deleted file mode 100644 index c12ca74e3b281e74e8893c87d2ba7e2b60931c65..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/panoptic_seg.py +++ /dev/null @@ -1,572 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -from typing import Callable, Dict, List, Union -import fvcore.nn.weight_init as weight_init -import torch -from torch import nn -from torch.nn import functional as F - -from detectron2.config import configurable -from detectron2.data import MetadataCatalog -from detectron2.layers import Conv2d, DepthwiseSeparableConv2d, ShapeSpec, get_norm -from detectron2.modeling import ( - META_ARCH_REGISTRY, - SEM_SEG_HEADS_REGISTRY, - build_backbone, - build_sem_seg_head, -) -from detectron2.modeling.postprocessing import sem_seg_postprocess -from detectron2.projects.deeplab import DeepLabV3PlusHead -from detectron2.projects.deeplab.loss import DeepLabCE -from detectron2.structures import BitMasks, ImageList, Instances -from detectron2.utils.registry import Registry - -from .post_processing import get_panoptic_segmentation - -__all__ = ["PanopticDeepLab", "INS_EMBED_BRANCHES_REGISTRY", "build_ins_embed_branch"] - - -INS_EMBED_BRANCHES_REGISTRY = Registry("INS_EMBED_BRANCHES") -INS_EMBED_BRANCHES_REGISTRY.__doc__ = """ -Registry for instance embedding branches, which make instance embedding -predictions from feature maps. -""" - - -@META_ARCH_REGISTRY.register() -class PanopticDeepLab(nn.Module): - """ - Main class for panoptic segmentation architectures. - """ - - def __init__(self, cfg): - super().__init__() - self.backbone = build_backbone(cfg) - self.sem_seg_head = build_sem_seg_head(cfg, self.backbone.output_shape()) - self.ins_embed_head = build_ins_embed_branch(cfg, self.backbone.output_shape()) - self.register_buffer("pixel_mean", torch.tensor(cfg.MODEL.PIXEL_MEAN).view(-1, 1, 1), False) - self.register_buffer("pixel_std", torch.tensor(cfg.MODEL.PIXEL_STD).view(-1, 1, 1), False) - self.meta = MetadataCatalog.get(cfg.DATASETS.TRAIN[0]) - self.stuff_area = cfg.MODEL.PANOPTIC_DEEPLAB.STUFF_AREA - self.threshold = cfg.MODEL.PANOPTIC_DEEPLAB.CENTER_THRESHOLD - self.nms_kernel = cfg.MODEL.PANOPTIC_DEEPLAB.NMS_KERNEL - self.top_k = cfg.MODEL.PANOPTIC_DEEPLAB.TOP_K_INSTANCE - self.predict_instances = cfg.MODEL.PANOPTIC_DEEPLAB.PREDICT_INSTANCES - self.use_depthwise_separable_conv = cfg.MODEL.PANOPTIC_DEEPLAB.USE_DEPTHWISE_SEPARABLE_CONV - assert ( - cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV - == cfg.MODEL.PANOPTIC_DEEPLAB.USE_DEPTHWISE_SEPARABLE_CONV - ) - self.size_divisibility = cfg.MODEL.PANOPTIC_DEEPLAB.SIZE_DIVISIBILITY - self.benchmark_network_speed = cfg.MODEL.PANOPTIC_DEEPLAB.BENCHMARK_NETWORK_SPEED - - @property - def device(self): - return self.pixel_mean.device - - def forward(self, batched_inputs): - """ - Args: - batched_inputs: a list, batched outputs of :class:`DatasetMapper`. - Each item in the list contains the inputs for one image. - For now, each item in the list is a dict that contains: - * "image": Tensor, image in (C, H, W) format. - * "sem_seg": semantic segmentation ground truth - * "center": center points heatmap ground truth - * "offset": pixel offsets to center points ground truth - * Other information that's included in the original dicts, such as: - "height", "width" (int): the output resolution of the model (may be different - from input resolution), used in inference. - Returns: - list[dict]: - each dict is the results for one image. The dict contains the following keys: - - * "panoptic_seg", "sem_seg": see documentation - :doc:`/tutorials/models` for the standard output format - * "instances": available if ``predict_instances is True``. see documentation - :doc:`/tutorials/models` for the standard output format - """ - images = [x["image"].to(self.device) for x in batched_inputs] - images = [(x - self.pixel_mean) / self.pixel_std for x in images] - # To avoid error in ASPP layer when input has different size. - size_divisibility = ( - self.size_divisibility - if self.size_divisibility > 0 - else self.backbone.size_divisibility - ) - images = ImageList.from_tensors(images, size_divisibility) - - features = self.backbone(images.tensor) - - losses = {} - if "sem_seg" in batched_inputs[0]: - targets = [x["sem_seg"].to(self.device) for x in batched_inputs] - targets = ImageList.from_tensors( - targets, size_divisibility, self.sem_seg_head.ignore_value - ).tensor - if "sem_seg_weights" in batched_inputs[0]: - # The default D2 DatasetMapper may not contain "sem_seg_weights" - # Avoid error in testing when default DatasetMapper is used. - weights = [x["sem_seg_weights"].to(self.device) for x in batched_inputs] - weights = ImageList.from_tensors(weights, size_divisibility).tensor - else: - weights = None - else: - targets = None - weights = None - sem_seg_results, sem_seg_losses = self.sem_seg_head(features, targets, weights) - losses.update(sem_seg_losses) - - if "center" in batched_inputs[0] and "offset" in batched_inputs[0]: - center_targets = [x["center"].to(self.device) for x in batched_inputs] - center_targets = ImageList.from_tensors( - center_targets, size_divisibility - ).tensor.unsqueeze(1) - center_weights = [x["center_weights"].to(self.device) for x in batched_inputs] - center_weights = ImageList.from_tensors(center_weights, size_divisibility).tensor - - offset_targets = [x["offset"].to(self.device) for x in batched_inputs] - offset_targets = ImageList.from_tensors(offset_targets, size_divisibility).tensor - offset_weights = [x["offset_weights"].to(self.device) for x in batched_inputs] - offset_weights = ImageList.from_tensors(offset_weights, size_divisibility).tensor - else: - center_targets = None - center_weights = None - - offset_targets = None - offset_weights = None - - center_results, offset_results, center_losses, offset_losses = self.ins_embed_head( - features, center_targets, center_weights, offset_targets, offset_weights - ) - losses.update(center_losses) - losses.update(offset_losses) - - if self.training: - return losses - - if self.benchmark_network_speed: - return [] - - processed_results = [] - for sem_seg_result, center_result, offset_result, input_per_image, image_size in zip( - sem_seg_results, center_results, offset_results, batched_inputs, images.image_sizes - ): - height = input_per_image.get("height") - width = input_per_image.get("width") - r = sem_seg_postprocess(sem_seg_result, image_size, height, width) - c = sem_seg_postprocess(center_result, image_size, height, width) - o = sem_seg_postprocess(offset_result, image_size, height, width) - # Post-processing to get panoptic segmentation. - panoptic_image, _ = get_panoptic_segmentation( - r.argmax(dim=0, keepdim=True), - c, - o, - thing_ids=self.meta.thing_dataset_id_to_contiguous_id.values(), - label_divisor=self.meta.label_divisor, - stuff_area=self.stuff_area, - void_label=-1, - threshold=self.threshold, - nms_kernel=self.nms_kernel, - top_k=self.top_k, - ) - # For semantic segmentation evaluation. - processed_results.append({"sem_seg": r}) - panoptic_image = panoptic_image.squeeze(0) - semantic_prob = F.softmax(r, dim=0) - # For panoptic segmentation evaluation. - processed_results[-1]["panoptic_seg"] = (panoptic_image, None) - # For instance segmentation evaluation. - if self.predict_instances: - instances = [] - panoptic_image_cpu = panoptic_image.cpu().numpy() - for panoptic_label in np.unique(panoptic_image_cpu): - if panoptic_label == -1: - continue - pred_class = panoptic_label // self.meta.label_divisor - isthing = pred_class in list( - self.meta.thing_dataset_id_to_contiguous_id.values() - ) - # Get instance segmentation results. - if isthing: - instance = Instances((height, width)) - # Evaluation code takes continuous id starting from 0 - instance.pred_classes = torch.tensor( - [pred_class], device=panoptic_image.device - ) - mask = panoptic_image == panoptic_label - instance.pred_masks = mask.unsqueeze(0) - # Average semantic probability - sem_scores = semantic_prob[pred_class, ...] - sem_scores = torch.mean(sem_scores[mask]) - # Center point probability - mask_indices = torch.nonzero(mask).float() - center_y, center_x = ( - torch.mean(mask_indices[:, 0]), - torch.mean(mask_indices[:, 1]), - ) - center_scores = c[0, int(center_y.item()), int(center_x.item())] - # Confidence score is semantic prob * center prob. - instance.scores = torch.tensor( - [sem_scores * center_scores], device=panoptic_image.device - ) - # Get bounding boxes - instance.pred_boxes = BitMasks(instance.pred_masks).get_bounding_boxes() - instances.append(instance) - if len(instances) > 0: - processed_results[-1]["instances"] = Instances.cat(instances) - - return processed_results - - -@SEM_SEG_HEADS_REGISTRY.register() -class PanopticDeepLabSemSegHead(DeepLabV3PlusHead): - """ - A semantic segmentation head described in :paper:`Panoptic-DeepLab`. - """ - - @configurable - def __init__( - self, - input_shape: Dict[str, ShapeSpec], - *, - decoder_channels: List[int], - norm: Union[str, Callable], - head_channels: int, - loss_weight: float, - loss_type: str, - loss_top_k: float, - ignore_value: int, - num_classes: int, - **kwargs, - ): - """ - NOTE: this interface is experimental. - - Args: - input_shape (ShapeSpec): shape of the input feature - decoder_channels (list[int]): a list of output channels of each - decoder stage. It should have the same length as "input_shape" - (each element in "input_shape" corresponds to one decoder stage). - norm (str or callable): normalization for all conv layers. - head_channels (int): the output channels of extra convolutions - between decoder and predictor. - loss_weight (float): loss weight. - loss_top_k: (float): setting the top k% hardest pixels for - "hard_pixel_mining" loss. - loss_type, ignore_value, num_classes: the same as the base class. - """ - super().__init__( - input_shape, - decoder_channels=decoder_channels, - norm=norm, - ignore_value=ignore_value, - **kwargs, - ) - assert self.decoder_only - - self.loss_weight = loss_weight - use_bias = norm == "" - # `head` is additional transform before predictor - if self.use_depthwise_separable_conv: - # We use a single 5x5 DepthwiseSeparableConv2d to replace - # 2 3x3 Conv2d since they have the same receptive field. - self.head = DepthwiseSeparableConv2d( - decoder_channels[0], - head_channels, - kernel_size=5, - padding=2, - norm1=norm, - activation1=F.relu, - norm2=norm, - activation2=F.relu, - ) - else: - self.head = nn.Sequential( - Conv2d( - decoder_channels[0], - decoder_channels[0], - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, decoder_channels[0]), - activation=F.relu, - ), - Conv2d( - decoder_channels[0], - head_channels, - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, head_channels), - activation=F.relu, - ), - ) - weight_init.c2_xavier_fill(self.head[0]) - weight_init.c2_xavier_fill(self.head[1]) - self.predictor = Conv2d(head_channels, num_classes, kernel_size=1) - nn.init.normal_(self.predictor.weight, 0, 0.001) - nn.init.constant_(self.predictor.bias, 0) - - if loss_type == "cross_entropy": - self.loss = nn.CrossEntropyLoss(reduction="mean", ignore_index=ignore_value) - elif loss_type == "hard_pixel_mining": - self.loss = DeepLabCE(ignore_label=ignore_value, top_k_percent_pixels=loss_top_k) - else: - raise ValueError("Unexpected loss type: %s" % loss_type) - - @classmethod - def from_config(cls, cfg, input_shape): - ret = super().from_config(cfg, input_shape) - ret["head_channels"] = cfg.MODEL.SEM_SEG_HEAD.HEAD_CHANNELS - ret["loss_top_k"] = cfg.MODEL.SEM_SEG_HEAD.LOSS_TOP_K - return ret - - def forward(self, features, targets=None, weights=None): - """ - Returns: - In training, returns (None, dict of losses) - In inference, returns (CxHxW logits, {}) - """ - y = self.layers(features) - if self.training: - return None, self.losses(y, targets, weights) - else: - y = F.interpolate( - y, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - return y, {} - - def layers(self, features): - assert self.decoder_only - y = super().layers(features) - y = self.head(y) - y = self.predictor(y) - return y - - def losses(self, predictions, targets, weights=None): - predictions = F.interpolate( - predictions, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - loss = self.loss(predictions, targets, weights) - losses = {"loss_sem_seg": loss * self.loss_weight} - return losses - - -def build_ins_embed_branch(cfg, input_shape): - """ - Build a instance embedding branch from `cfg.MODEL.INS_EMBED_HEAD.NAME`. - """ - name = cfg.MODEL.INS_EMBED_HEAD.NAME - return INS_EMBED_BRANCHES_REGISTRY.get(name)(cfg, input_shape) - - -@INS_EMBED_BRANCHES_REGISTRY.register() -class PanopticDeepLabInsEmbedHead(DeepLabV3PlusHead): - """ - A instance embedding head described in :paper:`Panoptic-DeepLab`. - """ - - @configurable - def __init__( - self, - input_shape: Dict[str, ShapeSpec], - *, - decoder_channels: List[int], - norm: Union[str, Callable], - head_channels: int, - center_loss_weight: float, - offset_loss_weight: float, - **kwargs, - ): - """ - NOTE: this interface is experimental. - - Args: - input_shape (ShapeSpec): shape of the input feature - decoder_channels (list[int]): a list of output channels of each - decoder stage. It should have the same length as "input_shape" - (each element in "input_shape" corresponds to one decoder stage). - norm (str or callable): normalization for all conv layers. - head_channels (int): the output channels of extra convolutions - between decoder and predictor. - center_loss_weight (float): loss weight for center point prediction. - offset_loss_weight (float): loss weight for center offset prediction. - """ - super().__init__(input_shape, decoder_channels=decoder_channels, norm=norm, **kwargs) - assert self.decoder_only - - self.center_loss_weight = center_loss_weight - self.offset_loss_weight = offset_loss_weight - use_bias = norm == "" - # center prediction - # `head` is additional transform before predictor - self.center_head = nn.Sequential( - Conv2d( - decoder_channels[0], - decoder_channels[0], - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, decoder_channels[0]), - activation=F.relu, - ), - Conv2d( - decoder_channels[0], - head_channels, - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, head_channels), - activation=F.relu, - ), - ) - weight_init.c2_xavier_fill(self.center_head[0]) - weight_init.c2_xavier_fill(self.center_head[1]) - self.center_predictor = Conv2d(head_channels, 1, kernel_size=1) - nn.init.normal_(self.center_predictor.weight, 0, 0.001) - nn.init.constant_(self.center_predictor.bias, 0) - - # offset prediction - # `head` is additional transform before predictor - if self.use_depthwise_separable_conv: - # We use a single 5x5 DepthwiseSeparableConv2d to replace - # 2 3x3 Conv2d since they have the same receptive field. - self.offset_head = DepthwiseSeparableConv2d( - decoder_channels[0], - head_channels, - kernel_size=5, - padding=2, - norm1=norm, - activation1=F.relu, - norm2=norm, - activation2=F.relu, - ) - else: - self.offset_head = nn.Sequential( - Conv2d( - decoder_channels[0], - decoder_channels[0], - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, decoder_channels[0]), - activation=F.relu, - ), - Conv2d( - decoder_channels[0], - head_channels, - kernel_size=3, - padding=1, - bias=use_bias, - norm=get_norm(norm, head_channels), - activation=F.relu, - ), - ) - weight_init.c2_xavier_fill(self.offset_head[0]) - weight_init.c2_xavier_fill(self.offset_head[1]) - self.offset_predictor = Conv2d(head_channels, 2, kernel_size=1) - nn.init.normal_(self.offset_predictor.weight, 0, 0.001) - nn.init.constant_(self.offset_predictor.bias, 0) - - self.center_loss = nn.MSELoss(reduction="none") - self.offset_loss = nn.L1Loss(reduction="none") - - @classmethod - def from_config(cls, cfg, input_shape): - if cfg.INPUT.CROP.ENABLED: - assert cfg.INPUT.CROP.TYPE == "absolute" - train_size = cfg.INPUT.CROP.SIZE - else: - train_size = None - decoder_channels = [cfg.MODEL.INS_EMBED_HEAD.CONVS_DIM] * ( - len(cfg.MODEL.INS_EMBED_HEAD.IN_FEATURES) - 1 - ) + [cfg.MODEL.INS_EMBED_HEAD.ASPP_CHANNELS] - ret = dict( - input_shape={ - k: v for k, v in input_shape.items() if k in cfg.MODEL.INS_EMBED_HEAD.IN_FEATURES - }, - project_channels=cfg.MODEL.INS_EMBED_HEAD.PROJECT_CHANNELS, - aspp_dilations=cfg.MODEL.INS_EMBED_HEAD.ASPP_DILATIONS, - aspp_dropout=cfg.MODEL.INS_EMBED_HEAD.ASPP_DROPOUT, - decoder_channels=decoder_channels, - common_stride=cfg.MODEL.INS_EMBED_HEAD.COMMON_STRIDE, - norm=cfg.MODEL.INS_EMBED_HEAD.NORM, - train_size=train_size, - head_channels=cfg.MODEL.INS_EMBED_HEAD.HEAD_CHANNELS, - center_loss_weight=cfg.MODEL.INS_EMBED_HEAD.CENTER_LOSS_WEIGHT, - offset_loss_weight=cfg.MODEL.INS_EMBED_HEAD.OFFSET_LOSS_WEIGHT, - use_depthwise_separable_conv=cfg.MODEL.SEM_SEG_HEAD.USE_DEPTHWISE_SEPARABLE_CONV, - ) - return ret - - def forward( - self, - features, - center_targets=None, - center_weights=None, - offset_targets=None, - offset_weights=None, - ): - """ - Returns: - In training, returns (None, dict of losses) - In inference, returns (CxHxW logits, {}) - """ - center, offset = self.layers(features) - if self.training: - return ( - None, - None, - self.center_losses(center, center_targets, center_weights), - self.offset_losses(offset, offset_targets, offset_weights), - ) - else: - center = F.interpolate( - center, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - offset = ( - F.interpolate( - offset, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - * self.common_stride - ) - return center, offset, {}, {} - - def layers(self, features): - assert self.decoder_only - y = super().layers(features) - # center - center = self.center_head(y) - center = self.center_predictor(center) - # offset - offset = self.offset_head(y) - offset = self.offset_predictor(offset) - return center, offset - - def center_losses(self, predictions, targets, weights): - predictions = F.interpolate( - predictions, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - loss = self.center_loss(predictions, targets) * weights - if weights.sum() > 0: - loss = loss.sum() / weights.sum() - else: - loss = loss.sum() * 0 - losses = {"loss_center": loss * self.center_loss_weight} - return losses - - def offset_losses(self, predictions, targets, weights): - predictions = ( - F.interpolate( - predictions, scale_factor=self.common_stride, mode="bilinear", align_corners=False - ) - * self.common_stride - ) - loss = self.offset_loss(predictions, targets) * weights - if weights.sum() > 0: - loss = loss.sum() / weights.sum() - else: - loss = loss.sum() * 0 - losses = {"loss_offset": loss * self.offset_loss_weight} - return losses diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/post_processing.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/post_processing.py deleted file mode 100644 index 194724eb414db073bde87bf482e5c647fa23cde7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/post_processing.py +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# Reference: https://github.com/bowenc0221/panoptic-deeplab/blob/master/segmentation/model/post_processing/instance_post_processing.py # noqa - -from collections import Counter -import torch -import torch.nn.functional as F - - -def find_instance_center(center_heatmap, threshold=0.1, nms_kernel=3, top_k=None): - """ - Find the center points from the center heatmap. - Args: - center_heatmap: A Tensor of shape [1, H, W] of raw center heatmap output. - threshold: A float, threshold applied to center heatmap score. - nms_kernel: An integer, NMS max pooling kernel size. - top_k: An integer, top k centers to keep. - Returns: - A Tensor of shape [K, 2] where K is the number of center points. The - order of second dim is (y, x). - """ - # Thresholding, setting values below threshold to -1. - center_heatmap = F.threshold(center_heatmap, threshold, -1) - - # NMS - nms_padding = (nms_kernel - 1) // 2 - center_heatmap_max_pooled = F.max_pool2d( - center_heatmap, kernel_size=nms_kernel, stride=1, padding=nms_padding - ) - center_heatmap[center_heatmap != center_heatmap_max_pooled] = -1 - - # Squeeze first two dimensions. - center_heatmap = center_heatmap.squeeze() - assert len(center_heatmap.size()) == 2, "Something is wrong with center heatmap dimension." - - # Find non-zero elements. - if top_k is None: - return torch.nonzero(center_heatmap > 0) - else: - # find top k centers. - top_k_scores, _ = torch.topk(torch.flatten(center_heatmap), top_k) - return torch.nonzero(center_heatmap > top_k_scores[-1].clamp_(min=0)) - - -def group_pixels(center_points, offsets): - """ - Gives each pixel in the image an instance id. - Args: - center_points: A Tensor of shape [K, 2] where K is the number of center points. - The order of second dim is (y, x). - offsets: A Tensor of shape [2, H, W] of raw offset output. The order of - second dim is (offset_y, offset_x). - Returns: - A Tensor of shape [1, H, W] with values in range [1, K], which represents - the center this pixel belongs to. - """ - height, width = offsets.size()[1:] - - # Generates a coordinate map, where each location is the coordinate of - # that location. - y_coord, x_coord = torch.meshgrid( - torch.arange(height, dtype=offsets.dtype, device=offsets.device), - torch.arange(width, dtype=offsets.dtype, device=offsets.device), - ) - coord = torch.cat((y_coord.unsqueeze(0), x_coord.unsqueeze(0)), dim=0) - - center_loc = coord + offsets - center_loc = center_loc.flatten(1).T.unsqueeze_(0) # [1, H*W, 2] - center_points = center_points.unsqueeze(1) # [K, 1, 2] - - # Distance: [K, H*W]. - distance = torch.norm(center_points - center_loc, dim=-1) - - # Finds center with minimum distance at each location, offset by 1, to - # reserve id=0 for stuff. - instance_id = torch.argmin(distance, dim=0).reshape((1, height, width)) + 1 - return instance_id - - -def get_instance_segmentation( - sem_seg, center_heatmap, offsets, thing_seg, thing_ids, threshold=0.1, nms_kernel=3, top_k=None -): - """ - Post-processing for instance segmentation, gets class agnostic instance id. - Args: - sem_seg: A Tensor of shape [1, H, W], predicted semantic label. - center_heatmap: A Tensor of shape [1, H, W] of raw center heatmap output. - offsets: A Tensor of shape [2, H, W] of raw offset output. The order of - second dim is (offset_y, offset_x). - thing_seg: A Tensor of shape [1, H, W], predicted foreground mask, - if not provided, inference from semantic prediction. - thing_ids: A set of ids from contiguous category ids belonging - to thing categories. - threshold: A float, threshold applied to center heatmap score. - nms_kernel: An integer, NMS max pooling kernel size. - top_k: An integer, top k centers to keep. - Returns: - A Tensor of shape [1, H, W] with value 0 represent stuff (not instance) - and other positive values represent different instances. - A Tensor of shape [1, K, 2] where K is the number of center points. - The order of second dim is (y, x). - """ - center_points = find_instance_center( - center_heatmap, threshold=threshold, nms_kernel=nms_kernel, top_k=top_k - ) - if center_points.size(0) == 0: - return torch.zeros_like(sem_seg), center_points.unsqueeze(0) - ins_seg = group_pixels(center_points, offsets) - return thing_seg * ins_seg, center_points.unsqueeze(0) - - -def merge_semantic_and_instance( - sem_seg, ins_seg, semantic_thing_seg, label_divisor, thing_ids, stuff_area, void_label -): - """ - Post-processing for panoptic segmentation, by merging semantic segmentation - label and class agnostic instance segmentation label. - Args: - sem_seg: A Tensor of shape [1, H, W], predicted category id for each pixel. - ins_seg: A Tensor of shape [1, H, W], predicted instance id for each pixel. - semantic_thing_seg: A Tensor of shape [1, H, W], predicted foreground mask. - label_divisor: An integer, used to convert panoptic id = - semantic id * label_divisor + instance_id. - thing_ids: Set, a set of ids from contiguous category ids belonging - to thing categories. - stuff_area: An integer, remove stuff whose area is less tan stuff_area. - void_label: An integer, indicates the region has no confident prediction. - Returns: - A Tensor of shape [1, H, W]. - """ - # In case thing mask does not align with semantic prediction. - pan_seg = torch.zeros_like(sem_seg) + void_label - is_thing = (ins_seg > 0) & (semantic_thing_seg > 0) - - # Keep track of instance id for each class. - class_id_tracker = Counter() - - # Paste thing by majority voting. - instance_ids = torch.unique(ins_seg) - for ins_id in instance_ids: - if ins_id == 0: - continue - # Make sure only do majority voting within `semantic_thing_seg`. - thing_mask = (ins_seg == ins_id) & is_thing - if torch.nonzero(thing_mask).size(0) == 0: - continue - class_id, _ = torch.mode(sem_seg[thing_mask].view(-1)) - class_id_tracker[class_id.item()] += 1 - new_ins_id = class_id_tracker[class_id.item()] - pan_seg[thing_mask] = class_id * label_divisor + new_ins_id - - # Paste stuff to unoccupied area. - class_ids = torch.unique(sem_seg) - for class_id in class_ids: - if class_id.item() in thing_ids: - # thing class - continue - # Calculate stuff area. - stuff_mask = (sem_seg == class_id) & (ins_seg == 0) - if stuff_mask.sum().item() >= stuff_area: - pan_seg[stuff_mask] = class_id * label_divisor - - return pan_seg - - -def get_panoptic_segmentation( - sem_seg, - center_heatmap, - offsets, - thing_ids, - label_divisor, - stuff_area, - void_label, - threshold=0.1, - nms_kernel=7, - top_k=200, - foreground_mask=None, -): - """ - Post-processing for panoptic segmentation. - Args: - sem_seg: A Tensor of shape [1, H, W] of predicted semantic label. - center_heatmap: A Tensor of shape [1, H, W] of raw center heatmap output. - offsets: A Tensor of shape [2, H, W] of raw offset output. The order of - second dim is (offset_y, offset_x). - thing_ids: A set of ids from contiguous category ids belonging - to thing categories. - label_divisor: An integer, used to convert panoptic id = - semantic id * label_divisor + instance_id. - stuff_area: An integer, remove stuff whose area is less tan stuff_area. - void_label: An integer, indicates the region has no confident prediction. - threshold: A float, threshold applied to center heatmap score. - nms_kernel: An integer, NMS max pooling kernel size. - top_k: An integer, top k centers to keep. - foreground_mask: Optional, A Tensor of shape [1, H, W] of predicted - binary foreground mask. If not provided, it will be generated from - sem_seg. - Returns: - A Tensor of shape [1, H, W], int64. - """ - if sem_seg.dim() != 3 and sem_seg.size(0) != 1: - raise ValueError("Semantic prediction with un-supported shape: {}.".format(sem_seg.size())) - if center_heatmap.dim() != 3: - raise ValueError( - "Center prediction with un-supported dimension: {}.".format(center_heatmap.dim()) - ) - if offsets.dim() != 3: - raise ValueError("Offset prediction with un-supported dimension: {}.".format(offsets.dim())) - if foreground_mask is not None: - if foreground_mask.dim() != 3 and foreground_mask.size(0) != 1: - raise ValueError( - "Foreground prediction with un-supported shape: {}.".format(sem_seg.size()) - ) - thing_seg = foreground_mask - else: - # inference from semantic segmentation - thing_seg = torch.zeros_like(sem_seg) - for thing_class in list(thing_ids): - thing_seg[sem_seg == thing_class] = 1 - - instance, center = get_instance_segmentation( - sem_seg, - center_heatmap, - offsets, - thing_seg, - thing_ids, - threshold=threshold, - nms_kernel=nms_kernel, - top_k=top_k, - ) - panoptic = merge_semantic_and_instance( - sem_seg, instance, thing_seg, label_divisor, thing_ids, stuff_area, void_label - ) - - return panoptic, center diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/target_generator.py b/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/target_generator.py deleted file mode 100644 index 318afcc22c0af30481cfbe4e712665bf476d32d5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/panoptic_deeplab/target_generator.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# Reference: https://github.com/bowenc0221/panoptic-deeplab/blob/aa934324b55a34ce95fea143aea1cb7a6dbe04bd/segmentation/data/transforms/target_transforms.py#L11 # noqa -import numpy as np -import torch - - -class PanopticDeepLabTargetGenerator: - """ - Generates training targets for Panoptic-DeepLab. - """ - - def __init__( - self, - ignore_label, - thing_ids, - sigma=8, - ignore_stuff_in_offset=False, - small_instance_area=0, - small_instance_weight=1, - ignore_crowd_in_semantic=False, - ): - """ - Args: - ignore_label: Integer, the ignore label for semantic segmentation. - thing_ids: Set, a set of ids from contiguous category ids belonging - to thing categories. - sigma: the sigma for Gaussian kernel. - ignore_stuff_in_offset: Boolean, whether to ignore stuff region when - training the offset branch. - small_instance_area: Integer, indicates largest area for small instances. - small_instance_weight: Integer, indicates semantic loss weights for - small instances. - ignore_crowd_in_semantic: Boolean, whether to ignore crowd region in - semantic segmentation branch, crowd region is ignored in the original - TensorFlow implementation. - """ - self.ignore_label = ignore_label - self.thing_ids = set(thing_ids) - self.ignore_stuff_in_offset = ignore_stuff_in_offset - self.small_instance_area = small_instance_area - self.small_instance_weight = small_instance_weight - self.ignore_crowd_in_semantic = ignore_crowd_in_semantic - - # Generate the default Gaussian image for each center - self.sigma = sigma - size = 6 * sigma + 3 - x = np.arange(0, size, 1, float) - y = x[:, np.newaxis] - x0, y0 = 3 * sigma + 1, 3 * sigma + 1 - self.g = np.exp(-((x - x0) ** 2 + (y - y0) ** 2) / (2 * sigma**2)) - - def __call__(self, panoptic, segments_info): - """Generates the training target. - reference: https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/preparation/createPanopticImgs.py # noqa - reference: https://github.com/facebookresearch/detectron2/blob/main/datasets/prepare_panoptic_fpn.py#L18 # noqa - - Args: - panoptic: numpy.array, panoptic label, we assume it is already - converted from rgb image by panopticapi.utils.rgb2id. - segments_info (list[dict]): see detectron2 documentation of "Use Custom Datasets". - - Returns: - A dictionary with fields: - - sem_seg: Tensor, semantic label, shape=(H, W). - - center: Tensor, center heatmap, shape=(H, W). - - center_points: List, center coordinates, with tuple - (y-coord, x-coord). - - offset: Tensor, offset, shape=(2, H, W), first dim is - (offset_y, offset_x). - - sem_seg_weights: Tensor, loss weight for semantic prediction, - shape=(H, W). - - center_weights: Tensor, ignore region of center prediction, - shape=(H, W), used as weights for center regression 0 is - ignore, 1 is has instance. Multiply this mask to loss. - - offset_weights: Tensor, ignore region of offset prediction, - shape=(H, W), used as weights for offset regression 0 is - ignore, 1 is has instance. Multiply this mask to loss. - """ - height, width = panoptic.shape[0], panoptic.shape[1] - semantic = np.zeros_like(panoptic, dtype=np.uint8) + self.ignore_label - center = np.zeros((height, width), dtype=np.float32) - center_pts = [] - offset = np.zeros((2, height, width), dtype=np.float32) - y_coord, x_coord = np.meshgrid( - np.arange(height, dtype=np.float32), np.arange(width, dtype=np.float32), indexing="ij" - ) - # Generate pixel-wise loss weights - semantic_weights = np.ones_like(panoptic, dtype=np.uint8) - # 0: ignore, 1: has instance - # three conditions for a region to be ignored for instance branches: - # (1) It is labeled as `ignore_label` - # (2) It is crowd region (iscrowd=1) - # (3) (Optional) It is stuff region (for offset branch) - center_weights = np.zeros_like(panoptic, dtype=np.uint8) - offset_weights = np.zeros_like(panoptic, dtype=np.uint8) - for seg in segments_info: - cat_id = seg["category_id"] - if not (self.ignore_crowd_in_semantic and seg["iscrowd"]): - semantic[panoptic == seg["id"]] = cat_id - if not seg["iscrowd"]: - # Ignored regions are not in `segments_info`. - # Handle crowd region. - center_weights[panoptic == seg["id"]] = 1 - if not self.ignore_stuff_in_offset or cat_id in self.thing_ids: - offset_weights[panoptic == seg["id"]] = 1 - if cat_id in self.thing_ids: - # find instance center - mask_index = np.where(panoptic == seg["id"]) - if len(mask_index[0]) == 0: - # the instance is completely cropped - continue - - # Find instance area - ins_area = len(mask_index[0]) - if ins_area < self.small_instance_area: - semantic_weights[panoptic == seg["id"]] = self.small_instance_weight - - center_y, center_x = np.mean(mask_index[0]), np.mean(mask_index[1]) - center_pts.append([center_y, center_x]) - - # generate center heatmap - y, x = int(round(center_y)), int(round(center_x)) - sigma = self.sigma - # upper left - ul = int(np.round(x - 3 * sigma - 1)), int(np.round(y - 3 * sigma - 1)) - # bottom right - br = int(np.round(x + 3 * sigma + 2)), int(np.round(y + 3 * sigma + 2)) - - # start and end indices in default Gaussian image - gaussian_x0, gaussian_x1 = max(0, -ul[0]), min(br[0], width) - ul[0] - gaussian_y0, gaussian_y1 = max(0, -ul[1]), min(br[1], height) - ul[1] - - # start and end indices in center heatmap image - center_x0, center_x1 = max(0, ul[0]), min(br[0], width) - center_y0, center_y1 = max(0, ul[1]), min(br[1], height) - center[center_y0:center_y1, center_x0:center_x1] = np.maximum( - center[center_y0:center_y1, center_x0:center_x1], - self.g[gaussian_y0:gaussian_y1, gaussian_x0:gaussian_x1], - ) - - # generate offset (2, h, w) -> (y-dir, x-dir) - offset[0][mask_index] = center_y - y_coord[mask_index] - offset[1][mask_index] = center_x - x_coord[mask_index] - - center_weights = center_weights[None] - offset_weights = offset_weights[None] - return dict( - sem_seg=torch.as_tensor(semantic.astype("long")), - center=torch.as_tensor(center.astype(np.float32)), - center_points=center_pts, - offset=torch.as_tensor(offset.astype(np.float32)), - sem_seg_weights=torch.as_tensor(semantic_weights.astype(np.float32)), - center_weights=torch.as_tensor(center_weights.astype(np.float32)), - offset_weights=torch.as_tensor(offset_weights.astype(np.float32)), - ) diff --git a/preprocess/detectron2/projects/Panoptic-DeepLab/train_net.py b/preprocess/detectron2/projects/Panoptic-DeepLab/train_net.py deleted file mode 100644 index 0a25e6032326b36d9bfb366467ecf5683568205a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Panoptic-DeepLab/train_net.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -Panoptic-DeepLab Training Script. -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -import detectron2.data.transforms as T -import torch -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_train_loader, MetadataCatalog -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import ( - CityscapesInstanceEvaluator, - CityscapesSemSegEvaluator, - COCOEvaluator, - COCOPanopticEvaluator, - DatasetEvaluators, -) -from detectron2.projects.deeplab import build_lr_scheduler -from detectron2.projects.panoptic_deeplab import ( - add_panoptic_deeplab_config, - PanopticDeeplabDatasetMapper, -) -from detectron2.solver import get_default_optimizer_params -from detectron2.solver.build import maybe_add_gradient_clipping - - -def build_sem_seg_train_aug(cfg): - augs = [ - T.ResizeShortestEdge( - cfg.INPUT.MIN_SIZE_TRAIN, - cfg.INPUT.MAX_SIZE_TRAIN, - cfg.INPUT.MIN_SIZE_TRAIN_SAMPLING, - ) - ] - if cfg.INPUT.CROP.ENABLED: - augs.append(T.RandomCrop(cfg.INPUT.CROP.TYPE, cfg.INPUT.CROP.SIZE)) - augs.append(T.RandomFlip()) - return augs - - -class Trainer(DefaultTrainer): - """ - We use the "DefaultTrainer" which contains a number pre-defined logic for - standard training workflow. They may not work for you, especially if you - are working on a new research project. In that case you can use the cleaner - "SimpleTrainer", or write your own training loop. - """ - - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if cfg.MODEL.PANOPTIC_DEEPLAB.BENCHMARK_NETWORK_SPEED: - return None - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type in ["cityscapes_panoptic_seg", "coco_panoptic_seg"]: - evaluator_list.append(COCOPanopticEvaluator(dataset_name, output_folder)) - if evaluator_type == "cityscapes_panoptic_seg": - evaluator_list.append(CityscapesSemSegEvaluator(dataset_name)) - evaluator_list.append(CityscapesInstanceEvaluator(dataset_name)) - if evaluator_type == "coco_panoptic_seg": - # `thing_classes` in COCO panoptic metadata includes both thing and - # stuff classes for visualization. COCOEvaluator requires metadata - # which only contains thing classes, thus we map the name of - # panoptic datasets to their corresponding instance datasets. - dataset_name_mapper = { - "coco_2017_val_panoptic": "coco_2017_val", - "coco_2017_val_100_panoptic": "coco_2017_val_100", - } - evaluator_list.append( - COCOEvaluator( - dataset_name_mapper[dataset_name], output_dir=output_folder - ) - ) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - elif len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - @classmethod - def build_train_loader(cls, cfg): - mapper = PanopticDeeplabDatasetMapper( - cfg, augmentations=build_sem_seg_train_aug(cfg) - ) - return build_detection_train_loader(cfg, mapper=mapper) - - @classmethod - def build_lr_scheduler(cls, cfg, optimizer): - """ - It now calls :func:`detectron2.solver.build_lr_scheduler`. - Overwrite it if you'd like a different scheduler. - """ - return build_lr_scheduler(cfg, optimizer) - - @classmethod - def build_optimizer(cls, cfg, model): - """ - Build an optimizer from config. - """ - params = get_default_optimizer_params( - model, - weight_decay=cfg.SOLVER.WEIGHT_DECAY, - weight_decay_norm=cfg.SOLVER.WEIGHT_DECAY_NORM, - ) - - optimizer_type = cfg.SOLVER.OPTIMIZER - if optimizer_type == "SGD": - return maybe_add_gradient_clipping(cfg, torch.optim.SGD)( - params, - cfg.SOLVER.BASE_LR, - momentum=cfg.SOLVER.MOMENTUM, - nesterov=cfg.SOLVER.NESTEROV, - ) - elif optimizer_type == "ADAM": - return maybe_add_gradient_clipping(cfg, torch.optim.Adam)( - params, cfg.SOLVER.BASE_LR - ) - else: - raise NotImplementedError(f"no optimizer type {optimizer_type}") - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_panoptic_deeplab_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/PointRend/README.md b/preprocess/detectron2/projects/PointRend/README.md deleted file mode 100644 index 79d75d506c6f5db710044d3c1cd2583027ac3dbe..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/README.md +++ /dev/null @@ -1,167 +0,0 @@ -# PointRend: Image Segmentation as Rendering - -Alexander Kirillov, Yuxin Wu, Kaiming He, Ross Girshick - -[[`arXiv`](https://arxiv.org/abs/1912.08193)] [[`BibTeX`](#CitingPointRend)] - -
- -

- -In this repository, we release code for PointRend in Detectron2. PointRend can be flexibly applied to both instance and semantic segmentation tasks by building on top of existing state-of-the-art models. - -## Quick start and visualization - -This [Colab Notebook](https://colab.research.google.com/drive/1isGPL5h5_cKoPPhVL9XhMokRtHDvmMVL) tutorial contains examples of PointRend usage and visualizations of its point sampling stages. - -## Training - -To train a model with 8 GPUs run: -```bash -cd /path/to/detectron2/projects/PointRend -python train_net.py --config-file configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly: -```bash -cd /path/to/detectron2/projects/PointRend -python train_net.py --config-file configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint -``` - -# Pretrained Models - -## Instance Segmentation -#### COCO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Mask
head
Backbonelr
sched
Output
resolution
mask
AP
mask
AP*
model iddownload
PointRendR50-FPN224×22436.239.7164254221model | metrics
PointRendR50-FPN224×22438.341.6164955410model | metrics
PointRendR101-FPN224×22440.143.8model | metrics
PointRendX101-FPN224×22441.144.7model | metrics
- -AP* is COCO mask AP evaluated against the higher-quality LVIS annotations; see the paper for details. -Run `python detectron2/datasets/prepare_cocofied_lvis.py` to prepare GT files for AP* evaluation. -Since LVIS annotations are not exhaustive, `lvis-api` and not `cocoapi` should be used to evaluate AP*. - -#### Cityscapes -Cityscapes model is trained with ImageNet pretraining. - - - - - - - - - - - - - - - - - - - - -
Mask
head
Backbonelr
sched
Output
resolution
mask
AP
model iddownload
PointRendR50-FPN224×22435.9164255101model | metrics
- - -## Semantic Segmentation - -#### Cityscapes -Cityscapes model is trained with ImageNet pretraining. - - - - - - - - - - - - - - - - - - -
MethodBackboneOutput
resolution
mIoUmodel iddownload
SemanticFPN + PointRendR101-FPN1024×204878.9202576688model | metrics
- -## Citing PointRend - -If you use PointRend, please use the following BibTeX entry. - -```BibTeX -@InProceedings{kirillov2019pointrend, - title={{PointRend}: Image Segmentation as Rendering}, - author={Alexander Kirillov and Yuxin Wu and Kaiming He and Ross Girshick}, - journal={ArXiv:1912.08193}, - year={2019} -} -``` - -## Citing Implicit PointRend - -If you use Implicit PointRend, please use the following BibTeX entry. - -```BibTeX -@InProceedings{cheng2021pointly, - title={Pointly-Supervised Instance Segmentation, - author={Bowen Cheng and Omkar Parkhi and Alexander Kirillov}, - journal={ArXiv}, - year={2021} -} -``` diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-Implicit-PointRend.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-Implicit-PointRend.yaml deleted file mode 100644 index 5ebafb30d3d8c5dfd24d03beff6d16bc2c9439fc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-Implicit-PointRend.yaml +++ /dev/null @@ -1,25 +0,0 @@ -_BASE_: "../../../../configs/Base-RCNN-FPN.yaml" -MODEL: - MASK_ON: true - ROI_MASK_HEAD: - NAME: "ImplicitPointRendMaskHead" - POOLER_TYPE: "" # No RoI pooling, let the head process image features directly - FC_DIM: 1024 - NUM_FC: 2 - POINT_HEAD: - NAME: "ImplicitPointHead" - FC_DIM: 256 - NUM_FC: 3 - IN_FEATURES: ["p2"] - NUM_CLASSES: 80 - CLS_AGNOSTIC_MASK: False - TRAIN_NUM_POINTS: 196 - SUBDIVISION_STEPS: 3 - SUBDIVISION_NUM_POINTS: 784 - IMPLICIT_POINTREND: - IMAGE_FEATURE_ENABLED: True - POS_ENC_ENABLED: True - PARAMS_L2_REGULARIZER: 0.00001 -INPUT: - # PointRend for instance segmentation does not work with "polygon" mask_format. - MASK_FORMAT: "bitmask" diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-PointRend-RCNN-FPN.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-PointRend-RCNN-FPN.yaml deleted file mode 100644 index e68e707f949f046a3ba0a48bc8e12572982b8316..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/Base-PointRend-RCNN-FPN.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "../../../../configs/Base-RCNN-FPN.yaml" -MODEL: - MASK_ON: true - ROI_BOX_HEAD: - TRAIN_ON_PRED_BOXES: True - ROI_MASK_HEAD: - POOLER_TYPE: "" # No RoI pooling, let the head process image features directly - NAME: "PointRendMaskHead" - FC_DIM: 1024 - NUM_FC: 2 - OUTPUT_SIDE_RESOLUTION: 7 - IN_FEATURES: ["p2"] # for the coarse mask head - POINT_HEAD_ON: True - POINT_HEAD: - FC_DIM: 256 - NUM_FC: 3 - IN_FEATURES: ["p2"] -INPUT: - # PointRend for instance segmentation does not work with "polygon" mask_format. - MASK_FORMAT: "bitmask" diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_1x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_1x_coco.yaml deleted file mode 100644 index ba35c24679a8b69109c2db3fdd0a9414bd8159a6..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_1x_coco.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: "Base-Implicit-PointRend.yaml" -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-50.pkl - RESNETS: - DEPTH: 50 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_3x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_3x_coco.yaml deleted file mode 100644 index 884236d07784cbebbf9905e37d9c361e89e25e91..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_3x_coco.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "Base-Implicit-PointRend.yaml" -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-50.pkl - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_101_FPN_3x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_101_FPN_3x_coco.yaml deleted file mode 100644 index 4269130ccd25fa4640f6e6836b5256241f2d50bc..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_101_FPN_3x_coco.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: Base-PointRend-RCNN-FPN.yaml -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-101.pkl - MASK_ON: true - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_cityscapes.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_cityscapes.yaml deleted file mode 100644 index 0402d6d645c0dafed7b8c6623371bd0a4701a85b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_cityscapes.yaml +++ /dev/null @@ -1,22 +0,0 @@ -_BASE_: Base-PointRend-RCNN-FPN.yaml -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-50.pkl - RESNETS: - DEPTH: 50 - ROI_HEADS: - NUM_CLASSES: 8 - POINT_HEAD: - NUM_CLASSES: 8 -DATASETS: - TEST: ("cityscapes_fine_instance_seg_val",) - TRAIN: ("cityscapes_fine_instance_seg_train",) -SOLVER: - BASE_LR: 0.01 - IMS_PER_BATCH: 8 - MAX_ITER: 24000 - STEPS: (18000,) -INPUT: - MAX_SIZE_TEST: 2048 - MAX_SIZE_TRAIN: 2048 - MIN_SIZE_TEST: 1024 - MIN_SIZE_TRAIN: (800, 832, 864, 896, 928, 960, 992, 1024) diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml deleted file mode 100644 index 0249b493e7446eccfc9a483287308b8f064e15e9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml +++ /dev/null @@ -1,8 +0,0 @@ -_BASE_: Base-PointRend-RCNN-FPN.yaml -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-50.pkl - RESNETS: - DEPTH: 50 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_3x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_3x_coco.yaml deleted file mode 100644 index a571b4c71911fa947f5e774f24071bcb37004a28..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_3x_coco.yaml +++ /dev/null @@ -1,12 +0,0 @@ -_BASE_: Base-PointRend-RCNN-FPN.yaml -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-50.pkl - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") - diff --git a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_X_101_32x8d_FPN_3x_coco.yaml b/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_X_101_32x8d_FPN_3x_coco.yaml deleted file mode 100644 index 85d26f3fabed2d4cf860cf57eb27808a30db76ee..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/InstanceSegmentation/pointrend_rcnn_X_101_32x8d_FPN_3x_coco.yaml +++ /dev/null @@ -1,16 +0,0 @@ -_BASE_: Base-PointRend-RCNN-FPN.yaml -MODEL: - MASK_ON: True - WEIGHTS: "detectron2://ImageNetPretrained/FAIR/X-101-32x8d.pkl" - PIXEL_STD: [57.375, 57.120, 58.395] - RESNETS: - STRIDE_IN_1X1: False # this is a C2 model - NUM_GROUPS: 32 - WIDTH_PER_GROUP: 8 - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 -# To add COCO AP evaluation against the higher-quality LVIS annotations. -# DATASETS: -# TEST: ("coco_2017_val", "lvis_v0.5_val_cocofied") diff --git a/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/Base-PointRend-Semantic-FPN.yaml b/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/Base-PointRend-Semantic-FPN.yaml deleted file mode 100644 index 9b7a1b40bb2e3b9e8e9264c227661dcdb2868348..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/Base-PointRend-Semantic-FPN.yaml +++ /dev/null @@ -1,20 +0,0 @@ -_BASE_: "../../../../configs/Base-RCNN-FPN.yaml" -MODEL: - META_ARCHITECTURE: "SemanticSegmentor" - BACKBONE: - FREEZE_AT: 0 - SEM_SEG_HEAD: - NAME: "PointRendSemSegHead" - POINT_HEAD: - NUM_CLASSES: 54 - FC_DIM: 256 - NUM_FC: 3 - IN_FEATURES: ["p2"] - TRAIN_NUM_POINTS: 1024 - SUBDIVISION_STEPS: 2 - SUBDIVISION_NUM_POINTS: 8192 - COARSE_SEM_SEG_HEAD_NAME: "SemSegFPNHead" - COARSE_PRED_EACH_LAYER: False -DATASETS: - TRAIN: ("coco_2017_train_panoptic_stuffonly",) - TEST: ("coco_2017_val_panoptic_stuffonly",) diff --git a/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/pointrend_semantic_R_101_FPN_1x_cityscapes.yaml b/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/pointrend_semantic_R_101_FPN_1x_cityscapes.yaml deleted file mode 100644 index 6be11fa3e80a83a0f138adbeb794fa98425606cf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/configs/SemanticSegmentation/pointrend_semantic_R_101_FPN_1x_cityscapes.yaml +++ /dev/null @@ -1,33 +0,0 @@ -_BASE_: Base-PointRend-Semantic-FPN.yaml -MODEL: - WEIGHTS: detectron2://ImageNetPretrained/MSRA/R-101.pkl - RESNETS: - DEPTH: 101 - SEM_SEG_HEAD: - NUM_CLASSES: 19 - POINT_HEAD: - NUM_CLASSES: 19 - TRAIN_NUM_POINTS: 2048 - SUBDIVISION_NUM_POINTS: 8192 -DATASETS: - TRAIN: ("cityscapes_fine_sem_seg_train",) - TEST: ("cityscapes_fine_sem_seg_val",) -SOLVER: - BASE_LR: 0.01 - STEPS: (40000, 55000) - MAX_ITER: 65000 - IMS_PER_BATCH: 32 -INPUT: - MIN_SIZE_TRAIN: (512, 768, 1024, 1280, 1536, 1792, 2048) - MIN_SIZE_TRAIN_SAMPLING: "choice" - MIN_SIZE_TEST: 1024 - MAX_SIZE_TRAIN: 4096 - MAX_SIZE_TEST: 2048 - CROP: - ENABLED: True - TYPE: "absolute" - SIZE: (512, 1024) - SINGLE_CATEGORY_MAX_AREA: 0.75 - COLOR_AUG_SSD: True -DATALOADER: - NUM_WORKERS: 10 diff --git a/preprocess/detectron2/projects/PointRend/point_rend/__init__.py b/preprocess/detectron2/projects/PointRend/point_rend/__init__.py deleted file mode 100644 index e3050cbddb92f4ec3acf091cc7aed0ea70484927..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .config import add_pointrend_config -from .mask_head import PointRendMaskHead, ImplicitPointRendMaskHead -from .semantic_seg import PointRendSemSegHead -from .color_augmentation import ColorAugSSDTransform - -from . import roi_heads as _ # only registration diff --git a/preprocess/detectron2/projects/PointRend/point_rend/color_augmentation.py b/preprocess/detectron2/projects/PointRend/point_rend/color_augmentation.py deleted file mode 100644 index cdcb051623d20e3bfad5167715e8082974d51ec2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/color_augmentation.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import random -import cv2 -from fvcore.transforms.transform import Transform - - -class ColorAugSSDTransform(Transform): - """ - A color related data augmentation used in Single Shot Multibox Detector (SSD). - - Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, - Scott Reed, Cheng-Yang Fu, Alexander C. Berg. - SSD: Single Shot MultiBox Detector. ECCV 2016. - - Implementation based on: - - https://github.com/weiliu89/caffe/blob - /4817bf8b4200b35ada8ed0dc378dceaf38c539e4 - /src/caffe/util/im_transforms.cpp - - https://github.com/chainer/chainercv/blob - /7159616642e0be7c5b3ef380b848e16b7e99355b/chainercv - /links/model/ssd/transforms.py - """ - - def __init__( - self, - img_format, - brightness_delta=32, - contrast_low=0.5, - contrast_high=1.5, - saturation_low=0.5, - saturation_high=1.5, - hue_delta=18, - ): - super().__init__() - assert img_format in ["BGR", "RGB"] - self.is_rgb = img_format == "RGB" - del img_format - self._set_attributes(locals()) - - def apply_coords(self, coords): - return coords - - def apply_segmentation(self, segmentation): - return segmentation - - def apply_image(self, img, interp=None): - if self.is_rgb: - img = img[:, :, [2, 1, 0]] - img = self.brightness(img) - if random.randrange(2): - img = self.contrast(img) - img = self.saturation(img) - img = self.hue(img) - else: - img = self.saturation(img) - img = self.hue(img) - img = self.contrast(img) - if self.is_rgb: - img = img[:, :, [2, 1, 0]] - return img - - def convert(self, img, alpha=1, beta=0): - img = img.astype(np.float32) * alpha + beta - img = np.clip(img, 0, 255) - return img.astype(np.uint8) - - def brightness(self, img): - if random.randrange(2): - return self.convert( - img, beta=random.uniform(-self.brightness_delta, self.brightness_delta) - ) - return img - - def contrast(self, img): - if random.randrange(2): - return self.convert(img, alpha=random.uniform(self.contrast_low, self.contrast_high)) - return img - - def saturation(self, img): - if random.randrange(2): - img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) - img[:, :, 1] = self.convert( - img[:, :, 1], alpha=random.uniform(self.saturation_low, self.saturation_high) - ) - return cv2.cvtColor(img, cv2.COLOR_HSV2BGR) - return img - - def hue(self, img): - if random.randrange(2): - img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) - img[:, :, 0] = ( - img[:, :, 0].astype(int) + random.randint(-self.hue_delta, self.hue_delta) - ) % 180 - return cv2.cvtColor(img, cv2.COLOR_HSV2BGR) - return img diff --git a/preprocess/detectron2/projects/PointRend/point_rend/config.py b/preprocess/detectron2/projects/PointRend/point_rend/config.py deleted file mode 100644 index a02c7829533545e81669785a53db90ef7e783156..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/config.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -from detectron2.config import CfgNode as CN - - -def add_pointrend_config(cfg): - """ - Add config for PointRend. - """ - # We retry random cropping until no single category in semantic segmentation GT occupies more - # than `SINGLE_CATEGORY_MAX_AREA` part of the crop. - cfg.INPUT.CROP.SINGLE_CATEGORY_MAX_AREA = 1.0 - # Color augmentatition from SSD paper for semantic segmentation model during training. - cfg.INPUT.COLOR_AUG_SSD = False - - # Names of the input feature maps to be used by a coarse mask head. - cfg.MODEL.ROI_MASK_HEAD.IN_FEATURES = ("p2",) - cfg.MODEL.ROI_MASK_HEAD.FC_DIM = 1024 - cfg.MODEL.ROI_MASK_HEAD.NUM_FC = 2 - # The side size of a coarse mask head prediction. - cfg.MODEL.ROI_MASK_HEAD.OUTPUT_SIDE_RESOLUTION = 7 - # True if point head is used. - cfg.MODEL.ROI_MASK_HEAD.POINT_HEAD_ON = False - - cfg.MODEL.POINT_HEAD = CN() - cfg.MODEL.POINT_HEAD.NAME = "StandardPointHead" - cfg.MODEL.POINT_HEAD.NUM_CLASSES = 80 - # Names of the input feature maps to be used by a mask point head. - cfg.MODEL.POINT_HEAD.IN_FEATURES = ("p2",) - # Number of points sampled during training for a mask point head. - cfg.MODEL.POINT_HEAD.TRAIN_NUM_POINTS = 14 * 14 - # Oversampling parameter for PointRend point sampling during training. Parameter `k` in the - # original paper. - cfg.MODEL.POINT_HEAD.OVERSAMPLE_RATIO = 3 - # Importance sampling parameter for PointRend point sampling during training. Parametr `beta` in - # the original paper. - cfg.MODEL.POINT_HEAD.IMPORTANCE_SAMPLE_RATIO = 0.75 - # Number of subdivision steps during inference. - cfg.MODEL.POINT_HEAD.SUBDIVISION_STEPS = 5 - # Maximum number of points selected at each subdivision step (N). - cfg.MODEL.POINT_HEAD.SUBDIVISION_NUM_POINTS = 28 * 28 - cfg.MODEL.POINT_HEAD.FC_DIM = 256 - cfg.MODEL.POINT_HEAD.NUM_FC = 3 - cfg.MODEL.POINT_HEAD.CLS_AGNOSTIC_MASK = False - # If True, then coarse prediction features are used as inout for each layer in PointRend's MLP. - cfg.MODEL.POINT_HEAD.COARSE_PRED_EACH_LAYER = True - cfg.MODEL.POINT_HEAD.COARSE_SEM_SEG_HEAD_NAME = "SemSegFPNHead" - - """ - Add config for Implicit PointRend. - """ - cfg.MODEL.IMPLICIT_POINTREND = CN() - - cfg.MODEL.IMPLICIT_POINTREND.IMAGE_FEATURE_ENABLED = True - cfg.MODEL.IMPLICIT_POINTREND.POS_ENC_ENABLED = True - - cfg.MODEL.IMPLICIT_POINTREND.PARAMS_L2_REGULARIZER = 0.00001 diff --git a/preprocess/detectron2/projects/PointRend/point_rend/mask_head.py b/preprocess/detectron2/projects/PointRend/point_rend/mask_head.py deleted file mode 100644 index 46dd64721578bd45eb208206bbd5e7908cb6a148..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/mask_head.py +++ /dev/null @@ -1,435 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import math -import numpy as np -from typing import Dict, List, Tuple -import fvcore.nn.weight_init as weight_init -import torch -from torch import Tensor, nn -from torch.nn import functional as F - -from detectron2.config import configurable -from detectron2.layers import Conv2d, ShapeSpec, cat, interpolate -from detectron2.modeling import ROI_MASK_HEAD_REGISTRY -from detectron2.modeling.roi_heads.mask_head import mask_rcnn_inference, mask_rcnn_loss -from detectron2.structures import Boxes - -from .point_features import ( - generate_regular_grid_point_coords, - get_point_coords_wrt_image, - get_uncertain_point_coords_on_grid, - get_uncertain_point_coords_with_randomness, - point_sample, - point_sample_fine_grained_features, - sample_point_labels, -) -from .point_head import build_point_head, roi_mask_point_loss - - -def calculate_uncertainty(logits, classes): - """ - We estimate uncerainty as L1 distance between 0.0 and the logit prediction in 'logits' for the - foreground class in `classes`. - Args: - logits (Tensor): A tensor of shape (R, C, ...) or (R, 1, ...) for class-specific or - class-agnostic, where R is the total number of predicted masks in all images and C is - the number of foreground classes. The values are logits. - classes (list): A list of length R that contains either predicted of ground truth class - for eash predicted mask. - Returns: - scores (Tensor): A tensor of shape (R, 1, ...) that contains uncertainty scores with - the most uncertain locations having the highest uncertainty score. - """ - if logits.shape[1] == 1: - gt_class_logits = logits.clone() - else: - gt_class_logits = logits[ - torch.arange(logits.shape[0], device=logits.device), classes - ].unsqueeze(1) - return -(torch.abs(gt_class_logits)) - - -class ConvFCHead(nn.Module): - """ - A mask head with fully connected layers. Given pooled features it first reduces channels and - spatial dimensions with conv layers and then uses FC layers to predict coarse masks analogously - to the standard box head. - """ - - _version = 2 - - @configurable - def __init__( - self, input_shape: ShapeSpec, *, conv_dim: int, fc_dims: List[int], output_shape: Tuple[int] - ): - """ - Args: - conv_dim: the output dimension of the conv layers - fc_dims: a list of N>0 integers representing the output dimensions of N FC layers - output_shape: shape of the output mask prediction - """ - super().__init__() - - # fmt: off - input_channels = input_shape.channels - input_h = input_shape.height - input_w = input_shape.width - self.output_shape = output_shape - # fmt: on - - self.conv_layers = [] - if input_channels > conv_dim: - self.reduce_channel_dim_conv = Conv2d( - input_channels, - conv_dim, - kernel_size=1, - stride=1, - padding=0, - bias=True, - activation=F.relu, - ) - self.conv_layers.append(self.reduce_channel_dim_conv) - - self.reduce_spatial_dim_conv = Conv2d( - conv_dim, conv_dim, kernel_size=2, stride=2, padding=0, bias=True, activation=F.relu - ) - self.conv_layers.append(self.reduce_spatial_dim_conv) - - input_dim = conv_dim * input_h * input_w - input_dim //= 4 - - self.fcs = [] - for k, fc_dim in enumerate(fc_dims): - fc = nn.Linear(input_dim, fc_dim) - self.add_module("fc{}".format(k + 1), fc) - self.fcs.append(fc) - input_dim = fc_dim - - output_dim = int(np.prod(self.output_shape)) - - self.prediction = nn.Linear(fc_dims[-1], output_dim) - # use normal distribution initialization for mask prediction layer - nn.init.normal_(self.prediction.weight, std=0.001) - nn.init.constant_(self.prediction.bias, 0) - - for layer in self.conv_layers: - weight_init.c2_msra_fill(layer) - for layer in self.fcs: - weight_init.c2_xavier_fill(layer) - - @classmethod - def from_config(cls, cfg, input_shape): - output_shape = ( - cfg.MODEL.ROI_HEADS.NUM_CLASSES, - cfg.MODEL.ROI_MASK_HEAD.OUTPUT_SIDE_RESOLUTION, - cfg.MODEL.ROI_MASK_HEAD.OUTPUT_SIDE_RESOLUTION, - ) - fc_dim = cfg.MODEL.ROI_MASK_HEAD.FC_DIM - num_fc = cfg.MODEL.ROI_MASK_HEAD.NUM_FC - ret = dict( - input_shape=input_shape, - conv_dim=cfg.MODEL.ROI_MASK_HEAD.CONV_DIM, - fc_dims=[fc_dim] * num_fc, - output_shape=output_shape, - ) - return ret - - def forward(self, x): - N = x.shape[0] - for layer in self.conv_layers: - x = layer(x) - x = torch.flatten(x, start_dim=1) - for layer in self.fcs: - x = F.relu(layer(x)) - output_shape = [N] + list(self.output_shape) - return self.prediction(x).view(*output_shape) - - def _load_from_state_dict( - self, state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs - ): - version = local_metadata.get("version", None) - - if version is None or version < 2: - logger = logging.getLogger(__name__) - logger.warning( - "Weight format of PointRend models have changed! " - "Applying automatic conversion now ..." - ) - for k in list(state_dict.keys()): - newk = k - if k.startswith(prefix + "coarse_mask_fc"): - newk = k.replace(prefix + "coarse_mask_fc", prefix + "fc") - if newk != k: - state_dict[newk] = state_dict[k] - del state_dict[k] - - -@ROI_MASK_HEAD_REGISTRY.register() -class PointRendMaskHead(nn.Module): - def __init__(self, cfg, input_shape: Dict[str, ShapeSpec]): - super().__init__() - self._feature_scales = {k: 1.0 / v.stride for k, v in input_shape.items()} - # point head - self._init_point_head(cfg, input_shape) - # coarse mask head - self.roi_pooler_in_features = cfg.MODEL.ROI_MASK_HEAD.IN_FEATURES - self.roi_pooler_size = cfg.MODEL.ROI_MASK_HEAD.POOLER_RESOLUTION - self._feature_scales = {k: 1.0 / v.stride for k, v in input_shape.items()} - in_channels = np.sum([input_shape[f].channels for f in self.roi_pooler_in_features]) - self._init_roi_head( - cfg, - ShapeSpec( - channels=in_channels, - width=self.roi_pooler_size, - height=self.roi_pooler_size, - ), - ) - - def _init_roi_head(self, cfg, input_shape): - self.coarse_head = ConvFCHead(cfg, input_shape) - - def _init_point_head(self, cfg, input_shape): - # fmt: off - self.mask_point_on = cfg.MODEL.ROI_MASK_HEAD.POINT_HEAD_ON - if not self.mask_point_on: - return - assert cfg.MODEL.ROI_HEADS.NUM_CLASSES == cfg.MODEL.POINT_HEAD.NUM_CLASSES - self.mask_point_in_features = cfg.MODEL.POINT_HEAD.IN_FEATURES - self.mask_point_train_num_points = cfg.MODEL.POINT_HEAD.TRAIN_NUM_POINTS - self.mask_point_oversample_ratio = cfg.MODEL.POINT_HEAD.OVERSAMPLE_RATIO - self.mask_point_importance_sample_ratio = cfg.MODEL.POINT_HEAD.IMPORTANCE_SAMPLE_RATIO - # next three parameters are use in the adaptive subdivions inference procedure - self.mask_point_subdivision_init_resolution = cfg.MODEL.ROI_MASK_HEAD.OUTPUT_SIDE_RESOLUTION - self.mask_point_subdivision_steps = cfg.MODEL.POINT_HEAD.SUBDIVISION_STEPS - self.mask_point_subdivision_num_points = cfg.MODEL.POINT_HEAD.SUBDIVISION_NUM_POINTS - # fmt: on - - in_channels = int(np.sum([input_shape[f].channels for f in self.mask_point_in_features])) - self.point_head = build_point_head(cfg, ShapeSpec(channels=in_channels, width=1, height=1)) - - # An optimization to skip unused subdivision steps: if after subdivision, all pixels on - # the mask will be selected and recomputed anyway, we should just double our init_resolution - while ( - 4 * self.mask_point_subdivision_init_resolution**2 - <= self.mask_point_subdivision_num_points - ): - self.mask_point_subdivision_init_resolution *= 2 - self.mask_point_subdivision_steps -= 1 - - def forward(self, features, instances): - """ - Args: - features (dict[str, Tensor]): a dict of image-level features - instances (list[Instances]): proposals in training; detected - instances in inference - """ - if self.training: - proposal_boxes = [x.proposal_boxes for x in instances] - coarse_mask = self.coarse_head(self._roi_pooler(features, proposal_boxes)) - losses = {"loss_mask": mask_rcnn_loss(coarse_mask, instances)} - if not self.mask_point_on: - return losses - - point_coords, point_labels = self._sample_train_points(coarse_mask, instances) - point_fine_grained_features = self._point_pooler(features, proposal_boxes, point_coords) - point_logits = self._get_point_logits( - point_fine_grained_features, point_coords, coarse_mask - ) - losses["loss_mask_point"] = roi_mask_point_loss(point_logits, instances, point_labels) - return losses - else: - pred_boxes = [x.pred_boxes for x in instances] - coarse_mask = self.coarse_head(self._roi_pooler(features, pred_boxes)) - return self._subdivision_inference(features, coarse_mask, instances) - - def _roi_pooler(self, features: List[Tensor], boxes: List[Boxes]): - """ - Extract per-box feature. This is similar to RoIAlign(sampling_ratio=1) except: - 1. It's implemented by point_sample - 2. It pools features across all levels and concat them, while typically - RoIAlign select one level for every box. However in the config we only use - one level (p2) so there is no difference. - - Returns: - Tensor of shape (R, C, pooler_size, pooler_size) where R is the total number of boxes - """ - features_list = [features[k] for k in self.roi_pooler_in_features] - features_scales = [self._feature_scales[k] for k in self.roi_pooler_in_features] - - num_boxes = sum(x.tensor.size(0) for x in boxes) - output_size = self.roi_pooler_size - point_coords = generate_regular_grid_point_coords(num_boxes, output_size, boxes[0].device) - # For regular grids of points, this function is equivalent to `len(features_list)' calls - # of `ROIAlign` (with `SAMPLING_RATIO=1`), and concat the results. - roi_features, _ = point_sample_fine_grained_features( - features_list, features_scales, boxes, point_coords - ) - return roi_features.view(num_boxes, roi_features.shape[1], output_size, output_size) - - def _sample_train_points(self, coarse_mask, instances): - assert self.training - gt_classes = cat([x.gt_classes for x in instances]) - with torch.no_grad(): - # sample point_coords - point_coords = get_uncertain_point_coords_with_randomness( - coarse_mask, - lambda logits: calculate_uncertainty(logits, gt_classes), - self.mask_point_train_num_points, - self.mask_point_oversample_ratio, - self.mask_point_importance_sample_ratio, - ) - # sample point_labels - proposal_boxes = [x.proposal_boxes for x in instances] - cat_boxes = Boxes.cat(proposal_boxes) - point_coords_wrt_image = get_point_coords_wrt_image(cat_boxes.tensor, point_coords) - point_labels = sample_point_labels(instances, point_coords_wrt_image) - return point_coords, point_labels - - def _point_pooler(self, features, proposal_boxes, point_coords): - point_features_list = [features[k] for k in self.mask_point_in_features] - point_features_scales = [self._feature_scales[k] for k in self.mask_point_in_features] - # sample image-level features - point_fine_grained_features, _ = point_sample_fine_grained_features( - point_features_list, point_features_scales, proposal_boxes, point_coords - ) - return point_fine_grained_features - - def _get_point_logits(self, point_fine_grained_features, point_coords, coarse_mask): - coarse_features = point_sample(coarse_mask, point_coords, align_corners=False) - point_logits = self.point_head(point_fine_grained_features, coarse_features) - return point_logits - - def _subdivision_inference(self, features, mask_representations, instances): - assert not self.training - - pred_boxes = [x.pred_boxes for x in instances] - pred_classes = cat([x.pred_classes for x in instances]) - - mask_logits = None - # +1 here to include an initial step to generate the coarsest mask - # prediction with init_resolution, when mask_logits is None. - # We compute initial mask by sampling on a regular grid. coarse_mask - # can be used as initial mask as well, but it's typically very low-res - # so it will be completely overwritten during subdivision anyway. - for _ in range(self.mask_point_subdivision_steps + 1): - if mask_logits is None: - point_coords = generate_regular_grid_point_coords( - pred_classes.size(0), - self.mask_point_subdivision_init_resolution, - pred_boxes[0].device, - ) - else: - mask_logits = interpolate( - mask_logits, scale_factor=2, mode="bilinear", align_corners=False - ) - uncertainty_map = calculate_uncertainty(mask_logits, pred_classes) - point_indices, point_coords = get_uncertain_point_coords_on_grid( - uncertainty_map, self.mask_point_subdivision_num_points - ) - - # Run the point head for every point in point_coords - fine_grained_features = self._point_pooler(features, pred_boxes, point_coords) - point_logits = self._get_point_logits( - fine_grained_features, point_coords, mask_representations - ) - - if mask_logits is None: - # Create initial mask_logits using point_logits on this regular grid - R, C, _ = point_logits.shape - mask_logits = point_logits.reshape( - R, - C, - self.mask_point_subdivision_init_resolution, - self.mask_point_subdivision_init_resolution, - ) - # The subdivision code will fail with the empty list of boxes - if len(pred_classes) == 0: - mask_rcnn_inference(mask_logits, instances) - return instances - else: - # Put point predictions to the right places on the upsampled grid. - R, C, H, W = mask_logits.shape - point_indices = point_indices.unsqueeze(1).expand(-1, C, -1) - mask_logits = ( - mask_logits.reshape(R, C, H * W) - .scatter_(2, point_indices, point_logits) - .view(R, C, H, W) - ) - mask_rcnn_inference(mask_logits, instances) - return instances - - -@ROI_MASK_HEAD_REGISTRY.register() -class ImplicitPointRendMaskHead(PointRendMaskHead): - def __init__(self, cfg, input_shape: Dict[str, ShapeSpec]): - super().__init__(cfg, input_shape) - - def _init_roi_head(self, cfg, input_shape): - assert hasattr(self, "num_params"), "Please initialize point_head first!" - self.parameter_head = ConvFCHead(cfg, input_shape, output_shape=(self.num_params,)) - self.regularizer = cfg.MODEL.IMPLICIT_POINTREND.PARAMS_L2_REGULARIZER - - def _init_point_head(self, cfg, input_shape): - # fmt: off - self.mask_point_on = True # always on - assert cfg.MODEL.ROI_HEADS.NUM_CLASSES == cfg.MODEL.POINT_HEAD.NUM_CLASSES - self.mask_point_in_features = cfg.MODEL.POINT_HEAD.IN_FEATURES - self.mask_point_train_num_points = cfg.MODEL.POINT_HEAD.TRAIN_NUM_POINTS - # next two parameters are use in the adaptive subdivions inference procedure - self.mask_point_subdivision_steps = cfg.MODEL.POINT_HEAD.SUBDIVISION_STEPS - self.mask_point_subdivision_num_points = cfg.MODEL.POINT_HEAD.SUBDIVISION_NUM_POINTS - # fmt: on - - in_channels = int(np.sum([input_shape[f].channels for f in self.mask_point_in_features])) - self.point_head = build_point_head(cfg, ShapeSpec(channels=in_channels, width=1, height=1)) - self.num_params = self.point_head.num_params - - # inference parameters - self.mask_point_subdivision_init_resolution = int( - math.sqrt(self.mask_point_subdivision_num_points) - ) - assert ( - self.mask_point_subdivision_init_resolution - * self.mask_point_subdivision_init_resolution - == self.mask_point_subdivision_num_points - ) - - def forward(self, features, instances): - """ - Args: - features (dict[str, Tensor]): a dict of image-level features - instances (list[Instances]): proposals in training; detected - instances in inference - """ - if self.training: - proposal_boxes = [x.proposal_boxes for x in instances] - parameters = self.parameter_head(self._roi_pooler(features, proposal_boxes)) - losses = {"loss_l2": self.regularizer * (parameters**2).mean()} - - point_coords, point_labels = self._uniform_sample_train_points(instances) - point_fine_grained_features = self._point_pooler(features, proposal_boxes, point_coords) - point_logits = self._get_point_logits( - point_fine_grained_features, point_coords, parameters - ) - losses["loss_mask_point"] = roi_mask_point_loss(point_logits, instances, point_labels) - return losses - else: - pred_boxes = [x.pred_boxes for x in instances] - parameters = self.parameter_head(self._roi_pooler(features, pred_boxes)) - return self._subdivision_inference(features, parameters, instances) - - def _uniform_sample_train_points(self, instances): - assert self.training - proposal_boxes = [x.proposal_boxes for x in instances] - cat_boxes = Boxes.cat(proposal_boxes) - # uniform sample - point_coords = torch.rand( - len(cat_boxes), self.mask_point_train_num_points, 2, device=cat_boxes.tensor.device - ) - # sample point_labels - point_coords_wrt_image = get_point_coords_wrt_image(cat_boxes.tensor, point_coords) - point_labels = sample_point_labels(instances, point_coords_wrt_image) - return point_coords, point_labels - - def _get_point_logits(self, fine_grained_features, point_coords, parameters): - return self.point_head(fine_grained_features, point_coords, parameters) diff --git a/preprocess/detectron2/projects/PointRend/point_rend/point_features.py b/preprocess/detectron2/projects/PointRend/point_rend/point_features.py deleted file mode 100644 index e46f442950ff248555e127dc3923b67adb37fb69..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/point_features.py +++ /dev/null @@ -1,259 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import torch -from torch.nn import functional as F - -from detectron2.layers import cat, shapes_to_tensor -from detectron2.structures import BitMasks, Boxes - - -""" -Shape shorthand in this module: - - N: minibatch dimension size, i.e. the number of RoIs for instance segmenation or the - number of images for semantic segmenation. - R: number of ROIs, combined over all images, in the minibatch - P: number of points -""" - - -def point_sample(input, point_coords, **kwargs): - """ - A wrapper around :function:`torch.nn.functional.grid_sample` to support 3D point_coords tensors. - Unlike :function:`torch.nn.functional.grid_sample` it assumes `point_coords` to lie inside - [0, 1] x [0, 1] square. - - Args: - input (Tensor): A tensor of shape (N, C, H, W) that contains features map on a H x W grid. - point_coords (Tensor): A tensor of shape (N, P, 2) or (N, Hgrid, Wgrid, 2) that contains - [0, 1] x [0, 1] normalized point coordinates. - - Returns: - output (Tensor): A tensor of shape (N, C, P) or (N, C, Hgrid, Wgrid) that contains - features for points in `point_coords`. The features are obtained via bilinear - interplation from `input` the same way as :function:`torch.nn.functional.grid_sample`. - """ - add_dim = False - if point_coords.dim() == 3: - add_dim = True - point_coords = point_coords.unsqueeze(2) - output = F.grid_sample(input, 2.0 * point_coords - 1.0, **kwargs) - if add_dim: - output = output.squeeze(3) - return output - - -def generate_regular_grid_point_coords(R, side_size, device): - """ - Generate regular square grid of points in [0, 1] x [0, 1] coordinate space. - - Args: - R (int): The number of grids to sample, one for each region. - side_size (int): The side size of the regular grid. - device (torch.device): Desired device of returned tensor. - - Returns: - (Tensor): A tensor of shape (R, side_size^2, 2) that contains coordinates - for the regular grids. - """ - aff = torch.tensor([[[0.5, 0, 0.5], [0, 0.5, 0.5]]], device=device) - r = F.affine_grid(aff, torch.Size((1, 1, side_size, side_size)), align_corners=False) - return r.view(1, -1, 2).expand(R, -1, -1) - - -def get_uncertain_point_coords_with_randomness( - coarse_logits, uncertainty_func, num_points, oversample_ratio, importance_sample_ratio -): - """ - Sample points in [0, 1] x [0, 1] coordinate space based on their uncertainty. The unceratinties - are calculated for each point using 'uncertainty_func' function that takes point's logit - prediction as input. - See PointRend paper for details. - - Args: - coarse_logits (Tensor): A tensor of shape (N, C, Hmask, Wmask) or (N, 1, Hmask, Wmask) for - class-specific or class-agnostic prediction. - uncertainty_func: A function that takes a Tensor of shape (N, C, P) or (N, 1, P) that - contains logit predictions for P points and returns their uncertainties as a Tensor of - shape (N, 1, P). - num_points (int): The number of points P to sample. - oversample_ratio (int): Oversampling parameter. - importance_sample_ratio (float): Ratio of points that are sampled via importnace sampling. - - Returns: - point_coords (Tensor): A tensor of shape (N, P, 2) that contains the coordinates of P - sampled points. - """ - assert oversample_ratio >= 1 - assert importance_sample_ratio <= 1 and importance_sample_ratio >= 0 - num_boxes = coarse_logits.shape[0] - num_sampled = int(num_points * oversample_ratio) - point_coords = torch.rand(num_boxes, num_sampled, 2, device=coarse_logits.device) - point_logits = point_sample(coarse_logits, point_coords, align_corners=False) - # It is crucial to calculate uncertainty based on the sampled prediction value for the points. - # Calculating uncertainties of the coarse predictions first and sampling them for points leads - # to incorrect results. - # To illustrate this: assume uncertainty_func(logits)=-abs(logits), a sampled point between - # two coarse predictions with -1 and 1 logits has 0 logits, and therefore 0 uncertainty value. - # However, if we calculate uncertainties for the coarse predictions first, - # both will have -1 uncertainty, and the sampled point will get -1 uncertainty. - point_uncertainties = uncertainty_func(point_logits) - num_uncertain_points = int(importance_sample_ratio * num_points) - num_random_points = num_points - num_uncertain_points - idx = torch.topk(point_uncertainties[:, 0, :], k=num_uncertain_points, dim=1)[1] - shift = num_sampled * torch.arange(num_boxes, dtype=torch.long, device=coarse_logits.device) - idx += shift[:, None] - point_coords = point_coords.view(-1, 2)[idx.view(-1), :].view( - num_boxes, num_uncertain_points, 2 - ) - if num_random_points > 0: - point_coords = cat( - [ - point_coords, - torch.rand(num_boxes, num_random_points, 2, device=coarse_logits.device), - ], - dim=1, - ) - return point_coords - - -def get_uncertain_point_coords_on_grid(uncertainty_map, num_points): - """ - Find `num_points` most uncertain points from `uncertainty_map` grid. - - Args: - uncertainty_map (Tensor): A tensor of shape (N, 1, H, W) that contains uncertainty - values for a set of points on a regular H x W grid. - num_points (int): The number of points P to select. - - Returns: - point_indices (Tensor): A tensor of shape (N, P) that contains indices from - [0, H x W) of the most uncertain points. - point_coords (Tensor): A tensor of shape (N, P, 2) that contains [0, 1] x [0, 1] normalized - coordinates of the most uncertain points from the H x W grid. - """ - R, _, H, W = uncertainty_map.shape - h_step = 1.0 / float(H) - w_step = 1.0 / float(W) - - num_points = min(H * W, num_points) - point_indices = torch.topk(uncertainty_map.view(R, H * W), k=num_points, dim=1)[1] - point_coords = torch.zeros(R, num_points, 2, dtype=torch.float, device=uncertainty_map.device) - point_coords[:, :, 0] = w_step / 2.0 + (point_indices % W).to(torch.float) * w_step - point_coords[:, :, 1] = h_step / 2.0 + (point_indices // W).to(torch.float) * h_step - return point_indices, point_coords - - -def point_sample_fine_grained_features(features_list, feature_scales, boxes, point_coords): - """ - Get features from feature maps in `features_list` that correspond to specific point coordinates - inside each bounding box from `boxes`. - - Args: - features_list (list[Tensor]): A list of feature map tensors to get features from. - feature_scales (list[float]): A list of scales for tensors in `features_list`. - boxes (list[Boxes]): A list of I Boxes objects that contain R_1 + ... + R_I = R boxes all - together. - point_coords (Tensor): A tensor of shape (R, P, 2) that contains - [0, 1] x [0, 1] box-normalized coordinates of the P sampled points. - - Returns: - point_features (Tensor): A tensor of shape (R, C, P) that contains features sampled - from all features maps in feature_list for P sampled points for all R boxes in `boxes`. - point_coords_wrt_image (Tensor): A tensor of shape (R, P, 2) that contains image-level - coordinates of P points. - """ - cat_boxes = Boxes.cat(boxes) - num_boxes = [b.tensor.size(0) for b in boxes] - - point_coords_wrt_image = get_point_coords_wrt_image(cat_boxes.tensor, point_coords) - split_point_coords_wrt_image = torch.split(point_coords_wrt_image, num_boxes) - - point_features = [] - for idx_img, point_coords_wrt_image_per_image in enumerate(split_point_coords_wrt_image): - point_features_per_image = [] - for idx_feature, feature_map in enumerate(features_list): - h, w = feature_map.shape[-2:] - scale = shapes_to_tensor([w, h]) / feature_scales[idx_feature] - point_coords_scaled = point_coords_wrt_image_per_image / scale.to(feature_map.device) - point_features_per_image.append( - point_sample( - feature_map[idx_img].unsqueeze(0), - point_coords_scaled.unsqueeze(0), - align_corners=False, - ) - .squeeze(0) - .transpose(1, 0) - ) - point_features.append(cat(point_features_per_image, dim=1)) - - return cat(point_features, dim=0), point_coords_wrt_image - - -def get_point_coords_wrt_image(boxes_coords, point_coords): - """ - Convert box-normalized [0, 1] x [0, 1] point cooordinates to image-level coordinates. - - Args: - boxes_coords (Tensor): A tensor of shape (R, 4) that contains bounding boxes. - coordinates. - point_coords (Tensor): A tensor of shape (R, P, 2) that contains - [0, 1] x [0, 1] box-normalized coordinates of the P sampled points. - - Returns: - point_coords_wrt_image (Tensor): A tensor of shape (R, P, 2) that contains - image-normalized coordinates of P sampled points. - """ - with torch.no_grad(): - point_coords_wrt_image = point_coords.clone() - point_coords_wrt_image[:, :, 0] = point_coords_wrt_image[:, :, 0] * ( - boxes_coords[:, None, 2] - boxes_coords[:, None, 0] - ) - point_coords_wrt_image[:, :, 1] = point_coords_wrt_image[:, :, 1] * ( - boxes_coords[:, None, 3] - boxes_coords[:, None, 1] - ) - point_coords_wrt_image[:, :, 0] += boxes_coords[:, None, 0] - point_coords_wrt_image[:, :, 1] += boxes_coords[:, None, 1] - return point_coords_wrt_image - - -def sample_point_labels(instances, point_coords): - """ - Sample point labels from ground truth mask given point_coords. - - Args: - instances (list[Instances]): A list of N Instances, where N is the number of images - in the batch. So, i_th elememt of the list contains R_i objects and R_1 + ... + R_N is - equal to R. The ground-truth gt_masks in each instance will be used to compute labels. - points_coords (Tensor): A tensor of shape (R, P, 2), where R is the total number of - instances and P is the number of points for each instance. The coordinates are in - the absolute image pixel coordinate space, i.e. [0, H] x [0, W]. - - Returns: - Tensor: A tensor of shape (R, P) that contains the labels of P sampled points. - """ - with torch.no_grad(): - gt_mask_logits = [] - point_coords_splits = torch.split( - point_coords, [len(instances_per_image) for instances_per_image in instances] - ) - for i, instances_per_image in enumerate(instances): - if len(instances_per_image) == 0: - continue - assert isinstance( - instances_per_image.gt_masks, BitMasks - ), "Point head works with GT in 'bitmask' format. Set INPUT.MASK_FORMAT to 'bitmask'." - - gt_bit_masks = instances_per_image.gt_masks.tensor - h, w = instances_per_image.gt_masks.image_size - scale = torch.tensor([w, h], dtype=torch.float, device=gt_bit_masks.device) - points_coord_grid_sample_format = point_coords_splits[i] / scale - gt_mask_logits.append( - point_sample( - gt_bit_masks.to(torch.float32).unsqueeze(1), - points_coord_grid_sample_format, - align_corners=False, - ).squeeze(1) - ) - - point_labels = cat(gt_mask_logits) - return point_labels diff --git a/preprocess/detectron2/projects/PointRend/point_rend/point_head.py b/preprocess/detectron2/projects/PointRend/point_rend/point_head.py deleted file mode 100644 index 1786fad5c54841faf86b1fbef83d909e3bf2b1f9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/point_head.py +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import fvcore.nn.weight_init as weight_init -import torch -from torch import nn -from torch.nn import functional as F - -from detectron2.layers import ShapeSpec, cat -from detectron2.utils.events import get_event_storage -from detectron2.utils.registry import Registry - -POINT_HEAD_REGISTRY = Registry("POINT_HEAD") -POINT_HEAD_REGISTRY.__doc__ = """ -Registry for point heads, which makes prediction for a given set of per-point features. - -The registered object will be called with `obj(cfg, input_shape)`. -""" - - -def roi_mask_point_loss(mask_logits, instances, point_labels): - """ - Compute the point-based loss for instance segmentation mask predictions - given point-wise mask prediction and its corresponding point-wise labels. - Args: - mask_logits (Tensor): A tensor of shape (R, C, P) or (R, 1, P) for class-specific or - class-agnostic, where R is the total number of predicted masks in all images, C is the - number of foreground classes, and P is the number of points sampled for each mask. - The values are logits. - instances (list[Instances]): A list of N Instances, where N is the number of images - in the batch. These instances are in 1:1 correspondence with the `mask_logits`. So, i_th - elememt of the list contains R_i objects and R_1 + ... + R_N is equal to R. - The ground-truth labels (class, box, mask, ...) associated with each instance are stored - in fields. - point_labels (Tensor): A tensor of shape (R, P), where R is the total number of - predicted masks and P is the number of points for each mask. - Labels with value of -1 will be ignored. - Returns: - point_loss (Tensor): A scalar tensor containing the loss. - """ - with torch.no_grad(): - cls_agnostic_mask = mask_logits.size(1) == 1 - total_num_masks = mask_logits.size(0) - - gt_classes = [] - for instances_per_image in instances: - if len(instances_per_image) == 0: - continue - - if not cls_agnostic_mask: - gt_classes_per_image = instances_per_image.gt_classes.to(dtype=torch.int64) - gt_classes.append(gt_classes_per_image) - - gt_mask_logits = point_labels - point_ignores = point_labels == -1 - if gt_mask_logits.shape[0] == 0: - return mask_logits.sum() * 0 - - assert gt_mask_logits.numel() > 0, gt_mask_logits.shape - - if cls_agnostic_mask: - mask_logits = mask_logits[:, 0] - else: - indices = torch.arange(total_num_masks) - gt_classes = cat(gt_classes, dim=0) - mask_logits = mask_logits[indices, gt_classes] - - # Log the training accuracy (using gt classes and 0.0 threshold for the logits) - mask_accurate = (mask_logits > 0.0) == gt_mask_logits.to(dtype=torch.uint8) - mask_accurate = mask_accurate[~point_ignores] - mask_accuracy = mask_accurate.nonzero().size(0) / max(mask_accurate.numel(), 1.0) - get_event_storage().put_scalar("point/accuracy", mask_accuracy) - - point_loss = F.binary_cross_entropy_with_logits( - mask_logits, gt_mask_logits.to(dtype=torch.float32), weight=~point_ignores, reduction="mean" - ) - return point_loss - - -@POINT_HEAD_REGISTRY.register() -class StandardPointHead(nn.Module): - """ - A point head multi-layer perceptron which we model with conv1d layers with kernel 1. The head - takes both fine-grained and coarse prediction features as its input. - """ - - def __init__(self, cfg, input_shape: ShapeSpec): - """ - The following attributes are parsed from config: - fc_dim: the output dimension of each FC layers - num_fc: the number of FC layers - coarse_pred_each_layer: if True, coarse prediction features are concatenated to each - layer's input - """ - super(StandardPointHead, self).__init__() - # fmt: off - num_classes = cfg.MODEL.POINT_HEAD.NUM_CLASSES - fc_dim = cfg.MODEL.POINT_HEAD.FC_DIM - num_fc = cfg.MODEL.POINT_HEAD.NUM_FC - cls_agnostic_mask = cfg.MODEL.POINT_HEAD.CLS_AGNOSTIC_MASK - self.coarse_pred_each_layer = cfg.MODEL.POINT_HEAD.COARSE_PRED_EACH_LAYER - input_channels = input_shape.channels - # fmt: on - - fc_dim_in = input_channels + num_classes - self.fc_layers = [] - for k in range(num_fc): - fc = nn.Conv1d(fc_dim_in, fc_dim, kernel_size=1, stride=1, padding=0, bias=True) - self.add_module("fc{}".format(k + 1), fc) - self.fc_layers.append(fc) - fc_dim_in = fc_dim - fc_dim_in += num_classes if self.coarse_pred_each_layer else 0 - - num_mask_classes = 1 if cls_agnostic_mask else num_classes - self.predictor = nn.Conv1d(fc_dim_in, num_mask_classes, kernel_size=1, stride=1, padding=0) - - for layer in self.fc_layers: - weight_init.c2_msra_fill(layer) - # use normal distribution initialization for mask prediction layer - nn.init.normal_(self.predictor.weight, std=0.001) - if self.predictor.bias is not None: - nn.init.constant_(self.predictor.bias, 0) - - def forward(self, fine_grained_features, coarse_features): - x = torch.cat((fine_grained_features, coarse_features), dim=1) - for layer in self.fc_layers: - x = F.relu(layer(x)) - if self.coarse_pred_each_layer: - x = cat((x, coarse_features), dim=1) - return self.predictor(x) - - -@POINT_HEAD_REGISTRY.register() -class ImplicitPointHead(nn.Module): - """ - A point head multi-layer perceptron which we model with conv1d layers with kernel 1. The head - takes both fine-grained features and instance-wise MLP parameters as its input. - """ - - def __init__(self, cfg, input_shape: ShapeSpec): - """ - The following attributes are parsed from config: - channels: the output dimension of each FC layers - num_layers: the number of FC layers (including the final prediction layer) - image_feature_enabled: if True, fine-grained image-level features are used - positional_encoding_enabled: if True, positional encoding is used - """ - super(ImplicitPointHead, self).__init__() - # fmt: off - self.num_layers = cfg.MODEL.POINT_HEAD.NUM_FC + 1 - self.channels = cfg.MODEL.POINT_HEAD.FC_DIM - self.image_feature_enabled = cfg.MODEL.IMPLICIT_POINTREND.IMAGE_FEATURE_ENABLED - self.positional_encoding_enabled = cfg.MODEL.IMPLICIT_POINTREND.POS_ENC_ENABLED - self.num_classes = ( - cfg.MODEL.POINT_HEAD.NUM_CLASSES if not cfg.MODEL.POINT_HEAD.CLS_AGNOSTIC_MASK else 1 - ) - self.in_channels = input_shape.channels - # fmt: on - - if not self.image_feature_enabled: - self.in_channels = 0 - if self.positional_encoding_enabled: - self.in_channels += 256 - self.register_buffer("positional_encoding_gaussian_matrix", torch.randn((2, 128))) - - assert self.in_channels > 0 - - num_weight_params, num_bias_params = [], [] - assert self.num_layers >= 2 - for l in range(self.num_layers): - if l == 0: - # input layer - num_weight_params.append(self.in_channels * self.channels) - num_bias_params.append(self.channels) - elif l == self.num_layers - 1: - # output layer - num_weight_params.append(self.channels * self.num_classes) - num_bias_params.append(self.num_classes) - else: - # intermediate layer - num_weight_params.append(self.channels * self.channels) - num_bias_params.append(self.channels) - - self.num_weight_params = num_weight_params - self.num_bias_params = num_bias_params - self.num_params = sum(num_weight_params) + sum(num_bias_params) - - def forward(self, fine_grained_features, point_coords, parameters): - # features: [R, channels, K] - # point_coords: [R, K, 2] - num_instances = fine_grained_features.size(0) - num_points = fine_grained_features.size(2) - - if num_instances == 0: - return torch.zeros((0, 1, num_points), device=fine_grained_features.device) - - if self.positional_encoding_enabled: - # locations: [R*K, 2] - locations = 2 * point_coords.reshape(num_instances * num_points, 2) - 1 - locations = locations @ self.positional_encoding_gaussian_matrix.to(locations.device) - locations = 2 * np.pi * locations - locations = torch.cat([torch.sin(locations), torch.cos(locations)], dim=1) - # locations: [R, C, K] - locations = locations.reshape(num_instances, num_points, 256).permute(0, 2, 1) - if not self.image_feature_enabled: - fine_grained_features = locations - else: - fine_grained_features = torch.cat([locations, fine_grained_features], dim=1) - - # features [R, C, K] - mask_feat = fine_grained_features.reshape(num_instances, self.in_channels, num_points) - - weights, biases = self._parse_params( - parameters, - self.in_channels, - self.channels, - self.num_classes, - self.num_weight_params, - self.num_bias_params, - ) - - point_logits = self._dynamic_mlp(mask_feat, weights, biases, num_instances) - point_logits = point_logits.reshape(-1, self.num_classes, num_points) - - return point_logits - - @staticmethod - def _dynamic_mlp(features, weights, biases, num_instances): - assert features.dim() == 3, features.dim() - n_layers = len(weights) - x = features - for i, (w, b) in enumerate(zip(weights, biases)): - x = torch.einsum("nck,ndc->ndk", x, w) + b - if i < n_layers - 1: - x = F.relu(x) - return x - - @staticmethod - def _parse_params( - pred_params, - in_channels, - channels, - num_classes, - num_weight_params, - num_bias_params, - ): - assert pred_params.dim() == 2 - assert len(num_weight_params) == len(num_bias_params) - assert pred_params.size(1) == sum(num_weight_params) + sum(num_bias_params) - - num_instances = pred_params.size(0) - num_layers = len(num_weight_params) - - params_splits = list( - torch.split_with_sizes(pred_params, num_weight_params + num_bias_params, dim=1) - ) - - weight_splits = params_splits[:num_layers] - bias_splits = params_splits[num_layers:] - - for l in range(num_layers): - if l == 0: - # input layer - weight_splits[l] = weight_splits[l].reshape(num_instances, channels, in_channels) - bias_splits[l] = bias_splits[l].reshape(num_instances, channels, 1) - elif l < num_layers - 1: - # intermediate layer - weight_splits[l] = weight_splits[l].reshape(num_instances, channels, channels) - bias_splits[l] = bias_splits[l].reshape(num_instances, channels, 1) - else: - # output layer - weight_splits[l] = weight_splits[l].reshape(num_instances, num_classes, channels) - bias_splits[l] = bias_splits[l].reshape(num_instances, num_classes, 1) - - return weight_splits, bias_splits - - -def build_point_head(cfg, input_channels): - """ - Build a point head defined by `cfg.MODEL.POINT_HEAD.NAME`. - """ - head_name = cfg.MODEL.POINT_HEAD.NAME - return POINT_HEAD_REGISTRY.get(head_name)(cfg, input_channels) diff --git a/preprocess/detectron2/projects/PointRend/point_rend/roi_heads.py b/preprocess/detectron2/projects/PointRend/point_rend/roi_heads.py deleted file mode 100644 index 74ccc34a1193c604fcc34b8deed5ece53fee3f19..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/roi_heads.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging - -from detectron2.modeling import ROI_HEADS_REGISTRY, StandardROIHeads - - -@ROI_HEADS_REGISTRY.register() -class PointRendROIHeads(StandardROIHeads): - """ - Identical to StandardROIHeads, except for some weights conversion code to - handle old models. - """ - - _version = 2 - - def _load_from_state_dict( - self, state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs - ): - version = local_metadata.get("version", None) - if version is None or version < 2: - logger = logging.getLogger(__name__) - logger.warning( - "Weight format of PointRend models have changed! " - "Please upgrade your models. Applying automatic conversion now ..." - ) - for k in list(state_dict.keys()): - newk = k - if k.startswith(prefix + "mask_point_head"): - newk = k.replace(prefix + "mask_point_head", prefix + "mask_head.point_head") - if k.startswith(prefix + "mask_coarse_head"): - newk = k.replace(prefix + "mask_coarse_head", prefix + "mask_head.coarse_head") - if newk != k: - state_dict[newk] = state_dict[k] - del state_dict[k] - - @classmethod - def _init_mask_head(cls, cfg, input_shape): - if cfg.MODEL.MASK_ON and cfg.MODEL.ROI_MASK_HEAD.NAME != "PointRendMaskHead": - logger = logging.getLogger(__name__) - logger.warning( - "Config of PointRend models have changed! " - "Please upgrade your models. Applying automatic conversion now ..." - ) - assert cfg.MODEL.ROI_MASK_HEAD.NAME == "CoarseMaskHead" - cfg.defrost() - cfg.MODEL.ROI_MASK_HEAD.NAME = "PointRendMaskHead" - cfg.MODEL.ROI_MASK_HEAD.POOLER_TYPE = "" - cfg.freeze() - return super()._init_mask_head(cfg, input_shape) diff --git a/preprocess/detectron2/projects/PointRend/point_rend/semantic_seg.py b/preprocess/detectron2/projects/PointRend/point_rend/semantic_seg.py deleted file mode 100644 index ea65200996777022cbb1c3c5dd9c943b67ca4ab1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/point_rend/semantic_seg.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -from typing import Dict -import torch -from torch import nn -from torch.nn import functional as F - -from detectron2.layers import ShapeSpec, cat -from detectron2.modeling import SEM_SEG_HEADS_REGISTRY - -from .point_features import ( - get_uncertain_point_coords_on_grid, - get_uncertain_point_coords_with_randomness, - point_sample, -) -from .point_head import build_point_head - - -def calculate_uncertainty(sem_seg_logits): - """ - For each location of the prediction `sem_seg_logits` we estimate uncerainty as the - difference between top first and top second predicted logits. - - Args: - mask_logits (Tensor): A tensor of shape (N, C, ...), where N is the minibatch size and - C is the number of foreground classes. The values are logits. - - Returns: - scores (Tensor): A tensor of shape (N, 1, ...) that contains uncertainty scores with - the most uncertain locations having the highest uncertainty score. - """ - top2_scores = torch.topk(sem_seg_logits, k=2, dim=1)[0] - return (top2_scores[:, 1] - top2_scores[:, 0]).unsqueeze(1) - - -@SEM_SEG_HEADS_REGISTRY.register() -class PointRendSemSegHead(nn.Module): - """ - A semantic segmentation head that combines a head set in `POINT_HEAD.COARSE_SEM_SEG_HEAD_NAME` - and a point head set in `MODEL.POINT_HEAD.NAME`. - """ - - def __init__(self, cfg, input_shape: Dict[str, ShapeSpec]): - super().__init__() - - self.ignore_value = cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE - - self.coarse_sem_seg_head = SEM_SEG_HEADS_REGISTRY.get( - cfg.MODEL.POINT_HEAD.COARSE_SEM_SEG_HEAD_NAME - )(cfg, input_shape) - self._init_point_head(cfg, input_shape) - - def _init_point_head(self, cfg, input_shape: Dict[str, ShapeSpec]): - # fmt: off - assert cfg.MODEL.SEM_SEG_HEAD.NUM_CLASSES == cfg.MODEL.POINT_HEAD.NUM_CLASSES - feature_channels = {k: v.channels for k, v in input_shape.items()} - self.in_features = cfg.MODEL.POINT_HEAD.IN_FEATURES - self.train_num_points = cfg.MODEL.POINT_HEAD.TRAIN_NUM_POINTS - self.oversample_ratio = cfg.MODEL.POINT_HEAD.OVERSAMPLE_RATIO - self.importance_sample_ratio = cfg.MODEL.POINT_HEAD.IMPORTANCE_SAMPLE_RATIO - self.subdivision_steps = cfg.MODEL.POINT_HEAD.SUBDIVISION_STEPS - self.subdivision_num_points = cfg.MODEL.POINT_HEAD.SUBDIVISION_NUM_POINTS - # fmt: on - - in_channels = int(np.sum([feature_channels[f] for f in self.in_features])) - self.point_head = build_point_head(cfg, ShapeSpec(channels=in_channels, width=1, height=1)) - - def forward(self, features, targets=None): - coarse_sem_seg_logits = self.coarse_sem_seg_head.layers(features) - - if self.training: - losses = self.coarse_sem_seg_head.losses(coarse_sem_seg_logits, targets) - - with torch.no_grad(): - point_coords = get_uncertain_point_coords_with_randomness( - coarse_sem_seg_logits, - calculate_uncertainty, - self.train_num_points, - self.oversample_ratio, - self.importance_sample_ratio, - ) - coarse_features = point_sample(coarse_sem_seg_logits, point_coords, align_corners=False) - - fine_grained_features = cat( - [ - point_sample(features[in_feature], point_coords, align_corners=False) - for in_feature in self.in_features - ], - dim=1, - ) - point_logits = self.point_head(fine_grained_features, coarse_features) - point_targets = ( - point_sample( - targets.unsqueeze(1).to(torch.float), - point_coords, - mode="nearest", - align_corners=False, - ) - .squeeze(1) - .to(torch.long) - ) - losses["loss_sem_seg_point"] = F.cross_entropy( - point_logits, point_targets, reduction="mean", ignore_index=self.ignore_value - ) - return None, losses - else: - sem_seg_logits = coarse_sem_seg_logits.clone() - for _ in range(self.subdivision_steps): - sem_seg_logits = F.interpolate( - sem_seg_logits, scale_factor=2, mode="bilinear", align_corners=False - ) - uncertainty_map = calculate_uncertainty(sem_seg_logits) - point_indices, point_coords = get_uncertain_point_coords_on_grid( - uncertainty_map, self.subdivision_num_points - ) - fine_grained_features = cat( - [ - point_sample(features[in_feature], point_coords, align_corners=False) - for in_feature in self.in_features - ] - ) - coarse_features = point_sample( - coarse_sem_seg_logits, point_coords, align_corners=False - ) - point_logits = self.point_head(fine_grained_features, coarse_features) - - # put sem seg point predictions to the right places on the upsampled grid. - N, C, H, W = sem_seg_logits.shape - point_indices = point_indices.unsqueeze(1).expand(-1, C, -1) - sem_seg_logits = ( - sem_seg_logits.reshape(N, C, H * W) - .scatter_(2, point_indices, point_logits) - .view(N, C, H, W) - ) - return sem_seg_logits, {} diff --git a/preprocess/detectron2/projects/PointRend/train_net.py b/preprocess/detectron2/projects/PointRend/train_net.py deleted file mode 100755 index 418ae9f866c9c9bbbaa047b37aaef484ad30dd6c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointRend/train_net.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -PointRend Training Script. - -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -import detectron2.data.transforms as T -import detectron2.utils.comm as comm -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_train_loader, DatasetMapper, MetadataCatalog -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import ( - CityscapesInstanceEvaluator, - CityscapesSemSegEvaluator, - COCOEvaluator, - DatasetEvaluators, - LVISEvaluator, - SemSegEvaluator, - verify_results, -) -from detectron2.projects.point_rend import add_pointrend_config, ColorAugSSDTransform - - -def build_sem_seg_train_aug(cfg): - augs = [ - T.ResizeShortestEdge( - cfg.INPUT.MIN_SIZE_TRAIN, - cfg.INPUT.MAX_SIZE_TRAIN, - cfg.INPUT.MIN_SIZE_TRAIN_SAMPLING, - ) - ] - if cfg.INPUT.CROP.ENABLED: - augs.append( - T.RandomCrop_CategoryAreaConstraint( - cfg.INPUT.CROP.TYPE, - cfg.INPUT.CROP.SIZE, - cfg.INPUT.CROP.SINGLE_CATEGORY_MAX_AREA, - cfg.MODEL.SEM_SEG_HEAD.IGNORE_VALUE, - ) - ) - if cfg.INPUT.COLOR_AUG_SSD: - augs.append(ColorAugSSDTransform(img_format=cfg.INPUT.FORMAT)) - augs.append(T.RandomFlip()) - return augs - - -class Trainer(DefaultTrainer): - """ - We use the "DefaultTrainer" which contains a number pre-defined logic for - standard training workflow. They may not work for you, especially if you - are working on a new research project. In that case you can use the cleaner - "SimpleTrainer", or write your own training loop. - """ - - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type == "lvis": - return LVISEvaluator(dataset_name, output_dir=output_folder) - if evaluator_type == "coco": - return COCOEvaluator(dataset_name, output_dir=output_folder) - if evaluator_type == "sem_seg": - return SemSegEvaluator( - dataset_name, - distributed=True, - output_dir=output_folder, - ) - if evaluator_type == "cityscapes_instance": - return CityscapesInstanceEvaluator(dataset_name) - if evaluator_type == "cityscapes_sem_seg": - return CityscapesSemSegEvaluator(dataset_name) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - if len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - @classmethod - def build_train_loader(cls, cfg): - if "SemanticSegmentor" in cfg.MODEL.META_ARCHITECTURE: - mapper = DatasetMapper( - cfg, is_train=True, augmentations=build_sem_seg_train_aug(cfg) - ) - else: - mapper = None - return build_detection_train_loader(cfg, mapper=mapper) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_pointrend_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - if comm.is_main_process(): - verify_results(cfg, res) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/PointSup/README.md b/preprocess/detectron2/projects/PointSup/README.md deleted file mode 100644 index 75ce084530d192a522824d01b98a474d77863e68..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pointly-Supervised Instance Segmentation - -Bowen Cheng, Omkar Parkhi, Alexander Kirillov - -[[`arXiv`](https://arxiv.org/abs/2104.06404)] [[`Project`](https://bowenc0221.github.io/point-sup)] [[`BibTeX`](#CitingPointSup)] - -
- -

- -## Data preparation -Please follow these steps to prepare your datasets: -1. Follow official Detectron2 instruction to prepare COCO dataset. Set up `DETECTRON2_DATASETS` environment variable to the location of your Detectron2 dataset. -2. Generate 10-points annotations for COCO by running: `python tools/prepare_coco_point_annotations_without_masks.py 10` - -## Training - -To train a model with 8 GPUs run: -```bash -python train_net.py --config-file configs/mask_rcnn_R_50_FPN_3x_point_sup_point_aug_coco.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly: -```bash -python train_net.py --config-file configs/mask_rcnn_R_50_FPN_3x_point_sup_point_aug_coco.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint -``` - -## Citing Pointly-Supervised Instance Segmentation - -If you use PointSup, please use the following BibTeX entry. - -```BibTeX -@article{cheng2021pointly, - title={Pointly-Supervised Instance Segmentation}, - author={Bowen Cheng and Omkar Parkhi and Alexander Kirillov}, - journal={arXiv}, - year={2021} -} -``` diff --git a/preprocess/detectron2/projects/PointSup/configs/implicit_pointrend_R_50_FPN_3x_point_sup_point_aug_coco.yaml b/preprocess/detectron2/projects/PointSup/configs/implicit_pointrend_R_50_FPN_3x_point_sup_point_aug_coco.yaml deleted file mode 100644 index 5b3d4272c6f8a3820c8d354bfb3c915ccdebfc4a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/configs/implicit_pointrend_R_50_FPN_3x_point_sup_point_aug_coco.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "../../PointRend/configs/InstanceSegmentation/implicit_pointrend_R_50_FPN_3x_coco.yaml" -MODEL: - ROI_MASK_HEAD: - NAME: "ImplicitPointRendPointSupHead" -INPUT: - POINT_SUP: True - SAMPLE_POINTS: 5 -DATASETS: - TRAIN: ("coco_2017_train_points_n10_v1_without_masks",) diff --git a/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_coco.yaml b/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_coco.yaml deleted file mode 100644 index 157e3844ef68779cda3579bee5d8c132826c9fba..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_coco.yaml +++ /dev/null @@ -1,15 +0,0 @@ -_BASE_: "../../../configs/Base-RCNN-FPN.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: True - RESNETS: - DEPTH: 50 - ROI_MASK_HEAD: - NAME: "MaskRCNNConvUpsamplePointSupHead" -INPUT: - POINT_SUP: True -DATASETS: - TRAIN: ("coco_2017_train_points_n10_v1_without_masks",) -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_point_aug_coco.yaml b/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_point_aug_coco.yaml deleted file mode 100644 index 4b11224d595bed88238e02caeb4833b0b1d7b286..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/configs/mask_rcnn_R_50_FPN_3x_point_sup_point_aug_coco.yaml +++ /dev/null @@ -1,3 +0,0 @@ -_BASE_: "mask_rcnn_R_50_FPN_3x_point_sup_coco.yaml" -INPUT: - SAMPLE_POINTS: 5 diff --git a/preprocess/detectron2/projects/PointSup/point_sup/__init__.py b/preprocess/detectron2/projects/PointSup/point_sup/__init__.py deleted file mode 100644 index 510e3814ac1bb273b48804191b4a7c1272ea9a9b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -from . import register_point_annotations -from .config import add_point_sup_config -from .dataset_mapper import PointSupDatasetMapper -from .mask_head import MaskRCNNConvUpsamplePointSupHead -from .point_utils import get_point_coords_from_point_annotation diff --git a/preprocess/detectron2/projects/PointSup/point_sup/config.py b/preprocess/detectron2/projects/PointSup/point_sup/config.py deleted file mode 100644 index 5e00b786cf6055a0cda664f143c1fac56a3c6d11..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/config.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - - -def add_point_sup_config(cfg): - """ - Add config for point supervision. - """ - # Use point annotation - cfg.INPUT.POINT_SUP = False - # Sample only part of points in each iteration. - # Default: 0, use all available points. - cfg.INPUT.SAMPLE_POINTS = 0 diff --git a/preprocess/detectron2/projects/PointSup/point_sup/dataset_mapper.py b/preprocess/detectron2/projects/PointSup/point_sup/dataset_mapper.py deleted file mode 100644 index aba7b9fd2a0366d3761af7022f9325040d750f0b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/dataset_mapper.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -import copy -import logging -import numpy as np -from typing import List, Union -import torch - -import detectron2.data.detection_utils as utils -import detectron2.data.transforms as T -from detectron2.config import configurable - -from .detection_utils import annotations_to_instances, transform_instance_annotations - -__all__ = [ - "PointSupDatasetMapper", -] - - -class PointSupDatasetMapper: - """ - The callable currently does the following: - 1. Read the image from "file_name" - 2. Applies transforms to the image and annotations - 3. Prepare data and annotations to Tensor and :class:`Instances` - """ - - @configurable - def __init__( - self, - is_train: bool, - *, - augmentations: List[Union[T.Augmentation, T.Transform]], - image_format: str, - # Extra data augmentation for point supervision - sample_points: int = 0, - ): - """ - NOTE: this interface is experimental. - - Args: - is_train: whether it's used in training or inference - augmentations: a list of augmentations or deterministic transforms to apply - image_format: an image format supported by :func:`detection_utils.read_image`. - sample_points: subsample points at each iteration - """ - # fmt: off - self.is_train = is_train - self.augmentations = T.AugmentationList(augmentations) - self.image_format = image_format - self.sample_points = sample_points - # fmt: on - logger = logging.getLogger(__name__) - mode = "training" if is_train else "inference" - logger.info(f"[DatasetMapper] Augmentations used in {mode}: {augmentations}") - logger.info(f"Point Augmentations used in {mode}: sample {sample_points} points") - - @classmethod - def from_config(cls, cfg, is_train: bool = True): - augs = utils.build_augmentation(cfg, is_train) - if cfg.INPUT.CROP.ENABLED and is_train: - raise ValueError("Crop augmentation not supported to point supervision.") - - ret = { - "is_train": is_train, - "augmentations": augs, - "image_format": cfg.INPUT.FORMAT, - "sample_points": cfg.INPUT.SAMPLE_POINTS, - } - - return ret - - def __call__(self, dataset_dict): - """ - Args: - dataset_dict (dict): Metadata of one image, in Detectron2 Dataset format. - Returns: - dict: a format that builtin models in detectron2 accept - """ - dataset_dict = copy.deepcopy(dataset_dict) # it will be modified by code below - image = utils.read_image(dataset_dict["file_name"], format=self.image_format) - utils.check_image_size(dataset_dict, image) - - aug_input = T.AugInput(image) - transforms = self.augmentations(aug_input) - image = aug_input.image - - image_shape = image.shape[:2] # h, w - # Pytorch's dataloader is efficient on torch.Tensor due to shared-memory, - # but not efficient on large generic data structures due to the use of pickle & mp.Queue. - # Therefore it's important to use torch.Tensor. - dataset_dict["image"] = torch.as_tensor(np.ascontiguousarray(image.transpose(2, 0, 1))) - - if not self.is_train: - dataset_dict.pop("annotations", None) - return dataset_dict - - if "annotations" in dataset_dict: - # Maps points from the closed interval [0, image_size - 1] on discrete - # image coordinates to the half-open interval [x1, x2) on continuous image - # coordinates. We use the continuous-discrete conversion from Heckbert - # 1990 ("What is the coordinate of a pixel?"): d = floor(c) and c = d + 0.5, - # where d is a discrete coordinate and c is a continuous coordinate. - for ann in dataset_dict["annotations"]: - point_coords_wrt_image = np.array(ann["point_coords"]).astype(float) - point_coords_wrt_image = point_coords_wrt_image + 0.5 - ann["point_coords"] = point_coords_wrt_image - - annos = [ - # also need to transform point coordinates - transform_instance_annotations( - obj, - transforms, - image_shape, - ) - for obj in dataset_dict.pop("annotations") - if obj.get("iscrowd", 0) == 0 - ] - instances = annotations_to_instances( - annos, - image_shape, - sample_points=self.sample_points, - ) - - dataset_dict["instances"] = utils.filter_empty_instances(instances) - return dataset_dict diff --git a/preprocess/detectron2/projects/PointSup/point_sup/detection_utils.py b/preprocess/detectron2/projects/PointSup/point_sup/detection_utils.py deleted file mode 100644 index c97ffcbe29ff744a91585e75e225557b6c0f2a35..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/detection_utils.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -import numpy as np -import torch - -# fmt: off -from detectron2.data.detection_utils import \ - annotations_to_instances as base_annotations_to_instances -from detectron2.data.detection_utils import \ - transform_instance_annotations as base_transform_instance_annotations - -# fmt: on - - -def annotations_to_instances(annos, image_size, sample_points=0): - """ - Create an :class:`Instances` object used by the models, - from instance annotations in the dataset dict. - - Args: - annos (list[dict]): a list of instance annotations in one image, each - element for one instance. - image_size (tuple): height, width - sample_points (int): subsample points at each iteration - - Returns: - Instances: - It will contain fields "gt_boxes", "gt_classes", - "gt_point_coords", "gt_point_labels", if they can be obtained from `annos`. - This is the format that builtin models with point supervision expect. - """ - target = base_annotations_to_instances(annos, image_size) - - assert ("point_coords" in annos[0]) == ("point_labels" in annos[0]) - - if len(annos) and "point_labels" in annos[0]: - point_coords = [] - point_labels = [] - for i, _ in enumerate(annos): - # Already in the image coordinate system - point_coords_wrt_image = np.array(annos[i]["point_coords"]) - point_labels_wrt_image = np.array(annos[i]["point_labels"]) - - if sample_points > 0: - random_indices = np.random.choice( - point_coords_wrt_image.shape[0], - sample_points, - replace=point_coords_wrt_image.shape[0] < sample_points, - ).astype(int) - point_coords_wrt_image = point_coords_wrt_image[random_indices] - point_labels_wrt_image = point_labels_wrt_image[random_indices] - assert point_coords_wrt_image.shape[0] == point_labels_wrt_image.size - - point_coords.append(point_coords_wrt_image) - point_labels.append(point_labels_wrt_image) - - point_coords = torch.stack([torch.from_numpy(x) for x in point_coords]) - point_labels = torch.stack([torch.from_numpy(x) for x in point_labels]) - target.gt_point_coords = point_coords - target.gt_point_labels = point_labels - - return target - - -def transform_instance_annotations( - annotation, transforms, image_size, *, keypoint_hflip_indices=None -): - """ - Apply transforms to box, and point annotations of a single instance. - It will use `transforms.apply_box` for the box, and - `transforms.apply_coords` for points. - Args: - annotation (dict): dict of instance annotations for a single instance. - It will be modified in-place. - transforms (TransformList or list[Transform]): - image_size (tuple): the height, width of the transformed image - keypoint_hflip_indices (ndarray[int]): see `create_keypoint_hflip_indices`. - Returns: - dict: - the same input dict with fields "bbox", "point_coords", "point_labels" - transformed according to `transforms`. - The "bbox_mode" field will be set to XYXY_ABS. - """ - annotation = base_transform_instance_annotations( - annotation, transforms, image_size, keypoint_hflip_indices - ) - - assert ("point_coords" in annotation) == ("point_labels" in annotation) - if "point_coords" in annotation and "point_labels" in annotation: - point_coords = annotation["point_coords"] - point_labels = np.array(annotation["point_labels"]).astype(float) - point_coords = transforms.apply_coords(point_coords) - - # Set all out-of-boundary points to "unlabeled" - inside = (point_coords >= np.array([0, 0])) & (point_coords <= np.array(image_size[::-1])) - inside = inside.all(axis=1) - point_labels[~inside] = -1 - - annotation["point_coords"] = point_coords - annotation["point_labels"] = point_labels - - return annotation diff --git a/preprocess/detectron2/projects/PointSup/point_sup/mask_head.py b/preprocess/detectron2/projects/PointSup/point_sup/mask_head.py deleted file mode 100644 index 81c21f55009b1891c4684e2eaa8fee0f144b0a54..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/mask_head.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -import numpy as np -from typing import Any, List - -from detectron2.modeling import ROI_MASK_HEAD_REGISTRY -from detectron2.modeling.roi_heads.mask_head import MaskRCNNConvUpsampleHead, mask_rcnn_inference -from detectron2.projects.point_rend import ImplicitPointRendMaskHead -from detectron2.projects.point_rend.point_features import point_sample -from detectron2.projects.point_rend.point_head import roi_mask_point_loss -from detectron2.structures import Instances - -from .point_utils import get_point_coords_from_point_annotation - -__all__ = [ - "ImplicitPointRendPointSupHead", - "MaskRCNNConvUpsamplePointSupHead", -] - - -@ROI_MASK_HEAD_REGISTRY.register() -class MaskRCNNConvUpsamplePointSupHead(MaskRCNNConvUpsampleHead): - """ - A mask head with several conv layers, plus an upsample layer (with `ConvTranspose2d`). - Predictions are made with a final 1x1 conv layer. - - The difference with `MaskRCNNConvUpsampleHead` is that this head is trained - with point supervision. Please use the `MaskRCNNConvUpsampleHead` if you want - to train the model with mask supervision. - """ - - def forward(self, x, instances: List[Instances]) -> Any: - """ - Args: - x: input region feature(s) provided by :class:`ROIHeads`. - instances (list[Instances]): contains the boxes & labels corresponding - to the input features. - Exact format is up to its caller to decide. - Typically, this is the foreground instances in training, with - "proposal_boxes" field and other gt annotations. - In inference, it contains boxes that are already predicted. - Returns: - A dict of losses in training. The predicted "instances" in inference. - """ - x = self.layers(x) - if self.training: - N, C, H, W = x.shape - assert H == W - - proposal_boxes = [x.proposal_boxes for x in instances] - assert N == np.sum(len(x) for x in proposal_boxes) - - if N == 0: - return {"loss_mask": x.sum() * 0} - - # Training with point supervision - point_coords, point_labels = get_point_coords_from_point_annotation(instances) - - mask_logits = point_sample( - x, - point_coords, - align_corners=False, - ) - - return {"loss_mask": roi_mask_point_loss(mask_logits, instances, point_labels)} - else: - mask_rcnn_inference(x, instances) - return instances - - -@ROI_MASK_HEAD_REGISTRY.register() -class ImplicitPointRendPointSupHead(ImplicitPointRendMaskHead): - def _uniform_sample_train_points(self, instances): - assert self.training - # Please keep in mind that "gt_masks" is not used in this mask head. - point_coords, point_labels = get_point_coords_from_point_annotation(instances) - - return point_coords, point_labels diff --git a/preprocess/detectron2/projects/PointSup/point_sup/point_utils.py b/preprocess/detectron2/projects/PointSup/point_sup/point_utils.py deleted file mode 100644 index eed876ea9e0127c584c008bd5aab3e16e2c8c66a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/point_utils.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -import torch - -from detectron2.layers import cat - - -def get_point_coords_from_point_annotation(instances): - """ - Load point coords and their corresponding labels from point annotation. - - Args: - instances (list[Instances]): A list of N Instances, where N is the number of images - in the batch. These instances are in 1:1 - correspondence with the pred_mask_logits. The ground-truth labels (class, box, mask, - ...) associated with each instance are stored in fields. - Returns: - point_coords (Tensor): A tensor of shape (N, P, 2) that contains the coordinates of P - sampled points. - point_labels (Tensor): A tensor of shape (N, P) that contains the labels of P - sampled points. `point_labels` takes 3 possible values: - - 0: the point belongs to background - - 1: the point belongs to the object - - -1: the point is ignored during training - """ - point_coords_list = [] - point_labels_list = [] - for instances_per_image in instances: - if len(instances_per_image) == 0: - continue - point_coords = instances_per_image.gt_point_coords.to(torch.float32) - point_labels = instances_per_image.gt_point_labels.to(torch.float32).clone() - proposal_boxes_per_image = instances_per_image.proposal_boxes.tensor - - # Convert point coordinate system, ground truth points are in image coord. - point_coords_wrt_box = get_point_coords_wrt_box(proposal_boxes_per_image, point_coords) - - # Ignore points that are outside predicted boxes. - point_ignores = ( - (point_coords_wrt_box[:, :, 0] < 0) - | (point_coords_wrt_box[:, :, 0] > 1) - | (point_coords_wrt_box[:, :, 1] < 0) - | (point_coords_wrt_box[:, :, 1] > 1) - ) - point_labels[point_ignores] = -1 - - point_coords_list.append(point_coords_wrt_box) - point_labels_list.append(point_labels) - - return ( - cat(point_coords_list, dim=0), - cat(point_labels_list, dim=0), - ) - - -def get_point_coords_wrt_box(boxes_coords, point_coords): - """ - Convert image-level absolute coordinates to box-normalized [0, 1] x [0, 1] point cooordinates. - Args: - boxes_coords (Tensor): A tensor of shape (R, 4) that contains bounding boxes. - coordinates. - point_coords (Tensor): A tensor of shape (R, P, 2) that contains - image-normalized coordinates of P sampled points. - Returns: - point_coords_wrt_box (Tensor): A tensor of shape (R, P, 2) that contains - [0, 1] x [0, 1] box-normalized coordinates of the P sampled points. - """ - with torch.no_grad(): - point_coords_wrt_box = point_coords.clone() - point_coords_wrt_box[:, :, 0] -= boxes_coords[:, None, 0] - point_coords_wrt_box[:, :, 1] -= boxes_coords[:, None, 1] - point_coords_wrt_box[:, :, 0] = point_coords_wrt_box[:, :, 0] / ( - boxes_coords[:, None, 2] - boxes_coords[:, None, 0] - ) - point_coords_wrt_box[:, :, 1] = point_coords_wrt_box[:, :, 1] / ( - boxes_coords[:, None, 3] - boxes_coords[:, None, 1] - ) - return point_coords_wrt_box diff --git a/preprocess/detectron2/projects/PointSup/point_sup/register_point_annotations.py b/preprocess/detectron2/projects/PointSup/point_sup/register_point_annotations.py deleted file mode 100644 index 32f2bb45e864e5be9d002f4d07badb91700ace4b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/point_sup/register_point_annotations.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved -import logging -import os - -from detectron2.data import DatasetCatalog, MetadataCatalog -from detectron2.data.datasets.builtin import _get_builtin_metadata -from detectron2.data.datasets.coco import load_coco_json - -logger = logging.getLogger(__name__) - - -# COCO dataset -def register_coco_instances_with_points(name, metadata, json_file, image_root): - """ - Register a dataset in COCO's json annotation format for - instance segmentation with point annotation. - - The point annotation json does not have "segmentation" field, instead, - it has "point_coords" and "point_labels" fields. - - Args: - name (str): the name that identifies a dataset, e.g. "coco_2014_train". - metadata (dict): extra metadata associated with this dataset. You can - leave it as an empty dict. - json_file (str): path to the json instance annotation file. - image_root (str or path-like): directory which contains all the images. - """ - assert isinstance(name, str), name - assert isinstance(json_file, (str, os.PathLike)), json_file - assert isinstance(image_root, (str, os.PathLike)), image_root - # 1. register a function which returns dicts - DatasetCatalog.register( - name, lambda: load_coco_json(json_file, image_root, name, ["point_coords", "point_labels"]) - ) - - # 2. Optionally, add metadata about this dataset, - # since they might be useful in evaluation, visualization or logging - MetadataCatalog.get(name).set( - json_file=json_file, image_root=image_root, evaluator_type="coco", **metadata - ) - - -_PREDEFINED_SPLITS_COCO = {} -_PREDEFINED_SPLITS_COCO["coco"] = { - # point annotations without masks - "coco_2017_train_points_n10_v1_without_masks": ( - "coco/train2017", - "coco/annotations/instances_train2017_n10_v1_without_masks.json", - ), -} - - -def register_all_coco_train_points(root): - for dataset_name, splits_per_dataset in _PREDEFINED_SPLITS_COCO.items(): - for key, (image_root, json_file) in splits_per_dataset.items(): - # Assume pre-defined datasets live in `./datasets`. - register_coco_instances_with_points( - key, - _get_builtin_metadata(dataset_name), - os.path.join(root, json_file) if "://" not in json_file else json_file, - os.path.join(root, image_root), - ) - - -# True for open source; -# Internally at fb, we register them elsewhere -if __name__.endswith(".register_point_annotations"): - _root = os.getenv("DETECTRON2_DATASETS", "datasets") - register_all_coco_train_points(_root) diff --git a/preprocess/detectron2/projects/PointSup/tools/prepare_coco_point_annotations_without_masks.py b/preprocess/detectron2/projects/PointSup/tools/prepare_coco_point_annotations_without_masks.py deleted file mode 100644 index e4aee2aedf2e62e2357f278417ac58c6b4ff264e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/tools/prepare_coco_point_annotations_without_masks.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -import copy -import json -import numpy as np -import os -import sys -import pycocotools.mask as mask_utils - -from detectron2.utils.env import seed_all_rng -from detectron2.utils.file_io import PathManager - - -def get_point_annotations(input_filename, output_filename, num_points_per_instance): - with PathManager.open(input_filename, "r") as f: - coco_json = json.load(f) - - coco_annos = coco_json.pop("annotations") - coco_points_json = copy.deepcopy(coco_json) - - imgs = {} - for img in coco_json["images"]: - imgs[img["id"]] = img - - new_annos = [] - for ann in coco_annos: - # convert mask - t = imgs[ann["image_id"]] - h, w = t["height"], t["width"] - segm = ann.pop("segmentation") - if type(segm) == list: - # polygon -- a single object might consist of multiple parts - # we merge all parts into one mask rle code - rles = mask_utils.frPyObjects(segm, h, w) - rle = mask_utils.merge(rles) - elif type(segm["counts"]) == list: - # uncompressed RLE - rle = mask_utils.frPyObjects(segm, h, w) - else: - # rle - rle = segm - mask = mask_utils.decode(rle) - new_ann = copy.deepcopy(ann) - # sample points in image coordinates - box = ann["bbox"] - point_coords_wrt_image = np.random.rand(num_points_per_instance, 2) - point_coords_wrt_image[:, 0] = point_coords_wrt_image[:, 0] * box[2] - point_coords_wrt_image[:, 1] = point_coords_wrt_image[:, 1] * box[3] - point_coords_wrt_image[:, 0] += box[0] - point_coords_wrt_image[:, 1] += box[1] - # round to integer coordinates - point_coords_wrt_image = np.floor(point_coords_wrt_image).astype(int) - # get labels - assert (point_coords_wrt_image >= 0).all(), (point_coords_wrt_image, mask.shape) - assert (point_coords_wrt_image[:, 0] < w).all(), (point_coords_wrt_image, mask.shape) - assert (point_coords_wrt_image[:, 1] < h).all(), (point_coords_wrt_image, mask.shape) - point_labels = mask[point_coords_wrt_image[:, 1], point_coords_wrt_image[:, 0]] - # store new annotations - new_ann["point_coords"] = point_coords_wrt_image.tolist() - new_ann["point_labels"] = point_labels.tolist() - new_annos.append(new_ann) - coco_points_json["annotations"] = new_annos - - with PathManager.open(output_filename, "w") as f: - json.dump(coco_points_json, f) - - print("{} is modified and stored in {}.".format(input_filename, output_filename)) - - -if __name__ == "__main__": - """ - Generate point-based supervision for COCO dataset. - - Usage: - python tools/prepare_coco_point_annotations_without_masks.py \ - NUM_POINTS_PER_INSTANCE NUM_VERSIONS_WITH_DIFFERENT_SEED - - Example to generate point-based COCO dataset with 10 points per instance: - python tools/prepare_coco_point_annotations_without_masks.py 10 - """ - - # Fix random seed - seed_all_rng(12345) - - assert len(sys.argv) >= 2, "Please provide number of points to sample per instance" - dataset_dir = os.path.join(os.getenv("DETECTRON2_DATASETS", "datasets"), "coco/annotations") - num_points_per_instance = int(sys.argv[1]) - if len(sys.argv) == 3: - repeat = int(sys.argv[2]) - else: - repeat = 1 - s = "instances_train2017" - for version in range(repeat): - print( - "Start sampling {} points per instance for annotations {}.".format( - num_points_per_instance, s - ) - ) - get_point_annotations( - os.path.join(dataset_dir, "{}.json".format(s)), - os.path.join( - dataset_dir, - "{}_n{}_v{}_without_masks.json".format(s, num_points_per_instance, version + 1), - ), - num_points_per_instance, - ) diff --git a/preprocess/detectron2/projects/PointSup/train_net.py b/preprocess/detectron2/projects/PointSup/train_net.py deleted file mode 100755 index 05291fa092a32baeecf6bbf64c77e8edd119b6fa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/PointSup/train_net.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -""" -Point supervision Training Script. - -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -import detectron2.utils.comm as comm -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_train_loader, MetadataCatalog -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import COCOEvaluator, DatasetEvaluators, verify_results -from detectron2.projects.point_rend import add_pointrend_config -from detectron2.utils.logger import setup_logger - -from point_sup import add_point_sup_config, PointSupDatasetMapper - - -class Trainer(DefaultTrainer): - """ - We use the "DefaultTrainer" which contains pre-defined default logic for - standard training workflow. They may not work for you, especially if you - are working on a new research project. In that case you can write your - own training loop. You can use "tools/plain_train_net.py" as an example. - """ - - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type == "coco": - evaluator_list.append(COCOEvaluator(dataset_name, output_dir=output_folder)) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - elif len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - @classmethod - def build_train_loader(cls, cfg): - if cfg.INPUT.POINT_SUP: - mapper = PointSupDatasetMapper(cfg, is_train=True) - else: - mapper = None - return build_detection_train_loader(cfg, mapper=mapper) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_pointrend_config(cfg) - add_point_sup_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - # Setup logger for "point_sup" module - setup_logger( - output=cfg.OUTPUT_DIR, distributed_rank=comm.get_rank(), name="point_sup" - ) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - if cfg.TEST.AUG.ENABLED: - res.update(Trainer.test_with_TTA(cfg, model)) - if comm.is_main_process(): - verify_results(cfg, res) - return res - - """ - If you'd like to do anything fancier than the standard training logic, - consider writing your own training loop (see plain_train_net.py) or - subclassing the trainer. - """ - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/README.md b/preprocess/detectron2/projects/README.md deleted file mode 100644 index 7fb29afcf239797ffe5061aabfef3000d820e38f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/README.md +++ /dev/null @@ -1,50 +0,0 @@ - -Here are a few projects that are built on detectron2. -They are examples of how to use detectron2 as a library, to make your projects more -maintainable. - -## Projects by Facebook - -Note that these are research projects, and therefore may not have the same level -of support or stability as detectron2. - -+ [DensePose: Dense Human Pose Estimation In The Wild](DensePose) -+ [Scale-Aware Trident Networks for Object Detection](TridentNet) -+ [TensorMask: A Foundation for Dense Object Segmentation](TensorMask) -+ [Mesh R-CNN](https://github.com/facebookresearch/meshrcnn) -+ [PointRend: Image Segmentation as Rendering](PointRend) -+ [Momentum Contrast for Unsupervised Visual Representation Learning](https://github.com/facebookresearch/moco/tree/master/detection) -+ [DETR: End-to-End Object Detection with Transformers](https://github.com/facebookresearch/detr/tree/master/d2) -+ [Panoptic-DeepLab: A Simple, Strong, and Fast Baseline for Bottom-Up Panoptic Segmentation](Panoptic-DeepLab) -+ [D2Go (Detectron2Go)](https://github.com/facebookresearch/d2go), an end-to-end production system for training and deployment for mobile platforms. -+ [Pointly-Supervised Instance Segmentation](PointSup) -+ [Unbiased Teacher for Semi-Supervised Object Detection](https://github.com/facebookresearch/unbiased-teacher) -+ [Rethinking "Batch" in BatchNorm](Rethinking-BatchNorm/) -+ [Per-Pixel Classification is Not All You Need for Semantic Segmentation](https://github.com/facebookresearch/MaskFormer) -+ [Exploring Plain Vision Transformer Backbones for Object Detection](ViTDet/) -+ [MViTv2: Improved Multiscale Vision Transformers for Classification and Detection](MViTv2/) - - -## External Projects - -External projects in the community that use detectron2: - - - -+ [AdelaiDet](https://github.com/aim-uofa/adet), a detection toolbox including FCOS, BlendMask, etc. -+ [CenterMask](https://github.com/youngwanLEE/centermask2) -+ [Res2Net backbones](https://github.com/Res2Net/Res2Net-detectron2) -+ [VoVNet backbones](https://github.com/youngwanLEE/vovnet-detectron2) -+ [FsDet](https://github.com/ucbdrive/few-shot-object-detection), Few-Shot Object Detection. -+ [Sparse R-CNN](https://github.com/PeizeSun/SparseR-CNN) -+ [BCNet](https://github.com/lkeab/BCNet), a bilayer decoupling instance segmentation method. -+ [DD3D](https://github.com/TRI-ML/dd3d), A fully convolutional 3D detector. -+ [detrex](https://github.com/IDEA-Research/detrex), a detection toolbox for transformer-based detection algorithms including Deformable-DETR, DAB-DETR, DN-DETR, DINO, etc. diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/README.md b/preprocess/detectron2/projects/Rethinking-BatchNorm/README.md deleted file mode 100644 index 42c5c68fb4837043df62ff398f15fe0326f96e1c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Rethinking "Batch" in BatchNorm - -We provide configs that reproduce detection experiments in the paper [Rethinking "Batch" in BatchNorm](https://arxiv.org/abs/2105.07576). - -All configs can be trained with: - -``` -../../tools/lazyconfig_train_net.py --config-file configs/X.py --num-gpus 8 -``` - -## Mask R-CNN - -* `mask_rcnn_BNhead.py`, `mask_rcnn_BNhead_batch_stats.py`: - Mask R-CNN with BatchNorm in the head. See Table 3 in the paper. - -* `mask_rcnn_BNhead_shuffle.py`: Mask R-CNN with cross-GPU shuffling of head inputs. - See Figure 9 and Table 6 in the paper. - -* `mask_rcnn_SyncBNhead.py`: Mask R-CNN with cross-GPU SyncBatchNorm in the head. - It matches Table 6 in the paper. - -## RetinaNet - -* `retinanet_SyncBNhead.py`: RetinaNet with SyncBN in head, a straightforward implementation - which matches row 3 of Table 5. - -* `retinanet_SyncBNhead_SharedTraining.py`: RetinaNet with SyncBN in head, normalizing - all 5 feature levels together. Match row 1 of Table 5. - -The script `retinanet-eval-domain-specific.py` evaluates a checkpoint after recomputing -domain-specific statistics. Running it with -``` -./retinanet-eval-domain-specific.py checkpoint.pth -``` -on a model produced by the above two configs, can produce results that match row 4 and -row 2 of Table 5. diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead.py deleted file mode 100644 index 336c133e0e34ee82674d595ef98d1844f801fa4f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead.py +++ /dev/null @@ -1,18 +0,0 @@ -from detectron2.model_zoo import get_config - -model = get_config("common/models/mask_rcnn_fpn.py").model - -model.backbone.bottom_up.freeze_at = 2 - -model.roi_heads.box_head.conv_norm = model.roi_heads.mask_head.conv_norm = "BN" -# 4conv1fc head -model.roi_heads.box_head.conv_dims = [256, 256, 256, 256] -model.roi_heads.box_head.fc_dims = [1024] - -dataloader = get_config("common/data/coco.py").dataloader -lr_multiplier = get_config("common/coco_schedule.py").lr_multiplier_3x -optimizer = get_config("common/optim.py").SGD -train = get_config("common/train.py").train - -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -train.max_iter = 270000 # 3x for batchsize = 16 diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_batch_stats.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_batch_stats.py deleted file mode 100644 index 872e17c8a9aa000250a0a61613ddb3e3886f9991..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_batch_stats.py +++ /dev/null @@ -1,20 +0,0 @@ -from torch.nn import BatchNorm2d -from torch.nn import functional as F - - -class BatchNormBatchStat(BatchNorm2d): - """ - BN that uses batch stat in inference - """ - - def forward(self, input): - if self.training: - return super().forward(input) - return F.batch_norm(input, None, None, self.weight, self.bias, True, 1.0, self.eps) - - -# After training with the base config, it's sufficient to load its model with -# this config only for inference -- because the training-time behavior is identical. -from .mask_rcnn_BNhead import model, dataloader, lr_multiplier, optimizer, train - -model.roi_heads.box_head.conv_norm = model.roi_heads.mask_head.conv_norm = BatchNormBatchStat diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_shuffle.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_shuffle.py deleted file mode 100644 index 5117a7dad0f952af02580e5373a7be52b749ee86..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_BNhead_shuffle.py +++ /dev/null @@ -1,74 +0,0 @@ -import math -import torch -import torch.distributed as dist - -from detectron2.modeling.roi_heads import FastRCNNConvFCHead, MaskRCNNConvUpsampleHead -from detectron2.utils import comm -from fvcore.nn.distributed import differentiable_all_gather - - -def concat_all_gather(input): - bs_int = input.shape[0] - size_list = comm.all_gather(bs_int) - max_size = max(size_list) - max_shape = (max_size,) + input.shape[1:] - - padded_input = input.new_zeros(max_shape) - padded_input[:bs_int] = input - all_inputs = differentiable_all_gather(padded_input) - inputs = [x[:sz] for sz, x in zip(size_list, all_inputs)] - return inputs, size_list - - -def batch_shuffle(x): - # gather from all gpus - batch_size_this = x.shape[0] - all_xs, batch_size_all = concat_all_gather(x) - all_xs_concat = torch.cat(all_xs, dim=0) - total_bs = sum(batch_size_all) - - rank = dist.get_rank() - assert batch_size_all[rank] == batch_size_this - - idx_range = (sum(batch_size_all[:rank]), sum(batch_size_all[: rank + 1])) - - # random shuffle index - idx_shuffle = torch.randperm(total_bs, device=x.device) - # broadcast to all gpus - dist.broadcast(idx_shuffle, src=0) - - # index for restoring - idx_unshuffle = torch.argsort(idx_shuffle) - - # shuffled index for this gpu - splits = torch.split(idx_shuffle, math.ceil(total_bs / dist.get_world_size())) - if len(splits) > rank: - idx_this = splits[rank] - else: - idx_this = idx_shuffle.new_zeros([0]) - return all_xs_concat[idx_this], idx_unshuffle[idx_range[0] : idx_range[1]] - - -def batch_unshuffle(x, idx_unshuffle): - all_x, _ = concat_all_gather(x) - x_gather = torch.cat(all_x, dim=0) - return x_gather[idx_unshuffle] - - -def wrap_shuffle(module_type, method): - def new_method(self, x): - if self.training: - x, idx = batch_shuffle(x) - x = getattr(module_type, method)(self, x) - if self.training: - x = batch_unshuffle(x, idx) - return x - - return type(module_type.__name__ + "WithShuffle", (module_type,), {method: new_method}) - - -from .mask_rcnn_BNhead import model, dataloader, lr_multiplier, optimizer, train - - -model.roi_heads.box_head._target_ = wrap_shuffle(FastRCNNConvFCHead, "forward") -model.roi_heads.mask_head._target_ = wrap_shuffle(MaskRCNNConvUpsampleHead, "layers") diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_SyncBNhead.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_SyncBNhead.py deleted file mode 100644 index 5f05da03514a4ee6aa37d6bc3e678873ead73c61..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/mask_rcnn_SyncBNhead.py +++ /dev/null @@ -1,3 +0,0 @@ -from .mask_rcnn_BNhead import model, dataloader, lr_multiplier, optimizer, train - -model.roi_heads.box_head.conv_norm = model.roi_heads.mask_head.conv_norm = "SyncBN" diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead.py deleted file mode 100644 index 222dfddffb1f9bedf87f4c345534045b29e2d8ee..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead.py +++ /dev/null @@ -1,19 +0,0 @@ -from detectron2.model_zoo import get_config -from torch import nn - -model = get_config("common/models/retinanet.py").model -model.backbone.bottom_up.freeze_at = 2 - -# The head will overwrite string "SyncBN" to use domain-specific BN, so we -# provide a class here to use shared BN in training. -model.head.norm = nn.SyncBatchNorm2d - -dataloader = get_config("common/data/coco.py").dataloader -lr_multiplier = get_config("common/coco_schedule.py").lr_multiplier_3x -optimizer = get_config("common/optim.py").SGD -train = get_config("common/train.py").train - -optimizer.lr = 0.01 - -train.init_checkpoint = "detectron2://ImageNetPretrained/MSRA/R-50.pkl" -train.max_iter = 270000 # 3x for batchsize = 16 diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead_SharedTraining.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead_SharedTraining.py deleted file mode 100644 index 3f146009d04aad2fca08d970569a4d76d46c9bd2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/configs/retinanet_SyncBNhead_SharedTraining.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import List -import torch -from torch import Tensor, nn - -from detectron2.modeling.meta_arch.retinanet import RetinaNetHead - - -def apply_sequential(inputs, modules): - for mod in modules: - if isinstance(mod, (nn.BatchNorm2d, nn.SyncBatchNorm)): - # for BN layer, normalize all inputs together - shapes = [i.shape for i in inputs] - spatial_sizes = [s[2] * s[3] for s in shapes] - x = [i.flatten(2) for i in inputs] - x = torch.cat(x, dim=2).unsqueeze(3) - x = mod(x).split(spatial_sizes, dim=2) - inputs = [i.view(s) for s, i in zip(shapes, x)] - else: - inputs = [mod(i) for i in inputs] - return inputs - - -class RetinaNetHead_SharedTrainingBN(RetinaNetHead): - def forward(self, features: List[Tensor]): - logits = apply_sequential(features, list(self.cls_subnet) + [self.cls_score]) - bbox_reg = apply_sequential(features, list(self.bbox_subnet) + [self.bbox_pred]) - return logits, bbox_reg - - -from .retinanet_SyncBNhead import model, dataloader, lr_multiplier, optimizer, train - -model.head._target_ = RetinaNetHead_SharedTrainingBN diff --git a/preprocess/detectron2/projects/Rethinking-BatchNorm/retinanet-eval-domain-specific.py b/preprocess/detectron2/projects/Rethinking-BatchNorm/retinanet-eval-domain-specific.py deleted file mode 100755 index 49a74adf1f286135c5551d9b31e722169f23b8f0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/Rethinking-BatchNorm/retinanet-eval-domain-specific.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -import sys -import torch -from fvcore.nn.precise_bn import update_bn_stats - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import LazyConfig, instantiate -from detectron2.evaluation import inference_on_dataset -from detectron2.layers import CycleBatchNormList -from detectron2.utils.events import EventStorage -from detectron2.utils.logger import setup_logger - -logger = setup_logger() -setup_logger(name="fvcore") - - -if __name__ == "__main__": - checkpoint = sys.argv[1] - cfg = LazyConfig.load_rel("./configs/retinanet_SyncBNhead.py") - model = cfg.model - model.head.norm = lambda c: CycleBatchNormList(len(model.head_in_features), num_features=c) - model = instantiate(model) - model.cuda() - DetectionCheckpointer(model).load(checkpoint) - - cfg.dataloader.train.total_batch_size = 8 - logger.info("Running PreciseBN ...") - with EventStorage(), torch.no_grad(): - update_bn_stats(model, instantiate(cfg.dataloader.train), 500) - - logger.info("Running evaluation ...") - inference_on_dataset( - model, instantiate(cfg.dataloader.test), instantiate(cfg.dataloader.evaluator) - ) diff --git a/preprocess/detectron2/projects/TensorMask/README.md b/preprocess/detectron2/projects/TensorMask/README.md deleted file mode 100644 index e81307c4c9be8d1cb2fd27b716531f4ebcd9ae5c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/README.md +++ /dev/null @@ -1,63 +0,0 @@ - -# TensorMask in Detectron2 -**A Foundation for Dense Object Segmentation** - -Xinlei Chen, Ross Girshick, Kaiming He, Piotr Dollár - -[[`arXiv`](https://arxiv.org/abs/1903.12174)] [[`BibTeX`](#CitingTensorMask)] - -
- -
- -In this repository, we release code for TensorMask in Detectron2. -TensorMask is a dense sliding-window instance segmentation framework that, for the first time, achieves results close to the well-developed Mask R-CNN framework -- both qualitatively and quantitatively. It establishes a conceptually complementary direction for object instance segmentation research. - -## Installation -First install Detectron2 following the [documentation](https://detectron2.readthedocs.io/tutorials/install.html) and -[setup the dataset](../../datasets). Then compile the TensorMask-specific op (`swap_align2nat`): -```bash -pip install -e /path/to/detectron2/projects/TensorMask -``` - -## Training - -To train a model, run: -```bash -python /path/to/detectron2/projects/TensorMask/train_net.py --config-file -``` - -For example, to launch TensorMask BiPyramid training (1x schedule) with ResNet-50 backbone on 8 GPUs, -one should execute: -```bash -python /path/to/detectron2/projects/TensorMask/train_net.py --config-file configs/tensormask_R_50_FPN_1x.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly (6x schedule with scale augmentation): -```bash -python /path/to/detectron2/projects/TensorMask/train_net.py --config-file configs/tensormask_R_50_FPN_6x.yaml --eval-only MODEL.WEIGHTS /path/to/model_checkpoint -``` - -# Pretrained Models - -| Backbone | lr sched | AP box | AP mask | download | -| -------- | -------- | -- | --- | -------- | -| R50 | 1x | 37.6 | 32.4 | model \|  metrics | -| R50 | 6x | 41.4 | 35.8 | model \|  metrics | - - -## Citing TensorMask - -If you use TensorMask, please use the following BibTeX entry. - -``` -@InProceedings{chen2019tensormask, - title={Tensormask: A Foundation for Dense Object Segmentation}, - author={Chen, Xinlei and Girshick, Ross and He, Kaiming and Doll{\'a}r, Piotr}, - journal={The International Conference on Computer Vision (ICCV)}, - year={2019} -} -``` - diff --git a/preprocess/detectron2/projects/TensorMask/configs/Base-TensorMask.yaml b/preprocess/detectron2/projects/TensorMask/configs/Base-TensorMask.yaml deleted file mode 100644 index a7245349b4aa9cfa00f20074cc7cb5cdb02607f9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/configs/Base-TensorMask.yaml +++ /dev/null @@ -1,25 +0,0 @@ -MODEL: - META_ARCHITECTURE: "TensorMask" - MASK_ON: True - BACKBONE: - NAME: "build_retinanet_resnet_fpn_backbone" - RESNETS: - OUT_FEATURES: ["res2", "res3", "res4", "res5"] - ANCHOR_GENERATOR: - SIZES: [[44, 60], [88, 120], [176, 240], [352, 480], [704, 960], [1408, 1920]] - ASPECT_RATIOS: [[1.0]] - FPN: - IN_FEATURES: ["res2", "res3", "res4", "res5"] - FUSE_TYPE: "avg" - TENSOR_MASK: - ALIGNED_ON: True - BIPYRAMID_ON: True -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -VERSION: 2 diff --git a/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_1x.yaml b/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_1x.yaml deleted file mode 100644 index 5d5eee135a93149a0c4b2148a47cee02e8aed8eb..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_1x.yaml +++ /dev/null @@ -1,5 +0,0 @@ -_BASE_: "Base-TensorMask.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_6x.yaml b/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_6x.yaml deleted file mode 100644 index 366a965c4adfdbba2482593c0c81f3e6af50dfd2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/configs/tensormask_R_50_FPN_6x.yaml +++ /dev/null @@ -1,11 +0,0 @@ -_BASE_: "Base-TensorMask.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (480000, 520000) - MAX_ITER: 540000 -INPUT: - MIN_SIZE_TRAIN_SAMPLING: "range" - MIN_SIZE_TRAIN: (640, 800) diff --git a/preprocess/detectron2/projects/TensorMask/setup.py b/preprocess/detectron2/projects/TensorMask/setup.py deleted file mode 100644 index f6980e0dd2d2d239faed11e1474e1a8394c9b843..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/setup.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. - -import glob -import os -from setuptools import find_packages, setup -import torch -from torch.utils.cpp_extension import CUDA_HOME, CppExtension, CUDAExtension - - -def get_extensions(): - this_dir = os.path.dirname(os.path.abspath(__file__)) - extensions_dir = os.path.join(this_dir, "tensormask", "layers", "csrc") - - main_source = os.path.join(extensions_dir, "vision.cpp") - sources = glob.glob(os.path.join(extensions_dir, "**", "*.cpp")) - source_cuda = glob.glob(os.path.join(extensions_dir, "**", "*.cu")) + glob.glob( - os.path.join(extensions_dir, "*.cu") - ) - - sources = [main_source] + sources - - extension = CppExtension - - extra_compile_args = {"cxx": []} - define_macros = [] - - if (torch.cuda.is_available() and CUDA_HOME is not None) or os.getenv("FORCE_CUDA", "0") == "1": - extension = CUDAExtension - sources += source_cuda - define_macros += [("WITH_CUDA", None)] - extra_compile_args["nvcc"] = [ - "-DCUDA_HAS_FP16=1", - "-D__CUDA_NO_HALF_OPERATORS__", - "-D__CUDA_NO_HALF_CONVERSIONS__", - "-D__CUDA_NO_HALF2_OPERATORS__", - ] - - # It's better if pytorch can do this by default .. - CC = os.environ.get("CC", None) - if CC is not None: - extra_compile_args["nvcc"].append("-ccbin={}".format(CC)) - - sources = [os.path.join(extensions_dir, s) for s in sources] - - include_dirs = [extensions_dir] - - ext_modules = [ - extension( - "tensormask._C", - sources, - include_dirs=include_dirs, - define_macros=define_macros, - extra_compile_args=extra_compile_args, - ) - ] - - return ext_modules - - -setup( - name="tensormask", - version="0.1", - author="FAIR", - packages=find_packages(exclude=("configs", "tests")), - python_requires=">=3.7", - ext_modules=get_extensions(), - cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension}, -) diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/__init__.py b/preprocess/detectron2/projects/TensorMask/tensormask/__init__.py deleted file mode 100644 index eec7978ac3c5204b1e51dac03ba3d45efc5b379d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .config import add_tensormask_config -from .arch import TensorMask diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/arch.py b/preprocess/detectron2/projects/TensorMask/tensormask/arch.py deleted file mode 100644 index d395beae6f81970cd96bc27331493a5f877024ec..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/arch.py +++ /dev/null @@ -1,913 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import copy -import math -from typing import List -import torch -import torch.nn.functional as F -from fvcore.nn import sigmoid_focal_loss_star_jit, smooth_l1_loss -from torch import nn - -from detectron2.layers import ShapeSpec, batched_nms, cat, paste_masks_in_image -from detectron2.modeling.anchor_generator import DefaultAnchorGenerator -from detectron2.modeling.backbone import build_backbone -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.meta_arch.build import META_ARCH_REGISTRY -from detectron2.modeling.meta_arch.retinanet import permute_to_N_HWA_K -from detectron2.structures import Boxes, ImageList, Instances - -from tensormask.layers import SwapAlign2Nat - -__all__ = ["TensorMask"] - - -def permute_all_cls_and_box_to_N_HWA_K_and_concat(pred_logits, pred_anchor_deltas, num_classes=80): - """ - Rearrange the tensor layout from the network output, i.e.: - list[Tensor]: #lvl tensors of shape (N, A x K, Hi, Wi) - to per-image predictions, i.e.: - Tensor: of shape (N x sum(Hi x Wi x A), K) - """ - # for each feature level, permute the outputs to make them be in the - # same format as the labels. - pred_logits_flattened = [permute_to_N_HWA_K(x, num_classes) for x in pred_logits] - pred_anchor_deltas_flattened = [permute_to_N_HWA_K(x, 4) for x in pred_anchor_deltas] - # concatenate on the first dimension (representing the feature levels), to - # take into account the way the labels were generated (with all feature maps - # being concatenated as well) - pred_logits = cat(pred_logits_flattened, dim=1).view(-1, num_classes) - pred_anchor_deltas = cat(pred_anchor_deltas_flattened, dim=1).view(-1, 4) - return pred_logits, pred_anchor_deltas - - -def _assignment_rule( - gt_boxes, - anchor_boxes, - unit_lengths, - min_anchor_size, - scale_thresh=2.0, - spatial_thresh=1.0, - uniqueness_on=True, -): - """ - Given two lists of boxes of N ground truth boxes and M anchor boxes, - compute the assignment between the two, following the assignment rules in - https://arxiv.org/abs/1903.12174. - The box order must be (xmin, ymin, xmax, ymax), so please make sure to convert - to BoxMode.XYXY_ABS before calling this function. - - Args: - gt_boxes, anchor_boxes (Boxes): two Boxes. Contains N & M boxes/anchors, respectively. - unit_lengths (Tensor): Contains the unit lengths of M anchor boxes. - min_anchor_size (float): Minimum size of the anchor, in pixels - scale_thresh (float): The `scale` threshold: the maximum size of the anchor - should not be greater than scale_thresh x max(h, w) of - the ground truth box. - spatial_thresh (float): The `spatial` threshold: the l2 distance between the - center of the anchor and the ground truth box should not - be greater than spatial_thresh x u where u is the unit length. - - Returns: - matches (Tensor[int64]): a vector of length M, where matches[i] is a matched - ground-truth index in [0, N) - match_labels (Tensor[int8]): a vector of length M, where pred_labels[i] indicates - whether a prediction is a true or false positive or ignored - """ - gt_boxes, anchor_boxes = gt_boxes.tensor, anchor_boxes.tensor - N = gt_boxes.shape[0] - M = anchor_boxes.shape[0] - if N == 0 or M == 0: - return ( - gt_boxes.new_full((N,), 0, dtype=torch.int64), - gt_boxes.new_full((N,), -1, dtype=torch.int8), - ) - - # Containment rule - lt = torch.min(gt_boxes[:, None, :2], anchor_boxes[:, :2]) # [N,M,2] - rb = torch.max(gt_boxes[:, None, 2:], anchor_boxes[:, 2:]) # [N,M,2] - union = cat([lt, rb], dim=2) # [N,M,4] - - dummy_gt_boxes = torch.zeros_like(gt_boxes) - anchor = dummy_gt_boxes[:, None, :] + anchor_boxes[:, :] # [N,M,4] - - contain_matrix = torch.all(union == anchor, dim=2) # [N,M] - - # Centrality rule, scale - gt_size_lower = torch.max(gt_boxes[:, 2:] - gt_boxes[:, :2], dim=1)[0] # [N] - gt_size_upper = gt_size_lower * scale_thresh # [N] - # Fall back for small objects - gt_size_upper[gt_size_upper < min_anchor_size] = min_anchor_size - # Due to sampling of locations, the anchor sizes are deducted with sampling strides - anchor_size = ( - torch.max(anchor_boxes[:, 2:] - anchor_boxes[:, :2], dim=1)[0] - unit_lengths - ) # [M] - - size_diff_upper = gt_size_upper[:, None] - anchor_size # [N,M] - scale_matrix = size_diff_upper >= 0 # [N,M] - - # Centrality rule, spatial - gt_center = (gt_boxes[:, 2:] + gt_boxes[:, :2]) / 2 # [N,2] - anchor_center = (anchor_boxes[:, 2:] + anchor_boxes[:, :2]) / 2 # [M,2] - offset_center = gt_center[:, None, :] - anchor_center[:, :] # [N,M,2] - offset_center /= unit_lengths[:, None] # [N,M,2] - spatial_square = spatial_thresh * spatial_thresh - spatial_matrix = torch.sum(offset_center * offset_center, dim=2) <= spatial_square - - assign_matrix = (contain_matrix & scale_matrix & spatial_matrix).int() - - # assign_matrix is N (gt) x M (predicted) - # Max over gt elements (dim 0) to find best gt candidate for each prediction - matched_vals, matches = assign_matrix.max(dim=0) - match_labels = matches.new_full(matches.size(), 1, dtype=torch.int8) - - match_labels[matched_vals == 0] = 0 - match_labels[matched_vals == 1] = 1 - - # find all the elements that match to ground truths multiple times - not_unique_idxs = assign_matrix.sum(dim=0) > 1 - if uniqueness_on: - match_labels[not_unique_idxs] = 0 - else: - match_labels[not_unique_idxs] = -1 - - return matches, match_labels - - -# TODO make the paste_mask function in d2 core support mask list -def _paste_mask_lists_in_image(masks, boxes, image_shape, threshold=0.5): - """ - Paste a list of masks that are of various resolutions (e.g., 28 x 28) into an image. - The location, height, and width for pasting each mask is determined by their - corresponding bounding boxes in boxes. - - Args: - masks (list(Tensor)): A list of Tensor of shape (1, Hmask_i, Wmask_i). - Values are in [0, 1]. The list length, Bimg, is the - number of detected object instances in the image. - boxes (Boxes): A Boxes of length Bimg. boxes.tensor[i] and masks[i] correspond - to the same object instance. - image_shape (tuple): height, width - threshold (float): A threshold in [0, 1] for converting the (soft) masks to - binary masks. - - Returns: - img_masks (Tensor): A tensor of shape (Bimg, Himage, Wimage), where Bimg is the - number of detected object instances and Himage, Wimage are the image width - and height. img_masks[i] is a binary mask for object instance i. - """ - if len(masks) == 0: - return torch.empty((0, 1) + image_shape, dtype=torch.uint8) - - # Loop over masks groups. Each group has the same mask prediction size. - img_masks = [] - ind_masks = [] - mask_sizes = torch.tensor([m.shape[-1] for m in masks]) - unique_sizes = torch.unique(mask_sizes) - for msize in unique_sizes.tolist(): - cur_ind = torch.where(mask_sizes == msize)[0] - ind_masks.append(cur_ind) - - cur_masks = cat([masks[i] for i in cur_ind]) - cur_boxes = boxes[cur_ind] - img_masks.append(paste_masks_in_image(cur_masks, cur_boxes, image_shape, threshold)) - - img_masks = cat(img_masks) - ind_masks = cat(ind_masks) - - img_masks_out = torch.empty_like(img_masks) - img_masks_out[ind_masks, :, :] = img_masks - - return img_masks_out - - -def _postprocess(results, result_mask_info, output_height, output_width, mask_threshold=0.5): - """ - Post-process the output boxes for TensorMask. - The input images are often resized when entering an object detector. - As a result, we often need the outputs of the detector in a different - resolution from its inputs. - - This function will postprocess the raw outputs of TensorMask - to produce outputs according to the desired output resolution. - - Args: - results (Instances): the raw outputs from the detector. - `results.image_size` contains the input image resolution the detector sees. - This object might be modified in-place. Note that it does not contain the field - `pred_masks`, which is provided by another input `result_masks`. - result_mask_info (list[Tensor], Boxes): a pair of two items for mask related results. - The first item is a list of #detection tensors, each is the predicted masks. - The second item is the anchors corresponding to the predicted masks. - output_height, output_width: the desired output resolution. - - Returns: - Instances: the postprocessed output from the model, based on the output resolution - """ - scale_x, scale_y = (output_width / results.image_size[1], output_height / results.image_size[0]) - results = Instances((output_height, output_width), **results.get_fields()) - - output_boxes = results.pred_boxes - output_boxes.tensor[:, 0::2] *= scale_x - output_boxes.tensor[:, 1::2] *= scale_y - output_boxes.clip(results.image_size) - - inds_nonempty = output_boxes.nonempty() - results = results[inds_nonempty] - result_masks, result_anchors = result_mask_info - if result_masks: - result_anchors.tensor[:, 0::2] *= scale_x - result_anchors.tensor[:, 1::2] *= scale_y - result_masks = [x for (i, x) in zip(inds_nonempty.tolist(), result_masks) if i] - results.pred_masks = _paste_mask_lists_in_image( - result_masks, - result_anchors[inds_nonempty], - results.image_size, - threshold=mask_threshold, - ) - return results - - -class TensorMaskAnchorGenerator(DefaultAnchorGenerator): - """ - For a set of image sizes and feature maps, computes a set of anchors for TensorMask. - It also computes the unit lengths and indexes for each anchor box. - """ - - def grid_anchors_with_unit_lengths_and_indexes(self, grid_sizes): - anchors = [] - unit_lengths = [] - indexes = [] - for lvl, (size, stride, base_anchors) in enumerate( - zip(grid_sizes, self.strides, self.cell_anchors) - ): - grid_height, grid_width = size - device = base_anchors.device - shifts_x = torch.arange( - 0, grid_width * stride, step=stride, dtype=torch.float32, device=device - ) - shifts_y = torch.arange( - 0, grid_height * stride, step=stride, dtype=torch.float32, device=device - ) - shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x) - shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=2) - # Stack anchors in shapes of (HWA, 4) - cur_anchor = (shifts[:, :, None, :] + base_anchors.view(1, 1, -1, 4)).view(-1, 4) - anchors.append(cur_anchor) - unit_lengths.append( - torch.full((cur_anchor.shape[0],), stride, dtype=torch.float32, device=device) - ) - # create mask indexes using mesh grid - shifts_l = torch.full((1,), lvl, dtype=torch.int64, device=device) - shifts_i = torch.zeros((1,), dtype=torch.int64, device=device) - shifts_h = torch.arange(0, grid_height, dtype=torch.int64, device=device) - shifts_w = torch.arange(0, grid_width, dtype=torch.int64, device=device) - shifts_a = torch.arange(0, base_anchors.shape[0], dtype=torch.int64, device=device) - grids = torch.meshgrid(shifts_l, shifts_i, shifts_h, shifts_w, shifts_a) - - indexes.append(torch.stack(grids, dim=5).view(-1, 5)) - - return anchors, unit_lengths, indexes - - def forward(self, features): - """ - Returns: - list[list[Boxes]]: a list of #image elements. Each is a list of #feature level Boxes. - The Boxes contains anchors of this image on the specific feature level. - list[list[Tensor]]: a list of #image elements. Each is a list of #feature level tensors. - The tensor contains strides, or unit lengths for the anchors. - list[list[Tensor]]: a list of #image elements. Each is a list of #feature level tensors. - The Tensor contains indexes for the anchors, with the last dimension meaning - (L, N, H, W, A), where L is level, I is image (not set yet), H is height, - W is width, and A is anchor. - """ - num_images = len(features[0]) - grid_sizes = [feature_map.shape[-2:] for feature_map in features] - anchors_list, lengths_list, indexes_list = self.grid_anchors_with_unit_lengths_and_indexes( - grid_sizes - ) - - # Convert anchors from Tensor to Boxes - anchors_per_im = [Boxes(x) for x in anchors_list] - - # TODO it can be simplified to not return duplicated information for - # each image, just like detectron2's own AnchorGenerator - anchors = [copy.deepcopy(anchors_per_im) for _ in range(num_images)] - unit_lengths = [copy.deepcopy(lengths_list) for _ in range(num_images)] - indexes = [copy.deepcopy(indexes_list) for _ in range(num_images)] - - return anchors, unit_lengths, indexes - - -@META_ARCH_REGISTRY.register() -class TensorMask(nn.Module): - """ - TensorMask model. Creates FPN backbone, anchors and a head for classification - and box regression. Calculates and applies proper losses to class, box, and - masks. - """ - - def __init__(self, cfg): - super().__init__() - - # fmt: off - self.num_classes = cfg.MODEL.TENSOR_MASK.NUM_CLASSES - self.in_features = cfg.MODEL.TENSOR_MASK.IN_FEATURES - self.anchor_sizes = cfg.MODEL.ANCHOR_GENERATOR.SIZES - self.num_levels = len(cfg.MODEL.ANCHOR_GENERATOR.SIZES) - # Loss parameters: - self.focal_loss_alpha = cfg.MODEL.TENSOR_MASK.FOCAL_LOSS_ALPHA - self.focal_loss_gamma = cfg.MODEL.TENSOR_MASK.FOCAL_LOSS_GAMMA - # Inference parameters: - self.score_threshold = cfg.MODEL.TENSOR_MASK.SCORE_THRESH_TEST - self.topk_candidates = cfg.MODEL.TENSOR_MASK.TOPK_CANDIDATES_TEST - self.nms_threshold = cfg.MODEL.TENSOR_MASK.NMS_THRESH_TEST - self.detections_im = cfg.TEST.DETECTIONS_PER_IMAGE - # Mask parameters: - self.mask_on = cfg.MODEL.MASK_ON - self.mask_loss_weight = cfg.MODEL.TENSOR_MASK.MASK_LOSS_WEIGHT - self.mask_pos_weight = torch.tensor(cfg.MODEL.TENSOR_MASK.POSITIVE_WEIGHT, - dtype=torch.float32) - self.bipyramid_on = cfg.MODEL.TENSOR_MASK.BIPYRAMID_ON - # fmt: on - - # build the backbone - self.backbone = build_backbone(cfg) - - backbone_shape = self.backbone.output_shape() - feature_shapes = [backbone_shape[f] for f in self.in_features] - feature_strides = [x.stride for x in feature_shapes] - # build anchors - self.anchor_generator = TensorMaskAnchorGenerator(cfg, feature_shapes) - self.num_anchors = self.anchor_generator.num_cell_anchors[0] - anchors_min_level = cfg.MODEL.ANCHOR_GENERATOR.SIZES[0] - self.mask_sizes = [size // feature_strides[0] for size in anchors_min_level] - self.min_anchor_size = min(anchors_min_level) - feature_strides[0] - - # head of the TensorMask - self.head = TensorMaskHead( - cfg, self.num_levels, self.num_anchors, self.mask_sizes, feature_shapes - ) - # box transform - self.box2box_transform = Box2BoxTransform(weights=cfg.MODEL.TENSOR_MASK.BBOX_REG_WEIGHTS) - self.register_buffer("pixel_mean", torch.tensor(cfg.MODEL.PIXEL_MEAN).view(-1, 1, 1), False) - self.register_buffer("pixel_std", torch.tensor(cfg.MODEL.PIXEL_STD).view(-1, 1, 1), False) - - @property - def device(self): - return self.pixel_mean.device - - def forward(self, batched_inputs): - """ - Args: - batched_inputs: a list, batched outputs of :class:`DetectionTransform` . - Each item in the list contains the inputs for one image. - For now, each item in the list is a dict that contains: - image: Tensor, image in (C, H, W) format. - instances: Instances - Other information that's included in the original dicts, such as: - "height", "width" (int): the output resolution of the model, used in inference. - See :meth:`postprocess` for details. - Returns: - losses (dict[str: Tensor]): mapping from a named loss to a tensor - storing the loss. Used during training only. - """ - images = self.preprocess_image(batched_inputs) - if "instances" in batched_inputs[0]: - gt_instances = [x["instances"].to(self.device) for x in batched_inputs] - else: - gt_instances = None - - features = self.backbone(images.tensor) - features = [features[f] for f in self.in_features] - # apply the TensorMask head - pred_logits, pred_deltas, pred_masks = self.head(features) - # generate anchors based on features, is it image specific? - anchors, unit_lengths, indexes = self.anchor_generator(features) - - if self.training: - # get ground truths for class labels and box targets, it will label each anchor - gt_class_info, gt_delta_info, gt_mask_info, num_fg = self.get_ground_truth( - anchors, unit_lengths, indexes, gt_instances - ) - # compute the loss - return self.losses( - gt_class_info, - gt_delta_info, - gt_mask_info, - num_fg, - pred_logits, - pred_deltas, - pred_masks, - ) - else: - # do inference to get the output - results = self.inference(pred_logits, pred_deltas, pred_masks, anchors, indexes, images) - processed_results = [] - for results_im, input_im, image_size in zip( - results, batched_inputs, images.image_sizes - ): - height = input_im.get("height", image_size[0]) - width = input_im.get("width", image_size[1]) - # this is to do post-processing with the image size - result_box, result_mask = results_im - r = _postprocess(result_box, result_mask, height, width) - processed_results.append({"instances": r}) - return processed_results - - def losses( - self, - gt_class_info, - gt_delta_info, - gt_mask_info, - num_fg, - pred_logits, - pred_deltas, - pred_masks, - ): - """ - Args: - For `gt_class_info`, `gt_delta_info`, `gt_mask_info` and `num_fg` parameters, see - :meth:`TensorMask.get_ground_truth`. - For `pred_logits`, `pred_deltas` and `pred_masks`, see - :meth:`TensorMaskHead.forward`. - - Returns: - losses (dict[str: Tensor]): mapping from a named loss to a scalar tensor - storing the loss. Used during training only. The potential dict keys are: - "loss_cls", "loss_box_reg" and "loss_mask". - """ - gt_classes_target, gt_valid_inds = gt_class_info - gt_deltas, gt_fg_inds = gt_delta_info - gt_masks, gt_mask_inds = gt_mask_info - loss_normalizer = torch.tensor(max(1, num_fg), dtype=torch.float32, device=self.device) - - # classification and regression - pred_logits, pred_deltas = permute_all_cls_and_box_to_N_HWA_K_and_concat( - pred_logits, pred_deltas, self.num_classes - ) - loss_cls = ( - sigmoid_focal_loss_star_jit( - pred_logits[gt_valid_inds], - gt_classes_target[gt_valid_inds], - alpha=self.focal_loss_alpha, - gamma=self.focal_loss_gamma, - reduction="sum", - ) - / loss_normalizer - ) - - if num_fg == 0: - loss_box_reg = pred_deltas.sum() * 0 - else: - loss_box_reg = ( - smooth_l1_loss(pred_deltas[gt_fg_inds], gt_deltas, beta=0.0, reduction="sum") - / loss_normalizer - ) - losses = {"loss_cls": loss_cls, "loss_box_reg": loss_box_reg} - - # mask prediction - if self.mask_on: - loss_mask = 0 - for lvl in range(self.num_levels): - cur_level_factor = 2**lvl if self.bipyramid_on else 1 - for anc in range(self.num_anchors): - cur_gt_mask_inds = gt_mask_inds[lvl][anc] - if cur_gt_mask_inds is None: - loss_mask += pred_masks[lvl][anc][0, 0, 0, 0] * 0 - else: - cur_mask_size = self.mask_sizes[anc] * cur_level_factor - # TODO maybe there are numerical issues when mask sizes are large - cur_size_divider = torch.tensor( - self.mask_loss_weight / (cur_mask_size**2), - dtype=torch.float32, - device=self.device, - ) - - cur_pred_masks = pred_masks[lvl][anc][ - cur_gt_mask_inds[:, 0], # N - :, # V x U - cur_gt_mask_inds[:, 1], # H - cur_gt_mask_inds[:, 2], # W - ] - - loss_mask += F.binary_cross_entropy_with_logits( - cur_pred_masks.view(-1, cur_mask_size, cur_mask_size), # V, U - gt_masks[lvl][anc].to(dtype=torch.float32), - reduction="sum", - weight=cur_size_divider, - pos_weight=self.mask_pos_weight, - ) - losses["loss_mask"] = loss_mask / loss_normalizer - return losses - - @torch.no_grad() - def get_ground_truth(self, anchors, unit_lengths, indexes, targets): - """ - Args: - anchors (list[list[Boxes]]): a list of N=#image elements. Each is a - list of #feature level Boxes. The Boxes contains anchors of - this image on the specific feature level. - unit_lengths (list[list[Tensor]]): a list of N=#image elements. Each is a - list of #feature level Tensor. The tensor contains unit lengths for anchors of - this image on the specific feature level. - indexes (list[list[Tensor]]): a list of N=#image elements. Each is a - list of #feature level Tensor. The tensor contains the 5D index of - each anchor, the second dimension means (L, N, H, W, A), where L - is level, I is image, H is height, W is width, and A is anchor. - targets (list[Instances]): a list of N `Instances`s. The i-th - `Instances` contains the ground-truth per-instance annotations - for the i-th input image. Specify `targets` during training only. - - Returns: - gt_class_info (Tensor, Tensor): A pair of two tensors for classification. - The first one is an integer tensor of shape (R, #classes) storing ground-truth - labels for each anchor. R is the total number of anchors in the batch. - The second one is an integer tensor of shape (R,), to indicate which - anchors are valid for loss computation, which anchors are not. - gt_delta_info (Tensor, Tensor): A pair of two tensors for boxes. - The first one, of shape (F, 4). F=#foreground anchors. - The last dimension represents ground-truth box2box transform - targets (dx, dy, dw, dh) that map each anchor to its matched ground-truth box. - Only foreground anchors have values in this tensor. Could be `None` if F=0. - The second one, of shape (R,), is an integer tensor indicating which anchors - are foreground ones used for box regression. Could be `None` if F=0. - gt_mask_info (list[list[Tensor]], list[list[Tensor]]): A pair of two lists for masks. - The first one is a list of P=#feature level elements. Each is a - list of A=#anchor tensors. Each tensor contains the ground truth - masks of the same size and for the same feature level. Could be `None`. - The second one is a list of P=#feature level elements. Each is a - list of A=#anchor tensors. Each tensor contains the location of the ground truth - masks of the same size and for the same feature level. The second dimension means - (N, H, W), where N is image, H is height, and W is width. Could be `None`. - num_fg (int): F=#foreground anchors, used later for loss normalization. - """ - gt_classes = [] - gt_deltas = [] - gt_masks = [[[] for _ in range(self.num_anchors)] for _ in range(self.num_levels)] - gt_mask_inds = [[[] for _ in range(self.num_anchors)] for _ in range(self.num_levels)] - - anchors = [Boxes.cat(anchors_i) for anchors_i in anchors] - unit_lengths = [cat(unit_lengths_i) for unit_lengths_i in unit_lengths] - indexes = [cat(indexes_i) for indexes_i in indexes] - - num_fg = 0 - for i, (anchors_im, unit_lengths_im, indexes_im, targets_im) in enumerate( - zip(anchors, unit_lengths, indexes, targets) - ): - # Initialize all - gt_classes_i = torch.full_like( - unit_lengths_im, self.num_classes, dtype=torch.int64, device=self.device - ) - # Ground truth classes - has_gt = len(targets_im) > 0 - if has_gt: - # Compute the pairwise matrix - gt_matched_inds, anchor_labels = _assignment_rule( - targets_im.gt_boxes, anchors_im, unit_lengths_im, self.min_anchor_size - ) - # Find the foreground instances - fg_inds = anchor_labels == 1 - fg_anchors = anchors_im[fg_inds] - num_fg += len(fg_anchors) - # Find the ground truths for foreground instances - gt_fg_matched_inds = gt_matched_inds[fg_inds] - # Assign labels for foreground instances - gt_classes_i[fg_inds] = targets_im.gt_classes[gt_fg_matched_inds] - # Anchors with label -1 are ignored, others are left as negative - gt_classes_i[anchor_labels == -1] = -1 - - # Boxes - # Ground truth box regression, only for foregrounds - matched_gt_boxes = targets_im[gt_fg_matched_inds].gt_boxes - # Compute box regression offsets for foregrounds only - gt_deltas_i = self.box2box_transform.get_deltas( - fg_anchors.tensor, matched_gt_boxes.tensor - ) - gt_deltas.append(gt_deltas_i) - - # Masks - if self.mask_on: - # Compute masks for each level and each anchor - matched_indexes = indexes_im[fg_inds, :] - for lvl in range(self.num_levels): - ids_lvl = matched_indexes[:, 0] == lvl - if torch.any(ids_lvl): - cur_level_factor = 2**lvl if self.bipyramid_on else 1 - for anc in range(self.num_anchors): - ids_lvl_anchor = ids_lvl & (matched_indexes[:, 4] == anc) - if torch.any(ids_lvl_anchor): - gt_masks[lvl][anc].append( - targets_im[ - gt_fg_matched_inds[ids_lvl_anchor] - ].gt_masks.crop_and_resize( - fg_anchors[ids_lvl_anchor].tensor, - self.mask_sizes[anc] * cur_level_factor, - ) - ) - # Select (N, H, W) dimensions - gt_mask_inds_lvl_anc = matched_indexes[ids_lvl_anchor, 1:4] - # Set the image index to the current image - gt_mask_inds_lvl_anc[:, 0] = i - gt_mask_inds[lvl][anc].append(gt_mask_inds_lvl_anc) - gt_classes.append(gt_classes_i) - - # Classes and boxes - gt_classes = cat(gt_classes) - gt_valid_inds = gt_classes >= 0 - gt_fg_inds = gt_valid_inds & (gt_classes < self.num_classes) - gt_classes_target = torch.zeros( - (gt_classes.shape[0], self.num_classes), dtype=torch.float32, device=self.device - ) - gt_classes_target[gt_fg_inds, gt_classes[gt_fg_inds]] = 1 - gt_deltas = cat(gt_deltas) if gt_deltas else None - - # Masks - gt_masks = [[cat(mla) if mla else None for mla in ml] for ml in gt_masks] - gt_mask_inds = [[cat(ila) if ila else None for ila in il] for il in gt_mask_inds] - return ( - (gt_classes_target, gt_valid_inds), - (gt_deltas, gt_fg_inds), - (gt_masks, gt_mask_inds), - num_fg, - ) - - def inference(self, pred_logits, pred_deltas, pred_masks, anchors, indexes, images): - """ - Arguments: - pred_logits, pred_deltas, pred_masks: Same as the output of: - meth:`TensorMaskHead.forward` - anchors, indexes: Same as the input of meth:`TensorMask.get_ground_truth` - images (ImageList): the input images - - Returns: - results (List[Instances]): a list of #images elements. - """ - assert len(anchors) == len(images) - results = [] - - pred_logits = [permute_to_N_HWA_K(x, self.num_classes) for x in pred_logits] - pred_deltas = [permute_to_N_HWA_K(x, 4) for x in pred_deltas] - - pred_logits = cat(pred_logits, dim=1) - pred_deltas = cat(pred_deltas, dim=1) - - for img_idx, (anchors_im, indexes_im) in enumerate(zip(anchors, indexes)): - # Get the size of the current image - image_size = images.image_sizes[img_idx] - - logits_im = pred_logits[img_idx] - deltas_im = pred_deltas[img_idx] - - if self.mask_on: - masks_im = [[mla[img_idx] for mla in ml] for ml in pred_masks] - else: - masks_im = [None] * self.num_levels - results_im = self.inference_single_image( - logits_im, - deltas_im, - masks_im, - Boxes.cat(anchors_im), - cat(indexes_im), - tuple(image_size), - ) - results.append(results_im) - return results - - def inference_single_image( - self, pred_logits, pred_deltas, pred_masks, anchors, indexes, image_size - ): - """ - Single-image inference. Return bounding-box detection results by thresholding - on scores and applying non-maximum suppression (NMS). - - Arguments: - pred_logits (list[Tensor]): list of #feature levels. Each entry contains - tensor of size (AxHxW, K) - pred_deltas (list[Tensor]): Same shape as 'pred_logits' except that K becomes 4. - pred_masks (list[list[Tensor]]): List of #feature levels, each is a list of #anchors. - Each entry contains tensor of size (M_i*M_i, H, W). `None` if mask_on=False. - anchors (list[Boxes]): list of #feature levels. Each entry contains - a Boxes object, which contains all the anchors for that - image in that feature level. - image_size (tuple(H, W)): a tuple of the image height and width. - - Returns: - Same as `inference`, but for only one image. - """ - pred_logits = pred_logits.flatten().sigmoid_() - # We get top locations across all levels to accelerate the inference speed, - # which does not seem to affect the accuracy. - # First select values above the threshold - logits_top_idxs = torch.where(pred_logits > self.score_threshold)[0] - # Then get the top values - num_topk = min(self.topk_candidates, logits_top_idxs.shape[0]) - pred_prob, topk_idxs = pred_logits[logits_top_idxs].sort(descending=True) - # Keep top k scoring values - pred_prob = pred_prob[:num_topk] - # Keep top k values - top_idxs = logits_top_idxs[topk_idxs[:num_topk]] - - # class index - cls_idxs = top_idxs % self.num_classes - # HWA index - top_idxs //= self.num_classes - # predict boxes - pred_boxes = self.box2box_transform.apply_deltas( - pred_deltas[top_idxs], anchors[top_idxs].tensor - ) - # apply nms - keep = batched_nms(pred_boxes, pred_prob, cls_idxs, self.nms_threshold) - # pick the top ones - keep = keep[: self.detections_im] - - results = Instances(image_size) - results.pred_boxes = Boxes(pred_boxes[keep]) - results.scores = pred_prob[keep] - results.pred_classes = cls_idxs[keep] - - # deal with masks - result_masks, result_anchors = [], None - if self.mask_on: - # index and anchors, useful for masks - top_indexes = indexes[top_idxs] - top_anchors = anchors[top_idxs] - result_indexes = top_indexes[keep] - result_anchors = top_anchors[keep] - # Get masks and do sigmoid - for lvl, _, h, w, anc in result_indexes.tolist(): - cur_size = self.mask_sizes[anc] * (2**lvl if self.bipyramid_on else 1) - result_masks.append( - torch.sigmoid(pred_masks[lvl][anc][:, h, w].view(1, cur_size, cur_size)) - ) - - return results, (result_masks, result_anchors) - - def preprocess_image(self, batched_inputs): - """ - Normalize, pad and batch the input images. - """ - images = [x["image"].to(self.device) for x in batched_inputs] - images = [(x - self.pixel_mean) / self.pixel_std for x in images] - images = ImageList.from_tensors(images, self.backbone.size_divisibility) - return images - - -class TensorMaskHead(nn.Module): - def __init__(self, cfg, num_levels, num_anchors, mask_sizes, input_shape: List[ShapeSpec]): - """ - TensorMask head. - """ - super().__init__() - # fmt: off - self.in_features = cfg.MODEL.TENSOR_MASK.IN_FEATURES - in_channels = input_shape[0].channels - num_classes = cfg.MODEL.TENSOR_MASK.NUM_CLASSES - cls_channels = cfg.MODEL.TENSOR_MASK.CLS_CHANNELS - num_convs = cfg.MODEL.TENSOR_MASK.NUM_CONVS - # box parameters - bbox_channels = cfg.MODEL.TENSOR_MASK.BBOX_CHANNELS - # mask parameters - self.mask_on = cfg.MODEL.MASK_ON - self.mask_sizes = mask_sizes - mask_channels = cfg.MODEL.TENSOR_MASK.MASK_CHANNELS - self.align_on = cfg.MODEL.TENSOR_MASK.ALIGNED_ON - self.bipyramid_on = cfg.MODEL.TENSOR_MASK.BIPYRAMID_ON - # fmt: on - - # class subnet - cls_subnet = [] - cur_channels = in_channels - for _ in range(num_convs): - cls_subnet.append( - nn.Conv2d(cur_channels, cls_channels, kernel_size=3, stride=1, padding=1) - ) - cur_channels = cls_channels - cls_subnet.append(nn.ReLU()) - - self.cls_subnet = nn.Sequential(*cls_subnet) - self.cls_score = nn.Conv2d( - cur_channels, num_anchors * num_classes, kernel_size=3, stride=1, padding=1 - ) - modules_list = [self.cls_subnet, self.cls_score] - - # box subnet - bbox_subnet = [] - cur_channels = in_channels - for _ in range(num_convs): - bbox_subnet.append( - nn.Conv2d(cur_channels, bbox_channels, kernel_size=3, stride=1, padding=1) - ) - cur_channels = bbox_channels - bbox_subnet.append(nn.ReLU()) - - self.bbox_subnet = nn.Sequential(*bbox_subnet) - self.bbox_pred = nn.Conv2d( - cur_channels, num_anchors * 4, kernel_size=3, stride=1, padding=1 - ) - modules_list.extend([self.bbox_subnet, self.bbox_pred]) - - # mask subnet - if self.mask_on: - mask_subnet = [] - cur_channels = in_channels - for _ in range(num_convs): - mask_subnet.append( - nn.Conv2d(cur_channels, mask_channels, kernel_size=3, stride=1, padding=1) - ) - cur_channels = mask_channels - mask_subnet.append(nn.ReLU()) - - self.mask_subnet = nn.Sequential(*mask_subnet) - modules_list.append(self.mask_subnet) - for mask_size in self.mask_sizes: - cur_mask_module = "mask_pred_%02d" % mask_size - self.add_module( - cur_mask_module, - nn.Conv2d( - cur_channels, mask_size * mask_size, kernel_size=1, stride=1, padding=0 - ), - ) - modules_list.append(getattr(self, cur_mask_module)) - if self.align_on: - if self.bipyramid_on: - for lvl in range(num_levels): - cur_mask_module = "align2nat_%02d" % lvl - lambda_val = 2**lvl - setattr(self, cur_mask_module, SwapAlign2Nat(lambda_val)) - # Also the fusing layer, stay at the same channel size - mask_fuse = [ - nn.Conv2d(cur_channels, cur_channels, kernel_size=3, stride=1, padding=1), - nn.ReLU(), - ] - self.mask_fuse = nn.Sequential(*mask_fuse) - modules_list.append(self.mask_fuse) - else: - self.align2nat = SwapAlign2Nat(1) - - # Initialization - for modules in modules_list: - for layer in modules.modules(): - if isinstance(layer, nn.Conv2d): - torch.nn.init.normal_(layer.weight, mean=0, std=0.01) - torch.nn.init.constant_(layer.bias, 0) - - # Use prior in model initialization to improve stability - bias_value = -(math.log((1 - 0.01) / 0.01)) - torch.nn.init.constant_(self.cls_score.bias, bias_value) - - def forward(self, features): - """ - Arguments: - features (list[Tensor]): FPN feature map tensors in high to low resolution. - Each tensor in the list correspond to different feature levels. - - Returns: - pred_logits (list[Tensor]): #lvl tensors, each has shape (N, AxK, Hi, Wi). - The tensor predicts the classification probability - at each spatial position for each of the A anchors and K object - classes. - pred_deltas (list[Tensor]): #lvl tensors, each has shape (N, Ax4, Hi, Wi). - The tensor predicts 4-vector (dx,dy,dw,dh) box - regression values for every anchor. These values are the - relative offset between the anchor and the ground truth box. - pred_masks (list(list[Tensor])): #lvl list of tensors, each is a list of - A tensors of shape (N, M_{i,a}, Hi, Wi). - The tensor predicts a dense set of M_ixM_i masks at every location. - """ - pred_logits = [self.cls_score(self.cls_subnet(x)) for x in features] - pred_deltas = [self.bbox_pred(self.bbox_subnet(x)) for x in features] - - pred_masks = None - if self.mask_on: - mask_feats = [self.mask_subnet(x) for x in features] - - if self.bipyramid_on: - mask_feat_high_res = mask_feats[0] - H, W = mask_feat_high_res.shape[-2:] - mask_feats_up = [] - for lvl, mask_feat in enumerate(mask_feats): - lambda_val = 2.0**lvl - mask_feat_up = mask_feat - if lvl > 0: - mask_feat_up = F.interpolate( - mask_feat, scale_factor=lambda_val, mode="bilinear", align_corners=False - ) - mask_feats_up.append( - self.mask_fuse(mask_feat_up[:, :, :H, :W] + mask_feat_high_res) - ) - mask_feats = mask_feats_up - - pred_masks = [] - for lvl, mask_feat in enumerate(mask_feats): - cur_masks = [] - for mask_size in self.mask_sizes: - cur_mask_module = getattr(self, "mask_pred_%02d" % mask_size) - cur_mask = cur_mask_module(mask_feat) - if self.align_on: - if self.bipyramid_on: - cur_mask_module = getattr(self, "align2nat_%02d" % lvl) - cur_mask = cur_mask_module(cur_mask) - else: - cur_mask = self.align2nat(cur_mask) - cur_masks.append(cur_mask) - pred_masks.append(cur_masks) - return pred_logits, pred_deltas, pred_masks diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/config.py b/preprocess/detectron2/projects/TensorMask/tensormask/config.py deleted file mode 100644 index cf62d7aea23a9bdf637c9dc80b810e2413c9c0ae..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/config.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -from detectron2.config import CfgNode as CN - - -def add_tensormask_config(cfg): - """ - Add config for TensorMask. - """ - cfg.MODEL.TENSOR_MASK = CN() - - # Anchor parameters - cfg.MODEL.TENSOR_MASK.IN_FEATURES = ["p2", "p3", "p4", "p5", "p6", "p7"] - - # Convolutions to use in the towers - cfg.MODEL.TENSOR_MASK.NUM_CONVS = 4 - - # Number of foreground classes. - cfg.MODEL.TENSOR_MASK.NUM_CLASSES = 80 - # Channel size for the classification tower - cfg.MODEL.TENSOR_MASK.CLS_CHANNELS = 256 - - cfg.MODEL.TENSOR_MASK.SCORE_THRESH_TEST = 0.05 - # Only the top (1000 * #levels) candidate boxes across all levels are - # considered jointly during test (to improve speed) - cfg.MODEL.TENSOR_MASK.TOPK_CANDIDATES_TEST = 6000 - cfg.MODEL.TENSOR_MASK.NMS_THRESH_TEST = 0.5 - - # Box parameters - # Channel size for the box tower - cfg.MODEL.TENSOR_MASK.BBOX_CHANNELS = 128 - # Weights on (dx, dy, dw, dh) - cfg.MODEL.TENSOR_MASK.BBOX_REG_WEIGHTS = (1.5, 1.5, 0.75, 0.75) - - # Loss parameters - cfg.MODEL.TENSOR_MASK.FOCAL_LOSS_GAMMA = 3.0 - cfg.MODEL.TENSOR_MASK.FOCAL_LOSS_ALPHA = 0.3 - - # Mask parameters - # Channel size for the mask tower - cfg.MODEL.TENSOR_MASK.MASK_CHANNELS = 128 - # Mask loss weight - cfg.MODEL.TENSOR_MASK.MASK_LOSS_WEIGHT = 2.0 - # weight on positive pixels within the mask - cfg.MODEL.TENSOR_MASK.POSITIVE_WEIGHT = 1.5 - # Whether to predict in the aligned representation - cfg.MODEL.TENSOR_MASK.ALIGNED_ON = False - # Whether to use the bipyramid architecture - cfg.MODEL.TENSOR_MASK.BIPYRAMID_ON = False diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/layers/__init__.py b/preprocess/detectron2/projects/TensorMask/tensormask/layers/__init__.py deleted file mode 100644 index 8b8e178445ebb67b84e9c9d547dba9108a30e3d9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/layers/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .swap_align2nat import SwapAlign2Nat, swap_align2nat - -__all__ = [k for k in globals().keys() if not k.startswith("_")] diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat.h b/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat.h deleted file mode 100644 index 75c21785fd60cf05d705707e8a0e04e2b619a85b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -#pragma once -#include - -namespace tensormask { - -#if defined(WITH_CUDA) || defined(WITH_HIP) -at::Tensor SwapAlign2Nat_forward_cuda( - const at::Tensor& X, - const int lambda_val, - const float pad_val); - -at::Tensor SwapAlign2Nat_backward_cuda( - const at::Tensor& gY, - const int lambda_val, - const int batch_size, - const int channel, - const int height, - const int width); -#endif - -inline at::Tensor SwapAlign2Nat_forward( - const at::Tensor& X, - const int lambda_val, - const float pad_val) { - if (X.type().is_cuda()) { -#if defined(WITH_CUDA) || defined(WITH_HIP) - return SwapAlign2Nat_forward_cuda(X, lambda_val, pad_val); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - AT_ERROR("Not implemented on the CPU"); -} - -inline at::Tensor SwapAlign2Nat_backward( - const at::Tensor& gY, - const int lambda_val, - const int batch_size, - const int channel, - const int height, - const int width) { - if (gY.type().is_cuda()) { -#if defined(WITH_CUDA) || defined(WITH_HIP) - return SwapAlign2Nat_backward_cuda( - gY, lambda_val, batch_size, channel, height, width); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - AT_ERROR("Not implemented on the CPU"); -} - -} // namespace tensormask diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat_cuda.cu b/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat_cuda.cu deleted file mode 100644 index 1398d70491bbbd86127a69f348e210e71a937305..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/SwapAlign2Nat/SwapAlign2Nat_cuda.cu +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -#include -#include -#include -#include - -// TODO make it in a common file -#define CUDA_1D_KERNEL_LOOP(i, n) \ - for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < n; \ - i += blockDim.x * gridDim.x) - -template -__device__ inline T get_pixel_val( - const T* tensor, - const int idx, - const int H, - const int W, - const int y, - const int x, - const int V, - const int U, - const int v, - const int u, - const T pad_val) { - if ((y < 0) || (y >= H) || (x < 0) || (x >= W) || (v < 0) || (v >= V) || - (u < 0) || (u >= U)) { - return pad_val; - } else { - return tensor[(((idx * V + v) * U + u) * H + y) * W + x]; - } -} - -template -__device__ inline void add_pixel_val( - T* tensor, - const T val, - const int idx, - const int H, - const int W, - const int y, - const int x, - const int V, - const int U, - const int v, - const int u) { - if ((val == 0.) || (y < 0) || (y >= H) || (x < 0) || (x >= W) || (v < 0) || - (v >= V) || (u < 0) || (u >= U)) { - return; - } else { - atomicAdd(tensor + ((((idx * V + v) * U + u) * H + y) * W + x), val); - } -} - -template -__global__ void SwapAlign2NatForwardFeat( - const int nthreads, - const T* bottom_data, - const int Vout, - const int Uout, - const float hVout, - const float hUout, - const int Vin, - const int Uin, - const float lambda, - const int Hin, - const int Win, - const int Hout, - const int Wout, - const T pad_val, - T* top_data) { - CUDA_1D_KERNEL_LOOP(index, nthreads) { - int idx = index; - const int x = idx % Wout; - idx /= Wout; - const int y = idx % Hout; - idx /= Hout; - const int u = idx % Uout; - idx /= Uout; - const int v = idx % Vout; - idx /= Vout; - - const float ox = x * lambda + u - hUout + 0.5; - const int xf = static_cast(floor(ox)); - const int xc = static_cast(ceil(ox)); - const float xwc = ox - xf; - const float xwf = 1. - xwc; - - const float oy = y * lambda + v - hVout + 0.5; - const int yf = static_cast(floor(oy)); - const int yc = static_cast(ceil(oy)); - const float ywc = oy - yf; - const float ywf = 1. - ywc; - - const float ou = (u + 0.5) / lambda - 0.5; - const int uf = static_cast(floor(ou)); - const int uc = static_cast(ceil(ou)); - const float uwc = ou - uf; - const float uwf = 1. - uwc; - - const float ov = (v + 0.5) / lambda - 0.5; - const int vf = static_cast(floor(ov)); - const int vc = static_cast(ceil(ov)); - const float vwc = ov - vf; - const float vwf = 1. - vwc; - - T val = ywf * xwf * vwf * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xf, Vin, Uin, vf, uf, pad_val) + - ywf * xwf * vwf * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xf, Vin, Uin, vf, uc, pad_val) + - ywf * xwf * vwc * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xf, Vin, Uin, vc, uf, pad_val) + - ywf * xwf * vwc * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xf, Vin, Uin, vc, uc, pad_val) + - ywf * xwc * vwf * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xc, Vin, Uin, vf, uf, pad_val) + - ywf * xwc * vwf * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xc, Vin, Uin, vf, uc, pad_val) + - ywf * xwc * vwc * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xc, Vin, Uin, vc, uf, pad_val) + - ywf * xwc * vwc * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yf, xc, Vin, Uin, vc, uc, pad_val) + - ywc * xwf * vwf * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xf, Vin, Uin, vf, uf, pad_val) + - ywc * xwf * vwf * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xf, Vin, Uin, vf, uc, pad_val) + - ywc * xwf * vwc * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xf, Vin, Uin, vc, uf, pad_val) + - ywc * xwf * vwc * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xf, Vin, Uin, vc, uc, pad_val) + - ywc * xwc * vwf * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xc, Vin, Uin, vf, uf, pad_val) + - ywc * xwc * vwf * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xc, Vin, Uin, vf, uc, pad_val) + - ywc * xwc * vwc * uwf * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xc, Vin, Uin, vc, uf, pad_val) + - ywc * xwc * vwc * uwc * - get_pixel_val( - bottom_data, idx, Hin, Win, yc, xc, Vin, Uin, vc, uc, pad_val); - - top_data[index] = val; - } -} - -template -__global__ void SwapAlign2NatBackwardFeat( - const int nthreads, - const T* top_diff, - const int Vout, - const int Uout, - const float hVout, - const float hUout, - const int Vin, - const int Uin, - const float lambda, - const int Hin, - const int Win, - const int Hout, - const int Wout, - T* bottom_diff) { - CUDA_1D_KERNEL_LOOP(index, nthreads) { - int idx = index; - const int x = idx % Wout; - idx /= Wout; - const int y = idx % Hout; - idx /= Hout; - const int u = idx % Uout; - idx /= Uout; - const int v = idx % Vout; - idx /= Vout; - - const float ox = x * lambda + u - hUout + 0.5; - const int xf = static_cast(floor(ox)); - const int xc = static_cast(ceil(ox)); - const float xwc = ox - xf; - const float xwf = 1. - xwc; - - const float oy = y * lambda + v - hVout + 0.5; - const int yf = static_cast(floor(oy)); - const int yc = static_cast(ceil(oy)); - const float ywc = oy - yf; - const float ywf = 1. - ywc; - - const float ou = (u + 0.5) / lambda - 0.5; - const int uf = static_cast(floor(ou)); - const int uc = static_cast(ceil(ou)); - const float uwc = ou - uf; - const float uwf = 1. - uwc; - - const float ov = (v + 0.5) / lambda - 0.5; - const int vf = static_cast(floor(ov)); - const int vc = static_cast(ceil(ov)); - const float vwc = ov - vf; - const float vwf = 1. - vwc; - - const T grad = top_diff[index]; - - add_pixel_val( - bottom_diff, - ywf * xwf * vwf * uwf * grad, - idx, - Hin, - Win, - yf, - xf, - Vin, - Uin, - vf, - uf); - add_pixel_val( - bottom_diff, - ywf * xwf * vwf * uwc * grad, - idx, - Hin, - Win, - yf, - xf, - Vin, - Uin, - vf, - uc); - add_pixel_val( - bottom_diff, - ywf * xwf * vwc * uwf * grad, - idx, - Hin, - Win, - yf, - xf, - Vin, - Uin, - vc, - uf); - add_pixel_val( - bottom_diff, - ywf * xwf * vwc * uwc * grad, - idx, - Hin, - Win, - yf, - xf, - Vin, - Uin, - vc, - uc); - add_pixel_val( - bottom_diff, - ywf * xwc * vwf * uwf * grad, - idx, - Hin, - Win, - yf, - xc, - Vin, - Uin, - vf, - uf); - add_pixel_val( - bottom_diff, - ywf * xwc * vwf * uwc * grad, - idx, - Hin, - Win, - yf, - xc, - Vin, - Uin, - vf, - uc); - add_pixel_val( - bottom_diff, - ywf * xwc * vwc * uwf * grad, - idx, - Hin, - Win, - yf, - xc, - Vin, - Uin, - vc, - uf); - add_pixel_val( - bottom_diff, - ywf * xwc * vwc * uwc * grad, - idx, - Hin, - Win, - yf, - xc, - Vin, - Uin, - vc, - uc); - add_pixel_val( - bottom_diff, - ywc * xwf * vwf * uwf * grad, - idx, - Hin, - Win, - yc, - xf, - Vin, - Uin, - vf, - uf); - add_pixel_val( - bottom_diff, - ywc * xwf * vwf * uwc * grad, - idx, - Hin, - Win, - yc, - xf, - Vin, - Uin, - vf, - uc); - add_pixel_val( - bottom_diff, - ywc * xwf * vwc * uwf * grad, - idx, - Hin, - Win, - yc, - xf, - Vin, - Uin, - vc, - uf); - add_pixel_val( - bottom_diff, - ywc * xwf * vwc * uwc * grad, - idx, - Hin, - Win, - yc, - xf, - Vin, - Uin, - vc, - uc); - add_pixel_val( - bottom_diff, - ywc * xwc * vwf * uwf * grad, - idx, - Hin, - Win, - yc, - xc, - Vin, - Uin, - vf, - uf); - add_pixel_val( - bottom_diff, - ywc * xwc * vwf * uwc * grad, - idx, - Hin, - Win, - yc, - xc, - Vin, - Uin, - vf, - uc); - add_pixel_val( - bottom_diff, - ywc * xwc * vwc * uwf * grad, - idx, - Hin, - Win, - yc, - xc, - Vin, - Uin, - vc, - uf); - add_pixel_val( - bottom_diff, - ywc * xwc * vwc * uwc * grad, - idx, - Hin, - Win, - yc, - xc, - Vin, - Uin, - vc, - uc); - } -} - -namespace tensormask { - -at::Tensor SwapAlign2Nat_forward_cuda( - const at::Tensor& X, - const int lambda_val, - const float pad_val) { - AT_ASSERTM(X.device().is_cuda(), "input must be a CUDA tensor"); - AT_ASSERTM(X.ndimension() == 4, "input must be a 4D tensor"); - AT_ASSERTM(lambda_val >= 1, "lambda should be greater or equal to 1"); - const int N = X.size(0); - const int C = X.size(1); - const int Vin = static_cast(sqrt(static_cast(C))); - const int Uin = C / Vin; - AT_ASSERTM( - C == Vin * Uin && Vin == Uin, "#channels should be a square number"); - const int Vout = lambda_val * Vin; - const int Uout = lambda_val * Uin; - const int Hin = X.size(2); - const int Win = X.size(3); - const float lambda = static_cast(lambda_val); - const int Hout = static_cast(ceil(Hin / lambda)); - const int Wout = static_cast(ceil(Win / lambda)); - const float hVout = Vout / 2.; - const float hUout = Uout / 2.; - - at::cuda::CUDAGuard device_guard(X.device()); - - at::Tensor Y = at::empty({N, Vout * Uout, Hout, Wout}, X.options()); - - cudaStream_t stream = at::cuda::getCurrentCUDAStream(); - - dim3 grid(std::min(at::cuda::ATenCeilDiv(Y.numel(), 512L), 4096L)); - dim3 block(512); - - if (Y.numel() == 0) { - AT_CUDA_CHECK(cudaGetLastError()); - return Y; - } - - auto X_ = X.contiguous(); - AT_DISPATCH_FLOATING_TYPES(X.scalar_type(), "SwapAlign2Nat_forward", [&] { - SwapAlign2NatForwardFeat<<>>( - Y.numel(), - X_.data_ptr(), - Vout, - Uout, - hVout, - hUout, - Vin, - Uin, - lambda, - Hin, - Win, - Hout, - Wout, - pad_val, - Y.data_ptr()); - }); - cudaDeviceSynchronize(); - AT_CUDA_CHECK(cudaGetLastError()); - return Y; -} - -at::Tensor SwapAlign2Nat_backward_cuda( - const at::Tensor& gY, - const int lambda_val, - const int batch_size, - const int channel, - const int height, - const int width) { - AT_ASSERTM(gY.device().is_cuda(), "input gradient must be a CUDA tensor"); - AT_ASSERTM(gY.ndimension() == 4, "input gradient must be a 4D tensor"); - AT_ASSERTM(lambda_val >= 1, "lambda should be greater or equal to 1"); - const int Vin = static_cast(sqrt(static_cast(channel))); - const int Uin = channel / Vin; - const int Vout = lambda_val * Vin; - const int Uout = lambda_val * Uin; - const float hVout = Vout / 2.; - const float hUout = Uout / 2.; - const int Hout = gY.size(2); - const int Wout = gY.size(3); - - at::cuda::CUDAGuard device_guard(gY.device()); - - at::Tensor gX = at::zeros({batch_size, channel, height, width}, gY.options()); - - cudaStream_t stream = at::cuda::getCurrentCUDAStream(); - - dim3 grid(std::min(at::cuda::ATenCeilDiv(gY.numel(), 512L), 4096L)); - dim3 block(512); - - // handle possibly empty gradients - if (gY.numel() == 0) { - AT_CUDA_CHECK(cudaGetLastError()); - return gX; - } - - auto gY_ = gY.contiguous(); - AT_DISPATCH_FLOATING_TYPES(gY.scalar_type(), "SwapAlign2Nat_backward", [&] { - SwapAlign2NatBackwardFeat<<>>( - gY.numel(), - gY_.data_ptr(), - Vout, - Uout, - hVout, - hUout, - Vin, - Uin, - static_cast(lambda_val), - height, - width, - Hout, - Wout, - gX.data_ptr()); - }); - AT_CUDA_CHECK(cudaGetLastError()); - return gX; -} - -} // namespace tensormask diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/vision.cpp b/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/vision.cpp deleted file mode 100644 index ed1ed0b3d5911021bf7b4a03126b5140b5286970..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/layers/csrc/vision.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -#include -#include "SwapAlign2Nat/SwapAlign2Nat.h" - -namespace tensormask { - -PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { - m.def( - "swap_align2nat_forward", - &SwapAlign2Nat_forward, - "SwapAlign2Nat_forward"); - m.def( - "swap_align2nat_backward", - &SwapAlign2Nat_backward, - "SwapAlign2Nat_backward"); -} - -} // namespace tensormask diff --git a/preprocess/detectron2/projects/TensorMask/tensormask/layers/swap_align2nat.py b/preprocess/detectron2/projects/TensorMask/tensormask/layers/swap_align2nat.py deleted file mode 100644 index 2b5e45013c2112187c82a95fe056a0b0a3d43489..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tensormask/layers/swap_align2nat.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from torch import nn -from torch.autograd import Function -from torch.autograd.function import once_differentiable - -from tensormask import _C - - -class _SwapAlign2Nat(Function): - @staticmethod - def forward(ctx, X, lambda_val, pad_val): - ctx.lambda_val = lambda_val - ctx.input_shape = X.size() - - Y = _C.swap_align2nat_forward(X, lambda_val, pad_val) - return Y - - @staticmethod - @once_differentiable - def backward(ctx, gY): - lambda_val = ctx.lambda_val - bs, ch, h, w = ctx.input_shape - - gX = _C.swap_align2nat_backward(gY, lambda_val, bs, ch, h, w) - - return gX, None, None - - -swap_align2nat = _SwapAlign2Nat.apply - - -class SwapAlign2Nat(nn.Module): - """ - The op `SwapAlign2Nat` described in https://arxiv.org/abs/1903.12174. - Given an input tensor that predicts masks of shape (N, C=VxU, H, W), - apply the op, it will return masks of shape (N, V'xU', H', W') where - the unit lengths of (V, U) and (H, W) are swapped, and the mask representation - is transformed from aligned to natural. - Args: - lambda_val (int): the relative unit length ratio between (V, U) and (H, W), - as we always have larger unit lengths for (V, U) than (H, W), - lambda_val is always >= 1. - pad_val (float): padding value for the values falling outside of the input - tensor, default set to -6 as sigmoid(-6) is ~0, indicating - that is no masks outside of the tensor. - """ - - def __init__(self, lambda_val, pad_val=-6.0): - super(SwapAlign2Nat, self).__init__() - self.lambda_val = lambda_val - self.pad_val = pad_val - - def forward(self, X): - return swap_align2nat(X, self.lambda_val, self.pad_val) - - def __repr__(self): - tmpstr = self.__class__.__name__ + "(" - tmpstr += "lambda_val=" + str(self.lambda_val) - tmpstr += ", pad_val=" + str(self.pad_val) - tmpstr += ")" - return tmpstr diff --git a/preprocess/detectron2/projects/TensorMask/tests/__init__.py b/preprocess/detectron2/projects/TensorMask/tests/__init__.py deleted file mode 100644 index 9020c2df23e2af280b7bb168b996ae9eaf312eb8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. diff --git a/preprocess/detectron2/projects/TensorMask/tests/test_swap_align2nat.py b/preprocess/detectron2/projects/TensorMask/tests/test_swap_align2nat.py deleted file mode 100755 index d9ee273de06cf881b89696ee4ee13a0953d6aa25..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/tests/test_swap_align2nat.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -import torch -from torch.autograd import gradcheck - -from tensormask.layers.swap_align2nat import SwapAlign2Nat - - -class SwapAlign2NatTest(unittest.TestCase): - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_swap_align2nat_gradcheck_cuda(self): - dtype = torch.float64 - device = torch.device("cuda") - m = SwapAlign2Nat(2).to(dtype=dtype, device=device) - x = torch.rand(2, 4, 10, 10, dtype=dtype, device=device, requires_grad=True) - - self.assertTrue(gradcheck(m, x), "gradcheck failed for SwapAlign2Nat CUDA") - - def _swap_align2nat(self, tensor, lambda_val): - """ - The basic setup for testing Swap_Align - """ - op = SwapAlign2Nat(lambda_val, pad_val=0.0) - input = torch.from_numpy(tensor[None, :, :, :].astype("float32")) - output = op.forward(input.cuda()).cpu().numpy() - return output[0] - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/projects/TensorMask/train_net.py b/preprocess/detectron2/projects/TensorMask/train_net.py deleted file mode 100755 index ff481797bdd5ca9ec32f67751bfe9fb8aa695288..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TensorMask/train_net.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -TensorMask Training Script. - -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -import detectron2.utils.comm as comm -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import COCOEvaluator, verify_results - -from tensormask import add_tensormask_config - - -class Trainer(DefaultTrainer): - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - return COCOEvaluator(dataset_name, output_dir=output_folder) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_tensormask_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - if comm.is_main_process(): - verify_results(cfg, res) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/TridentNet/README.md b/preprocess/detectron2/projects/TridentNet/README.md deleted file mode 100644 index 4b7a90102d008a498e93dff595a09206be5269e7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/README.md +++ /dev/null @@ -1,60 +0,0 @@ - -# TridentNet in Detectron2 -**Scale-Aware Trident Networks for Object Detection** - -Yanghao Li\*, Yuntao Chen\*, Naiyan Wang, Zhaoxiang Zhang - -[[`TridentNet`](https://github.com/TuSimple/simpledet/tree/master/models/tridentnet)] [[`arXiv`](https://arxiv.org/abs/1901.01892)] [[`BibTeX`](#CitingTridentNet)] - -
- -
- -In this repository, we implement TridentNet-Fast in Detectron2. -Trident Network (TridentNet) aims to generate scale-specific feature maps with a uniform representational power. We construct a parallel multi-branch architecture in which each branch shares the same transformation parameters but with different receptive fields. TridentNet-Fast is a fast approximation version of TridentNet that could achieve significant improvements without any additional parameters and computational cost. - -## Training - -To train a model, run -```bash -python /path/to/detectron2/projects/TridentNet/train_net.py --config-file -``` - -For example, to launch end-to-end TridentNet training with ResNet-50 backbone on 8 GPUs, -one should execute: -```bash -python /path/to/detectron2/projects/TridentNet/train_net.py --config-file configs/tridentnet_fast_R_50_C4_1x.yaml --num-gpus 8 -``` - -## Evaluation - -Model evaluation can be done similarly: -```bash -python /path/to/detectron2/projects/TridentNet/train_net.py --config-file configs/tridentnet_fast_R_50_C4_1x.yaml --eval-only MODEL.WEIGHTS model.pth -``` - -## Results on MS-COCO in Detectron2 - -|Model|Backbone|Head|lr sched|AP|AP50|AP75|APs|APm|APl|download| -|-----|--------|----|--------|--|----|----|---|---|---|--------| -|Faster|R50-C4|C5-512ROI|1X|35.7|56.1|38.0|19.2|40.9|48.7|model \| metrics| -|TridentFast|R50-C4|C5-128ROI|1X|38.0|58.1|40.8|19.5|42.2|54.6|model \| metrics| -|Faster|R50-C4|C5-512ROI|3X|38.4|58.7|41.3|20.7|42.7|53.1|model \| metrics| -|TridentFast|R50-C4|C5-128ROI|3X|40.6|60.8|43.6|23.4|44.7|57.1|model \| metrics| -|Faster|R101-C4|C5-512ROI|3X|41.1|61.4|44.0|22.2|45.5|55.9|model \| metrics| -|TridentFast|R101-C4|C5-128ROI|3X|43.6|63.4|47.0|24.3|47.8|60.0|model \| metrics| - - -## Citing TridentNet - -If you use TridentNet, please use the following BibTeX entry. - -``` -@InProceedings{li2019scale, - title={Scale-Aware Trident Networks for Object Detection}, - author={Li, Yanghao and Chen, Yuntao and Wang, Naiyan and Zhang, Zhaoxiang}, - journal={The International Conference on Computer Vision (ICCV)}, - year={2019} -} -``` - diff --git a/preprocess/detectron2/projects/TridentNet/configs/Base-TridentNet-Fast-C4.yaml b/preprocess/detectron2/projects/TridentNet/configs/Base-TridentNet-Fast-C4.yaml deleted file mode 100644 index 8c3d80797ba9ae63a5669ccbd74a0d2006fee3b7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/configs/Base-TridentNet-Fast-C4.yaml +++ /dev/null @@ -1,29 +0,0 @@ -MODEL: - META_ARCHITECTURE: "GeneralizedRCNN" - BACKBONE: - NAME: "build_trident_resnet_backbone" - ROI_HEADS: - NAME: "TridentRes5ROIHeads" - POSITIVE_FRACTION: 0.5 - BATCH_SIZE_PER_IMAGE: 128 - PROPOSAL_APPEND_GT: False - PROPOSAL_GENERATOR: - NAME: "TridentRPN" - RPN: - POST_NMS_TOPK_TRAIN: 500 - TRIDENT: - NUM_BRANCH: 3 - BRANCH_DILATIONS: [1, 2, 3] - TEST_BRANCH_IDX: 1 - TRIDENT_STAGE: "res4" -DATASETS: - TRAIN: ("coco_2017_train",) - TEST: ("coco_2017_val",) -SOLVER: - IMS_PER_BATCH: 16 - BASE_LR: 0.02 - STEPS: (60000, 80000) - MAX_ITER: 90000 -INPUT: - MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) -VERSION: 2 diff --git a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_101_C4_3x.yaml b/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_101_C4_3x.yaml deleted file mode 100644 index bc83c2f9e7b7653c8982e657b5f116abe6ad6e1f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_101_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "Base-TridentNet-Fast-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-101.pkl" - MASK_ON: False - RESNETS: - DEPTH: 101 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_1x.yaml b/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_1x.yaml deleted file mode 100644 index fda2cb6622d732c0f70d74d567c26182a9a41c44..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_1x.yaml +++ /dev/null @@ -1,6 +0,0 @@ -_BASE_: "Base-TridentNet-Fast-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 diff --git a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_3x.yaml b/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_3x.yaml deleted file mode 100644 index ebf89d03ea043810b02e71ecc2c1711c250e161c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/configs/tridentnet_fast_R_50_C4_3x.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_BASE_: "Base-TridentNet-Fast-C4.yaml" -MODEL: - WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" - MASK_ON: False - RESNETS: - DEPTH: 50 -SOLVER: - STEPS: (210000, 250000) - MAX_ITER: 270000 diff --git a/preprocess/detectron2/projects/TridentNet/train_net.py b/preprocess/detectron2/projects/TridentNet/train_net.py deleted file mode 100755 index a34c3fdc733e5f9172dabf3cca22947dc5a2fce5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/train_net.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. - -""" -TridentNet Training Script. - -This script is a simplified version of the training script in detectron2/tools. -""" - -import os - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - launch, -) -from detectron2.evaluation import COCOEvaluator - -from tridentnet import add_tridentnet_config - - -class Trainer(DefaultTrainer): - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - return COCOEvaluator(dataset_name, output_dir=output_folder) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - add_tridentnet_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - return res - - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/__init__.py b/preprocess/detectron2/projects/TridentNet/tridentnet/__init__.py deleted file mode 100644 index abaa9579051e7ef5ee7f388b9d59b5962440155c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from .config import add_tridentnet_config -from .trident_backbone import ( - TridentBottleneckBlock, - build_trident_resnet_backbone, - make_trident_stage, -) -from .trident_rpn import TridentRPN -from .trident_rcnn import TridentRes5ROIHeads, TridentStandardROIHeads diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/config.py b/preprocess/detectron2/projects/TridentNet/tridentnet/config.py deleted file mode 100644 index 4b8732a43f6974ec60168652bf08e382ddc9c941..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/config.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -from detectron2.config import CfgNode as CN - - -def add_tridentnet_config(cfg): - """ - Add config for tridentnet. - """ - _C = cfg - - _C.MODEL.TRIDENT = CN() - - # Number of branches for TridentNet. - _C.MODEL.TRIDENT.NUM_BRANCH = 3 - # Specify the dilations for each branch. - _C.MODEL.TRIDENT.BRANCH_DILATIONS = [1, 2, 3] - # Specify the stage for applying trident blocks. Default stage is Res4 according to the - # TridentNet paper. - _C.MODEL.TRIDENT.TRIDENT_STAGE = "res4" - # Specify the test branch index TridentNet Fast inference: - # - use -1 to aggregate results of all branches during inference. - # - otherwise, only using specified branch for fast inference. Recommended setting is - # to use the middle branch. - _C.MODEL.TRIDENT.TEST_BRANCH_IDX = 1 diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_backbone.py b/preprocess/detectron2/projects/TridentNet/tridentnet/trident_backbone.py deleted file mode 100644 index 7789bd219b01d452e876ad2ad7f811502719465c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_backbone.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import fvcore.nn.weight_init as weight_init -import torch -import torch.nn.functional as F - -from detectron2.layers import Conv2d, FrozenBatchNorm2d, get_norm -from detectron2.modeling import BACKBONE_REGISTRY, ResNet, ResNetBlockBase -from detectron2.modeling.backbone.resnet import BasicStem, BottleneckBlock, DeformBottleneckBlock - -from .trident_conv import TridentConv - -__all__ = ["TridentBottleneckBlock", "make_trident_stage", "build_trident_resnet_backbone"] - - -class TridentBottleneckBlock(ResNetBlockBase): - def __init__( - self, - in_channels, - out_channels, - *, - bottleneck_channels, - stride=1, - num_groups=1, - norm="BN", - stride_in_1x1=False, - num_branch=3, - dilations=(1, 2, 3), - concat_output=False, - test_branch_idx=-1, - ): - """ - Args: - num_branch (int): the number of branches in TridentNet. - dilations (tuple): the dilations of multiple branches in TridentNet. - concat_output (bool): if concatenate outputs of multiple branches in TridentNet. - Use 'True' for the last trident block. - """ - super().__init__(in_channels, out_channels, stride) - - assert num_branch == len(dilations) - - self.num_branch = num_branch - self.concat_output = concat_output - self.test_branch_idx = test_branch_idx - - if in_channels != out_channels: - self.shortcut = Conv2d( - in_channels, - out_channels, - kernel_size=1, - stride=stride, - bias=False, - norm=get_norm(norm, out_channels), - ) - else: - self.shortcut = None - - stride_1x1, stride_3x3 = (stride, 1) if stride_in_1x1 else (1, stride) - - self.conv1 = Conv2d( - in_channels, - bottleneck_channels, - kernel_size=1, - stride=stride_1x1, - bias=False, - norm=get_norm(norm, bottleneck_channels), - ) - - self.conv2 = TridentConv( - bottleneck_channels, - bottleneck_channels, - kernel_size=3, - stride=stride_3x3, - paddings=dilations, - bias=False, - groups=num_groups, - dilations=dilations, - num_branch=num_branch, - test_branch_idx=test_branch_idx, - norm=get_norm(norm, bottleneck_channels), - ) - - self.conv3 = Conv2d( - bottleneck_channels, - out_channels, - kernel_size=1, - bias=False, - norm=get_norm(norm, out_channels), - ) - - for layer in [self.conv1, self.conv2, self.conv3, self.shortcut]: - if layer is not None: # shortcut can be None - weight_init.c2_msra_fill(layer) - - def forward(self, x): - num_branch = self.num_branch if self.training or self.test_branch_idx == -1 else 1 - if not isinstance(x, list): - x = [x] * num_branch - out = [self.conv1(b) for b in x] - out = [F.relu_(b) for b in out] - - out = self.conv2(out) - out = [F.relu_(b) for b in out] - - out = [self.conv3(b) for b in out] - - if self.shortcut is not None: - shortcut = [self.shortcut(b) for b in x] - else: - shortcut = x - - out = [out_b + shortcut_b for out_b, shortcut_b in zip(out, shortcut)] - out = [F.relu_(b) for b in out] - if self.concat_output: - out = torch.cat(out) - return out - - -def make_trident_stage(block_class, num_blocks, **kwargs): - """ - Create a resnet stage by creating many blocks for TridentNet. - """ - concat_output = [False] * (num_blocks - 1) + [True] - kwargs["concat_output_per_block"] = concat_output - return ResNet.make_stage(block_class, num_blocks, **kwargs) - - -@BACKBONE_REGISTRY.register() -def build_trident_resnet_backbone(cfg, input_shape): - """ - Create a ResNet instance from config for TridentNet. - - Returns: - ResNet: a :class:`ResNet` instance. - """ - # need registration of new blocks/stems? - norm = cfg.MODEL.RESNETS.NORM - stem = BasicStem( - in_channels=input_shape.channels, - out_channels=cfg.MODEL.RESNETS.STEM_OUT_CHANNELS, - norm=norm, - ) - freeze_at = cfg.MODEL.BACKBONE.FREEZE_AT - - if freeze_at >= 1: - for p in stem.parameters(): - p.requires_grad = False - stem = FrozenBatchNorm2d.convert_frozen_batchnorm(stem) - - # fmt: off - out_features = cfg.MODEL.RESNETS.OUT_FEATURES - depth = cfg.MODEL.RESNETS.DEPTH - num_groups = cfg.MODEL.RESNETS.NUM_GROUPS - width_per_group = cfg.MODEL.RESNETS.WIDTH_PER_GROUP - bottleneck_channels = num_groups * width_per_group - in_channels = cfg.MODEL.RESNETS.STEM_OUT_CHANNELS - out_channels = cfg.MODEL.RESNETS.RES2_OUT_CHANNELS - stride_in_1x1 = cfg.MODEL.RESNETS.STRIDE_IN_1X1 - res5_dilation = cfg.MODEL.RESNETS.RES5_DILATION - deform_on_per_stage = cfg.MODEL.RESNETS.DEFORM_ON_PER_STAGE - deform_modulated = cfg.MODEL.RESNETS.DEFORM_MODULATED - deform_num_groups = cfg.MODEL.RESNETS.DEFORM_NUM_GROUPS - num_branch = cfg.MODEL.TRIDENT.NUM_BRANCH - branch_dilations = cfg.MODEL.TRIDENT.BRANCH_DILATIONS - trident_stage = cfg.MODEL.TRIDENT.TRIDENT_STAGE - test_branch_idx = cfg.MODEL.TRIDENT.TEST_BRANCH_IDX - # fmt: on - assert res5_dilation in {1, 2}, "res5_dilation cannot be {}.".format(res5_dilation) - - num_blocks_per_stage = {50: [3, 4, 6, 3], 101: [3, 4, 23, 3], 152: [3, 8, 36, 3]}[depth] - - stages = [] - - res_stage_idx = {"res2": 2, "res3": 3, "res4": 4, "res5": 5} - out_stage_idx = [res_stage_idx[f] for f in out_features] - trident_stage_idx = res_stage_idx[trident_stage] - max_stage_idx = max(out_stage_idx) - for idx, stage_idx in enumerate(range(2, max_stage_idx + 1)): - dilation = res5_dilation if stage_idx == 5 else 1 - first_stride = 1 if idx == 0 or (stage_idx == 5 and dilation == 2) else 2 - stage_kargs = { - "num_blocks": num_blocks_per_stage[idx], - "stride_per_block": [first_stride] + [1] * (num_blocks_per_stage[idx] - 1), - "in_channels": in_channels, - "bottleneck_channels": bottleneck_channels, - "out_channels": out_channels, - "num_groups": num_groups, - "norm": norm, - "stride_in_1x1": stride_in_1x1, - "dilation": dilation, - } - if stage_idx == trident_stage_idx: - assert not deform_on_per_stage[ - idx - ], "Not support deformable conv in Trident blocks yet." - stage_kargs["block_class"] = TridentBottleneckBlock - stage_kargs["num_branch"] = num_branch - stage_kargs["dilations"] = branch_dilations - stage_kargs["test_branch_idx"] = test_branch_idx - stage_kargs.pop("dilation") - elif deform_on_per_stage[idx]: - stage_kargs["block_class"] = DeformBottleneckBlock - stage_kargs["deform_modulated"] = deform_modulated - stage_kargs["deform_num_groups"] = deform_num_groups - else: - stage_kargs["block_class"] = BottleneckBlock - blocks = ( - make_trident_stage(**stage_kargs) - if stage_idx == trident_stage_idx - else ResNet.make_stage(**stage_kargs) - ) - in_channels = out_channels - out_channels *= 2 - bottleneck_channels *= 2 - - if freeze_at >= stage_idx: - for block in blocks: - block.freeze() - stages.append(blocks) - return ResNet(stem, stages, out_features=out_features) diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_conv.py b/preprocess/detectron2/projects/TridentNet/tridentnet/trident_conv.py deleted file mode 100644 index 18d5b0b9d73f2da263e7e026a82c62231a88d279..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_conv.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import torch -from torch import nn -from torch.nn import functional as F -from torch.nn.modules.utils import _pair - -from detectron2.layers.wrappers import _NewEmptyTensorOp - - -class TridentConv(nn.Module): - def __init__( - self, - in_channels, - out_channels, - kernel_size, - stride=1, - paddings=0, - dilations=1, - groups=1, - num_branch=1, - test_branch_idx=-1, - bias=False, - norm=None, - activation=None, - ): - super(TridentConv, self).__init__() - self.in_channels = in_channels - self.out_channels = out_channels - self.kernel_size = _pair(kernel_size) - self.num_branch = num_branch - self.stride = _pair(stride) - self.groups = groups - self.with_bias = bias - if isinstance(paddings, int): - paddings = [paddings] * self.num_branch - if isinstance(dilations, int): - dilations = [dilations] * self.num_branch - self.paddings = [_pair(padding) for padding in paddings] - self.dilations = [_pair(dilation) for dilation in dilations] - self.test_branch_idx = test_branch_idx - self.norm = norm - self.activation = activation - - assert len({self.num_branch, len(self.paddings), len(self.dilations)}) == 1 - - self.weight = nn.Parameter( - torch.Tensor(out_channels, in_channels // groups, *self.kernel_size) - ) - if bias: - self.bias = nn.Parameter(torch.Tensor(out_channels)) - else: - self.bias = None - - nn.init.kaiming_uniform_(self.weight, nonlinearity="relu") - if self.bias is not None: - nn.init.constant_(self.bias, 0) - - def forward(self, inputs): - num_branch = self.num_branch if self.training or self.test_branch_idx == -1 else 1 - assert len(inputs) == num_branch - - if inputs[0].numel() == 0: - output_shape = [ - (i + 2 * p - (di * (k - 1) + 1)) // s + 1 - for i, p, di, k, s in zip( - inputs[0].shape[-2:], self.padding, self.dilation, self.kernel_size, self.stride - ) - ] - output_shape = [input[0].shape[0], self.weight.shape[0]] + output_shape - return [_NewEmptyTensorOp.apply(input, output_shape) for input in inputs] - - if self.training or self.test_branch_idx == -1: - outputs = [ - F.conv2d(input, self.weight, self.bias, self.stride, padding, dilation, self.groups) - for input, dilation, padding in zip(inputs, self.dilations, self.paddings) - ] - else: - outputs = [ - F.conv2d( - inputs[0], - self.weight, - self.bias, - self.stride, - self.paddings[self.test_branch_idx], - self.dilations[self.test_branch_idx], - self.groups, - ) - ] - - if self.norm is not None: - outputs = [self.norm(x) for x in outputs] - if self.activation is not None: - outputs = [self.activation(x) for x in outputs] - return outputs - - def extra_repr(self): - tmpstr = "in_channels=" + str(self.in_channels) - tmpstr += ", out_channels=" + str(self.out_channels) - tmpstr += ", kernel_size=" + str(self.kernel_size) - tmpstr += ", num_branch=" + str(self.num_branch) - tmpstr += ", test_branch_idx=" + str(self.test_branch_idx) - tmpstr += ", stride=" + str(self.stride) - tmpstr += ", paddings=" + str(self.paddings) - tmpstr += ", dilations=" + str(self.dilations) - tmpstr += ", groups=" + str(self.groups) - tmpstr += ", bias=" + str(self.with_bias) - return tmpstr diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rcnn.py b/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rcnn.py deleted file mode 100644 index fc22c712c84f96813fb275931ad4e350ee1f3bfd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rcnn.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from detectron2.layers import batched_nms -from detectron2.modeling import ROI_HEADS_REGISTRY, StandardROIHeads -from detectron2.modeling.roi_heads.roi_heads import Res5ROIHeads -from detectron2.structures import Instances - - -def merge_branch_instances(instances, num_branch, nms_thresh, topk_per_image): - """ - Merge detection results from different branches of TridentNet. - Return detection results by applying non-maximum suppression (NMS) on bounding boxes - and keep the unsuppressed boxes and other instances (e.g mask) if any. - - Args: - instances (list[Instances]): A list of N * num_branch instances that store detection - results. Contain N images and each image has num_branch instances. - num_branch (int): Number of branches used for merging detection results for each image. - nms_thresh (float): The threshold to use for box non-maximum suppression. Value in [0, 1]. - topk_per_image (int): The number of top scoring detections to return. Set < 0 to return - all detections. - - Returns: - results: (list[Instances]): A list of N instances, one for each image in the batch, - that stores the topk most confidence detections after merging results from multiple - branches. - """ - if num_branch == 1: - return instances - - batch_size = len(instances) // num_branch - results = [] - for i in range(batch_size): - instance = Instances.cat([instances[i + batch_size * j] for j in range(num_branch)]) - - # Apply per-class NMS - keep = batched_nms( - instance.pred_boxes.tensor, instance.scores, instance.pred_classes, nms_thresh - ) - keep = keep[:topk_per_image] - result = instance[keep] - - results.append(result) - - return results - - -@ROI_HEADS_REGISTRY.register() -class TridentRes5ROIHeads(Res5ROIHeads): - """ - The TridentNet ROIHeads in a typical "C4" R-CNN model. - See :class:`Res5ROIHeads`. - """ - - def __init__(self, cfg, input_shape): - super().__init__(cfg, input_shape) - - self.num_branch = cfg.MODEL.TRIDENT.NUM_BRANCH - self.trident_fast = cfg.MODEL.TRIDENT.TEST_BRANCH_IDX != -1 - - def forward(self, images, features, proposals, targets=None): - """ - See :class:`Res5ROIHeads.forward`. - """ - num_branch = self.num_branch if self.training or not self.trident_fast else 1 - all_targets = targets * num_branch if targets is not None else None - pred_instances, losses = super().forward(images, features, proposals, all_targets) - del images, all_targets, targets - - if self.training: - return pred_instances, losses - else: - pred_instances = merge_branch_instances( - pred_instances, - num_branch, - self.box_predictor.test_nms_thresh, - self.box_predictor.test_topk_per_image, - ) - - return pred_instances, {} - - -@ROI_HEADS_REGISTRY.register() -class TridentStandardROIHeads(StandardROIHeads): - """ - The `StandardROIHeads` for TridentNet. - See :class:`StandardROIHeads`. - """ - - def __init__(self, cfg, input_shape): - super(TridentStandardROIHeads, self).__init__(cfg, input_shape) - - self.num_branch = cfg.MODEL.TRIDENT.NUM_BRANCH - self.trident_fast = cfg.MODEL.TRIDENT.TEST_BRANCH_IDX != -1 - - def forward(self, images, features, proposals, targets=None): - """ - See :class:`Res5ROIHeads.forward`. - """ - # Use 1 branch if using trident_fast during inference. - num_branch = self.num_branch if self.training or not self.trident_fast else 1 - # Duplicate targets for all branches in TridentNet. - all_targets = targets * num_branch if targets is not None else None - pred_instances, losses = super().forward(images, features, proposals, all_targets) - del images, all_targets, targets - - if self.training: - return pred_instances, losses - else: - pred_instances = merge_branch_instances( - pred_instances, - num_branch, - self.box_predictor.test_nms_thresh, - self.box_predictor.test_topk_per_image, - ) - - return pred_instances, {} diff --git a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rpn.py b/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rpn.py deleted file mode 100644 index f95fbbf8ea59ad014f3337c47d41b5410f2c9d45..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/TridentNet/tridentnet/trident_rpn.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import torch - -from detectron2.modeling import PROPOSAL_GENERATOR_REGISTRY -from detectron2.modeling.proposal_generator.rpn import RPN -from detectron2.structures import ImageList - - -@PROPOSAL_GENERATOR_REGISTRY.register() -class TridentRPN(RPN): - """ - Trident RPN subnetwork. - """ - - def __init__(self, cfg, input_shape): - super(TridentRPN, self).__init__(cfg, input_shape) - - self.num_branch = cfg.MODEL.TRIDENT.NUM_BRANCH - self.trident_fast = cfg.MODEL.TRIDENT.TEST_BRANCH_IDX != -1 - - def forward(self, images, features, gt_instances=None): - """ - See :class:`RPN.forward`. - """ - num_branch = self.num_branch if self.training or not self.trident_fast else 1 - # Duplicate images and gt_instances for all branches in TridentNet. - all_images = ImageList( - torch.cat([images.tensor] * num_branch), images.image_sizes * num_branch - ) - all_gt_instances = gt_instances * num_branch if gt_instances is not None else None - - return super(TridentRPN, self).forward(all_images, features, all_gt_instances) diff --git a/preprocess/detectron2/projects/ViTDet/README.md b/preprocess/detectron2/projects/ViTDet/README.md deleted file mode 100644 index 0a525e00e643017fc971566931936f1573d9b47c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/README.md +++ /dev/null @@ -1,364 +0,0 @@ -# ViTDet: Exploring Plain Vision Transformer Backbones for Object Detection - -Yanghao Li, Hanzi Mao, Ross Girshick†, Kaiming He† - -[[`arXiv`](https://arxiv.org/abs/2203.16527)] [[`BibTeX`](#CitingViTDet)] - -In this repository, we provide configs and models in Detectron2 for ViTDet as well as MViTv2 and Swin backbones with our implementation and settings as described in [ViTDet](https://arxiv.org/abs/2203.16527) paper. - - -## Pretrained Models - -### COCO - -#### Mask R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namepre-traintrain
time
(s/im)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
ViTDet, ViT-BIN1K, MAE0.3140.07910.951.645.9325346929model
ViTDet, ViT-LIN1K, MAE0.6030.12520.955.549.2325599698model
ViTDet, ViT-HIN1K, MAE1.0980.17831.556.750.2329145471model
- -#### Cascade Mask R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namepre-traintrain
time
(s/im)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
Swin-BIN21K, sup0.3890.0778.753.946.2342979038model
Swin-LIN21K, sup0.5080.09712.655.047.2342979186model
MViTv2-BIN21K, sup0.4750.0908.955.648.1325820315model
MViTv2-LIN21K, sup0.8440.15719.755.748.3325607715model
MViTv2-HIN21K, sup1.6550.28518.4*55.948.3326187358model
ViTDet, ViT-BIN1K, MAE0.3620.08912.354.046.7325358525model
ViTDet, ViT-LIN1K, MAE0.6430.14222.357.650.0328021305model
ViTDet, ViT-HIN1K, MAE1.1370.19632.958.751.0328730692model
- - -### LVIS - -#### Mask R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namepre-traintrain
time
(s/im)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
ViTDet, ViT-BIN1K, MAE0.3170.08514.440.238.2329225748model
ViTDet, ViT-LIN1K, MAE0.5760.13724.746.143.6329211570model
ViTDet, ViT-HIN1K, MAE1.0590.18635.349.146.0332434656model
- -#### Cascade Mask R-CNN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Namepre-traintrain
time
(s/im)
inference
time
(s/im)
train
mem
(GB)
box
AP
mask
AP
model iddownload
Swin-BIN21K, sup0.3680.09011.544.039.6329222304model
Swin-LIN21K, sup0.4860.10513.846.041.4329222724model
MViTv2-BIN21K, sup0.4750.10011.846.342.0329477206model
MViTv2-LIN21K, sup0.8440.17221.049.444.2329661552model
MViTv2-HIN21K, sup1.6610.29021.3*49.544.1330445165model
ViTDet, ViT-BIN1K, MAE0.3560.09915.243.038.9329226874model
ViTDet, ViT-LIN1K, MAE0.6290.15024.949.244.5329042206model
ViTDet, ViT-HIN1K, MAE1.1000.20435.551.546.6332552778model
- -Note: Unlike the system-level comparisons in the paper, these models use a lower resolution (1024 instead of 1280) and standard NMS (instead of soft NMS). As a result, they have slightly lower box and mask AP. - -We observed higher variance on LVIS evalution results compared to COCO. For example, the standard deviations of box AP and mask AP were 0.30% (compared to 0.10% on COCO) when we trained ViTDet, ViT-B five times with varying random seeds. - -The above models were trained and measured on 8-node with 64 NVIDIA A100 GPUs in total. *: Activation checkpointing is used. - - -## Training -All configs can be trained with: - -``` -../../tools/lazyconfig_train_net.py --config-file configs/path/to/config.py -``` -By default, we use 64 GPUs with batch size as 64 for training. - -## Evaluation -Model evaluation can be done similarly: -``` -../../tools/lazyconfig_train_net.py --config-file configs/path/to/config.py --eval-only train.init_checkpoint=/path/to/model_checkpoint -``` - - -## Citing ViTDet - -If you use ViTDet, please use the following BibTeX entry. - -```BibTeX -@article{li2022exploring, - title={Exploring plain vision transformer backbones for object detection}, - author={Li, Yanghao and Mao, Hanzi and Girshick, Ross and He, Kaiming}, - journal={arXiv preprint arXiv:2203.16527}, - year={2022} -} -``` diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py deleted file mode 100644 index 9dba203086f8b34221ea9bed9f5fc280579f97df..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py +++ /dev/null @@ -1,95 +0,0 @@ -from functools import partial -import torch.nn as nn -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2 import model_zoo -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler -from detectron2.modeling import MViT -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import ( - FastRCNNOutputLayers, - FastRCNNConvFCHead, - CascadeROIHeads, -) - -from ..common.coco_loader_lsj import dataloader - -model = model_zoo.get_config("common/models/mask_rcnn_fpn.py").model -constants = model_zoo.get_config("common/data/constants.py").constants -model.pixel_mean = constants.imagenet_rgb256_mean -model.pixel_std = constants.imagenet_rgb256_std -model.input_format = "RGB" -model.backbone.bottom_up = L(MViT)( - embed_dim=96, - depth=24, - num_heads=1, - last_block_indexes=(1, 4, 20, 23), - residual_pooling=True, - drop_path_rate=0.4, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - out_features=("scale2", "scale3", "scale4", "scale5"), -) -model.backbone.in_features = "${.bottom_up.out_features}" -model.backbone.square_pad = 1024 - -# New heads and LN -model.backbone.norm = "LN" # Use LN in FPN -model.roi_heads.box_head.conv_norm = model.roi_heads.mask_head.conv_norm = "LN" - -# 2conv in RPN: -model.proposal_generator.head.conv_dims = [-1, -1] - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] -model.roi_heads.update( - _target_=CascadeROIHeads, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm="LN", - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - cls_agnostic_bbox_reg=True, - num_classes="${...num_classes}", - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) - -# Initialization and trainer settings -train = model_zoo.get_config("common/train.py").train -train.amp.enabled = True -train.ddp.fp16_compression = True -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_B_in21k.pyth" - -# Schedule -# 100 ep = 184375 iters * 64 images/iter / 118000 images/ep -train.max_iter = 184375 -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[163889, 177546], - num_updates=train.max_iter, - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) - -optimizer = model_zoo.get_config("common/optim.py").AdamW -optimizer.params.overrides = {"pos_embed": {"weight_decay": 0.0}} -optimizer.lr = 8e-5 diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_h_in21k_36ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_h_in21k_36ep.py deleted file mode 100644 index 577045043b960384953a00eac4dc45ee43c1045e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_h_in21k_36ep.py +++ /dev/null @@ -1,39 +0,0 @@ -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler - -from .cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.embed_dim = 192 -model.backbone.bottom_up.depth = 80 -model.backbone.bottom_up.num_heads = 3 -model.backbone.bottom_up.last_block_indexes = (3, 11, 71, 79) -model.backbone.bottom_up.drop_path_rate = 0.6 -model.backbone.bottom_up.use_act_checkpoint = True - - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_H_in21k.pyth" - - -# 36 epochs -train.max_iter = 67500 -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[ - 52500, - 62500, - 67500, - ], - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) -optimizer.lr = 1.6e-4 diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py deleted file mode 100644 index c64f0c18aea5dfe49fef028a6300ab1dc9f2537a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py +++ /dev/null @@ -1,22 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.embed_dim = 144 -model.backbone.bottom_up.depth = 48 -model.backbone.bottom_up.num_heads = 2 -model.backbone.bottom_up.last_block_indexes = (1, 7, 43, 47) -model.backbone.bottom_up.drop_path_rate = 0.5 - - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_L_in21k.pyth" - -train.max_iter = train.max_iter // 2 # 100ep -> 50ep -lr_multiplier.scheduler.milestones = [ - milestone // 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_b_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_b_in21k_50ep.py deleted file mode 100644 index b2aad98526e39240ff82cbf96cb005ce75e5c577..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_b_in21k_50ep.py +++ /dev/null @@ -1,50 +0,0 @@ -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2 import model_zoo -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler -from detectron2.modeling import SwinTransformer - -from ..common.coco_loader_lsj import dataloader -from .cascade_mask_rcnn_mvitv2_b_in21k_100ep import model - -model.backbone.bottom_up = L(SwinTransformer)( - depths=[2, 2, 18, 2], - drop_path_rate=0.4, - embed_dim=128, - num_heads=[4, 8, 16, 32], -) -model.backbone.in_features = ("p0", "p1", "p2", "p3") -model.backbone.square_pad = 1024 - -# Initialization and trainer settings -train = model_zoo.get_config("common/train.py").train -train.amp.enabled = True -train.ddp.fp16_compression = True -train.init_checkpoint = "detectron2://ImageNetPretrained/swin/swin_base_patch4_window7_224_22k.pth" - -# Schedule -# 100 ep = 184375 iters * 64 images/iter / 118000 images/ep -train.max_iter = 184375 -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[163889, 177546], - num_updates=train.max_iter, - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) - -# Rescale schedule -train.max_iter = train.max_iter // 2 # 100ep -> 50ep -lr_multiplier.scheduler.milestones = [ - milestone // 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter - - -optimizer = model_zoo.get_config("common/optim.py").AdamW -optimizer.lr = 4e-5 -optimizer.weight_decay = 0.05 -optimizer.params.overrides = {"relative_position_bias_table": {"weight_decay": 0.0}} diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_l_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_l_in21k_50ep.py deleted file mode 100644 index 60bc917b5938338f87c96b17041432d1fb637ce3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_swin_l_in21k_50ep.py +++ /dev/null @@ -1,15 +0,0 @@ -from .cascade_mask_rcnn_swin_b_in21k_50ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.depths = [2, 2, 18, 2] -model.backbone.bottom_up.drop_path_rate = 0.4 -model.backbone.bottom_up.embed_dim = 192 -model.backbone.bottom_up.num_heads = [6, 12, 24, 48] - - -train.init_checkpoint = "detectron2://ImageNetPretrained/swin/swin_large_patch4_window7_224_22k.pth" diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_b_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_b_100ep.py deleted file mode 100644 index 95823ef4fbfa0745713ab6a7df4716056367f8b2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_b_100ep.py +++ /dev/null @@ -1,48 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import ( - FastRCNNOutputLayers, - FastRCNNConvFCHead, - CascadeROIHeads, -) - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, - get_vit_lr_decay_rate, -) - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm="LN", - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - test_score_thresh=0.05, - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - cls_agnostic_bbox_reg=True, - num_classes="${...num_classes}", - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_h_75ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_h_75ep.py deleted file mode 100644 index e508a68f5cebbf0960f3c307819dc2f5ef900057..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_h_75ep.py +++ /dev/null @@ -1,33 +0,0 @@ -from functools import partial - -from .cascade_mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, - get_vit_lr_decay_rate, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_huge_p14to16.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1280 -model.backbone.net.depth = 32 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.5 -# 7, 15, 23, 31 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 7)) + list(range(8, 15)) + list(range(16, 23)) + list(range(24, 31)) -) - -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.9, num_layers=32) -optimizer.params.overrides = {} -optimizer.params.weight_decay_norm = None - -train.max_iter = train.max_iter * 3 // 4 # 100ep -> 75ep -lr_multiplier.scheduler.milestones = [ - milestone * 3 // 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_l_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_l_100ep.py deleted file mode 100644 index 2743603ad2b6cc3f99aa0600c715887f7550d1cd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_vitdet_l_100ep.py +++ /dev/null @@ -1,25 +0,0 @@ -from functools import partial - -from .cascade_mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, - get_vit_lr_decay_rate, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_large.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1024 -model.backbone.net.depth = 24 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.4 -# 5, 11, 17, 23 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 5)) + list(range(6, 11)) + list(range(12, 17)) + list(range(18, 23)) -) - -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.8, num_layers=24) diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py deleted file mode 100644 index 8fd36e92da0137df8aae5935e71b7af419ac1016..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py +++ /dev/null @@ -1,40 +0,0 @@ -from functools import partial -from fvcore.common.param_scheduler import MultiStepParamScheduler - -from detectron2 import model_zoo -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler -from detectron2.modeling.backbone.vit import get_vit_lr_decay_rate - -from ..common.coco_loader_lsj import dataloader - - -model = model_zoo.get_config("common/models/mask_rcnn_vitdet.py").model - -# Initialization and trainer settings -train = model_zoo.get_config("common/train.py").train -train.amp.enabled = True -train.ddp.fp16_compression = True -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_base.pth?matching_heuristics=True" -) - - -# Schedule -# 100 ep = 184375 iters * 64 images/iter / 118000 images/ep -train.max_iter = 184375 - -lr_multiplier = L(WarmupParamScheduler)( - scheduler=L(MultiStepParamScheduler)( - values=[1.0, 0.1, 0.01], - milestones=[163889, 177546], - num_updates=train.max_iter, - ), - warmup_length=250 / train.max_iter, - warmup_factor=0.001, -) - -# Optimizer -optimizer = model_zoo.get_config("common/optim.py").AdamW -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, num_layers=12, lr_decay_rate=0.7) -optimizer.params.overrides = {"pos_embed": {"weight_decay": 0.0}} diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_h_75ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_h_75ep.py deleted file mode 100644 index 7de96f0a6c760ac41152726ac1e4faeb1fb9a818..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_h_75ep.py +++ /dev/null @@ -1,33 +0,0 @@ -from functools import partial - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, - get_vit_lr_decay_rate, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_huge_p14to16.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1280 -model.backbone.net.depth = 32 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.5 -# 7, 15, 23, 31 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 7)) + list(range(8, 15)) + list(range(16, 23)) + list(range(24, 31)) -) - -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.9, num_layers=32) -optimizer.params.overrides = {} -optimizer.params.weight_decay_norm = None - -train.max_iter = train.max_iter * 3 // 4 # 100ep -> 75ep -lr_multiplier.scheduler.milestones = [ - milestone * 3 // 4 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter diff --git a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_l_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_l_100ep.py deleted file mode 100644 index 0d193cbb1e09943812c23fc16f0cde66f6a59fce..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_l_100ep.py +++ /dev/null @@ -1,25 +0,0 @@ -from functools import partial - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, - get_vit_lr_decay_rate, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_large.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1024 -model.backbone.net.depth = 24 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.4 -# 5, 11, 17, 23 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 5)) + list(range(6, 11)) + list(range(12, 17)) + list(range(18, 23)) -) - -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.8, num_layers=24) diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py deleted file mode 100644 index 1cf9c3ea7a962bd890fc3b22e0449323f8dc0dfa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py +++ /dev/null @@ -1,48 +0,0 @@ -from functools import partial -import torch.nn as nn - -from detectron2.config import LazyCall as L -from detectron2.data.detection_utils import get_fed_loss_cls_weights -from detectron2.data.samplers import RepeatFactorTrainingSampler -from detectron2.evaluation.lvis_evaluation import LVISEvaluator - -from ..COCO.cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( - dataloader, - model, - train, - lr_multiplier, - optimizer, -) - -dataloader.train.dataset.names = "lvis_v1_train" -dataloader.train.sampler = L(RepeatFactorTrainingSampler)( - repeat_factors=L(RepeatFactorTrainingSampler.repeat_factors_from_category_frequency)( - dataset_dicts="${dataloader.train.dataset}", repeat_thresh=0.001 - ) -) -dataloader.test.dataset.names = "lvis_v1_val" -dataloader.evaluator = L(LVISEvaluator)( - dataset_name="${..test.dataset.names}", - max_dets_per_image=300, -) - -model.roi_heads.num_classes = 1203 -for i in range(3): - model.roi_heads.box_predictors[i].test_score_thresh = 0.02 - model.roi_heads.box_predictors[i].test_topk_per_image = 300 - model.roi_heads.box_predictors[i].use_sigmoid_ce = True - model.roi_heads.box_predictors[i].use_fed_loss = True - model.roi_heads.box_predictors[i].get_fed_loss_cls_weights = lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 - ) - -# Schedule -# 100 ep = 156250 iters * 64 images/iter / 100000 images/ep -train.max_iter = 156250 -train.eval_period = 30000 - -lr_multiplier.scheduler.milestones = [138889, 150463] -lr_multiplier.scheduler.num_updates = train.max_iter -lr_multiplier.warmup_length = 250 / train.max_iter - -optimizer.lr = 1e-4 diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_h_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_h_in21k_50ep.py deleted file mode 100644 index 084444bf0338d1bab2ee426ae226a0f8004dd0f5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_h_in21k_50ep.py +++ /dev/null @@ -1,25 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.embed_dim = 192 -model.backbone.bottom_up.depth = 80 -model.backbone.bottom_up.num_heads = 3 -model.backbone.bottom_up.last_block_indexes = (3, 11, 71, 79) -model.backbone.bottom_up.drop_path_rate = 0.6 -model.backbone.bottom_up.use_act_checkpoint = True - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_H_in21k.pyth" - -train.max_iter = train.max_iter // 2 # 100ep -> 50ep -lr_multiplier.scheduler.milestones = [ - milestone // 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter -lr_multiplier.warmup_length = 250 / train.max_iter - -optimizer.lr = 2e-5 diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py deleted file mode 100644 index 779442c60fa32f1d36e823e86c62979f8e48ec2c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_mvitv2_l_in21k_50ep.py +++ /dev/null @@ -1,24 +0,0 @@ -from .cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.embed_dim = 144 -model.backbone.bottom_up.depth = 48 -model.backbone.bottom_up.num_heads = 2 -model.backbone.bottom_up.last_block_indexes = (1, 7, 43, 47) -model.backbone.bottom_up.drop_path_rate = 0.5 - -train.init_checkpoint = "detectron2://ImageNetPretrained/mvitv2/MViTv2_L_in21k.pyth" - -train.max_iter = train.max_iter // 2 # 100ep -> 50ep -lr_multiplier.scheduler.milestones = [ - milestone // 2 for milestone in lr_multiplier.scheduler.milestones -] -lr_multiplier.scheduler.num_updates = train.max_iter -lr_multiplier.warmup_length = 250 / train.max_iter - -optimizer.lr = 4e-5 diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_b_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_b_in21k_50ep.py deleted file mode 100644 index d18c925f7349b42e52adb9c7b4e5461e1a25657f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_b_in21k_50ep.py +++ /dev/null @@ -1,49 +0,0 @@ -from detectron2.config.lazy import LazyCall as L -from detectron2.data.detection_utils import get_fed_loss_cls_weights -from detectron2.data.samplers import RepeatFactorTrainingSampler -from detectron2.evaluation.lvis_evaluation import LVISEvaluator - -from ..COCO.cascade_mask_rcnn_swin_b_in21k_50ep import ( - dataloader, - model, - train, - lr_multiplier, - optimizer, -) - -dataloader.train.dataset.names = "lvis_v1_train" -dataloader.train.sampler = L(RepeatFactorTrainingSampler)( - repeat_factors=L(RepeatFactorTrainingSampler.repeat_factors_from_category_frequency)( - dataset_dicts="${dataloader.train.dataset}", repeat_thresh=0.001 - ) -) -dataloader.test.dataset.names = "lvis_v1_val" -dataloader.evaluator = L(LVISEvaluator)( - dataset_name="${..test.dataset.names}", - max_dets_per_image=300, -) - -model.backbone.bottom_up.drop_path_rate = 0.3 - -model.roi_heads.num_classes = 1203 -for i in range(3): - model.roi_heads.box_predictors[i].test_score_thresh = 0.02 - model.roi_heads.box_predictors[i].test_topk_per_image = 300 - model.roi_heads.box_predictors[i].use_sigmoid_ce = True - model.roi_heads.box_predictors[i].use_fed_loss = True - model.roi_heads.box_predictors[i].get_fed_loss_cls_weights = lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 - ) - -# Schedule -# 100 ep = 156250 iters * 64 images/iter / 100000 images/ep -# 100 ep -> 50 ep as the model achieves better performance with 50 epochs -train.max_iter = 156250 // 2 -train.eval_period = 30000 - -lr_multiplier.scheduler.milestones = [milestone // 2 for milestone in [138889, 150463]] -lr_multiplier.scheduler.num_updates = train.max_iter -lr_multiplier.warmup_length = 250 / train.max_iter - -# Optimized hyperparams -optimizer.lr = 1e-4 diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_l_in21k_50ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_l_in21k_50ep.py deleted file mode 100644 index 9e22e3b28777003776774f61273c04bbb2abea1e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_swin_l_in21k_50ep.py +++ /dev/null @@ -1,12 +0,0 @@ -from .cascade_mask_rcnn_swin_b_in21k_50ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -model.backbone.bottom_up.embed_dim = 192 -model.backbone.bottom_up.num_heads = [6, 12, 24, 48] - -train.init_checkpoint = "detectron2://ImageNetPretrained/swin/swin_large_patch4_window7_224_22k.pth" diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_b_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_b_100ep.py deleted file mode 100644 index 8115224ca85b71e772302e97bda676cca3acfbd8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_b_100ep.py +++ /dev/null @@ -1,51 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.data.detection_utils import get_fed_loss_cls_weights -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import FastRCNNOutputLayers, FastRCNNConvFCHead, CascadeROIHeads - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - num_classes=1203, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm="LN", - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - num_classes="${...num_classes}", - test_score_thresh=0.02, - test_topk_per_image=300, - cls_agnostic_bbox_reg=True, - use_sigmoid_ce=True, - use_fed_loss=True, - get_fed_loss_cls_weights=lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 - ), - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_h_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_h_100ep.py deleted file mode 100644 index 68bec5734456c9bbc813becd5da83bc2a0f90932..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_h_100ep.py +++ /dev/null @@ -1,51 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.data.detection_utils import get_fed_loss_cls_weights -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import FastRCNNOutputLayers, FastRCNNConvFCHead, CascadeROIHeads - -from .mask_rcnn_vitdet_h_100ep import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - num_classes=1203, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm="LN", - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - num_classes="${...num_classes}", - test_score_thresh=0.02, - test_topk_per_image=300, - cls_agnostic_bbox_reg=True, - use_sigmoid_ce=True, - use_fed_loss=True, - get_fed_loss_cls_weights=lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 - ), - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_l_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_l_100ep.py deleted file mode 100644 index ebaf526ab7735309d5f50527136ad6207ce9d58b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/cascade_mask_rcnn_vitdet_l_100ep.py +++ /dev/null @@ -1,51 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.data.detection_utils import get_fed_loss_cls_weights -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform -from detectron2.modeling.matcher import Matcher -from detectron2.modeling.roi_heads import FastRCNNOutputLayers, FastRCNNConvFCHead, CascadeROIHeads - -from .mask_rcnn_vitdet_l_100ep import ( - dataloader, - lr_multiplier, - model, - optimizer, - train, -) - -# arguments that don't exist for Cascade R-CNN -[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]] - -model.roi_heads.update( - _target_=CascadeROIHeads, - num_classes=1203, - box_heads=[ - L(FastRCNNConvFCHead)( - input_shape=ShapeSpec(channels=256, height=7, width=7), - conv_dims=[256, 256, 256, 256], - fc_dims=[1024], - conv_norm="LN", - ) - for _ in range(3) - ], - box_predictors=[ - L(FastRCNNOutputLayers)( - input_shape=ShapeSpec(channels=1024), - box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)), - num_classes="${...num_classes}", - test_score_thresh=0.02, - test_topk_per_image=300, - cls_agnostic_bbox_reg=True, - use_sigmoid_ce=True, - use_fed_loss=True, - get_fed_loss_cls_weights=lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 - ), - ) - for (w1, w2) in [(10, 5), (20, 10), (30, 15)] - ], - proposal_matchers=[ - L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False) - for th in [0.5, 0.6, 0.7] - ], -) diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_b_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_b_100ep.py deleted file mode 100644 index ef905457ba8813f9f293beda4da20f49efca73db..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_b_100ep.py +++ /dev/null @@ -1,44 +0,0 @@ -from detectron2.config import LazyCall as L -from detectron2.data.samplers import RepeatFactorTrainingSampler -from detectron2.evaluation.lvis_evaluation import LVISEvaluator -from detectron2.data.detection_utils import get_fed_loss_cls_weights - -from ..COCO.mask_rcnn_vitdet_b_100ep import ( - dataloader, - model, - train, - lr_multiplier, - optimizer, -) - -dataloader.train.dataset.names = "lvis_v1_train" -dataloader.train.sampler = L(RepeatFactorTrainingSampler)( - repeat_factors=L(RepeatFactorTrainingSampler.repeat_factors_from_category_frequency)( - dataset_dicts="${dataloader.train.dataset}", repeat_thresh=0.001 - ) -) -dataloader.test.dataset.names = "lvis_v1_val" -dataloader.evaluator = L(LVISEvaluator)( - dataset_name="${..test.dataset.names}", - max_dets_per_image=300, -) - -model.roi_heads.num_classes = 1203 -model.roi_heads.box_predictor.test_score_thresh = 0.02 -model.roi_heads.box_predictor.test_topk_per_image = 300 -model.roi_heads.box_predictor.use_sigmoid_ce = True -model.roi_heads.box_predictor.use_fed_loss = True -model.roi_heads.box_predictor.get_fed_loss_cls_weights = lambda: get_fed_loss_cls_weights( - dataloader.train.dataset.names, 0.5 -) - -# Schedule -# 100 ep = 156250 iters * 64 images/iter / 100000 images/ep -train.max_iter = 156250 -train.eval_period = 30000 - -lr_multiplier.scheduler.milestones = [138889, 150463] -lr_multiplier.scheduler.num_updates = train.max_iter -lr_multiplier.warmup_length = 250 / train.max_iter - -optimizer.lr = 2e-4 diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_h_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_h_100ep.py deleted file mode 100644 index 0f99bad24e6702e91abe226446e7d7b00ef14df2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_h_100ep.py +++ /dev/null @@ -1,30 +0,0 @@ -from functools import partial - -from detectron2.modeling.backbone.vit import get_vit_lr_decay_rate - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_huge_p14to16.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1280 -model.backbone.net.depth = 32 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.4 -# 7, 15, 23, 31 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 7)) + list(range(8, 15)) + list(range(16, 23)) + list(range(24, 31)) -) - - -optimizer.lr = 1e-4 -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.9, num_layers=32) -optimizer.params.overrides = {} -optimizer.params.weight_decay_norm = None diff --git a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_l_100ep.py b/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_l_100ep.py deleted file mode 100644 index 15d879230fb3b8e4e0cb4bd6c8c07de8e2dda268..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/LVIS/mask_rcnn_vitdet_l_100ep.py +++ /dev/null @@ -1,26 +0,0 @@ -from functools import partial - -from detectron2.modeling.backbone.vit import get_vit_lr_decay_rate - -from .mask_rcnn_vitdet_b_100ep import ( - dataloader, - lr_multiplier, - model, - train, - optimizer, -) - -train.init_checkpoint = ( - "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_large.pth?matching_heuristics=True" -) - -model.backbone.net.embed_dim = 1024 -model.backbone.net.depth = 24 -model.backbone.net.num_heads = 16 -model.backbone.net.drop_path_rate = 0.4 -# 5, 11, 17, 23 for global attention -model.backbone.net.window_block_indexes = ( - list(range(0, 5)) + list(range(6, 11)) + list(range(12, 17)) + list(range(18, 23)) -) - -optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.8, num_layers=24) diff --git a/preprocess/detectron2/projects/ViTDet/configs/common/coco_loader_lsj.py b/preprocess/detectron2/projects/ViTDet/configs/common/coco_loader_lsj.py deleted file mode 100644 index e6c2f1e913a9f629290ce345fc4ffd4db4037e14..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/projects/ViTDet/configs/common/coco_loader_lsj.py +++ /dev/null @@ -1,22 +0,0 @@ -import detectron2.data.transforms as T -from detectron2 import model_zoo -from detectron2.config import LazyCall as L - -# Data using LSJ -image_size = 1024 -dataloader = model_zoo.get_config("common/data/coco.py").dataloader -dataloader.train.mapper.augmentations = [ - L(T.RandomFlip)(horizontal=True), # flip first - L(T.ResizeScale)( - min_scale=0.1, max_scale=2.0, target_height=image_size, target_width=image_size - ), - L(T.FixedSizeCrop)(crop_size=(image_size, image_size), pad=False), -] -dataloader.train.mapper.image_format = "RGB" -dataloader.train.total_batch_size = 64 -# recompute boxes due to cropping -dataloader.train.mapper.recompute_boxes = True - -dataloader.test.mapper.augmentations = [ - L(T.ResizeShortestEdge)(short_edge_length=image_size, max_size=image_size), -] diff --git a/preprocess/detectron2/setup.cfg b/preprocess/detectron2/setup.cfg deleted file mode 100644 index f127d7ba0575e80cc08d35e71272756aff840ee2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/setup.cfg +++ /dev/null @@ -1,26 +0,0 @@ -[isort] -line_length=100 -multi_line_output=3 -include_trailing_comma=True -known_standard_library=numpy,setuptools,mock -skip=./datasets,docs -skip_glob=*/__init__.py,**/configs/**,**/tests/config/** -known_myself=detectron2 -known_third_party=fvcore,matplotlib,cv2,torch,torchvision,PIL,pycocotools,yacs,termcolor,cityscapesscripts,tabulate,tqdm,scipy,lvis,psutil,pkg_resources,caffe2,onnx,panopticapi,black,isort,av,iopath,omegaconf,hydra,yaml,pydoc,submitit,cloudpickle,packaging,timm,pandas,fairscale,pytorch3d,pytorch_lightning -no_lines_before=STDLIB,THIRDPARTY -sections=FUTURE,STDLIB,THIRDPARTY,myself,FIRSTPARTY,LOCALFOLDER -default_section=FIRSTPARTY - -[mypy] -python_version=3.7 -ignore_missing_imports = True -warn_unused_configs = True -disallow_untyped_defs = True -check_untyped_defs = True -warn_unused_ignores = True -warn_redundant_casts = True -show_column_numbers = True -follow_imports = silent -allow_redefinition = True -; Require all functions to be annotated -disallow_incomplete_defs = True diff --git a/preprocess/detectron2/setup.py b/preprocess/detectron2/setup.py deleted file mode 100644 index b51307a625e7102d19cb18fb0cd555f9bc3ba36f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/setup.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. - -import glob -import os -import shutil -from os import path -from setuptools import find_packages, setup -from typing import List -import torch -from torch.utils.cpp_extension import CUDA_HOME, CppExtension, CUDAExtension - -torch_ver = [int(x) for x in torch.__version__.split(".")[:2]] -assert torch_ver >= [1, 8], "Requires PyTorch >= 1.8" - - -def get_version(): - init_py_path = path.join(path.abspath(path.dirname(__file__)), "detectron2", "__init__.py") - init_py = open(init_py_path, "r").readlines() - version_line = [l.strip() for l in init_py if l.startswith("__version__")][0] - version = version_line.split("=")[-1].strip().strip("'\"") - - # The following is used to build release packages. - # Users should never use it. - suffix = os.getenv("D2_VERSION_SUFFIX", "") - version = version + suffix - if os.getenv("BUILD_NIGHTLY", "0") == "1": - from datetime import datetime - - date_str = datetime.today().strftime("%y%m%d") - version = version + ".dev" + date_str - - new_init_py = [l for l in init_py if not l.startswith("__version__")] - new_init_py.append('__version__ = "{}"\n'.format(version)) - with open(init_py_path, "w") as f: - f.write("".join(new_init_py)) - return version - - -def get_extensions(): - this_dir = path.dirname(path.abspath(__file__)) - extensions_dir = path.join(this_dir, "detectron2", "layers", "csrc") - - main_source = path.join(extensions_dir, "vision.cpp") - sources = glob.glob(path.join(extensions_dir, "**", "*.cpp")) - - from torch.utils.cpp_extension import ROCM_HOME - - is_rocm_pytorch = ( - True if ((torch.version.hip is not None) and (ROCM_HOME is not None)) else False - ) - if is_rocm_pytorch: - assert torch_ver >= [1, 8], "ROCM support requires PyTorch >= 1.8!" - - # common code between cuda and rocm platforms, for hipify version [1,0,0] and later. - source_cuda = glob.glob(path.join(extensions_dir, "**", "*.cu")) + glob.glob( - path.join(extensions_dir, "*.cu") - ) - sources = [main_source] + sources - - extension = CppExtension - - extra_compile_args = {"cxx": []} - define_macros = [] - - if (torch.cuda.is_available() and ((CUDA_HOME is not None) or is_rocm_pytorch)) or os.getenv( - "FORCE_CUDA", "0" - ) == "1": - extension = CUDAExtension - sources += source_cuda - - if not is_rocm_pytorch: - define_macros += [("WITH_CUDA", None)] - extra_compile_args["nvcc"] = [ - "-O3", - "-DCUDA_HAS_FP16=1", - "-D__CUDA_NO_HALF_OPERATORS__", - "-D__CUDA_NO_HALF_CONVERSIONS__", - "-D__CUDA_NO_HALF2_OPERATORS__", - ] - else: - define_macros += [("WITH_HIP", None)] - extra_compile_args["nvcc"] = [] - - nvcc_flags_env = os.getenv("NVCC_FLAGS", "") - if nvcc_flags_env != "": - extra_compile_args["nvcc"].extend(nvcc_flags_env.split(" ")) - - if torch_ver < [1, 7]: - # supported by https://github.com/pytorch/pytorch/pull/43931 - CC = os.environ.get("CC", None) - if CC is not None: - extra_compile_args["nvcc"].append("-ccbin={}".format(CC)) - - include_dirs = [extensions_dir] - - ext_modules = [ - extension( - "detectron2._C", - sources, - include_dirs=include_dirs, - define_macros=define_macros, - extra_compile_args=extra_compile_args, - ) - ] - - return ext_modules - - -def get_model_zoo_configs() -> List[str]: - """ - Return a list of configs to include in package for model zoo. Copy over these configs inside - detectron2/model_zoo. - """ - - # Use absolute paths while symlinking. - source_configs_dir = path.join(path.dirname(path.realpath(__file__)), "configs") - destination = path.join( - path.dirname(path.realpath(__file__)), "detectron2", "model_zoo", "configs" - ) - # Symlink the config directory inside package to have a cleaner pip install. - - # Remove stale symlink/directory from a previous build. - if path.exists(source_configs_dir): - if path.islink(destination): - os.unlink(destination) - elif path.isdir(destination): - shutil.rmtree(destination) - - if not path.exists(destination): - try: - os.symlink(source_configs_dir, destination) - except OSError: - # Fall back to copying if symlink fails: ex. on Windows. - shutil.copytree(source_configs_dir, destination) - - config_paths = glob.glob("configs/**/*.yaml", recursive=True) + glob.glob( - "configs/**/*.py", recursive=True - ) - return config_paths - - -# For projects that are relative small and provide features that are very close -# to detectron2's core functionalities, we install them under detectron2.projects -PROJECTS = { - "detectron2.projects.point_rend": "projects/PointRend/point_rend", - "detectron2.projects.deeplab": "projects/DeepLab/deeplab", - "detectron2.projects.panoptic_deeplab": "projects/Panoptic-DeepLab/panoptic_deeplab", -} - -setup( - name="detectron2", - version=get_version(), - author="FAIR", - url="https://github.com/facebookresearch/detectron2", - description="Detectron2 is FAIR's next-generation research " - "platform for object detection and segmentation.", - packages=find_packages(exclude=("configs", "tests*")) + list(PROJECTS.keys()), - package_dir=PROJECTS, - package_data={"detectron2.model_zoo": get_model_zoo_configs()}, - python_requires=">=3.7", - install_requires=[ - # These dependencies are not pure-python. - # In general, avoid adding dependencies that are not pure-python because they are not - # guaranteed to be installable by `pip install` on all platforms. - "Pillow>=7.1", # or use pillow-simd for better performance - "matplotlib", # TODO move it to optional after we add opencv visualization - "pycocotools>=2.0.2", # corresponds to https://github.com/ppwwyyxx/cocoapi - # Do not add opencv here. Just like pytorch, user should install - # opencv themselves, preferrably by OS's package manager, or by - # choosing the proper pypi package name at https://github.com/skvark/opencv-python - # Also, avoid adding dependencies that transitively depend on pytorch or opencv. - # ------------------------------------------------------------ - # The following are pure-python dependencies that should be easily installable. - # But still be careful when adding more: fewer people are able to use the software - # with every new dependency added. - "termcolor>=1.1", - "yacs>=0.1.8", - "tabulate", - "cloudpickle", - "tqdm>4.29.0", - "tensorboard", - # Lock version of fvcore/iopath because they may have breaking changes - # NOTE: when updating fvcore/iopath version, make sure fvcore depends - # on compatible version of iopath. - "fvcore>=0.1.5,<0.1.6", # required like this to make it pip installable - "iopath>=0.1.7,<0.1.10", - "dataclasses; python_version<'3.7'", - "omegaconf>=2.1,<2.4", - "hydra-core>=1.1", - "black", - "packaging", - # NOTE: When adding new dependencies, if it is required at import time (in addition - # to runtime), it probably needs to appear in docs/requirements.txt, or as a mock - # in docs/conf.py - ], - extras_require={ - # optional dependencies, required by some features - "all": [ - "fairscale", - "timm", # Used by a few ViT models. - "scipy>1.5.1", - "shapely", - "pygments>=2.2", - "psutil", - "panopticapi @ https://github.com/cocodataset/panopticapi/archive/master.zip", - ], - # dev dependencies. Install them by `pip install 'detectron2[dev]'` - "dev": [ - "flake8==3.8.1", - "isort==4.3.21", - "flake8-bugbear", - "flake8-comprehensions", - "black==22.3.0", - ], - }, - ext_modules=get_extensions(), - cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension}, -) diff --git a/preprocess/detectron2/tests/README.md b/preprocess/detectron2/tests/README.md deleted file mode 100644 index f560384045ab4f6bc2beabef1170308fca117eb3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Unit Tests - -To run the unittests, do: -``` -cd detectron2 -python -m unittest discover -v -s ./tests -``` - -There are also end-to-end inference & training tests, in [dev/run_*_tests.sh](../dev). diff --git a/preprocess/detectron2/tests/__init__.py b/preprocess/detectron2/tests/__init__.py deleted file mode 100644 index 9020c2df23e2af280b7bb168b996ae9eaf312eb8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. diff --git a/preprocess/detectron2/tests/config/dir1/bad_import.py b/preprocess/detectron2/tests/config/dir1/bad_import.py deleted file mode 100644 index d7452c4dfc211223c946f22df7a2eb6bdc2cd829..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/dir1/bad_import.py +++ /dev/null @@ -1,2 +0,0 @@ -# import from directory is not allowed -from . import dir1a diff --git a/preprocess/detectron2/tests/config/dir1/bad_import2.py b/preprocess/detectron2/tests/config/dir1/bad_import2.py deleted file mode 100644 index 085a4dfa84a28b92f7d515e1911ac2cc12cbbf7d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/dir1/bad_import2.py +++ /dev/null @@ -1 +0,0 @@ -from .does_not_exist import x diff --git a/preprocess/detectron2/tests/config/dir1/dir1_a.py b/preprocess/detectron2/tests/config/dir1/dir1_a.py deleted file mode 100644 index a939955124556355524f48c0f0c16abb07cfc4c4..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/dir1/dir1_a.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -dir1a_str = "base_a_1" -dir1a_dict = {"a": 1, "b": 2} diff --git a/preprocess/detectron2/tests/config/dir1/dir1_b.py b/preprocess/detectron2/tests/config/dir1/dir1_b.py deleted file mode 100644 index 2dcb54cb1054c5d80ccc823af21f13b9ebbcf1a3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/dir1/dir1_b.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from detectron2.config import LazyConfig - -# equivalent to relative import -dir1a_str, dir1a_dict = LazyConfig.load_rel("dir1_a.py", ("dir1a_str", "dir1a_dict")) - -dir1b_str = dir1a_str + "_from_b" -dir1b_dict = dir1a_dict - -# Every import is a reload: not modified by other config files -assert dir1a_dict.a == 1 diff --git a/preprocess/detectron2/tests/config/dir1/load_rel.py b/preprocess/detectron2/tests/config/dir1/load_rel.py deleted file mode 100644 index 22d10db7fe28ad66819aeb8e991f129301095ea1..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/dir1/load_rel.py +++ /dev/null @@ -1,5 +0,0 @@ -# test that load_rel can work -from detectron2.config import LazyConfig - -x = LazyConfig.load_rel("dir1_a.py", "dir1a_dict") -assert x["a"] == 1 diff --git a/preprocess/detectron2/tests/config/root_cfg.py b/preprocess/detectron2/tests/config/root_cfg.py deleted file mode 100644 index 33d1d4bd2d9ddf31d55c655c49d13a8b7ac7b376..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/root_cfg.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from itertools import count - -from detectron2.config import LazyCall as L - -from .dir1.dir1_a import dir1a_dict, dir1a_str - -dir1a_dict.a = "modified" - -# modification above won't affect future imports -from .dir1.dir1_b import dir1b_dict, dir1b_str - - -lazyobj = L(count)(x=dir1a_str, y=dir1b_str) diff --git a/preprocess/detectron2/tests/config/test_instantiate_config.py b/preprocess/detectron2/tests/config/test_instantiate_config.py deleted file mode 100644 index 6b728943ada9bc20af5a60fbe2b3ea58d804a362..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/test_instantiate_config.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import os -import tempfile -import unittest -import yaml -from omegaconf import OmegaConf -from omegaconf import __version__ as oc_version -from dataclasses import dataclass - -from detectron2.config import LazyConfig, instantiate, LazyCall as L -from detectron2.layers import ShapeSpec -from detectron2.utils.testing import reload_lazy_config - -OC_VERSION = tuple(int(x) for x in oc_version.split(".")[:2]) - - -class TestClass: - def __init__(self, int_arg, list_arg=None, dict_arg=None, extra_arg=None): - self.int_arg = int_arg - self.list_arg = list_arg - self.dict_arg = dict_arg - self.extra_arg = extra_arg - - def __call__(self, call_arg): - return call_arg + self.int_arg - - -@unittest.skipIf(OC_VERSION < (2, 1), "omegaconf version too old") -class TestConstruction(unittest.TestCase): - def test_basic_construct(self): - cfg = L(TestClass)( - int_arg=3, - list_arg=[10], - dict_arg={}, - extra_arg=L(TestClass)(int_arg=4, list_arg="${..list_arg}"), - ) - - for x in [cfg, reload_lazy_config(cfg)]: - obj = instantiate(x) - self.assertIsInstance(obj, TestClass) - self.assertEqual(obj.int_arg, 3) - self.assertEqual(obj.extra_arg.int_arg, 4) - self.assertEqual(obj.extra_arg.list_arg, obj.list_arg) - - # Test interpolation - x.extra_arg.list_arg = [5] - obj = instantiate(x) - self.assertIsInstance(obj, TestClass) - self.assertEqual(obj.extra_arg.list_arg, [5]) - - def test_instantiate_other_obj(self): - # do nothing for other obj - self.assertEqual(instantiate(5), 5) - x = [3, 4, 5] - self.assertEqual(instantiate(x), x) - x = TestClass(1) - self.assertIs(instantiate(x), x) - x = {"xx": "yy"} - self.assertIs(instantiate(x), x) - - def test_instantiate_lazy_target(self): - # _target_ is result of instantiate - objconf = L(L(len)(int_arg=3))(call_arg=4) - objconf._target_._target_ = TestClass - self.assertEqual(instantiate(objconf), 7) - - def test_instantiate_list(self): - lst = [1, 2, L(TestClass)(int_arg=1)] - x = L(TestClass)(int_arg=lst) # list as an argument should be recursively instantiated - x = instantiate(x).int_arg - self.assertEqual(x[:2], [1, 2]) - self.assertIsInstance(x[2], TestClass) - self.assertEqual(x[2].int_arg, 1) - - def test_instantiate_dataclass(self): - cfg = L(ShapeSpec)(channels=1, width=3) - # Test original cfg as well as serialization - for x in [cfg, reload_lazy_config(cfg)]: - obj = instantiate(x) - self.assertIsInstance(obj, ShapeSpec) - self.assertEqual(obj.channels, 1) - self.assertEqual(obj.height, None) - - def test_instantiate_dataclass_as_subconfig(self): - cfg = L(TestClass)(int_arg=1, extra_arg=ShapeSpec(channels=1, width=3)) - # Test original cfg as well as serialization - for x in [cfg, reload_lazy_config(cfg)]: - obj = instantiate(x) - self.assertIsInstance(obj.extra_arg, ShapeSpec) - self.assertEqual(obj.extra_arg.channels, 1) - self.assertEqual(obj.extra_arg.height, None) - - def test_bad_lazycall(self): - with self.assertRaises(Exception): - L(3) - - def test_interpolation(self): - cfg = L(TestClass)(int_arg=3, extra_arg="${int_arg}") - - cfg.int_arg = 4 - obj = instantiate(cfg) - self.assertEqual(obj.extra_arg, 4) - - # Test that interpolation still works after serialization - cfg = reload_lazy_config(cfg) - cfg.int_arg = 5 - obj = instantiate(cfg) - self.assertEqual(obj.extra_arg, 5) diff --git a/preprocess/detectron2/tests/config/test_lazy_config.py b/preprocess/detectron2/tests/config/test_lazy_config.py deleted file mode 100644 index ff68143dbe60742fe0a44ba874837ca65d07c386..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/test_lazy_config.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import os -import unittest -import tempfile -from itertools import count - -from detectron2.config import LazyConfig, LazyCall as L -from omegaconf import DictConfig - - -class TestLazyPythonConfig(unittest.TestCase): - def setUp(self): - self.curr_dir = os.path.dirname(__file__) - self.root_filename = os.path.join(self.curr_dir, "root_cfg.py") - - def test_load(self): - cfg = LazyConfig.load(self.root_filename) - - self.assertEqual(cfg.dir1a_dict.a, "modified") - self.assertEqual(cfg.dir1b_dict.a, 1) - self.assertEqual(cfg.lazyobj.x, "base_a_1") - - cfg.lazyobj.x = "new_x" - # reload - cfg = LazyConfig.load(self.root_filename) - self.assertEqual(cfg.lazyobj.x, "base_a_1") - - def test_save_load(self): - cfg = LazyConfig.load(self.root_filename) - with tempfile.TemporaryDirectory(prefix="detectron2") as d: - fname = os.path.join(d, "test_config.yaml") - LazyConfig.save(cfg, fname) - cfg2 = LazyConfig.load(fname) - - self.assertEqual(cfg2.lazyobj._target_, "itertools.count") - self.assertEqual(cfg.lazyobj._target_, count) - cfg2.lazyobj.pop("_target_") - cfg.lazyobj.pop("_target_") - # the rest are equal - self.assertEqual(cfg, cfg2) - - def test_failed_save(self): - cfg = DictConfig({"x": lambda: 3}, flags={"allow_objects": True}) - with tempfile.TemporaryDirectory(prefix="detectron2") as d: - fname = os.path.join(d, "test_config.yaml") - LazyConfig.save(cfg, fname) - self.assertTrue(os.path.exists(fname)) - self.assertTrue(os.path.exists(fname + ".pkl")) - - def test_overrides(self): - cfg = LazyConfig.load(self.root_filename) - LazyConfig.apply_overrides(cfg, ["lazyobj.x=123", 'dir1b_dict.a="123"']) - self.assertEqual(cfg.dir1b_dict.a, "123") - self.assertEqual(cfg.lazyobj.x, 123) - - LazyConfig.apply_overrides(cfg, ["dir1b_dict.a=abc"]) - self.assertEqual(cfg.dir1b_dict.a, "abc") - - def test_invalid_overrides(self): - cfg = LazyConfig.load(self.root_filename) - with self.assertRaises(KeyError): - LazyConfig.apply_overrides(cfg, ["lazyobj.x.xxx=123"]) - - def test_to_py(self): - cfg = LazyConfig.load(self.root_filename) - cfg.lazyobj.x = {"a": 1, "b": 2, "c": L(count)(x={"r": "a", "s": 2.4, "t": [1, 2, 3, "z"]})} - cfg.list = ["a", 1, "b", 3.2] - py_str = LazyConfig.to_py(cfg) - expected = """cfg.dir1a_dict.a = "modified" -cfg.dir1a_dict.b = 2 -cfg.dir1b_dict.a = 1 -cfg.dir1b_dict.b = 2 -cfg.lazyobj = itertools.count( - x={ - "a": 1, - "b": 2, - "c": itertools.count(x={"r": "a", "s": 2.4, "t": [1, 2, 3, "z"]}), - }, - y="base_a_1_from_b", -) -cfg.list = ["a", 1, "b", 3.2] -""" - self.assertEqual(py_str, expected) - - def test_bad_import(self): - file = os.path.join(self.curr_dir, "dir1", "bad_import.py") - with self.assertRaisesRegex(ImportError, "relative import"): - LazyConfig.load(file) - - def test_bad_import2(self): - file = os.path.join(self.curr_dir, "dir1", "bad_import2.py") - with self.assertRaisesRegex(ImportError, "not exist"): - LazyConfig.load(file) - - def test_load_rel(self): - file = os.path.join(self.curr_dir, "dir1", "load_rel.py") - cfg = LazyConfig.load(file) - self.assertIn("x", cfg) diff --git a/preprocess/detectron2/tests/config/test_yacs_config.py b/preprocess/detectron2/tests/config/test_yacs_config.py deleted file mode 100644 index 01dd6955f78e2700ffc10ed723ab1c95df0e5a18..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/config/test_yacs_config.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. - - -import os -import tempfile -import unittest -import torch -from omegaconf import OmegaConf - -from detectron2 import model_zoo -from detectron2.config import configurable, downgrade_config, get_cfg, upgrade_config -from detectron2.layers import ShapeSpec -from detectron2.modeling import build_model - -_V0_CFG = """ -MODEL: - RPN_HEAD: - NAME: "TEST" -VERSION: 0 -""" - -_V1_CFG = """ -MODEL: - WEIGHT: "/path/to/weight" -""" - - -class TestConfigVersioning(unittest.TestCase): - def test_upgrade_downgrade_consistency(self): - cfg = get_cfg() - # check that custom is preserved - cfg.USER_CUSTOM = 1 - - down = downgrade_config(cfg, to_version=0) - up = upgrade_config(down) - self.assertTrue(up == cfg) - - def _merge_cfg_str(self, cfg, merge_str): - f = tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) - try: - f.write(merge_str) - f.close() - cfg.merge_from_file(f.name) - finally: - os.remove(f.name) - return cfg - - def test_auto_upgrade(self): - cfg = get_cfg() - latest_ver = cfg.VERSION - cfg.USER_CUSTOM = 1 - - self._merge_cfg_str(cfg, _V0_CFG) - - self.assertEqual(cfg.MODEL.RPN.HEAD_NAME, "TEST") - self.assertEqual(cfg.VERSION, latest_ver) - - def test_guess_v1(self): - cfg = get_cfg() - latest_ver = cfg.VERSION - self._merge_cfg_str(cfg, _V1_CFG) - self.assertEqual(cfg.VERSION, latest_ver) - - -class _TestClassA(torch.nn.Module): - @configurable - def __init__(self, arg1, arg2, arg3=3): - super().__init__() - self.arg1 = arg1 - self.arg2 = arg2 - self.arg3 = arg3 - assert arg1 == 1 - assert arg2 == 2 - assert arg3 == 3 - - @classmethod - def from_config(cls, cfg): - args = {"arg1": cfg.ARG1, "arg2": cfg.ARG2} - return args - - -class _TestClassB(_TestClassA): - @configurable - def __init__(self, input_shape, arg1, arg2, arg3=3): - """ - Doc of _TestClassB - """ - assert input_shape == "shape" - super().__init__(arg1, arg2, arg3) - - @classmethod - def from_config(cls, cfg, input_shape): # test extra positional arg in from_config - args = {"arg1": cfg.ARG1, "arg2": cfg.ARG2} - args["input_shape"] = input_shape - return args - - -class _LegacySubClass(_TestClassB): - # an old subclass written in cfg style - def __init__(self, cfg, input_shape, arg4=4): - super().__init__(cfg, input_shape) - assert self.arg1 == 1 - assert self.arg2 == 2 - assert self.arg3 == 3 - - -class _NewSubClassNewInit(_TestClassB): - # test new subclass with a new __init__ - @configurable - def __init__(self, input_shape, arg4=4, **kwargs): - super().__init__(input_shape, **kwargs) - assert self.arg1 == 1 - assert self.arg2 == 2 - assert self.arg3 == 3 - - -class _LegacySubClassNotCfg(_TestClassB): - # an old subclass written in cfg style, but argument is not called "cfg" - def __init__(self, config, input_shape): - super().__init__(config, input_shape) - assert self.arg1 == 1 - assert self.arg2 == 2 - assert self.arg3 == 3 - - -class _TestClassC(_TestClassB): - @classmethod - def from_config(cls, cfg, input_shape, **kwargs): # test extra kwarg overwrite - args = {"arg1": cfg.ARG1, "arg2": cfg.ARG2} - args["input_shape"] = input_shape - args.update(kwargs) - return args - - -class _TestClassD(_TestClassA): - @configurable - def __init__(self, input_shape: ShapeSpec, arg1: int, arg2, arg3=3): - assert input_shape == "shape" - super().__init__(arg1, arg2, arg3) - - # _TestClassA.from_config does not have input_shape args. - # Test whether input_shape will be forwarded to __init__ - - -@configurable(from_config=lambda cfg, arg2: {"arg1": cfg.ARG1, "arg2": arg2, "arg3": cfg.ARG3}) -def _test_func(arg1, arg2=2, arg3=3, arg4=4): - return arg1, arg2, arg3, arg4 - - -class TestConfigurable(unittest.TestCase): - def testInitWithArgs(self): - _ = _TestClassA(arg1=1, arg2=2, arg3=3) - _ = _TestClassB("shape", arg1=1, arg2=2) - _ = _TestClassC("shape", arg1=1, arg2=2) - _ = _TestClassD("shape", arg1=1, arg2=2, arg3=3) - - def testPatchedAttr(self): - self.assertTrue("Doc" in _TestClassB.__init__.__doc__) - self.assertEqual(_TestClassD.__init__.__annotations__["arg1"], int) - - def testInitWithCfg(self): - cfg = get_cfg() - cfg.ARG1 = 1 - cfg.ARG2 = 2 - cfg.ARG3 = 3 - _ = _TestClassA(cfg) - _ = _TestClassB(cfg, input_shape="shape") - _ = _TestClassC(cfg, input_shape="shape") - _ = _TestClassD(cfg, input_shape="shape") - _ = _LegacySubClass(cfg, input_shape="shape") - _ = _NewSubClassNewInit(cfg, input_shape="shape") - _ = _LegacySubClassNotCfg(cfg, input_shape="shape") - with self.assertRaises(TypeError): - # disallow forwarding positional args to __init__ since it's prone to errors - _ = _TestClassD(cfg, "shape") - - # call with kwargs instead - _ = _TestClassA(cfg=cfg) - _ = _TestClassB(cfg=cfg, input_shape="shape") - _ = _TestClassC(cfg=cfg, input_shape="shape") - _ = _TestClassD(cfg=cfg, input_shape="shape") - _ = _LegacySubClass(cfg=cfg, input_shape="shape") - _ = _NewSubClassNewInit(cfg=cfg, input_shape="shape") - _ = _LegacySubClassNotCfg(config=cfg, input_shape="shape") - - def testInitWithCfgOverwrite(self): - cfg = get_cfg() - cfg.ARG1 = 1 - cfg.ARG2 = 999 # wrong config - with self.assertRaises(AssertionError): - _ = _TestClassA(cfg, arg3=3) - - # overwrite arg2 with correct config later: - _ = _TestClassA(cfg, arg2=2, arg3=3) - _ = _TestClassB(cfg, input_shape="shape", arg2=2, arg3=3) - _ = _TestClassC(cfg, input_shape="shape", arg2=2, arg3=3) - _ = _TestClassD(cfg, input_shape="shape", arg2=2, arg3=3) - - # call with kwargs cfg=cfg instead - _ = _TestClassA(cfg=cfg, arg2=2, arg3=3) - _ = _TestClassB(cfg=cfg, input_shape="shape", arg2=2, arg3=3) - _ = _TestClassC(cfg=cfg, input_shape="shape", arg2=2, arg3=3) - _ = _TestClassD(cfg=cfg, input_shape="shape", arg2=2, arg3=3) - - def testInitWithCfgWrongArgs(self): - cfg = get_cfg() - cfg.ARG1 = 1 - cfg.ARG2 = 2 - with self.assertRaises(TypeError): - _ = _TestClassB(cfg, "shape", not_exist=1) - with self.assertRaises(TypeError): - _ = _TestClassC(cfg, "shape", not_exist=1) - with self.assertRaises(TypeError): - _ = _TestClassD(cfg, "shape", not_exist=1) - - def testBadClass(self): - class _BadClass1: - @configurable - def __init__(self, a=1, b=2): - pass - - class _BadClass2: - @configurable - def __init__(self, a=1, b=2): - pass - - def from_config(self, cfg): # noqa - pass - - class _BadClass3: - @configurable - def __init__(self, a=1, b=2): - pass - - # bad name: must be cfg - @classmethod - def from_config(cls, config): # noqa - pass - - with self.assertRaises(AttributeError): - _ = _BadClass1(a=1) - - with self.assertRaises(TypeError): - _ = _BadClass2(a=1) - - with self.assertRaises(TypeError): - _ = _BadClass3(get_cfg()) - - def testFuncWithCfg(self): - cfg = get_cfg() - cfg.ARG1 = 10 - cfg.ARG3 = 30 - - self.assertEqual(_test_func(1), (1, 2, 3, 4)) - with self.assertRaises(TypeError): - _test_func(cfg) - self.assertEqual(_test_func(cfg, arg2=2), (10, 2, 30, 4)) - self.assertEqual(_test_func(cfg, arg1=100, arg2=20), (100, 20, 30, 4)) - self.assertEqual(_test_func(cfg, arg1=100, arg2=20, arg4=40), (100, 20, 30, 40)) - - self.assertTrue(callable(_test_func.from_config)) - - def testOmegaConf(self): - cfg = model_zoo.get_config("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml") - cfg = OmegaConf.create(cfg.dump()) - if not torch.cuda.is_available(): - cfg.MODEL.DEVICE = "cpu" - # test that a model can be built with omegaconf config as well - build_model(cfg) diff --git a/preprocess/detectron2/tests/data/__init__.py b/preprocess/detectron2/tests/data/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tests/data/test_coco.py b/preprocess/detectron2/tests/data/test_coco.py deleted file mode 100644 index caabead5527639056daeef71027a69c47ee2ebf7..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_coco.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import json -import numpy as np -import os -import tempfile -import unittest -import pycocotools.mask as mask_util - -from detectron2.data import DatasetCatalog, MetadataCatalog -from detectron2.data.datasets.coco import convert_to_coco_dict, load_coco_json -from detectron2.structures import BoxMode - - -def make_mask(): - """ - Makes a donut shaped binary mask. - """ - H = 100 - W = 100 - mask = np.zeros([H, W], dtype=np.uint8) - for x in range(W): - for y in range(H): - d = np.linalg.norm(np.array([W, H]) / 2 - np.array([x, y])) - if d > 10 and d < 20: - mask[y, x] = 1 - return mask - - -def uncompressed_rle(mask): - l = mask.flatten(order="F").tolist() - counts = [] - p = False - cnt = 0 - for i in l: - if i == p: - cnt += 1 - else: - counts.append(cnt) - p = i - cnt = 1 - counts.append(cnt) - return {"counts": counts, "size": [mask.shape[0], mask.shape[1]]} - - -def make_dataset_dicts(mask, compressed: bool = True): - """ - Returns a list of dicts that represents a single COCO data point for - object detection. The single instance given by `mask` is represented by - RLE, either compressed or uncompressed. - """ - record = {} - record["file_name"] = "test" - record["image_id"] = 0 - record["height"] = mask.shape[0] - record["width"] = mask.shape[1] - - y, x = np.nonzero(mask) - if compressed: - segmentation = mask_util.encode(np.asarray(mask, order="F")) - else: - segmentation = uncompressed_rle(mask) - min_x = np.min(x) - max_x = np.max(x) - min_y = np.min(y) - max_y = np.max(y) - obj = { - "bbox": [min_x, min_y, max_x, max_y], - "bbox_mode": BoxMode.XYXY_ABS, - "category_id": 0, - "iscrowd": 0, - "segmentation": segmentation, - } - record["annotations"] = [obj] - return [record] - - -class TestRLEToJson(unittest.TestCase): - def test(self): - # Make a dummy dataset. - mask = make_mask() - DatasetCatalog.register("test_dataset", lambda: make_dataset_dicts(mask)) - MetadataCatalog.get("test_dataset").set(thing_classes=["test_label"]) - - # Dump to json. - json_dict = convert_to_coco_dict("test_dataset") - with tempfile.TemporaryDirectory() as tmpdir: - json_file_name = os.path.join(tmpdir, "test.json") - with open(json_file_name, "w") as f: - json.dump(json_dict, f) - # Load from json. - dicts = load_coco_json(json_file_name, "") - - # Check the loaded mask matches the original. - anno = dicts[0]["annotations"][0] - loaded_mask = mask_util.decode(anno["segmentation"]) - self.assertTrue(np.array_equal(loaded_mask, mask)) - DatasetCatalog.pop("test_dataset") - MetadataCatalog.pop("test_dataset") - - def test_uncompressed_RLE(self): - mask = make_mask() - rle = mask_util.encode(np.asarray(mask, order="F")) - uncompressed = uncompressed_rle(mask) - compressed = mask_util.frPyObjects(uncompressed, *rle["size"]) - self.assertEqual(rle, compressed) - - -class TestConvertCOCO(unittest.TestCase): - @staticmethod - def generate_data(): - record = { - "file_name": "test", - "image_id": 0, - "height": 100, - "width": 100, - "annotations": [ - { - "bbox": [10, 10, 10, 10, 5], - "bbox_mode": BoxMode.XYWHA_ABS, - "category_id": 0, - "iscrowd": 0, - }, - { - "bbox": [15, 15, 3, 3], - "bbox_mode": BoxMode.XYXY_ABS, - "category_id": 0, - "iscrowd": 0, - }, - ], - } - - return [record] - - def test_convert_to_coco(self): - DatasetCatalog.register("test_dataset", lambda: TestConvertCOCO.generate_data()) - MetadataCatalog.get("test_dataset").set(thing_classes=["test_label"]) - convert_to_coco_dict("test_dataset") - DatasetCatalog.pop("test_dataset") - MetadataCatalog.pop("test_dataset") diff --git a/preprocess/detectron2/tests/data/test_coco_evaluation.py b/preprocess/detectron2/tests/data/test_coco_evaluation.py deleted file mode 100644 index 964f00284df64d3378ebfe32913c07deb5a1f819..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_coco_evaluation.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import contextlib -import copy -import io -import json -import numpy as np -import os -import tempfile -import unittest -import torch -from pycocotools.coco import COCO -from pycocotools.cocoeval import COCOeval - -from detectron2.data import DatasetCatalog -from detectron2.evaluation import COCOEvaluator -from detectron2.evaluation.fast_eval_api import COCOeval_opt -from detectron2.structures import Boxes, Instances - - -class TestCOCOeval(unittest.TestCase): - def test_fast_eval(self): - # A small set of images/categories from COCO val - # fmt: off - detections = [{"image_id": 139, "category_id": 1, "bbox": [417.3332824707031, 159.27003479003906, 47.66064453125, 143.00193786621094], "score": 0.9949821829795837, "segmentation": {"size": [426, 640], "counts": "Tc`52W=3N0N4aNN^E7]:4XE1g:8kDMT;U100000001O1gE[Nk8h1dFiNY9Z1aFkN]9g2J3NdN`FlN`9S1cFRN07]9g1bFoM6;X9c1cFoM=8R9g1bFQN>3U9Y30O01OO1O001N2O1N1O4L4L5UNoE3V:CVF6Q:@YF9l9@ZF 0 else 0.0 - msg = "%s: comparing COCO APIs, %s differs by %f" % (name, k, abs_diff) - self.assertTrue(abs_diff < 1e-4, msg=msg) - - def test_unknown_category(self): - dataset = "coco_2017_val_100" - evaluator = COCOEvaluator(dataset) - evaluator.reset() - inputs = DatasetCatalog.get(dataset)[:2] - pred = Instances((100, 100)) - pred.pred_boxes = Boxes(torch.rand(2, 4)) - pred.scores = torch.rand(2) - pred.pred_classes = torch.tensor([10, 80]) - output = {"instances": pred} - evaluator.process(inputs, [output, output]) - with self.assertRaises(AssertionError): - evaluator.evaluate() diff --git a/preprocess/detectron2/tests/data/test_dataset.py b/preprocess/detectron2/tests/data/test_dataset.py deleted file mode 100644 index b412ca760ab4e47d2a93b975decedbdf8578ca3f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_dataset.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import os -import pickle -import sys -import unittest -from functools import partial -import torch -from iopath.common.file_io import LazyPath - -from detectron2 import model_zoo -from detectron2.config import get_cfg, instantiate -from detectron2.data import ( - DatasetCatalog, - DatasetFromList, - MapDataset, - ToIterableDataset, - build_batch_data_loader, - build_detection_test_loader, - build_detection_train_loader, -) -from detectron2.data.common import ( - AspectRatioGroupedDataset, - set_default_dataset_from_list_serialize_method, -) -from detectron2.data.samplers import InferenceSampler, TrainingSampler - - -def _a_slow_func(x): - return "path/{}".format(x) - - -class TestDatasetFromList(unittest.TestCase): - # Failing for py3.6, likely due to pickle - @unittest.skipIf(sys.version_info.minor <= 6, "Not supported in Python 3.6") - def test_using_lazy_path(self): - dataset = [] - for i in range(10): - dataset.append({"file_name": LazyPath(partial(_a_slow_func, i))}) - - dataset = DatasetFromList(dataset) - for i in range(10): - path = dataset[i]["file_name"] - self.assertTrue(isinstance(path, LazyPath)) - self.assertEqual(os.fspath(path), _a_slow_func(i)) - - def test_alternative_serialize_method(self): - dataset = [1, 2, 3] - dataset = DatasetFromList(dataset, serialize=torch.tensor) - self.assertEqual(dataset[2], torch.tensor(3)) - - def test_change_default_serialize_method(self): - dataset = [1, 2, 3] - with set_default_dataset_from_list_serialize_method(torch.tensor): - dataset_1 = DatasetFromList(dataset, serialize=True) - self.assertEqual(dataset_1[2], torch.tensor(3)) - dataset_2 = DatasetFromList(dataset, serialize=True) - self.assertEqual(dataset_2[2], 3) - - -class TestMapDataset(unittest.TestCase): - @staticmethod - def map_func(x): - if x == 2: - return None - return x * 2 - - def test_map_style(self): - ds = DatasetFromList([1, 2, 3]) - ds = MapDataset(ds, TestMapDataset.map_func) - self.assertEqual(ds[0], 2) - self.assertEqual(ds[2], 6) - self.assertIn(ds[1], [2, 6]) - - def test_iter_style(self): - class DS(torch.utils.data.IterableDataset): - def __iter__(self): - yield from [1, 2, 3] - - ds = DS() - ds = MapDataset(ds, TestMapDataset.map_func) - self.assertIsInstance(ds, torch.utils.data.IterableDataset) - - data = list(iter(ds)) - self.assertEqual(data, [2, 6]) - - def test_pickleability(self): - ds = DatasetFromList([1, 2, 3]) - ds = MapDataset(ds, lambda x: x * 2) - ds = pickle.loads(pickle.dumps(ds)) - self.assertEqual(ds[0], 2) - - -class TestAspectRatioGrouping(unittest.TestCase): - def test_reiter_leak(self): - data = [(1, 0), (0, 1), (1, 0), (0, 1)] - data = [{"width": a, "height": b} for (a, b) in data] - batchsize = 2 - dataset = AspectRatioGroupedDataset(data, batchsize) - - for _ in range(5): - for idx, __ in enumerate(dataset): - if idx == 1: - # manually break, so the iterator does not stop by itself - break - # check that bucket sizes are valid - for bucket in dataset._buckets: - self.assertLess(len(bucket), batchsize) - - -class _MyData(torch.utils.data.IterableDataset): - def __iter__(self): - while True: - yield 1 - - -class TestDataLoader(unittest.TestCase): - def _get_kwargs(self): - # get kwargs of build_detection_train_loader - cfg = model_zoo.get_config("common/data/coco.py").dataloader.train - cfg.dataset.names = "coco_2017_val_100" - cfg.pop("_target_") - kwargs = {k: instantiate(v) for k, v in cfg.items()} - return kwargs - - def test_build_dataloader_train(self): - kwargs = self._get_kwargs() - dl = build_detection_train_loader(**kwargs) - next(iter(dl)) - - def test_build_iterable_dataloader_train(self): - kwargs = self._get_kwargs() - ds = DatasetFromList(kwargs.pop("dataset")) - ds = ToIterableDataset(ds, TrainingSampler(len(ds))) - dl = build_detection_train_loader(dataset=ds, **kwargs) - next(iter(dl)) - - def test_build_iterable_dataloader_from_cfg(self): - cfg = get_cfg() - cfg.DATASETS.TRAIN = ["iter_data"] - DatasetCatalog.register("iter_data", lambda: _MyData()) - dl = build_detection_train_loader(cfg, mapper=lambda x: x, aspect_ratio_grouping=False) - next(iter(dl)) - - dl = build_detection_test_loader(cfg, "iter_data", mapper=lambda x: x) - next(iter(dl)) - - def _check_is_range(self, data_loader, N): - # check that data_loader produces range(N) - data = list(iter(data_loader)) - data = [x for batch in data for x in batch] # flatten the batches - self.assertEqual(len(data), N) - self.assertEqual(set(data), set(range(N))) - - def test_build_batch_dataloader_inference(self): - # Test that build_batch_data_loader can be used for inference - N = 96 - ds = DatasetFromList(list(range(N))) - sampler = InferenceSampler(len(ds)) - dl = build_batch_data_loader(ds, sampler, 8, num_workers=3) - self._check_is_range(dl, N) - - def test_build_batch_dataloader_inference_incomplete_batch(self): - # Test that build_batch_data_loader works when dataset size is not multiple of - # batch size or num_workers - def _test(N, batch_size, num_workers): - ds = DatasetFromList(list(range(N))) - sampler = InferenceSampler(len(ds)) - - dl = build_batch_data_loader(ds, sampler, batch_size, num_workers=num_workers) - data = list(iter(dl)) - self.assertEqual(len(data), len(dl)) # floor(N / batch_size) - self._check_is_range(dl, N // batch_size * batch_size) - - dl = build_batch_data_loader( - ds, sampler, batch_size, num_workers=num_workers, drop_last=False - ) - data = list(iter(dl)) - self.assertEqual(len(data), len(dl)) # ceil(N / batch_size) - self._check_is_range(dl, N) - - _test(48, batch_size=8, num_workers=3) - _test(47, batch_size=8, num_workers=3) - _test(46, batch_size=8, num_workers=3) - _test(40, batch_size=8, num_workers=3) - _test(39, batch_size=8, num_workers=3) - - def test_build_dataloader_inference(self): - N = 50 - ds = DatasetFromList(list(range(N))) - sampler = InferenceSampler(len(ds)) - # test that parallel loader works correctly - dl = build_detection_test_loader( - dataset=ds, sampler=sampler, mapper=lambda x: x, num_workers=3 - ) - self._check_is_range(dl, N) - - # test that batch_size works correctly - dl = build_detection_test_loader( - dataset=ds, sampler=sampler, mapper=lambda x: x, batch_size=4, num_workers=0 - ) - self._check_is_range(dl, N) - - def test_build_iterable_dataloader_inference(self): - # Test that build_detection_test_loader supports iterable dataset - N = 50 - ds = DatasetFromList(list(range(N))) - ds = ToIterableDataset(ds, InferenceSampler(len(ds))) - dl = build_detection_test_loader(dataset=ds, mapper=lambda x: x, num_workers=3) - self._check_is_range(dl, N) diff --git a/preprocess/detectron2/tests/data/test_detection_utils.py b/preprocess/detectron2/tests/data/test_detection_utils.py deleted file mode 100644 index aac56c07da2be4e181e3e95de8cee1fc2858286d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_detection_utils.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import copy -import numpy as np -import os -import unittest -import pycocotools.mask as mask_util - -from detectron2.data import MetadataCatalog, detection_utils -from detectron2.data import transforms as T -from detectron2.structures import BitMasks, BoxMode -from detectron2.utils.file_io import PathManager - - -class TestTransformAnnotations(unittest.TestCase): - def test_transform_simple_annotation(self): - transforms = T.TransformList([T.HFlipTransform(400)]) - anno = { - "bbox": np.asarray([10, 10, 200, 300]), - "bbox_mode": BoxMode.XYXY_ABS, - "category_id": 3, - "segmentation": [[10, 10, 100, 100, 100, 10], [150, 150, 200, 150, 200, 200]], - } - - output = detection_utils.transform_instance_annotations(anno, transforms, (400, 400)) - self.assertTrue(np.allclose(output["bbox"], [200, 10, 390, 300])) - self.assertEqual(len(output["segmentation"]), len(anno["segmentation"])) - self.assertTrue(np.allclose(output["segmentation"][0], [390, 10, 300, 100, 300, 10])) - - detection_utils.annotations_to_instances([output, output], (400, 400)) - - def test_transform_empty_annotation(self): - detection_utils.annotations_to_instances([], (400, 400)) - - def test_flip_keypoints(self): - transforms = T.TransformList([T.HFlipTransform(400)]) - anno = { - "bbox": np.asarray([10, 10, 200, 300]), - "bbox_mode": BoxMode.XYXY_ABS, - "keypoints": np.random.rand(17, 3) * 50 + 15, - } - - output = detection_utils.transform_instance_annotations( - copy.deepcopy(anno), - transforms, - (400, 400), - keypoint_hflip_indices=detection_utils.create_keypoint_hflip_indices( - ["keypoints_coco_2017_train"] - ), - ) - # The first keypoint is nose - self.assertTrue(np.allclose(output["keypoints"][0, 0], 400 - anno["keypoints"][0, 0])) - # The last 16 keypoints are 8 left-right pairs - self.assertTrue( - np.allclose( - output["keypoints"][1:, 0].reshape(-1, 2)[:, ::-1], - 400 - anno["keypoints"][1:, 0].reshape(-1, 2), - ) - ) - self.assertTrue( - np.allclose( - output["keypoints"][1:, 1:].reshape(-1, 2, 2)[:, ::-1, :], - anno["keypoints"][1:, 1:].reshape(-1, 2, 2), - ) - ) - - def test_crop(self): - transforms = T.TransformList([T.CropTransform(300, 300, 10, 10)]) - keypoints = np.random.rand(17, 3) * 50 + 15 - keypoints[:, 2] = 2 - anno = { - "bbox": np.asarray([10, 10, 200, 400]), - "bbox_mode": BoxMode.XYXY_ABS, - "keypoints": keypoints, - } - - output = detection_utils.transform_instance_annotations( - copy.deepcopy(anno), transforms, (10, 10) - ) - # box is shifted and cropped - self.assertTrue((output["bbox"] == np.asarray([0, 0, 0, 10])).all()) - # keypoints are no longer visible - self.assertTrue((output["keypoints"][:, 2] == 0).all()) - - def test_transform_RLE(self): - transforms = T.TransformList([T.HFlipTransform(400)]) - mask = np.zeros((300, 400), order="F").astype("uint8") - mask[:, :200] = 1 - - anno = { - "bbox": np.asarray([10, 10, 200, 300]), - "bbox_mode": BoxMode.XYXY_ABS, - "segmentation": mask_util.encode(mask[:, :, None])[0], - "category_id": 3, - } - output = detection_utils.transform_instance_annotations( - copy.deepcopy(anno), transforms, (300, 400) - ) - mask = output["segmentation"] - self.assertTrue((mask[:, 200:] == 1).all()) - self.assertTrue((mask[:, :200] == 0).all()) - - inst = detection_utils.annotations_to_instances( - [output, output], (400, 400), mask_format="bitmask" - ) - self.assertTrue(isinstance(inst.gt_masks, BitMasks)) - - def test_transform_RLE_resize(self): - transforms = T.TransformList( - [T.HFlipTransform(400), T.ScaleTransform(300, 400, 400, 400, "bilinear")] - ) - mask = np.zeros((300, 400), order="F").astype("uint8") - mask[:, :200] = 1 - - anno = { - "bbox": np.asarray([10, 10, 200, 300]), - "bbox_mode": BoxMode.XYXY_ABS, - "segmentation": mask_util.encode(mask[:, :, None])[0], - "category_id": 3, - } - output = detection_utils.transform_instance_annotations( - copy.deepcopy(anno), transforms, (400, 400) - ) - - inst = detection_utils.annotations_to_instances( - [output, output], (400, 400), mask_format="bitmask" - ) - self.assertTrue(isinstance(inst.gt_masks, BitMasks)) - - def test_gen_crop(self): - instance = {"bbox": [10, 10, 100, 100], "bbox_mode": BoxMode.XYXY_ABS} - t = detection_utils.gen_crop_transform_with_instance((10, 10), (150, 150), instance) - # the box center must fall into the cropped region - self.assertTrue(t.x0 <= 55 <= t.x0 + t.w) - - def test_gen_crop_outside_boxes(self): - instance = {"bbox": [10, 10, 100, 100], "bbox_mode": BoxMode.XYXY_ABS} - with self.assertRaises(AssertionError): - detection_utils.gen_crop_transform_with_instance((10, 10), (15, 15), instance) - - def test_read_sem_seg(self): - cityscapes_dir = MetadataCatalog.get("cityscapes_fine_sem_seg_val").gt_dir - sem_seg_gt_path = os.path.join( - cityscapes_dir, "frankfurt", "frankfurt_000001_083852_gtFine_labelIds.png" - ) - if not PathManager.exists(sem_seg_gt_path): - raise unittest.SkipTest( - "Semantic segmentation ground truth {} not found.".format(sem_seg_gt_path) - ) - sem_seg = detection_utils.read_image(sem_seg_gt_path, "L") - self.assertEqual(sem_seg.ndim, 3) - self.assertEqual(sem_seg.shape[2], 1) - self.assertEqual(sem_seg.dtype, np.uint8) - self.assertEqual(sem_seg.max(), 32) - self.assertEqual(sem_seg.min(), 1) - - def test_read_exif_orientation(self): - # https://github.com/recurser/exif-orientation-examples/raw/master/Landscape_5.jpg - URL = "detectron2://assets/Landscape_5.jpg" - img = detection_utils.read_image(URL, "RGB") - self.assertEqual(img.ndim, 3) - self.assertEqual(img.dtype, np.uint8) - self.assertEqual(img.shape, (1200, 1800, 3)) # check that shape is not transposed - - def test_opencv_exif_orientation(self): - import cv2 - - URL = "detectron2://assets/Landscape_5.jpg" - with PathManager.open(URL, "rb") as f: - img = cv2.imdecode(np.frombuffer(f.read(), dtype="uint8"), cv2.IMREAD_COLOR) - self.assertEqual(img.dtype, np.uint8) - self.assertEqual(img.shape, (1200, 1800, 3)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/data/test_rotation_transform.py b/preprocess/detectron2/tests/data/test_rotation_transform.py deleted file mode 100644 index 0e8299ed78a425c91fc2e43fede0b26461d1c9ff..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_rotation_transform.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest - -from detectron2.data.transforms.transform import RotationTransform - - -class TestRotationTransform(unittest.TestCase): - def assertEqualsArrays(self, a1, a2): - self.assertTrue(np.allclose(a1, a2)) - - def randomData(self, h=5, w=5): - image = np.random.rand(h, w) - coords = np.array([[i, j] for j in range(h + 1) for i in range(w + 1)], dtype=float) - return image, coords, h, w - - def test180(self): - image, coords, h, w = self.randomData(6, 6) - rot = RotationTransform(h, w, 180, expand=False, center=None) - self.assertEqualsArrays(rot.apply_image(image), image[::-1, ::-1]) - rotated_coords = [[w - c[0], h - c[1]] for c in coords] - self.assertEqualsArrays(rot.apply_coords(coords), rotated_coords) - - def test45_coords(self): - _, coords, h, w = self.randomData(4, 6) - rot = RotationTransform(h, w, 45, expand=False, center=None) - rotated_coords = [ - [(x + y - (h + w) / 2) / np.sqrt(2) + w / 2, h / 2 + (y + (w - h) / 2 - x) / np.sqrt(2)] - for (x, y) in coords - ] - self.assertEqualsArrays(rot.apply_coords(coords), rotated_coords) - - def test90(self): - image, coords, h, w = self.randomData() - rot = RotationTransform(h, w, 90, expand=False, center=None) - self.assertEqualsArrays(rot.apply_image(image), image.T[::-1]) - rotated_coords = [[c[1], w - c[0]] for c in coords] - self.assertEqualsArrays(rot.apply_coords(coords), rotated_coords) - - def test90_expand(self): # non-square image - image, coords, h, w = self.randomData(h=5, w=8) - rot = RotationTransform(h, w, 90, expand=True, center=None) - self.assertEqualsArrays(rot.apply_image(image), image.T[::-1]) - rotated_coords = [[c[1], w - c[0]] for c in coords] - self.assertEqualsArrays(rot.apply_coords(coords), rotated_coords) - - def test_center_expand(self): - # center has no effect if expand=True because it only affects shifting - image, coords, h, w = self.randomData(h=5, w=8) - angle = np.random.randint(360) - rot1 = RotationTransform(h, w, angle, expand=True, center=None) - rot2 = RotationTransform(h, w, angle, expand=True, center=(0, 0)) - rot3 = RotationTransform(h, w, angle, expand=True, center=(h, w)) - rot4 = RotationTransform(h, w, angle, expand=True, center=(2, 5)) - for r1 in [rot1, rot2, rot3, rot4]: - for r2 in [rot1, rot2, rot3, rot4]: - self.assertEqualsArrays(r1.apply_image(image), r2.apply_image(image)) - self.assertEqualsArrays(r1.apply_coords(coords), r2.apply_coords(coords)) - - def test_inverse_transform(self): - image, coords, h, w = self.randomData(h=5, w=8) - rot = RotationTransform(h, w, 90, expand=True, center=None) - rot_image = rot.apply_image(image) - self.assertEqualsArrays(rot.inverse().apply_image(rot_image), image) - rot = RotationTransform(h, w, 65, expand=True, center=None) - rotated_coords = rot.apply_coords(coords) - self.assertEqualsArrays(rot.inverse().apply_coords(rotated_coords), coords) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/data/test_sampler.py b/preprocess/detectron2/tests/data/test_sampler.py deleted file mode 100644 index 0d2784390801314862524e1b85703535d199e41d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_sampler.py +++ /dev/null @@ -1,111 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import itertools -import math -import operator -import unittest -import torch -from torch.utils import data -from torch.utils.data.sampler import SequentialSampler - -from detectron2.data.build import worker_init_reset_seed -from detectron2.data.common import DatasetFromList, ToIterableDataset -from detectron2.data.samplers import ( - GroupedBatchSampler, - InferenceSampler, - RepeatFactorTrainingSampler, - TrainingSampler, -) -from detectron2.utils.env import seed_all_rng - - -class TestGroupedBatchSampler(unittest.TestCase): - def test_missing_group_id(self): - sampler = SequentialSampler(list(range(100))) - group_ids = [1] * 100 - samples = GroupedBatchSampler(sampler, group_ids, 2) - - for mini_batch in samples: - self.assertEqual(len(mini_batch), 2) - - def test_groups(self): - sampler = SequentialSampler(list(range(100))) - group_ids = [1, 0] * 50 - samples = GroupedBatchSampler(sampler, group_ids, 2) - - for mini_batch in samples: - self.assertEqual((mini_batch[0] + mini_batch[1]) % 2, 0) - - -class TestSamplerDeterministic(unittest.TestCase): - def test_to_iterable(self): - sampler = TrainingSampler(100, seed=10) - gt_output = list(itertools.islice(sampler, 100)) - self.assertEqual(set(gt_output), set(range(100))) - - dataset = DatasetFromList(list(range(100))) - dataset = ToIterableDataset(dataset, sampler) - data_loader = data.DataLoader(dataset, num_workers=0, collate_fn=operator.itemgetter(0)) - - output = list(itertools.islice(data_loader, 100)) - self.assertEqual(output, gt_output) - - data_loader = data.DataLoader( - dataset, - num_workers=2, - collate_fn=operator.itemgetter(0), - worker_init_fn=worker_init_reset_seed, - # reset seed should not affect behavior of TrainingSampler - ) - output = list(itertools.islice(data_loader, 100)) - # multiple workers should not lead to duplicate or different data - self.assertEqual(output, gt_output) - - def test_training_sampler_seed(self): - seed_all_rng(42) - sampler = TrainingSampler(30) - data = list(itertools.islice(sampler, 65)) - - seed_all_rng(42) - sampler = TrainingSampler(30) - seed_all_rng(999) # should be ineffective - data2 = list(itertools.islice(sampler, 65)) - self.assertEqual(data, data2) - - -class TestRepeatFactorTrainingSampler(unittest.TestCase): - def test_repeat_factors_from_category_frequency(self): - repeat_thresh = 0.5 - - dataset_dicts = [ - {"annotations": [{"category_id": 0}, {"category_id": 1}]}, - {"annotations": [{"category_id": 0}]}, - {"annotations": []}, - ] - - rep_factors = RepeatFactorTrainingSampler.repeat_factors_from_category_frequency( - dataset_dicts, repeat_thresh - ) - - expected_rep_factors = torch.tensor([math.sqrt(3 / 2), 1.0, 1.0]) - self.assertTrue(torch.allclose(rep_factors, expected_rep_factors)) - - -class TestInferenceSampler(unittest.TestCase): - def test_local_indices(self): - sizes = [0, 16, 2, 42] - world_sizes = [5, 2, 3, 4] - - expected_results = [ - [range(0) for _ in range(5)], - [range(8), range(8, 16)], - [range(1), range(1, 2), range(0)], - [range(11), range(11, 22), range(22, 32), range(32, 42)], - ] - - for size, world_size, expected_result in zip(sizes, world_sizes, expected_results): - with self.subTest(f"size={size}, world_size={world_size}"): - local_indices = [ - InferenceSampler._get_local_indices(size, world_size, r) - for r in range(world_size) - ] - self.assertEqual(local_indices, expected_result) diff --git a/preprocess/detectron2/tests/data/test_transforms.py b/preprocess/detectron2/tests/data/test_transforms.py deleted file mode 100644 index 382048e533708dec3fabf89528564ebc2ad4c83f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/data/test_transforms.py +++ /dev/null @@ -1,268 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import logging -import numpy as np -import unittest -from unittest import mock -import torch -from PIL import Image, ImageOps -from torch.nn import functional as F - -from detectron2.config import get_cfg -from detectron2.data import detection_utils -from detectron2.data import transforms as T -from detectron2.utils.logger import setup_logger - -logger = logging.getLogger(__name__) - - -def polygon_allclose(poly1, poly2): - """ - Test whether two polygons are the same. - Both arguments are nx2 numpy arrays. - """ - # ABCD and CDAB are the same polygon. So it's important to check after rolling - for k in range(len(poly1)): - rolled_poly1 = np.roll(poly1, k, axis=0) - if np.allclose(rolled_poly1, poly2): - return True - return False - - -class TestTransforms(unittest.TestCase): - def setUp(self): - setup_logger() - - def test_apply_rotated_boxes(self): - np.random.seed(125) - cfg = get_cfg() - is_train = True - augs = detection_utils.build_augmentation(cfg, is_train) - image = np.random.rand(200, 300) - image, transforms = T.apply_augmentations(augs, image) - image_shape = image.shape[:2] # h, w - assert image_shape == (800, 1200) - annotation = {"bbox": [179, 97, 62, 40, -56]} - - boxes = np.array([annotation["bbox"]], dtype=np.float64) # boxes.shape = (1, 5) - transformed_bbox = transforms.apply_rotated_box(boxes)[0] - - expected_bbox = np.array([484, 388, 248, 160, 56], dtype=np.float64) - err_msg = "transformed_bbox = {}, expected {}".format(transformed_bbox, expected_bbox) - assert np.allclose(transformed_bbox, expected_bbox), err_msg - - def test_resize_and_crop(self): - np.random.seed(125) - min_scale = 0.2 - max_scale = 2.0 - target_height = 1100 - target_width = 1000 - resize_aug = T.ResizeScale(min_scale, max_scale, target_height, target_width) - fixed_size_crop_aug = T.FixedSizeCrop((target_height, target_width)) - hflip_aug = T.RandomFlip() - augs = [resize_aug, fixed_size_crop_aug, hflip_aug] - original_image = np.random.rand(900, 800) - image, transforms = T.apply_augmentations(augs, original_image) - image_shape = image.shape[:2] # h, w - self.assertEqual((1100, 1000), image_shape) - - boxes = np.array( - [[91, 46, 144, 111], [523, 251, 614, 295]], - dtype=np.float64, - ) - transformed_bboxs = transforms.apply_box(boxes) - expected_bboxs = np.array( - [ - [895.42, 33.42666667, 933.91125, 80.66], - [554.0825, 182.39333333, 620.17125, 214.36666667], - ], - dtype=np.float64, - ) - err_msg = "transformed_bbox = {}, expected {}".format(transformed_bboxs, expected_bboxs) - self.assertTrue(np.allclose(transformed_bboxs, expected_bboxs), err_msg) - - polygon = np.array([[91, 46], [144, 46], [144, 111], [91, 111]]) - transformed_polygons = transforms.apply_polygons([polygon]) - expected_polygon = np.array([[934.0, 33.0], [934.0, 80.0], [896.0, 80.0], [896.0, 33.0]]) - self.assertEqual(1, len(transformed_polygons)) - err_msg = "transformed_polygon = {}, expected {}".format( - transformed_polygons[0], expected_polygon - ) - self.assertTrue(polygon_allclose(transformed_polygons[0], expected_polygon), err_msg) - - def test_apply_rotated_boxes_unequal_scaling_factor(self): - np.random.seed(125) - h, w = 400, 200 - newh, neww = 800, 800 - image = np.random.rand(h, w) - augs = [] - augs.append(T.Resize(shape=(newh, neww))) - image, transforms = T.apply_augmentations(augs, image) - image_shape = image.shape[:2] # h, w - assert image_shape == (newh, neww) - - boxes = np.array( - [ - [150, 100, 40, 20, 0], - [150, 100, 40, 20, 30], - [150, 100, 40, 20, 90], - [150, 100, 40, 20, -90], - ], - dtype=np.float64, - ) - transformed_boxes = transforms.apply_rotated_box(boxes) - - expected_bboxes = np.array( - [ - [600, 200, 160, 40, 0], - [600, 200, 144.22205102, 52.91502622, 49.10660535], - [600, 200, 80, 80, 90], - [600, 200, 80, 80, -90], - ], - dtype=np.float64, - ) - err_msg = "transformed_boxes = {}, expected {}".format(transformed_boxes, expected_bboxes) - assert np.allclose(transformed_boxes, expected_bboxes), err_msg - - def test_print_augmentation(self): - t = T.RandomCrop("relative", (100, 100)) - self.assertEqual(str(t), "RandomCrop(crop_type='relative', crop_size=(100, 100))") - - t0 = T.RandomFlip(prob=0.5) - self.assertEqual(str(t0), "RandomFlip(prob=0.5)") - - t1 = T.RandomFlip() - self.assertEqual(str(t1), "RandomFlip()") - - t = T.AugmentationList([t0, t1]) - self.assertEqual(str(t), f"AugmentationList[{t0}, {t1}]") - - def test_random_apply_prob_out_of_range_check(self): - test_probabilities = {0.0: True, 0.5: True, 1.0: True, -0.01: False, 1.01: False} - - for given_probability, is_valid in test_probabilities.items(): - if not is_valid: - self.assertRaises(AssertionError, T.RandomApply, None, prob=given_probability) - else: - T.RandomApply(T.NoOpTransform(), prob=given_probability) - - def test_random_apply_wrapping_aug_probability_occured_evaluation(self): - transform_mock = mock.MagicMock(name="MockTransform", spec=T.Augmentation) - image_mock = mock.MagicMock(name="MockImage") - random_apply = T.RandomApply(transform_mock, prob=0.001) - - with mock.patch.object(random_apply, "_rand_range", return_value=0.0001): - transform = random_apply.get_transform(image_mock) - transform_mock.get_transform.assert_called_once_with(image_mock) - self.assertIsNot(transform, transform_mock) - - def test_random_apply_wrapping_std_transform_probability_occured_evaluation(self): - transform_mock = mock.MagicMock(name="MockTransform", spec=T.Transform) - image_mock = mock.MagicMock(name="MockImage") - random_apply = T.RandomApply(transform_mock, prob=0.001) - - with mock.patch.object(random_apply, "_rand_range", return_value=0.0001): - transform = random_apply.get_transform(image_mock) - self.assertIs(transform, transform_mock) - - def test_random_apply_probability_not_occured_evaluation(self): - transform_mock = mock.MagicMock(name="MockTransform", spec=T.Augmentation) - image_mock = mock.MagicMock(name="MockImage") - random_apply = T.RandomApply(transform_mock, prob=0.001) - - with mock.patch.object(random_apply, "_rand_range", return_value=0.9): - transform = random_apply.get_transform(image_mock) - transform_mock.get_transform.assert_not_called() - self.assertIsInstance(transform, T.NoOpTransform) - - def test_augmentation_input_args(self): - input_shape = (100, 100) - output_shape = (50, 50) - - # define two augmentations with different args - class TG1(T.Augmentation): - def get_transform(self, image, sem_seg): - return T.ResizeTransform( - input_shape[0], input_shape[1], output_shape[0], output_shape[1] - ) - - class TG2(T.Augmentation): - def get_transform(self, image): - assert image.shape[:2] == output_shape # check that TG1 is applied - return T.HFlipTransform(output_shape[1]) - - image = np.random.rand(*input_shape).astype("float32") - sem_seg = (np.random.rand(*input_shape) < 0.5).astype("uint8") - inputs = T.AugInput(image, sem_seg=sem_seg) # provide two args - tfms = inputs.apply_augmentations([TG1(), TG2()]) - self.assertIsInstance(tfms[0], T.ResizeTransform) - self.assertIsInstance(tfms[1], T.HFlipTransform) - self.assertTrue(inputs.image.shape[:2] == output_shape) - self.assertTrue(inputs.sem_seg.shape[:2] == output_shape) - - class TG3(T.Augmentation): - def get_transform(self, image, nonexist): - pass - - with self.assertRaises(AttributeError): - inputs.apply_augmentations([TG3()]) - - def test_augmentation_list(self): - input_shape = (100, 100) - image = np.random.rand(*input_shape).astype("float32") - sem_seg = (np.random.rand(*input_shape) < 0.5).astype("uint8") - inputs = T.AugInput(image, sem_seg=sem_seg) # provide two args - - augs = T.AugmentationList([T.RandomFlip(), T.Resize(20)]) - _ = T.AugmentationList([augs, T.Resize(30)])(inputs) - # 3 in latest fvcore (flattened transformlist), 2 in older - # self.assertEqual(len(tfms), 3) - - def test_color_transforms(self): - rand_img = np.random.random((100, 100, 3)) * 255 - rand_img = rand_img.astype("uint8") - - # Test no-op - noop_transform = T.ColorTransform(lambda img: img) - self.assertTrue(np.array_equal(rand_img, noop_transform.apply_image(rand_img))) - - # Test a ImageOps operation - magnitude = np.random.randint(0, 256) - solarize_transform = T.PILColorTransform(lambda img: ImageOps.solarize(img, magnitude)) - expected_img = ImageOps.solarize(Image.fromarray(rand_img), magnitude) - self.assertTrue(np.array_equal(expected_img, solarize_transform.apply_image(rand_img))) - - def test_resize_transform(self): - input_shapes = [(100, 100), (100, 100, 1), (100, 100, 3)] - output_shapes = [(200, 200), (200, 200, 1), (200, 200, 3)] - for in_shape, out_shape in zip(input_shapes, output_shapes): - in_img = np.random.randint(0, 255, size=in_shape, dtype=np.uint8) - tfm = T.ResizeTransform(in_shape[0], in_shape[1], out_shape[0], out_shape[1]) - out_img = tfm.apply_image(in_img) - self.assertEqual(out_img.shape, out_shape) - - def test_resize_shorted_edge_scriptable(self): - def f(image): - newh, neww = T.ResizeShortestEdge.get_output_shape( - image.shape[-2], image.shape[-1], 80, 133 - ) - return F.interpolate(image.unsqueeze(0), size=(newh, neww)) - - input = torch.randn(3, 10, 10) - script_f = torch.jit.script(f) - self.assertTrue(torch.allclose(f(input), script_f(input))) - - # generalize to new shapes - input = torch.randn(3, 8, 100) - self.assertTrue(torch.allclose(f(input), script_f(input))) - - def test_extent_transform(self): - input_shapes = [(100, 100), (100, 100, 1), (100, 100, 3)] - src_rect = (20, 20, 80, 80) - output_shapes = [(200, 200), (200, 200, 1), (200, 200, 3)] - for in_shape, out_shape in zip(input_shapes, output_shapes): - in_img = np.random.randint(0, 255, size=in_shape, dtype=np.uint8) - tfm = T.ExtentTransform(src_rect, out_shape[:2]) - out_img = tfm.apply_image(in_img) - self.assertTrue(out_img.shape == out_shape) diff --git a/preprocess/detectron2/tests/export/test_c10.py b/preprocess/detectron2/tests/export/test_c10.py deleted file mode 100644 index 55076abd15beb50b1774f0b5fe399b22d7cc630f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/export/test_c10.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest - -try: - # Caffe2 used to be included in PyTorch, but since PyTorch 1.10+, - # it is not included in pre-built packages. This is a safety BC check - from detectron2.config import get_cfg - from detectron2.export.c10 import Caffe2RPN - from detectron2.layers import ShapeSpec -except ImportError: - raise unittest.SkipTest( - f"PyTorch does not have Caffe2 support. Skipping all tests in {__name__}" - ) from None - - -class TestCaffe2RPN(unittest.TestCase): - def test_instantiation(self): - cfg = get_cfg() - cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1, 1) - input_shapes = {"res4": ShapeSpec(channels=256, stride=4)} - rpn = Caffe2RPN(cfg, input_shapes) - assert rpn is not None - cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (10, 10, 5, 5, 1) - with self.assertRaises(AssertionError): - rpn = Caffe2RPN(cfg, input_shapes) diff --git a/preprocess/detectron2/tests/layers/__init__.py b/preprocess/detectron2/tests/layers/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tests/layers/test_blocks.py b/preprocess/detectron2/tests/layers/test_blocks.py deleted file mode 100644 index 5a0488adbfcf0c7eca08616f43ebf695acad4b7e..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_blocks.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -import torch -from torch import nn - -from detectron2.layers import ASPP, DepthwiseSeparableConv2d, FrozenBatchNorm2d -from detectron2.modeling.backbone.resnet import BasicStem, ResNet - - -""" -Test for misc layers. -""" - - -class TestBlocks(unittest.TestCase): - def test_separable_conv(self): - DepthwiseSeparableConv2d(3, 10, norm1="BN", activation1=nn.PReLU()) - - def test_aspp(self): - m = ASPP(3, 10, [2, 3, 4], norm="", activation=nn.PReLU()) - self.assertIsNot(m.convs[0].activation.weight, m.convs[1].activation.weight) - self.assertIsNot(m.convs[0].activation.weight, m.project.activation.weight) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_frozen_batchnorm_fp16(self): - from torch.cuda.amp import autocast - - C = 10 - input = torch.rand(1, C, 10, 10).cuda() - m = FrozenBatchNorm2d(C).cuda() - with autocast(): - output = m(input.half()) - self.assertEqual(output.dtype, torch.float16) - - # requires_grad triggers a different codepath - input.requires_grad_() - with autocast(): - output = m(input.half()) - self.assertEqual(output.dtype, torch.float16) - - def test_resnet_unused_stages(self): - resnet = ResNet(BasicStem(), ResNet.make_default_stages(18), out_features=["res2"]) - self.assertTrue(hasattr(resnet, "res2")) - self.assertFalse(hasattr(resnet, "res3")) - self.assertFalse(hasattr(resnet, "res5")) - - resnet = ResNet(BasicStem(), ResNet.make_default_stages(18), out_features=["res2", "res5"]) - self.assertTrue(hasattr(resnet, "res2")) - self.assertTrue(hasattr(resnet, "res4")) - self.assertTrue(hasattr(resnet, "res5")) diff --git a/preprocess/detectron2/tests/layers/test_deformable.py b/preprocess/detectron2/tests/layers/test_deformable.py deleted file mode 100644 index 4aa319fc7e614f6a7a8ece7a45c177211c03012d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_deformable.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest -import torch - -from detectron2.layers import DeformConv, ModulatedDeformConv -from detectron2.utils.env import TORCH_VERSION - - -@unittest.skipIf( - TORCH_VERSION == (1, 8) and torch.cuda.is_available(), - "This test fails under cuda11 + torch1.8.", -) -class DeformableTest(unittest.TestCase): - @unittest.skipIf(not torch.cuda.is_available(), "Deformable not supported for cpu") - def test_forward_output(self): - device = torch.device("cuda") - N, C, H, W = shape = 1, 1, 5, 5 - kernel_size = 3 - padding = 1 - - inputs = torch.arange(np.prod(shape), dtype=torch.float32).reshape(*shape).to(device) - """ - 0 1 2 3 4 - 5 6 7 8 9 - 10 11 12 13 14 - 15 16 17 18 19 - 20 21 22 23 24 - """ - offset_channels = kernel_size * kernel_size * 2 - offset = torch.full((N, offset_channels, H, W), 0.5, dtype=torch.float32).to(device) - - # Test DCN v1 - deform = DeformConv(C, C, kernel_size=kernel_size, padding=padding).to(device) - deform.weight = torch.nn.Parameter(torch.ones_like(deform.weight)) - output = deform(inputs, offset) - output = output.detach().cpu().numpy() - deform_results = np.array( - [ - [30, 41.25, 48.75, 45, 28.75], - [62.25, 81, 90, 80.25, 50.25], - [99.75, 126, 135, 117.75, 72.75], - [105, 131.25, 138.75, 120, 73.75], - [71.75, 89.25, 93.75, 80.75, 49.5], - ] - ) - self.assertTrue(np.allclose(output.flatten(), deform_results.flatten())) - - # Test DCN v2 - mask_channels = kernel_size * kernel_size - mask = torch.full((N, mask_channels, H, W), 0.5, dtype=torch.float32).to(device) - modulate_deform = ModulatedDeformConv(C, C, kernel_size, padding=padding, bias=False).to( - device - ) - modulate_deform.weight = deform.weight - output = modulate_deform(inputs, offset, mask) - output = output.detach().cpu().numpy() - self.assertTrue(np.allclose(output.flatten(), deform_results.flatten() * 0.5)) - - def test_forward_output_on_cpu(self): - device = torch.device("cpu") - N, C, H, W = shape = 1, 1, 5, 5 - kernel_size = 3 - padding = 1 - - inputs = torch.arange(np.prod(shape), dtype=torch.float32).reshape(*shape).to(device) - - offset_channels = kernel_size * kernel_size * 2 - offset = torch.full((N, offset_channels, H, W), 0.5, dtype=torch.float32).to(device) - - # Test DCN v1 on cpu - deform = DeformConv(C, C, kernel_size=kernel_size, padding=padding).to(device) - deform.weight = torch.nn.Parameter(torch.ones_like(deform.weight)) - output = deform(inputs, offset) - output = output.detach().cpu().numpy() - deform_results = np.array( - [ - [30, 41.25, 48.75, 45, 28.75], - [62.25, 81, 90, 80.25, 50.25], - [99.75, 126, 135, 117.75, 72.75], - [105, 131.25, 138.75, 120, 73.75], - [71.75, 89.25, 93.75, 80.75, 49.5], - ] - ) - self.assertTrue(np.allclose(output.flatten(), deform_results.flatten())) - - @unittest.skipIf(not torch.cuda.is_available(), "This test requires gpu access") - def test_forward_output_on_cpu_equals_output_on_gpu(self): - N, C, H, W = shape = 2, 4, 10, 10 - kernel_size = 3 - padding = 1 - - for groups in [1, 2]: - inputs = torch.arange(np.prod(shape), dtype=torch.float32).reshape(*shape) - offset_channels = kernel_size * kernel_size * 2 - offset = torch.full((N, offset_channels, H, W), 0.5, dtype=torch.float32) - - deform_gpu = DeformConv( - C, C, kernel_size=kernel_size, padding=padding, groups=groups - ).to("cuda") - deform_gpu.weight = torch.nn.Parameter(torch.ones_like(deform_gpu.weight)) - output_gpu = deform_gpu(inputs.to("cuda"), offset.to("cuda")).detach().cpu().numpy() - - deform_cpu = DeformConv( - C, C, kernel_size=kernel_size, padding=padding, groups=groups - ).to("cpu") - deform_cpu.weight = torch.nn.Parameter(torch.ones_like(deform_cpu.weight)) - output_cpu = deform_cpu(inputs.to("cpu"), offset.to("cpu")).detach().numpy() - - self.assertTrue(np.allclose(output_gpu.flatten(), output_cpu.flatten())) - - @unittest.skipIf(not torch.cuda.is_available(), "Deformable not supported for cpu") - def test_small_input(self): - device = torch.device("cuda") - for kernel_size in [3, 5]: - padding = kernel_size // 2 - N, C, H, W = shape = (1, 1, kernel_size - 1, kernel_size - 1) - - inputs = torch.rand(shape).to(device) # input size is smaller than kernel size - - offset_channels = kernel_size * kernel_size * 2 - offset = torch.randn((N, offset_channels, H, W), dtype=torch.float32).to(device) - deform = DeformConv(C, C, kernel_size=kernel_size, padding=padding).to(device) - output = deform(inputs, offset) - self.assertTrue(output.shape == inputs.shape) - - mask_channels = kernel_size * kernel_size - mask = torch.ones((N, mask_channels, H, W), dtype=torch.float32).to(device) - modulate_deform = ModulatedDeformConv( - C, C, kernel_size, padding=padding, bias=False - ).to(device) - output = modulate_deform(inputs, offset, mask) - self.assertTrue(output.shape == inputs.shape) - - @unittest.skipIf(not torch.cuda.is_available(), "Deformable not supported for cpu") - def test_raise_exception(self): - device = torch.device("cuda") - N, C, H, W = shape = 1, 1, 3, 3 - kernel_size = 3 - padding = 1 - - inputs = torch.rand(shape, dtype=torch.float32).to(device) - offset_channels = kernel_size * kernel_size # This is wrong channels for offset - offset = torch.randn((N, offset_channels, H, W), dtype=torch.float32).to(device) - deform = DeformConv(C, C, kernel_size=kernel_size, padding=padding).to(device) - self.assertRaises(RuntimeError, deform, inputs, offset) - - offset_channels = kernel_size * kernel_size * 2 - offset = torch.randn((N, offset_channels, H, W), dtype=torch.float32).to(device) - mask_channels = kernel_size * kernel_size * 2 # This is wrong channels for mask - mask = torch.ones((N, mask_channels, H, W), dtype=torch.float32).to(device) - modulate_deform = ModulatedDeformConv(C, C, kernel_size, padding=padding, bias=False).to( - device - ) - self.assertRaises(RuntimeError, modulate_deform, inputs, offset, mask) - - def test_repr(self): - module = DeformConv(3, 10, kernel_size=3, padding=1, deformable_groups=2) - correct_string = ( - "DeformConv(in_channels=3, out_channels=10, kernel_size=(3, 3), " - "stride=(1, 1), padding=(1, 1), dilation=(1, 1), " - "groups=1, deformable_groups=2, bias=False)" - ) - self.assertEqual(repr(module), correct_string) - - module = ModulatedDeformConv(3, 10, kernel_size=3, padding=1, deformable_groups=2) - correct_string = ( - "ModulatedDeformConv(in_channels=3, out_channels=10, kernel_size=(3, 3), " - "stride=1, padding=1, dilation=1, groups=1, deformable_groups=2, bias=True)" - ) - self.assertEqual(repr(module), correct_string) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/layers/test_losses.py b/preprocess/detectron2/tests/layers/test_losses.py deleted file mode 100644 index d74920246cbd4a188b3c81cf0c78e982af6da1ac..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_losses.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest -import torch - -from detectron2.layers import ciou_loss, diou_loss - - -class TestLosses(unittest.TestCase): - def test_diou_loss(self): - """ - loss = 1 - iou + d/c - where, - d = (distance between centers of the 2 boxes)^2 - c = (diagonal length of the smallest enclosing box covering the 2 boxes)^2 - """ - # Identical boxes should have loss of 0 - box = torch.tensor([-1, -1, 1, 1], dtype=torch.float32) - loss = diou_loss(box, box) - self.assertTrue(np.allclose(loss, [0.0])) - - # Half size box inside other box - # iou = 0.5, d = 0.25, c = 8 - box2 = torch.tensor([0, -1, 1, 1], dtype=torch.float32) - loss = diou_loss(box, box2) - self.assertTrue(np.allclose(loss, [0.53125])) - - # Two diagonally adjacent boxes - # iou = 0, d = 2, c = 8 - box3 = torch.tensor([0, 0, 1, 1], dtype=torch.float32) - box4 = torch.tensor([1, 1, 2, 2], dtype=torch.float32) - loss = diou_loss(box3, box4) - self.assertTrue(np.allclose(loss, [1.25])) - - # Test batched loss and reductions - box1s = torch.stack([box, box3], dim=0) - box2s = torch.stack([box2, box4], dim=0) - - loss = diou_loss(box1s, box2s, reduction="sum") - self.assertTrue(np.allclose(loss, [1.78125])) - - loss = diou_loss(box1s, box2s, reduction="mean") - self.assertTrue(np.allclose(loss, [0.890625])) - - def test_ciou_loss(self): - """ - loss = 1 - iou + d/c + alpha*v - where, - d = (distance between centers of the 2 boxes)^2 - c = (diagonal length of the smallest enclosing box covering the 2 boxes)^2 - v = (4/pi^2) * (arctan(box1_w/box1_h) - arctan(box2_w/box2_h))^2 - alpha = v/(1 - iou + v) - """ - # Identical boxes should have loss of 0 - box = torch.tensor([-1, -1, 1, 1], dtype=torch.float32) - loss = ciou_loss(box, box) - self.assertTrue(np.allclose(loss, [0.0])) - - # Half size box inside other box - # iou = 0.5, d = 0.25, c = 8 - # v = (4/pi^2) * (arctan(1) - arctan(0.5))^2 = 0.042 - # alpha = 0.0775 - box2 = torch.tensor([0, -1, 1, 1], dtype=torch.float32) - loss = ciou_loss(box, box2) - self.assertTrue(np.allclose(loss, [0.5345])) - - # Two diagonally adjacent boxes - # iou = 0, d = 2, c = 8, v = 0, alpha = 0 - box3 = torch.tensor([0, 0, 1, 1], dtype=torch.float32) - box4 = torch.tensor([1, 1, 2, 2], dtype=torch.float32) - loss = ciou_loss(box3, box4) - self.assertTrue(np.allclose(loss, [1.25])) - - # Test batched loss and reductions - box1s = torch.stack([box, box3], dim=0) - box2s = torch.stack([box2, box4], dim=0) - - loss = ciou_loss(box1s, box2s, reduction="sum") - self.assertTrue(np.allclose(loss, [1.7845])) - - loss = ciou_loss(box1s, box2s, reduction="mean") - self.assertTrue(np.allclose(loss, [0.89225])) diff --git a/preprocess/detectron2/tests/layers/test_mask_ops.py b/preprocess/detectron2/tests/layers/test_mask_ops.py deleted file mode 100644 index dfbcaf5291a87ec85617d5e7a7aa959c68b06770..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_mask_ops.py +++ /dev/null @@ -1,202 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import contextlib -import io -import numpy as np -import unittest -from collections import defaultdict -import torch -import tqdm -from fvcore.common.benchmark import benchmark -from pycocotools.coco import COCO -from tabulate import tabulate -from torch.nn import functional as F - -from detectron2.data import MetadataCatalog -from detectron2.layers.mask_ops import ( - pad_masks, - paste_mask_in_image_old, - paste_masks_in_image, - scale_boxes, -) -from detectron2.structures import BitMasks, Boxes, BoxMode, PolygonMasks -from detectron2.structures.masks import polygons_to_bitmask -from detectron2.utils.file_io import PathManager -from detectron2.utils.testing import random_boxes - - -def iou_between_full_image_bit_masks(a, b): - intersect = (a & b).sum() - union = (a | b).sum() - return intersect / union - - -def rasterize_polygons_with_grid_sample(full_image_bit_mask, box, mask_size, threshold=0.5): - x0, y0, x1, y1 = box[0], box[1], box[2], box[3] - - img_h, img_w = full_image_bit_mask.shape - - mask_y = np.arange(0.0, mask_size) + 0.5 # mask y sample coords in [0.5, mask_size - 0.5] - mask_x = np.arange(0.0, mask_size) + 0.5 # mask x sample coords in [0.5, mask_size - 0.5] - mask_y = mask_y / mask_size * (y1 - y0) + y0 - mask_x = mask_x / mask_size * (x1 - x0) + x0 - - mask_x = (mask_x - 0.5) / (img_w - 1) * 2 + -1 - mask_y = (mask_y - 0.5) / (img_h - 1) * 2 + -1 - gy, gx = torch.meshgrid(torch.from_numpy(mask_y), torch.from_numpy(mask_x)) - ind = torch.stack([gx, gy], dim=-1).to(dtype=torch.float32) - - full_image_bit_mask = torch.from_numpy(full_image_bit_mask) - mask = F.grid_sample( - full_image_bit_mask[None, None, :, :].to(dtype=torch.float32), - ind[None, :, :, :], - align_corners=True, - ) - - return mask[0, 0] >= threshold - - -class TestMaskCropPaste(unittest.TestCase): - def setUp(self): - json_file = MetadataCatalog.get("coco_2017_val_100").json_file - if not PathManager.isfile(json_file): - raise unittest.SkipTest("{} not found".format(json_file)) - with contextlib.redirect_stdout(io.StringIO()): - json_file = PathManager.get_local_path(json_file) - self.coco = COCO(json_file) - - def test_crop_paste_consistency(self): - """ - rasterize_polygons_within_box (used in training) - and - paste_masks_in_image (used in inference) - should be inverse operations to each other. - - This function runs several implementation of the above two operations and prints - the reconstruction error. - """ - - anns = self.coco.loadAnns(self.coco.getAnnIds(iscrowd=False)) # avoid crowd annotations - - selected_anns = anns[:100] - - ious = [] - for ann in tqdm.tqdm(selected_anns): - results = self.process_annotation(ann) - ious.append([k[2] for k in results]) - - ious = np.array(ious) - mean_ious = ious.mean(axis=0) - table = [] - res_dic = defaultdict(dict) - for row, iou in zip(results, mean_ious): - table.append((row[0], row[1], iou)) - res_dic[row[0]][row[1]] = iou - print(tabulate(table, headers=["rasterize", "paste", "iou"], tablefmt="simple")) - # assert that the reconstruction is good: - self.assertTrue(res_dic["polygon"]["aligned"] > 0.94) - self.assertTrue(res_dic["roialign"]["aligned"] > 0.95) - - def process_annotation(self, ann, mask_side_len=28): - # Parse annotation data - img_info = self.coco.loadImgs(ids=[ann["image_id"]])[0] - height, width = img_info["height"], img_info["width"] - gt_polygons = [np.array(p, dtype=np.float64) for p in ann["segmentation"]] - gt_bbox = BoxMode.convert(ann["bbox"], BoxMode.XYWH_ABS, BoxMode.XYXY_ABS) - gt_bit_mask = polygons_to_bitmask(gt_polygons, height, width) - - # Run rasterize .. - torch_gt_bbox = torch.tensor(gt_bbox).to(dtype=torch.float32).reshape(-1, 4) - box_bitmasks = { - "polygon": PolygonMasks([gt_polygons]).crop_and_resize(torch_gt_bbox, mask_side_len)[0], - "gridsample": rasterize_polygons_with_grid_sample(gt_bit_mask, gt_bbox, mask_side_len), - "roialign": BitMasks(torch.from_numpy(gt_bit_mask[None, :, :])).crop_and_resize( - torch_gt_bbox, mask_side_len - )[0], - } - - # Run paste .. - results = defaultdict(dict) - for k, box_bitmask in box_bitmasks.items(): - padded_bitmask, scale = pad_masks(box_bitmask[None, :, :], 1) - scaled_boxes = scale_boxes(torch_gt_bbox, scale) - - r = results[k] - r["old"] = paste_mask_in_image_old( - padded_bitmask[0], scaled_boxes[0], height, width, threshold=0.5 - ) - r["aligned"] = paste_masks_in_image( - box_bitmask[None, :, :], Boxes(torch_gt_bbox), (height, width) - )[0] - - table = [] - for rasterize_method, r in results.items(): - for paste_method, mask in r.items(): - mask = np.asarray(mask) - iou = iou_between_full_image_bit_masks(gt_bit_mask.astype("uint8"), mask) - table.append((rasterize_method, paste_method, iou)) - return table - - def test_polygon_area(self): - # Draw polygon boxes - for d in [5.0, 10.0, 1000.0]: - polygon = PolygonMasks([[[0, 0, 0, d, d, d, d, 0]]]) - area = polygon.area()[0] - target = d**2 - self.assertEqual(area, target) - - # Draw polygon triangles - for d in [5.0, 10.0, 1000.0]: - polygon = PolygonMasks([[[0, 0, 0, d, d, d]]]) - area = polygon.area()[0] - target = d**2 / 2 - self.assertEqual(area, target) - - def test_paste_mask_scriptable(self): - scripted_f = torch.jit.script(paste_masks_in_image) - N = 10 - masks = torch.rand(N, 28, 28) - boxes = Boxes(random_boxes(N, 100)).tensor - image_shape = (150, 150) - - out = paste_masks_in_image(masks, boxes, image_shape) - scripted_out = scripted_f(masks, boxes, image_shape) - self.assertTrue(torch.equal(out, scripted_out)) - - -def benchmark_paste(): - S = 800 - H, W = image_shape = (S, S) - N = 64 - torch.manual_seed(42) - masks = torch.rand(N, 28, 28) - - center = torch.rand(N, 2) * 600 + 100 - wh = torch.clamp(torch.randn(N, 2) * 40 + 200, min=50) - x0y0 = torch.clamp(center - wh * 0.5, min=0.0) - x1y1 = torch.clamp(center + wh * 0.5, max=S) - boxes = Boxes(torch.cat([x0y0, x1y1], axis=1)) - - def func(device, n=3): - m = masks.to(device=device) - b = boxes.to(device=device) - - def bench(): - for _ in range(n): - paste_masks_in_image(m, b, image_shape) - if device.type == "cuda": - torch.cuda.synchronize() - - return bench - - specs = [{"device": torch.device("cpu"), "n": 3}] - if torch.cuda.is_available(): - specs.append({"device": torch.device("cuda"), "n": 3}) - - benchmark(func, "paste_masks", specs, num_iters=10, warmup_iters=2) - - -if __name__ == "__main__": - benchmark_paste() - unittest.main() diff --git a/preprocess/detectron2/tests/layers/test_nms.py b/preprocess/detectron2/tests/layers/test_nms.py deleted file mode 100644 index a042db6147f110a82597c98f38e6b2221ccad53c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_nms.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from __future__ import absolute_import, division, print_function, unicode_literals -import unittest -import torch - -from detectron2.layers import batched_nms -from detectron2.utils.testing import random_boxes - - -class TestNMS(unittest.TestCase): - def _create_tensors(self, N): - boxes = random_boxes(N, 200) - scores = torch.rand(N) - return boxes, scores - - def test_nms_scriptability(self): - N = 2000 - num_classes = 50 - boxes, scores = self._create_tensors(N) - idxs = torch.randint(0, num_classes, (N,)) - scripted_batched_nms = torch.jit.script(batched_nms) - err_msg = "NMS is incompatible with jit-scripted NMS for IoU={}" - - for iou in [0.2, 0.5, 0.8]: - keep_ref = batched_nms(boxes, scores, idxs, iou) - backup = boxes.clone() - scripted_keep = scripted_batched_nms(boxes, scores, idxs, iou) - assert torch.allclose(boxes, backup), "boxes modified by jit-scripted batched_nms" - self.assertTrue(torch.equal(keep_ref, scripted_keep), err_msg.format(iou)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/layers/test_nms_rotated.py b/preprocess/detectron2/tests/layers/test_nms_rotated.py deleted file mode 100644 index 4b45384892ab2a7cb20871cf19374f1bd08907ce..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_nms_rotated.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from __future__ import absolute_import, division, print_function, unicode_literals -import numpy as np -import unittest -from copy import deepcopy -import torch -from torchvision import ops - -from detectron2.layers import batched_nms, batched_nms_rotated, nms_rotated -from detectron2.utils.testing import random_boxes - - -def nms_edit_distance(keep1, keep2): - """ - Compare the "keep" result of two nms call. - They are allowed to be different in terms of edit distance - due to floating point precision issues, e.g., - if a box happen to have an IoU of 0.5 with another box, - one implentation may choose to keep it while another may discard it. - """ - keep1, keep2 = keep1.cpu(), keep2.cpu() - if torch.equal(keep1, keep2): - # they should be equal most of the time - return 0 - keep1, keep2 = tuple(keep1), tuple(keep2) - m, n = len(keep1), len(keep2) - - # edit distance with DP - f = [np.arange(n + 1), np.arange(n + 1)] - for i in range(m): - cur_row = i % 2 - other_row = (i + 1) % 2 - f[other_row][0] = i + 1 - for j in range(n): - f[other_row][j + 1] = ( - f[cur_row][j] - if keep1[i] == keep2[j] - else min(min(f[cur_row][j], f[cur_row][j + 1]), f[other_row][j]) + 1 - ) - return f[m % 2][n] - - -class TestNMSRotated(unittest.TestCase): - def reference_horizontal_nms(self, boxes, scores, iou_threshold): - """ - Args: - box_scores (N, 5): boxes in corner-form and probabilities. - (Note here 5 == 4 + 1, i.e., 4-dim horizontal box + 1-dim prob) - iou_threshold: intersection over union threshold. - Returns: - picked: a list of indexes of the kept boxes - """ - picked = [] - _, indexes = scores.sort(descending=True) - while len(indexes) > 0: - current = indexes[0] - picked.append(current.item()) - if len(indexes) == 1: - break - current_box = boxes[current, :] - indexes = indexes[1:] - rest_boxes = boxes[indexes, :] - iou = ops.box_iou(rest_boxes, current_box.unsqueeze(0)).squeeze(1) - indexes = indexes[iou <= iou_threshold] - - return torch.as_tensor(picked) - - def _create_tensors(self, N, device="cpu"): - boxes = random_boxes(N, 200, device=device) - scores = torch.rand(N, device=device) - return boxes, scores - - def test_batched_nms_rotated_0_degree_cpu(self, device="cpu"): - N = 2000 - num_classes = 50 - boxes, scores = self._create_tensors(N, device=device) - idxs = torch.randint(0, num_classes, (N,)) - rotated_boxes = torch.zeros(N, 5, device=device) - rotated_boxes[:, 0] = (boxes[:, 0] + boxes[:, 2]) / 2.0 - rotated_boxes[:, 1] = (boxes[:, 1] + boxes[:, 3]) / 2.0 - rotated_boxes[:, 2] = boxes[:, 2] - boxes[:, 0] - rotated_boxes[:, 3] = boxes[:, 3] - boxes[:, 1] - err_msg = "Rotated NMS with 0 degree is incompatible with horizontal NMS for IoU={}" - for iou in [0.2, 0.5, 0.8]: - backup = boxes.clone() - keep_ref = batched_nms(boxes, scores, idxs, iou) - assert torch.allclose(boxes, backup), "boxes modified by batched_nms" - backup = rotated_boxes.clone() - keep = batched_nms_rotated(rotated_boxes, scores, idxs, iou) - assert torch.allclose( - rotated_boxes, backup - ), "rotated_boxes modified by batched_nms_rotated" - # Occasionally the gap can be large if there are many IOU on the threshold boundary - self.assertLessEqual(nms_edit_distance(keep, keep_ref), 5, err_msg.format(iou)) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_batched_nms_rotated_0_degree_cuda(self): - self.test_batched_nms_rotated_0_degree_cpu(device="cuda") - - def test_nms_rotated_0_degree_cpu(self, device="cpu"): - N = 1000 - boxes, scores = self._create_tensors(N, device=device) - rotated_boxes = torch.zeros(N, 5, device=device) - rotated_boxes[:, 0] = (boxes[:, 0] + boxes[:, 2]) / 2.0 - rotated_boxes[:, 1] = (boxes[:, 1] + boxes[:, 3]) / 2.0 - rotated_boxes[:, 2] = boxes[:, 2] - boxes[:, 0] - rotated_boxes[:, 3] = boxes[:, 3] - boxes[:, 1] - err_msg = "Rotated NMS incompatible between CPU and reference implementation for IoU={}" - for iou in [0.2, 0.5, 0.8]: - keep_ref = self.reference_horizontal_nms(boxes, scores, iou) - keep = nms_rotated(rotated_boxes, scores, iou) - self.assertLessEqual(nms_edit_distance(keep, keep_ref), 1, err_msg.format(iou)) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_nms_rotated_0_degree_cuda(self): - self.test_nms_rotated_0_degree_cpu(device="cuda") - - def test_nms_rotated_90_degrees_cpu(self): - N = 1000 - boxes, scores = self._create_tensors(N) - rotated_boxes = torch.zeros(N, 5) - rotated_boxes[:, 0] = (boxes[:, 0] + boxes[:, 2]) / 2.0 - rotated_boxes[:, 1] = (boxes[:, 1] + boxes[:, 3]) / 2.0 - # Note for rotated_boxes[:, 2] and rotated_boxes[:, 3]: - # widths and heights are intentionally swapped here for 90 degrees case - # so that the reference horizontal nms could be used - rotated_boxes[:, 2] = boxes[:, 3] - boxes[:, 1] - rotated_boxes[:, 3] = boxes[:, 2] - boxes[:, 0] - - rotated_boxes[:, 4] = torch.ones(N) * 90 - err_msg = "Rotated NMS incompatible between CPU and reference implementation for IoU={}" - for iou in [0.2, 0.5, 0.8]: - keep_ref = self.reference_horizontal_nms(boxes, scores, iou) - keep = nms_rotated(rotated_boxes, scores, iou) - self.assertLessEqual(nms_edit_distance(keep, keep_ref), 1, err_msg.format(iou)) - - def test_nms_rotated_180_degrees_cpu(self): - N = 1000 - boxes, scores = self._create_tensors(N) - rotated_boxes = torch.zeros(N, 5) - rotated_boxes[:, 0] = (boxes[:, 0] + boxes[:, 2]) / 2.0 - rotated_boxes[:, 1] = (boxes[:, 1] + boxes[:, 3]) / 2.0 - rotated_boxes[:, 2] = boxes[:, 2] - boxes[:, 0] - rotated_boxes[:, 3] = boxes[:, 3] - boxes[:, 1] - rotated_boxes[:, 4] = torch.ones(N) * 180 - err_msg = "Rotated NMS incompatible between CPU and reference implementation for IoU={}" - for iou in [0.2, 0.5, 0.8]: - keep_ref = self.reference_horizontal_nms(boxes, scores, iou) - keep = nms_rotated(rotated_boxes, scores, iou) - self.assertLessEqual(nms_edit_distance(keep, keep_ref), 1, err_msg.format(iou)) - - -class TestScriptable(unittest.TestCase): - def setUp(self): - class TestingModule(torch.nn.Module): - def forward(self, boxes, scores, threshold): - return nms_rotated(boxes, scores, threshold) - - self.module = TestingModule() - - def test_scriptable_cpu(self): - m = deepcopy(self.module).cpu() - _ = torch.jit.script(m) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_scriptable_cuda(self): - m = deepcopy(self.module).cuda() - _ = torch.jit.script(m) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/layers/test_roi_align.py b/preprocess/detectron2/tests/layers/test_roi_align.py deleted file mode 100644 index b6fd8edefd107b727e3e523f1364fea1f4a20576..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_roi_align.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest -from copy import copy -import cv2 -import torch -from fvcore.common.benchmark import benchmark -from torch.nn import functional as F - -from detectron2.layers.roi_align import ROIAlign, roi_align - - -class ROIAlignTest(unittest.TestCase): - def test_forward_output(self): - input = np.arange(25).reshape(5, 5).astype("float32") - """ - 0 1 2 3 4 - 5 6 7 8 9 - 10 11 12 13 14 - 15 16 17 18 19 - 20 21 22 23 24 - """ - - output = self._simple_roialign(input, [1, 1, 3, 3], (4, 4), aligned=False) - output_correct = self._simple_roialign(input, [1, 1, 3, 3], (4, 4), aligned=True) - - # without correction: - old_results = [ - [7.5, 8, 8.5, 9], - [10, 10.5, 11, 11.5], - [12.5, 13, 13.5, 14], - [15, 15.5, 16, 16.5], - ] - - # with 0.5 correction: - correct_results = [ - [4.5, 5.0, 5.5, 6.0], - [7.0, 7.5, 8.0, 8.5], - [9.5, 10.0, 10.5, 11.0], - [12.0, 12.5, 13.0, 13.5], - ] - # This is an upsampled version of [[6, 7], [11, 12]] - - self.assertTrue(np.allclose(output.flatten(), np.asarray(old_results).flatten())) - self.assertTrue( - np.allclose(output_correct.flatten(), np.asarray(correct_results).flatten()) - ) - - # Also see similar issues in tensorflow at - # https://github.com/tensorflow/tensorflow/issues/26278 - - def test_resize(self): - H, W = 30, 30 - input = np.random.rand(H, W).astype("float32") * 100 - box = [10, 10, 20, 20] - output = self._simple_roialign(input, box, (5, 5), aligned=True) - - input2x = cv2.resize(input, (W // 2, H // 2), interpolation=cv2.INTER_LINEAR) - box2x = [x / 2 for x in box] - output2x = self._simple_roialign(input2x, box2x, (5, 5), aligned=True) - diff = np.abs(output2x - output) - self.assertTrue(diff.max() < 1e-4) - - def test_grid_sample_equivalence(self): - H, W = 30, 30 - input = np.random.rand(H, W).astype("float32") * 100 - box = [10, 10, 20, 20] - for ratio in [1, 2, 3]: - output = self._simple_roialign(input, box, (5, 5), sampling_ratio=ratio) - output_grid_sample = grid_sample_roi_align( - torch.from_numpy(input[None, None, :, :]).float(), - torch.as_tensor(box).float()[None, :], - 5, - 1.0, - ratio, - ) - self.assertTrue(torch.allclose(output, output_grid_sample)) - - def _simple_roialign(self, img, box, resolution, sampling_ratio=0, aligned=True): - """ - RoiAlign with scale 1.0. - """ - if isinstance(resolution, int): - resolution = (resolution, resolution) - op = ROIAlign(resolution, 1.0, sampling_ratio, aligned=aligned) - input = torch.from_numpy(img[None, None, :, :].astype("float32")) - - rois = [0] + list(box) - rois = torch.from_numpy(np.asarray(rois)[None, :].astype("float32")) - output = op.forward(input, rois) - if torch.cuda.is_available(): - output_cuda = op.forward(input.cuda(), rois.cuda()).cpu() - self.assertTrue(torch.allclose(output, output_cuda)) - return output[0, 0] - - def _simple_roialign_with_grad(self, img, box, resolution, device): - if isinstance(resolution, int): - resolution = (resolution, resolution) - - op = ROIAlign(resolution, 1.0, 0, aligned=True) - input = torch.from_numpy(img[None, None, :, :].astype("float32")) - - rois = [0] + list(box) - rois = torch.from_numpy(np.asarray(rois)[None, :].astype("float32")) - input = input.to(device=device) - rois = rois.to(device=device) - input.requires_grad = True - output = op.forward(input, rois) - return input, output - - def test_empty_box(self): - img = np.random.rand(5, 5) - box = [3, 4, 5, 4] - o = self._simple_roialign(img, box, 7) - self.assertTrue(o.shape == (7, 7)) - self.assertTrue((o == 0).all()) - - for dev in ["cpu"] + ["cuda"] if torch.cuda.is_available() else []: - input, output = self._simple_roialign_with_grad(img, box, 7, torch.device(dev)) - output.sum().backward() - self.assertTrue(torch.allclose(input.grad, torch.zeros_like(input))) - - def test_empty_batch(self): - input = torch.zeros(0, 3, 10, 10, dtype=torch.float32) - rois = torch.zeros(0, 5, dtype=torch.float32) - op = ROIAlign((7, 7), 1.0, 0, aligned=True) - output = op.forward(input, rois) - self.assertTrue(output.shape == (0, 3, 7, 7)) - - -def grid_sample_roi_align(input, boxes, output_size, scale, sampling_ratio): - # unlike true roi_align, this does not support different batch_idx - from detectron2.projects.point_rend.point_features import ( - generate_regular_grid_point_coords, - get_point_coords_wrt_image, - point_sample, - ) - - N, _, H, W = input.shape - R = len(boxes) - assert N == 1 - boxes = boxes * scale - grid = generate_regular_grid_point_coords(R, output_size * sampling_ratio, device=boxes.device) - coords = get_point_coords_wrt_image(boxes, grid) - coords = coords / torch.as_tensor([W, H], device=coords.device) # R, s^2, 2 - res = point_sample(input, coords.unsqueeze(0), align_corners=False) # 1,C, R,s^2 - res = ( - res.squeeze(0) - .permute(1, 0, 2) - .reshape(R, -1, output_size * sampling_ratio, output_size * sampling_ratio) - ) - res = F.avg_pool2d(res, sampling_ratio) - return res - - -def benchmark_roi_align(): - def random_boxes(mean_box, stdev, N, maxsize): - ret = torch.rand(N, 4) * stdev + torch.tensor(mean_box, dtype=torch.float) - ret.clamp_(min=0, max=maxsize) - return ret - - def func(shape, nboxes_per_img, sampling_ratio, device, box_size="large"): - N, _, H, _ = shape - input = torch.rand(*shape) - boxes = [] - batch_idx = [] - for k in range(N): - if box_size == "large": - b = random_boxes([80, 80, 130, 130], 24, nboxes_per_img, H) - else: - b = random_boxes([100, 100, 110, 110], 4, nboxes_per_img, H) - boxes.append(b) - batch_idx.append(torch.zeros(nboxes_per_img, 1, dtype=torch.float32) + k) - boxes = torch.cat(boxes, axis=0) - batch_idx = torch.cat(batch_idx, axis=0) - boxes = torch.cat([batch_idx, boxes], axis=1) - - input = input.to(device=device) - boxes = boxes.to(device=device) - - def bench(): - if False and sampling_ratio > 0 and N == 1: - # enable to benchmark grid_sample (slower) - grid_sample_roi_align(input, boxes[:, 1:], 7, 1.0, sampling_ratio) - else: - roi_align(input, boxes, 7, 1.0, sampling_ratio, True) - if device == "cuda": - torch.cuda.synchronize() - - return bench - - def gen_args(arg): - args = [] - for size in ["small", "large"]: - for ratio in [0, 2]: - args.append(copy(arg)) - args[-1]["sampling_ratio"] = ratio - args[-1]["box_size"] = size - return args - - arg = dict(shape=(1, 512, 256, 256), nboxes_per_img=512, device="cuda") - benchmark(func, "cuda_roialign", gen_args(arg), num_iters=20, warmup_iters=1) - arg.update({"device": "cpu", "shape": (1, 256, 128, 128)}) - benchmark(func, "cpu_roialign", gen_args(arg), num_iters=5, warmup_iters=1) - - -if __name__ == "__main__": - if torch.cuda.is_available(): - benchmark_roi_align() - unittest.main() diff --git a/preprocess/detectron2/tests/layers/test_roi_align_rotated.py b/preprocess/detectron2/tests/layers/test_roi_align_rotated.py deleted file mode 100644 index 7323d7d5a86816f337571221313c428238c439f4..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/layers/test_roi_align_rotated.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import cv2 -import torch -from torch.autograd import Variable, gradcheck - -from detectron2.layers.roi_align import ROIAlign -from detectron2.layers.roi_align_rotated import ROIAlignRotated - -logger = logging.getLogger(__name__) - - -class ROIAlignRotatedTest(unittest.TestCase): - def _box_to_rotated_box(self, box, angle): - return [ - (box[0] + box[2]) / 2.0, - (box[1] + box[3]) / 2.0, - box[2] - box[0], - box[3] - box[1], - angle, - ] - - def _rot90(self, img, num): - num = num % 4 # note: -1 % 4 == 3 - for _ in range(num): - img = img.transpose(0, 1).flip(0) - return img - - def test_forward_output_0_90_180_270(self): - for i in range(4): - # i = 0, 1, 2, 3 corresponding to 0, 90, 180, 270 degrees - img = torch.arange(25, dtype=torch.float32).reshape(5, 5) - """ - 0 1 2 3 4 - 5 6 7 8 9 - 10 11 12 13 14 - 15 16 17 18 19 - 20 21 22 23 24 - """ - box = [1, 1, 3, 3] - rotated_box = self._box_to_rotated_box(box=box, angle=90 * i) - - result = self._simple_roi_align_rotated(img=img, box=rotated_box, resolution=(4, 4)) - - # Here's an explanation for 0 degree case: - # point 0 in the original input lies at [0.5, 0.5] - # (the center of bin [0, 1] x [0, 1]) - # point 1 in the original input lies at [1.5, 0.5], etc. - # since the resolution is (4, 4) that divides [1, 3] x [1, 3] - # into 4 x 4 equal bins, - # the top-left bin is [1, 1.5] x [1, 1.5], and its center - # (1.25, 1.25) lies at the 3/4 position - # between point 0 and point 1, point 5 and point 6, - # point 0 and point 5, point 1 and point 6, so it can be calculated as - # 0.25*(0*0.25+1*0.75)+(5*0.25+6*0.75)*0.75 = 4.5 - result_expected = torch.tensor( - [ - [4.5, 5.0, 5.5, 6.0], - [7.0, 7.5, 8.0, 8.5], - [9.5, 10.0, 10.5, 11.0], - [12.0, 12.5, 13.0, 13.5], - ] - ) - # This is also an upsampled version of [[6, 7], [11, 12]] - - # When the box is rotated by 90 degrees CCW, - # the result would be rotated by 90 degrees CW, thus it's -i here - result_expected = self._rot90(result_expected, -i) - - assert torch.allclose(result, result_expected) - - def test_resize(self): - H, W = 30, 30 - input = torch.rand(H, W) * 100 - box = [10, 10, 20, 20] - rotated_box = self._box_to_rotated_box(box, angle=0) - output = self._simple_roi_align_rotated(img=input, box=rotated_box, resolution=(5, 5)) - - input2x = cv2.resize(input.numpy(), (W // 2, H // 2), interpolation=cv2.INTER_LINEAR) - input2x = torch.from_numpy(input2x) - box2x = [x / 2 for x in box] - rotated_box2x = self._box_to_rotated_box(box2x, angle=0) - output2x = self._simple_roi_align_rotated(img=input2x, box=rotated_box2x, resolution=(5, 5)) - assert torch.allclose(output2x, output) - - def _simple_roi_align_rotated(self, img, box, resolution): - """ - RoiAlignRotated with scale 1.0 and 0 sample ratio. - """ - op = ROIAlignRotated(output_size=resolution, spatial_scale=1.0, sampling_ratio=0) - input = img[None, None, :, :] - - rois = [0] + list(box) - rois = torch.tensor(rois, dtype=torch.float32)[None, :] - result_cpu = op.forward(input, rois) - if torch.cuda.is_available(): - result_cuda = op.forward(input.cuda(), rois.cuda()) - assert torch.allclose(result_cpu, result_cuda.cpu()) - return result_cpu[0, 0] - - def test_empty_box(self): - img = torch.rand(5, 5) - out = self._simple_roi_align_rotated(img, [2, 3, 0, 0, 0], (7, 7)) - self.assertTrue((out == 0).all()) - - def test_roi_align_rotated_gradcheck_cpu(self): - dtype = torch.float64 - device = torch.device("cpu") - roi_align_rotated_op = ROIAlignRotated( - output_size=(5, 5), spatial_scale=0.5, sampling_ratio=1 - ).to(dtype=dtype, device=device) - x = torch.rand(1, 1, 10, 10, dtype=dtype, device=device, requires_grad=True) - # roi format is (batch index, x_center, y_center, width, height, angle) - rois = torch.tensor( - [[0, 4.5, 4.5, 9, 9, 0], [0, 2, 7, 4, 4, 0], [0, 7, 7, 4, 4, 0]], - dtype=dtype, - device=device, - ) - - def func(input): - return roi_align_rotated_op(input, rois) - - assert gradcheck(func, (x,)), "gradcheck failed for RoIAlignRotated CPU" - assert gradcheck(func, (x.transpose(2, 3),)), "gradcheck failed for RoIAlignRotated CPU" - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_roi_align_rotated_gradient_cuda(self): - """ - Compute gradients for ROIAlignRotated with multiple bounding boxes on the GPU, - and compare the result with ROIAlign - """ - # torch.manual_seed(123) - dtype = torch.float64 - device = torch.device("cuda") - pool_h, pool_w = (5, 5) - - roi_align = ROIAlign(output_size=(pool_h, pool_w), spatial_scale=1, sampling_ratio=2).to( - device=device - ) - - roi_align_rotated = ROIAlignRotated( - output_size=(pool_h, pool_w), spatial_scale=1, sampling_ratio=2 - ).to(device=device) - - x = torch.rand(1, 1, 10, 10, dtype=dtype, device=device, requires_grad=True) - # x_rotated = x.clone() won't work (will lead to grad_fun=CloneBackward)! - x_rotated = Variable(x.data.clone(), requires_grad=True) - - # roi_rotated format is (batch index, x_center, y_center, width, height, angle) - rois_rotated = torch.tensor( - [[0, 4.5, 4.5, 9, 9, 0], [0, 2, 7, 4, 4, 0], [0, 7, 7, 4, 4, 0]], - dtype=dtype, - device=device, - ) - - y_rotated = roi_align_rotated(x_rotated, rois_rotated) - s_rotated = y_rotated.sum() - s_rotated.backward() - - # roi format is (batch index, x1, y1, x2, y2) - rois = torch.tensor( - [[0, 0, 0, 9, 9], [0, 0, 5, 4, 9], [0, 5, 5, 9, 9]], dtype=dtype, device=device - ) - - y = roi_align(x, rois) - s = y.sum() - s.backward() - - assert torch.allclose( - x.grad, x_rotated.grad - ), "gradients for ROIAlign and ROIAlignRotated mismatch on CUDA" - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/__init__.py b/preprocess/detectron2/tests/modeling/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tests/modeling/test_anchor_generator.py b/preprocess/detectron2/tests/modeling/test_anchor_generator.py deleted file mode 100644 index 13a808e587382216da6fe7ee957603f448172657..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_anchor_generator.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import torch - -from detectron2.config import get_cfg -from detectron2.layers import ShapeSpec -from detectron2.modeling.anchor_generator import DefaultAnchorGenerator, RotatedAnchorGenerator - -logger = logging.getLogger(__name__) - - -class TestAnchorGenerator(unittest.TestCase): - def test_default_anchor_generator(self): - cfg = get_cfg() - cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] - cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1, 4]] - - anchor_generator = DefaultAnchorGenerator(cfg, [ShapeSpec(stride=4)]) - - # only the last two dimensions of features matter here - num_images = 2 - features = {"stage3": torch.rand(num_images, 96, 1, 2)} - anchors = anchor_generator([features["stage3"]]) - expected_anchor_tensor = torch.tensor( - [ - [-32.0, -8.0, 32.0, 8.0], - [-16.0, -16.0, 16.0, 16.0], - [-8.0, -32.0, 8.0, 32.0], - [-64.0, -16.0, 64.0, 16.0], - [-32.0, -32.0, 32.0, 32.0], - [-16.0, -64.0, 16.0, 64.0], - [-28.0, -8.0, 36.0, 8.0], # -28.0 == -32.0 + STRIDE (4) - [-12.0, -16.0, 20.0, 16.0], - [-4.0, -32.0, 12.0, 32.0], - [-60.0, -16.0, 68.0, 16.0], - [-28.0, -32.0, 36.0, 32.0], - [-12.0, -64.0, 20.0, 64.0], - ] - ) - - self.assertTrue(torch.allclose(anchors[0].tensor, expected_anchor_tensor)) - - def test_default_anchor_generator_centered(self): - # test explicit args - anchor_generator = DefaultAnchorGenerator( - sizes=[32, 64], aspect_ratios=[0.25, 1, 4], strides=[4] - ) - - # only the last two dimensions of features matter here - num_images = 2 - features = {"stage3": torch.rand(num_images, 96, 1, 2)} - expected_anchor_tensor = torch.tensor( - [ - [-30.0, -6.0, 34.0, 10.0], - [-14.0, -14.0, 18.0, 18.0], - [-6.0, -30.0, 10.0, 34.0], - [-62.0, -14.0, 66.0, 18.0], - [-30.0, -30.0, 34.0, 34.0], - [-14.0, -62.0, 18.0, 66.0], - [-26.0, -6.0, 38.0, 10.0], - [-10.0, -14.0, 22.0, 18.0], - [-2.0, -30.0, 14.0, 34.0], - [-58.0, -14.0, 70.0, 18.0], - [-26.0, -30.0, 38.0, 34.0], - [-10.0, -62.0, 22.0, 66.0], - ] - ) - - anchors = anchor_generator([features["stage3"]]) - self.assertTrue(torch.allclose(anchors[0].tensor, expected_anchor_tensor)) - - anchors = torch.jit.script(anchor_generator)([features["stage3"]]) - self.assertTrue(torch.allclose(anchors[0].tensor, expected_anchor_tensor)) - - def test_rrpn_anchor_generator(self): - cfg = get_cfg() - cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] - cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1, 4]] - cfg.MODEL.ANCHOR_GENERATOR.ANGLES = [0, 45] # test single list[float] - anchor_generator = RotatedAnchorGenerator(cfg, [ShapeSpec(stride=4)]) - - # only the last two dimensions of features matter here - num_images = 2 - features = {"stage3": torch.rand(num_images, 96, 1, 2)} - anchors = anchor_generator([features["stage3"]]) - expected_anchor_tensor = torch.tensor( - [ - [0.0, 0.0, 64.0, 16.0, 0.0], - [0.0, 0.0, 64.0, 16.0, 45.0], - [0.0, 0.0, 32.0, 32.0, 0.0], - [0.0, 0.0, 32.0, 32.0, 45.0], - [0.0, 0.0, 16.0, 64.0, 0.0], - [0.0, 0.0, 16.0, 64.0, 45.0], - [0.0, 0.0, 128.0, 32.0, 0.0], - [0.0, 0.0, 128.0, 32.0, 45.0], - [0.0, 0.0, 64.0, 64.0, 0.0], - [0.0, 0.0, 64.0, 64.0, 45.0], - [0.0, 0.0, 32.0, 128.0, 0.0], - [0.0, 0.0, 32.0, 128.0, 45.0], - [4.0, 0.0, 64.0, 16.0, 0.0], # 4.0 == 0.0 + STRIDE (4) - [4.0, 0.0, 64.0, 16.0, 45.0], - [4.0, 0.0, 32.0, 32.0, 0.0], - [4.0, 0.0, 32.0, 32.0, 45.0], - [4.0, 0.0, 16.0, 64.0, 0.0], - [4.0, 0.0, 16.0, 64.0, 45.0], - [4.0, 0.0, 128.0, 32.0, 0.0], - [4.0, 0.0, 128.0, 32.0, 45.0], - [4.0, 0.0, 64.0, 64.0, 0.0], - [4.0, 0.0, 64.0, 64.0, 45.0], - [4.0, 0.0, 32.0, 128.0, 0.0], - [4.0, 0.0, 32.0, 128.0, 45.0], - ] - ) - - self.assertTrue(torch.allclose(anchors[0].tensor, expected_anchor_tensor)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_backbone.py b/preprocess/detectron2/tests/modeling/test_backbone.py deleted file mode 100644 index 3bb100f9bd5b4939e4646821c5a60d51c8ea65fd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_backbone.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved - -import unittest -import torch - -import detectron2.export.torchscript # apply patch # noqa -from detectron2 import model_zoo -from detectron2.config import get_cfg -from detectron2.layers import ShapeSpec -from detectron2.modeling.backbone import build_resnet_backbone -from detectron2.modeling.backbone.fpn import build_resnet_fpn_backbone - - -class TestBackBone(unittest.TestCase): - def test_resnet_scriptability(self): - cfg = get_cfg() - resnet = build_resnet_backbone(cfg, ShapeSpec(channels=3)) - - scripted_resnet = torch.jit.script(resnet) - - inp = torch.rand(2, 3, 100, 100) - out1 = resnet(inp)["res4"] - out2 = scripted_resnet(inp)["res4"] - self.assertTrue(torch.allclose(out1, out2)) - - def test_fpn_scriptability(self): - cfg = model_zoo.get_config("Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml") - bb = build_resnet_fpn_backbone(cfg, ShapeSpec(channels=3)) - bb_s = torch.jit.script(bb) - - inp = torch.rand(2, 3, 128, 128) - out1 = bb(inp)["p5"] - out2 = bb_s(inp)["p5"] - self.assertTrue(torch.allclose(out1, out2)) diff --git a/preprocess/detectron2/tests/modeling/test_box2box_transform.py b/preprocess/detectron2/tests/modeling/test_box2box_transform.py deleted file mode 100644 index fd3a7b79b6b7a3608ad7cb3918de020a5a600d2f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_box2box_transform.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import torch - -from detectron2.modeling.box_regression import ( - Box2BoxTransform, - Box2BoxTransformLinear, - Box2BoxTransformRotated, -) -from detectron2.utils.testing import random_boxes - -logger = logging.getLogger(__name__) - - -class TestBox2BoxTransform(unittest.TestCase): - def test_reconstruction(self): - weights = (5, 5, 10, 10) - b2b_tfm = Box2BoxTransform(weights=weights) - src_boxes = random_boxes(10) - dst_boxes = random_boxes(10) - - devices = [torch.device("cpu")] - if torch.cuda.is_available(): - devices.append(torch.device("cuda")) - for device in devices: - src_boxes = src_boxes.to(device=device) - dst_boxes = dst_boxes.to(device=device) - deltas = b2b_tfm.get_deltas(src_boxes, dst_boxes) - dst_boxes_reconstructed = b2b_tfm.apply_deltas(deltas, src_boxes) - self.assertTrue(torch.allclose(dst_boxes, dst_boxes_reconstructed)) - - def test_apply_deltas_tracing(self): - weights = (5, 5, 10, 10) - b2b_tfm = Box2BoxTransform(weights=weights) - - with torch.no_grad(): - func = torch.jit.trace(b2b_tfm.apply_deltas, (torch.randn(10, 20), torch.randn(10, 4))) - - o = func(torch.randn(10, 20), torch.randn(10, 4)) - self.assertEqual(o.shape, (10, 20)) - o = func(torch.randn(5, 20), torch.randn(5, 4)) - self.assertEqual(o.shape, (5, 20)) - - -def random_rotated_boxes(mean_box, std_length, std_angle, N): - return torch.cat( - [torch.rand(N, 4) * std_length, torch.rand(N, 1) * std_angle], dim=1 - ) + torch.tensor(mean_box, dtype=torch.float) - - -class TestBox2BoxTransformRotated(unittest.TestCase): - def test_reconstruction(self): - weights = (5, 5, 10, 10, 1) - b2b_transform = Box2BoxTransformRotated(weights=weights) - src_boxes = random_rotated_boxes([10, 10, 20, 20, -30], 5, 60.0, 10) - dst_boxes = random_rotated_boxes([10, 10, 20, 20, -30], 5, 60.0, 10) - - devices = [torch.device("cpu")] - if torch.cuda.is_available(): - devices.append(torch.device("cuda")) - for device in devices: - src_boxes = src_boxes.to(device=device) - dst_boxes = dst_boxes.to(device=device) - deltas = b2b_transform.get_deltas(src_boxes, dst_boxes) - dst_boxes_reconstructed = b2b_transform.apply_deltas(deltas, src_boxes) - assert torch.allclose(dst_boxes[:, :4], dst_boxes_reconstructed[:, :4], atol=1e-5) - # angle difference has to be normalized - assert torch.allclose( - (dst_boxes[:, 4] - dst_boxes_reconstructed[:, 4] + 180.0) % 360.0 - 180.0, - torch.zeros_like(dst_boxes[:, 4]), - atol=1e-4, - ) - - -class TestBox2BoxTransformLinear(unittest.TestCase): - def test_reconstruction(self): - b2b_tfm = Box2BoxTransformLinear() - src_boxes = random_boxes(10) - dst_boxes = torch.tensor([0, 0, 101, 101] * 10).reshape(10, 4).float() - - devices = [torch.device("cpu")] - if torch.cuda.is_available(): - devices.append(torch.device("cuda")) - for device in devices: - src_boxes = src_boxes.to(device=device) - dst_boxes = dst_boxes.to(device=device) - deltas = b2b_tfm.get_deltas(src_boxes, dst_boxes) - dst_boxes_reconstructed = b2b_tfm.apply_deltas(deltas, src_boxes) - self.assertTrue(torch.allclose(dst_boxes, dst_boxes_reconstructed, atol=1e-3)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_fast_rcnn.py b/preprocess/detectron2/tests/modeling/test_fast_rcnn.py deleted file mode 100644 index e29b944bffca1ccbf5b02be59a753f3188d90a4f..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_fast_rcnn.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import torch - -from detectron2.layers import ShapeSpec -from detectron2.modeling.box_regression import Box2BoxTransform, Box2BoxTransformRotated -from detectron2.modeling.roi_heads.fast_rcnn import FastRCNNOutputLayers -from detectron2.modeling.roi_heads.rotated_fast_rcnn import RotatedFastRCNNOutputLayers -from detectron2.structures import Boxes, Instances, RotatedBoxes -from detectron2.utils.events import EventStorage - -logger = logging.getLogger(__name__) - - -class FastRCNNTest(unittest.TestCase): - def test_fast_rcnn(self): - torch.manual_seed(132) - - box_head_output_size = 8 - - box_predictor = FastRCNNOutputLayers( - ShapeSpec(channels=box_head_output_size), - box2box_transform=Box2BoxTransform(weights=(10, 10, 5, 5)), - num_classes=5, - ) - feature_pooled = torch.rand(2, box_head_output_size) - predictions = box_predictor(feature_pooled) - - proposal_boxes = torch.tensor([[0.8, 1.1, 3.2, 2.8], [2.3, 2.5, 7, 8]], dtype=torch.float32) - gt_boxes = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) - proposal = Instances((10, 10)) - proposal.proposal_boxes = Boxes(proposal_boxes) - proposal.gt_boxes = Boxes(gt_boxes) - proposal.gt_classes = torch.tensor([1, 2]) - - with EventStorage(): # capture events in a new storage to discard them - losses = box_predictor.losses(predictions, [proposal]) - - expected_losses = { - "loss_cls": torch.tensor(1.7951188087), - "loss_box_reg": torch.tensor(4.0357131958), - } - for name in expected_losses.keys(): - assert torch.allclose(losses[name], expected_losses[name]) - - def test_fast_rcnn_empty_batch(self, device="cpu"): - box_predictor = FastRCNNOutputLayers( - ShapeSpec(channels=10), - box2box_transform=Box2BoxTransform(weights=(10, 10, 5, 5)), - num_classes=8, - ).to(device=device) - - logits = torch.randn(0, 100, requires_grad=True, device=device) - deltas = torch.randn(0, 4, requires_grad=True, device=device) - losses = box_predictor.losses([logits, deltas], []) - for value in losses.values(): - self.assertTrue(torch.allclose(value, torch.zeros_like(value))) - sum(losses.values()).backward() - self.assertTrue(logits.grad is not None) - self.assertTrue(deltas.grad is not None) - - predictions, _ = box_predictor.inference([logits, deltas], []) - self.assertEqual(len(predictions), 0) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_fast_rcnn_empty_batch_cuda(self): - self.test_fast_rcnn_empty_batch(device=torch.device("cuda")) - - def test_fast_rcnn_rotated(self): - torch.manual_seed(132) - box_head_output_size = 8 - - box_predictor = RotatedFastRCNNOutputLayers( - ShapeSpec(channels=box_head_output_size), - box2box_transform=Box2BoxTransformRotated(weights=(10, 10, 5, 5, 1)), - num_classes=5, - ) - feature_pooled = torch.rand(2, box_head_output_size) - predictions = box_predictor(feature_pooled) - proposal_boxes = torch.tensor( - [[2, 1.95, 2.4, 1.7, 0], [4.65, 5.25, 4.7, 5.5, 0]], dtype=torch.float32 - ) - gt_boxes = torch.tensor([[2, 2, 2, 2, 0], [4, 4, 4, 4, 0]], dtype=torch.float32) - proposal = Instances((10, 10)) - proposal.proposal_boxes = RotatedBoxes(proposal_boxes) - proposal.gt_boxes = RotatedBoxes(gt_boxes) - proposal.gt_classes = torch.tensor([1, 2]) - - with EventStorage(): # capture events in a new storage to discard them - losses = box_predictor.losses(predictions, [proposal]) - - # Note: the expected losses are slightly different even if - # the boxes are essentially the same as in the FastRCNNOutput test, because - # bbox_pred in FastRCNNOutputLayers have different Linear layers/initialization - # between the two cases. - expected_losses = { - "loss_cls": torch.tensor(1.7920907736), - "loss_box_reg": torch.tensor(4.0410838127), - } - for name in expected_losses.keys(): - assert torch.allclose(losses[name], expected_losses[name]) - - def test_predict_boxes_tracing(self): - class Model(torch.nn.Module): - def __init__(self, output_layer): - super(Model, self).__init__() - self._output_layer = output_layer - - def forward(self, proposal_deltas, proposal_boxes): - instances = Instances((10, 10)) - instances.proposal_boxes = Boxes(proposal_boxes) - return self._output_layer.predict_boxes((None, proposal_deltas), [instances]) - - box_head_output_size = 8 - - box_predictor = FastRCNNOutputLayers( - ShapeSpec(channels=box_head_output_size), - box2box_transform=Box2BoxTransform(weights=(10, 10, 5, 5)), - num_classes=5, - ) - - model = Model(box_predictor) - - from detectron2.export.torchscript_patch import patch_builtin_len - - with torch.no_grad(), patch_builtin_len(): - func = torch.jit.trace(model, (torch.randn(10, 20), torch.randn(10, 4))) - - o = func(torch.randn(10, 20), torch.randn(10, 4)) - self.assertEqual(o[0].shape, (10, 20)) - o = func(torch.randn(5, 20), torch.randn(5, 4)) - self.assertEqual(o[0].shape, (5, 20)) - o = func(torch.randn(20, 20), torch.randn(20, 4)) - self.assertEqual(o[0].shape, (20, 20)) - - def test_predict_probs_tracing(self): - class Model(torch.nn.Module): - def __init__(self, output_layer): - super(Model, self).__init__() - self._output_layer = output_layer - - def forward(self, scores, proposal_boxes): - instances = Instances((10, 10)) - instances.proposal_boxes = Boxes(proposal_boxes) - return self._output_layer.predict_probs((scores, None), [instances]) - - box_head_output_size = 8 - - box_predictor = FastRCNNOutputLayers( - ShapeSpec(channels=box_head_output_size), - box2box_transform=Box2BoxTransform(weights=(10, 10, 5, 5)), - num_classes=5, - ) - - model = Model(box_predictor) - - from detectron2.export.torchscript_patch import patch_builtin_len - - with torch.no_grad(), patch_builtin_len(): - func = torch.jit.trace(model, (torch.randn(10, 6), torch.rand(10, 4))) - o = func(torch.randn(10, 6), torch.randn(10, 4)) - self.assertEqual(o[0].shape, (10, 6)) - o = func(torch.randn(5, 6), torch.randn(5, 4)) - self.assertEqual(o[0].shape, (5, 6)) - o = func(torch.randn(20, 6), torch.randn(20, 4)) - self.assertEqual(o[0].shape, (20, 6)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_matcher.py b/preprocess/detectron2/tests/modeling/test_matcher.py deleted file mode 100644 index 6eb2db0c24b117337c431e9ef00a85a3bced71b9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_matcher.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest -from typing import List -import torch - -from detectron2.config import get_cfg -from detectron2.modeling.matcher import Matcher - - -class TestMatcher(unittest.TestCase): - def test_scriptability(self): - cfg = get_cfg() - anchor_matcher = Matcher( - cfg.MODEL.RPN.IOU_THRESHOLDS, cfg.MODEL.RPN.IOU_LABELS, allow_low_quality_matches=True - ) - match_quality_matrix = torch.tensor( - [[0.15, 0.45, 0.2, 0.6], [0.3, 0.65, 0.05, 0.1], [0.05, 0.4, 0.25, 0.4]] - ) - expected_matches = torch.tensor([1, 1, 2, 0]) - expected_match_labels = torch.tensor([-1, 1, 0, 1], dtype=torch.int8) - - matches, match_labels = anchor_matcher(match_quality_matrix) - self.assertTrue(torch.allclose(matches, expected_matches)) - self.assertTrue(torch.allclose(match_labels, expected_match_labels)) - - # nonzero_tuple must be import explicitly to let jit know what it is. - # https://github.com/pytorch/pytorch/issues/38964 - from detectron2.layers import nonzero_tuple # noqa F401 - - def f(thresholds: List[float], labels: List[int]): - return Matcher(thresholds, labels, allow_low_quality_matches=True) - - scripted_anchor_matcher = torch.jit.script(f)( - cfg.MODEL.RPN.IOU_THRESHOLDS, cfg.MODEL.RPN.IOU_LABELS - ) - matches, match_labels = scripted_anchor_matcher(match_quality_matrix) - self.assertTrue(torch.allclose(matches, expected_matches)) - self.assertTrue(torch.allclose(match_labels, expected_match_labels)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_mmdet.py b/preprocess/detectron2/tests/modeling/test_mmdet.py deleted file mode 100644 index a743b0b67d5ab664257040621d28c1b1b4451709..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_mmdet.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest - -from detectron2.layers import ShapeSpec -from detectron2.modeling.mmdet_wrapper import MMDetBackbone, MMDetDetector - -try: - import mmdet.models # noqa - - HAS_MMDET = True -except ImportError: - HAS_MMDET = False - - -@unittest.skipIf(not HAS_MMDET, "mmdet not available") -class TestMMDetWrapper(unittest.TestCase): - def test_backbone(self): - MMDetBackbone( - backbone=dict( - type="DetectoRS_ResNet", - conv_cfg=dict(type="ConvAWS"), - sac=dict(type="SAC", use_deform=True), - stage_with_sac=(False, True, True, True), - depth=50, - num_stages=4, - out_indices=(0, 1, 2, 3), - frozen_stages=1, - norm_cfg=dict(type="BN", requires_grad=True), - norm_eval=True, - style="pytorch", - ), - neck=dict( - type="FPN", - in_channels=[256, 512, 1024, 2048], - out_channels=256, - num_outs=5, - ), - # skip pretrained model for tests - # pretrained_backbone="torchvision://resnet50", - output_shapes=[ShapeSpec(channels=256, stride=s) for s in [4, 8, 16, 32, 64]], - output_names=["p2", "p3", "p4", "p5", "p6"], - ) - - def test_detector(self): - # a basic R50 Mask R-CNN - MMDetDetector( - detector=dict( - type="MaskRCNN", - backbone=dict( - type="ResNet", - depth=50, - num_stages=4, - out_indices=(0, 1, 2, 3), - frozen_stages=1, - norm_cfg=dict(type="BN", requires_grad=True), - norm_eval=True, - style="pytorch", - # skip pretrained model for tests - # init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')) - ), - neck=dict( - type="FPN", in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=5 - ), - rpn_head=dict( - type="RPNHead", - in_channels=256, - feat_channels=256, - anchor_generator=dict( - type="AnchorGenerator", - scales=[8], - ratios=[0.5, 1.0, 2.0], - strides=[4, 8, 16, 32, 64], - ), - bbox_coder=dict( - type="DeltaXYWHBBoxCoder", - target_means=[0.0, 0.0, 0.0, 0.0], - target_stds=[1.0, 1.0, 1.0, 1.0], - ), - loss_cls=dict(type="CrossEntropyLoss", use_sigmoid=True, loss_weight=1.0), - loss_bbox=dict(type="L1Loss", loss_weight=1.0), - ), - roi_head=dict( - type="StandardRoIHead", - bbox_roi_extractor=dict( - type="SingleRoIExtractor", - roi_layer=dict(type="RoIAlign", output_size=7, sampling_ratio=0), - out_channels=256, - featmap_strides=[4, 8, 16, 32], - ), - bbox_head=dict( - type="Shared2FCBBoxHead", - in_channels=256, - fc_out_channels=1024, - roi_feat_size=7, - num_classes=80, - bbox_coder=dict( - type="DeltaXYWHBBoxCoder", - target_means=[0.0, 0.0, 0.0, 0.0], - target_stds=[0.1, 0.1, 0.2, 0.2], - ), - reg_class_agnostic=False, - loss_cls=dict(type="CrossEntropyLoss", use_sigmoid=False, loss_weight=1.0), - loss_bbox=dict(type="L1Loss", loss_weight=1.0), - ), - mask_roi_extractor=dict( - type="SingleRoIExtractor", - roi_layer=dict(type="RoIAlign", output_size=14, sampling_ratio=0), - out_channels=256, - featmap_strides=[4, 8, 16, 32], - ), - mask_head=dict( - type="FCNMaskHead", - num_convs=4, - in_channels=256, - conv_out_channels=256, - num_classes=80, - loss_mask=dict(type="CrossEntropyLoss", use_mask=True, loss_weight=1.0), - ), - ), - # model training and testing settings - train_cfg=dict( - rpn=dict( - assigner=dict( - type="MaxIoUAssigner", - pos_iou_thr=0.7, - neg_iou_thr=0.3, - min_pos_iou=0.3, - match_low_quality=True, - ignore_iof_thr=-1, - ), - sampler=dict( - type="RandomSampler", - num=256, - pos_fraction=0.5, - neg_pos_ub=-1, - add_gt_as_proposals=False, - ), - allowed_border=-1, - pos_weight=-1, - debug=False, - ), - rpn_proposal=dict( - nms_pre=2000, - max_per_img=1000, - nms=dict(type="nms", iou_threshold=0.7), - min_bbox_size=0, - ), - rcnn=dict( - assigner=dict( - type="MaxIoUAssigner", - pos_iou_thr=0.5, - neg_iou_thr=0.5, - min_pos_iou=0.5, - match_low_quality=True, - ignore_iof_thr=-1, - ), - sampler=dict( - type="RandomSampler", - num=512, - pos_fraction=0.25, - neg_pos_ub=-1, - add_gt_as_proposals=True, - ), - mask_size=28, - pos_weight=-1, - debug=False, - ), - ), - test_cfg=dict( - rpn=dict( - nms_pre=1000, - max_per_img=1000, - nms=dict(type="nms", iou_threshold=0.7), - min_bbox_size=0, - ), - rcnn=dict( - score_thr=0.05, - nms=dict(type="nms", iou_threshold=0.5), - max_per_img=100, - mask_thr_binary=0.5, - ), - ), - ), - pixel_mean=[1, 2, 3], - pixel_std=[1, 2, 3], - ) diff --git a/preprocess/detectron2/tests/modeling/test_model_e2e.py b/preprocess/detectron2/tests/modeling/test_model_e2e.py deleted file mode 100644 index 8c07e6856d2f4304e0b0cb32747fb667e3bbcb4c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_model_e2e.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - - -import itertools -import unittest -from contextlib import contextmanager -from copy import deepcopy -import torch - -from detectron2.structures import BitMasks, Boxes, ImageList, Instances -from detectron2.utils.events import EventStorage -from detectron2.utils.testing import get_model_no_weights - - -@contextmanager -def typecheck_hook(model, *, in_dtype=None, out_dtype=None): - """ - Check that the model must be called with the given input/output dtype - """ - if not isinstance(in_dtype, set): - in_dtype = {in_dtype} - if not isinstance(out_dtype, set): - out_dtype = {out_dtype} - - def flatten(x): - if isinstance(x, torch.Tensor): - return [x] - if isinstance(x, (list, tuple)): - return list(itertools.chain(*[flatten(t) for t in x])) - if isinstance(x, dict): - return flatten(list(x.values())) - return [] - - def hook(module, input, output): - if in_dtype is not None: - dtypes = {x.dtype for x in flatten(input)} - assert ( - dtypes == in_dtype - ), f"Expected input dtype of {type(module)} is {in_dtype}. Got {dtypes} instead!" - - if out_dtype is not None: - dtypes = {x.dtype for x in flatten(output)} - assert ( - dtypes == out_dtype - ), f"Expected output dtype of {type(module)} is {out_dtype}. Got {dtypes} instead!" - - with model.register_forward_hook(hook): - yield - - -def create_model_input(img, inst=None): - if inst is not None: - return {"image": img, "instances": inst} - else: - return {"image": img} - - -def get_empty_instance(h, w): - inst = Instances((h, w)) - inst.gt_boxes = Boxes(torch.rand(0, 4)) - inst.gt_classes = torch.tensor([]).to(dtype=torch.int64) - inst.gt_masks = BitMasks(torch.rand(0, h, w)) - return inst - - -def get_regular_bitmask_instances(h, w): - inst = Instances((h, w)) - inst.gt_boxes = Boxes(torch.rand(3, 4)) - inst.gt_boxes.tensor[:, 2:] += inst.gt_boxes.tensor[:, :2] - inst.gt_classes = torch.tensor([3, 4, 5]).to(dtype=torch.int64) - inst.gt_masks = BitMasks((torch.rand(3, h, w) > 0.5)) - return inst - - -class InstanceModelE2ETest: - def setUp(self): - torch.manual_seed(43) - self.model = get_model_no_weights(self.CONFIG_PATH) - - def _test_eval(self, input_sizes): - inputs = [create_model_input(torch.rand(3, s[0], s[1])) for s in input_sizes] - self.model.eval() - self.model(inputs) - - def _test_train(self, input_sizes, instances): - assert len(input_sizes) == len(instances) - inputs = [ - create_model_input(torch.rand(3, s[0], s[1]), inst) - for s, inst in zip(input_sizes, instances) - ] - self.model.train() - with EventStorage(): - losses = self.model(inputs) - sum(losses.values()).backward() - del losses - - def _inf_tensor(self, *shape): - return 1.0 / torch.zeros(*shape, device=self.model.device) - - def _nan_tensor(self, *shape): - return torch.zeros(*shape, device=self.model.device).fill_(float("nan")) - - def test_empty_data(self): - instances = [get_empty_instance(200, 250), get_empty_instance(200, 249)] - self._test_eval([(200, 250), (200, 249)]) - self._test_train([(200, 250), (200, 249)], instances) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") - def test_eval_tocpu(self): - model = deepcopy(self.model).cpu() - model.eval() - input_sizes = [(200, 250), (200, 249)] - inputs = [create_model_input(torch.rand(3, s[0], s[1])) for s in input_sizes] - model(inputs) - - -class MaskRCNNE2ETest(InstanceModelE2ETest, unittest.TestCase): - CONFIG_PATH = "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml" - - def test_half_empty_data(self): - instances = [get_empty_instance(200, 250), get_regular_bitmask_instances(200, 249)] - self._test_train([(200, 250), (200, 249)], instances) - - # This test is flaky because in some environment the output features are zero due to relu - # def test_rpn_inf_nan_data(self): - # self.model.eval() - # for tensor in [self._inf_tensor, self._nan_tensor]: - # images = ImageList(tensor(1, 3, 512, 512), [(510, 510)]) - # features = { - # "p2": tensor(1, 256, 256, 256), - # "p3": tensor(1, 256, 128, 128), - # "p4": tensor(1, 256, 64, 64), - # "p5": tensor(1, 256, 32, 32), - # "p6": tensor(1, 256, 16, 16), - # } - # props, _ = self.model.proposal_generator(images, features) - # self.assertEqual(len(props[0]), 0) - - def test_roiheads_inf_nan_data(self): - self.model.eval() - for tensor in [self._inf_tensor, self._nan_tensor]: - images = ImageList(tensor(1, 3, 512, 512), [(510, 510)]) - features = { - "p2": tensor(1, 256, 256, 256), - "p3": tensor(1, 256, 128, 128), - "p4": tensor(1, 256, 64, 64), - "p5": tensor(1, 256, 32, 32), - "p6": tensor(1, 256, 16, 16), - } - props = [Instances((510, 510))] - props[0].proposal_boxes = Boxes([[10, 10, 20, 20]]).to(device=self.model.device) - props[0].objectness_logits = torch.tensor([1.0]).reshape(1, 1) - det, _ = self.model.roi_heads(images, features, props) - self.assertEqual(len(det[0]), 0) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_autocast(self): - from torch.cuda.amp import autocast - - inputs = [{"image": torch.rand(3, 100, 100)}] - self.model.eval() - with autocast(), typecheck_hook( - self.model.backbone, in_dtype=torch.float32, out_dtype=torch.float16 - ), typecheck_hook( - self.model.roi_heads.box_predictor, in_dtype=torch.float16, out_dtype=torch.float16 - ): - out = self.model.inference(inputs, do_postprocess=False)[0] - self.assertEqual(out.pred_boxes.tensor.dtype, torch.float32) - self.assertEqual(out.pred_masks.dtype, torch.float16) - self.assertEqual(out.scores.dtype, torch.float32) # scores comes from softmax - - -class RetinaNetE2ETest(InstanceModelE2ETest, unittest.TestCase): - CONFIG_PATH = "COCO-Detection/retinanet_R_50_FPN_1x.yaml" - - def test_inf_nan_data(self): - self.model.eval() - self.model.score_threshold = -999999999 - for tensor in [self._inf_tensor, self._nan_tensor]: - images = ImageList(tensor(1, 3, 512, 512), [(510, 510)]) - features = [ - tensor(1, 256, 128, 128), - tensor(1, 256, 64, 64), - tensor(1, 256, 32, 32), - tensor(1, 256, 16, 16), - tensor(1, 256, 8, 8), - ] - pred_logits, pred_anchor_deltas = self.model.head(features) - pred_logits = [tensor(*x.shape) for x in pred_logits] - pred_anchor_deltas = [tensor(*x.shape) for x in pred_anchor_deltas] - det = self.model.forward_inference(images, features, [pred_logits, pred_anchor_deltas]) - # all predictions (if any) are infinite or nan - if len(det[0]): - self.assertTrue(torch.isfinite(det[0].pred_boxes.tensor).sum() == 0) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_autocast(self): - from torch.cuda.amp import autocast - - inputs = [{"image": torch.rand(3, 100, 100)}] - self.model.eval() - with autocast(), typecheck_hook( - self.model.backbone, in_dtype=torch.float32, out_dtype=torch.float16 - ), typecheck_hook(self.model.head, in_dtype=torch.float16, out_dtype=torch.float16): - out = self.model(inputs)[0]["instances"] - self.assertEqual(out.pred_boxes.tensor.dtype, torch.float32) - self.assertEqual(out.scores.dtype, torch.float16) - - -class FCOSE2ETest(InstanceModelE2ETest, unittest.TestCase): - CONFIG_PATH = "COCO-Detection/fcos_R_50_FPN_1x.py" - - -class SemSegE2ETest(unittest.TestCase): - CONFIG_PATH = "Misc/semantic_R_50_FPN_1x.yaml" - - def setUp(self): - torch.manual_seed(43) - self.model = get_model_no_weights(self.CONFIG_PATH) - - def _test_eval(self, input_sizes): - inputs = [create_model_input(torch.rand(3, s[0], s[1])) for s in input_sizes] - self.model.eval() - self.model(inputs) - - def test_forward(self): - self._test_eval([(200, 250), (200, 249)]) diff --git a/preprocess/detectron2/tests/modeling/test_roi_heads.py b/preprocess/detectron2/tests/modeling/test_roi_heads.py deleted file mode 100644 index 86360e1e36bf2e2d969db426eb11e54318a95385..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_roi_heads.py +++ /dev/null @@ -1,323 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -from copy import deepcopy -import torch -from torch import nn - -from detectron2 import model_zoo -from detectron2.config import get_cfg -from detectron2.export.torchscript_patch import ( - freeze_training_mode, - patch_builtin_len, - patch_instances, -) -from detectron2.layers import ShapeSpec -from detectron2.modeling.proposal_generator.build import build_proposal_generator -from detectron2.modeling.roi_heads import ( - FastRCNNConvFCHead, - KRCNNConvDeconvUpsampleHead, - MaskRCNNConvUpsampleHead, - StandardROIHeads, - build_roi_heads, -) -from detectron2.projects import point_rend -from detectron2.structures import BitMasks, Boxes, ImageList, Instances, RotatedBoxes -from detectron2.utils.events import EventStorage -from detectron2.utils.testing import assert_instances_allclose, random_boxes - -logger = logging.getLogger(__name__) - -""" -Make sure the losses of ROIHeads/RPN do not change, to avoid -breaking the forward logic by mistake. -This relies on assumption that pytorch's RNG is stable. -""" - - -class ROIHeadsTest(unittest.TestCase): - def test_roi_heads(self): - torch.manual_seed(121) - cfg = get_cfg() - cfg.MODEL.ROI_BOX_HEAD.NAME = "FastRCNNConvFCHead" - cfg.MODEL.ROI_BOX_HEAD.NUM_FC = 2 - cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE = "ROIAlignV2" - cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5) - cfg.MODEL.MASK_ON = True - num_images = 2 - images_tensor = torch.rand(num_images, 20, 30) - image_sizes = [(10, 10), (20, 30)] - images = ImageList(images_tensor, image_sizes) - num_channels = 1024 - features = {"res4": torch.rand(num_images, num_channels, 1, 2)} - feature_shape = {"res4": ShapeSpec(channels=num_channels, stride=16)} - - image_shape = (15, 15) - gt_boxes0 = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) - gt_instance0 = Instances(image_shape) - gt_instance0.gt_boxes = Boxes(gt_boxes0) - gt_instance0.gt_classes = torch.tensor([2, 1]) - gt_instance0.gt_masks = BitMasks(torch.rand((2,) + image_shape) > 0.5) - gt_boxes1 = torch.tensor([[1, 5, 2, 8], [7, 3, 10, 5]], dtype=torch.float32) - gt_instance1 = Instances(image_shape) - gt_instance1.gt_boxes = Boxes(gt_boxes1) - gt_instance1.gt_classes = torch.tensor([1, 2]) - gt_instance1.gt_masks = BitMasks(torch.rand((2,) + image_shape) > 0.5) - gt_instances = [gt_instance0, gt_instance1] - - proposal_generator = build_proposal_generator(cfg, feature_shape) - roi_heads = StandardROIHeads(cfg, feature_shape) - - with EventStorage(): # capture events in a new storage to discard them - proposals, proposal_losses = proposal_generator(images, features, gt_instances) - _, detector_losses = roi_heads(images, features, proposals, gt_instances) - - detector_losses.update(proposal_losses) - expected_losses = { - "loss_cls": 4.5253729820251465, - "loss_box_reg": 0.009785720147192478, - "loss_mask": 0.693184494972229, - "loss_rpn_cls": 0.08186662942171097, - "loss_rpn_loc": 0.1104838103055954, - } - succ = all( - torch.allclose(detector_losses[name], torch.tensor(expected_losses.get(name, 0.0))) - for name in detector_losses.keys() - ) - self.assertTrue( - succ, - "Losses has changed! New losses: {}".format( - {k: v.item() for k, v in detector_losses.items()} - ), - ) - - def test_rroi_heads(self): - torch.manual_seed(121) - cfg = get_cfg() - cfg.MODEL.PROPOSAL_GENERATOR.NAME = "RRPN" - cfg.MODEL.ANCHOR_GENERATOR.NAME = "RotatedAnchorGenerator" - cfg.MODEL.ROI_HEADS.NAME = "RROIHeads" - cfg.MODEL.ROI_BOX_HEAD.NAME = "FastRCNNConvFCHead" - cfg.MODEL.ROI_BOX_HEAD.NUM_FC = 2 - cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1, 1) - cfg.MODEL.RPN.HEAD_NAME = "StandardRPNHead" - cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE = "ROIAlignRotated" - cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5, 1) - num_images = 2 - images_tensor = torch.rand(num_images, 20, 30) - image_sizes = [(10, 10), (20, 30)] - images = ImageList(images_tensor, image_sizes) - num_channels = 1024 - features = {"res4": torch.rand(num_images, num_channels, 1, 2)} - feature_shape = {"res4": ShapeSpec(channels=num_channels, stride=16)} - - image_shape = (15, 15) - gt_boxes0 = torch.tensor([[2, 2, 2, 2, 30], [4, 4, 4, 4, 0]], dtype=torch.float32) - gt_instance0 = Instances(image_shape) - gt_instance0.gt_boxes = RotatedBoxes(gt_boxes0) - gt_instance0.gt_classes = torch.tensor([2, 1]) - gt_boxes1 = torch.tensor([[1.5, 5.5, 1, 3, 0], [8.5, 4, 3, 2, -50]], dtype=torch.float32) - gt_instance1 = Instances(image_shape) - gt_instance1.gt_boxes = RotatedBoxes(gt_boxes1) - gt_instance1.gt_classes = torch.tensor([1, 2]) - gt_instances = [gt_instance0, gt_instance1] - - proposal_generator = build_proposal_generator(cfg, feature_shape) - roi_heads = build_roi_heads(cfg, feature_shape) - - with EventStorage(): # capture events in a new storage to discard them - proposals, proposal_losses = proposal_generator(images, features, gt_instances) - _, detector_losses = roi_heads(images, features, proposals, gt_instances) - - detector_losses.update(proposal_losses) - expected_losses = { - "loss_cls": 4.365657806396484, - "loss_box_reg": 0.0015851043863222003, - "loss_rpn_cls": 0.2427729219198227, - "loss_rpn_loc": 0.3646621108055115, - } - succ = all( - torch.allclose(detector_losses[name], torch.tensor(expected_losses.get(name, 0.0))) - for name in detector_losses.keys() - ) - self.assertTrue( - succ, - "Losses has changed! New losses: {}".format( - {k: v.item() for k, v in detector_losses.items()} - ), - ) - - def test_box_head_scriptability(self): - input_shape = ShapeSpec(channels=1024, height=14, width=14) - box_features = torch.randn(4, 1024, 14, 14) - - box_head = FastRCNNConvFCHead( - input_shape, conv_dims=[512, 512], fc_dims=[1024, 1024] - ).eval() - script_box_head = torch.jit.script(box_head) - - origin_output = box_head(box_features) - script_output = script_box_head(box_features) - self.assertTrue(torch.equal(origin_output, script_output)) - - def test_mask_head_scriptability(self): - input_shape = ShapeSpec(channels=1024) - mask_features = torch.randn(4, 1024, 14, 14) - - image_shapes = [(10, 10), (15, 15)] - pred_instance0 = Instances(image_shapes[0]) - pred_classes0 = torch.tensor([1, 2, 3], dtype=torch.int64) - pred_instance0.pred_classes = pred_classes0 - pred_instance1 = Instances(image_shapes[1]) - pred_classes1 = torch.tensor([4], dtype=torch.int64) - pred_instance1.pred_classes = pred_classes1 - - mask_head = MaskRCNNConvUpsampleHead( - input_shape, num_classes=80, conv_dims=[256, 256] - ).eval() - # pred_instance will be in-place changed during the inference - # process of `MaskRCNNConvUpsampleHead` - origin_outputs = mask_head(mask_features, deepcopy([pred_instance0, pred_instance1])) - - fields = {"pred_masks": torch.Tensor, "pred_classes": torch.Tensor} - with freeze_training_mode(mask_head), patch_instances(fields) as NewInstances: - sciript_mask_head = torch.jit.script(mask_head) - pred_instance0 = NewInstances.from_instances(pred_instance0) - pred_instance1 = NewInstances.from_instances(pred_instance1) - script_outputs = sciript_mask_head(mask_features, [pred_instance0, pred_instance1]) - - for origin_ins, script_ins in zip(origin_outputs, script_outputs): - assert_instances_allclose(origin_ins, script_ins, rtol=0) - - def test_keypoint_head_scriptability(self): - input_shape = ShapeSpec(channels=1024, height=14, width=14) - keypoint_features = torch.randn(4, 1024, 14, 14) - - image_shapes = [(10, 10), (15, 15)] - pred_boxes0 = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6], [1, 5, 2, 8]], dtype=torch.float32) - pred_instance0 = Instances(image_shapes[0]) - pred_instance0.pred_boxes = Boxes(pred_boxes0) - pred_boxes1 = torch.tensor([[7, 3, 10, 5]], dtype=torch.float32) - pred_instance1 = Instances(image_shapes[1]) - pred_instance1.pred_boxes = Boxes(pred_boxes1) - - keypoint_head = KRCNNConvDeconvUpsampleHead( - input_shape, num_keypoints=17, conv_dims=[512, 512] - ).eval() - origin_outputs = keypoint_head( - keypoint_features, deepcopy([pred_instance0, pred_instance1]) - ) - - fields = { - "pred_boxes": Boxes, - "pred_keypoints": torch.Tensor, - "pred_keypoint_heatmaps": torch.Tensor, - } - with freeze_training_mode(keypoint_head), patch_instances(fields) as NewInstances: - script_keypoint_head = torch.jit.script(keypoint_head) - pred_instance0 = NewInstances.from_instances(pred_instance0) - pred_instance1 = NewInstances.from_instances(pred_instance1) - script_outputs = script_keypoint_head( - keypoint_features, [pred_instance0, pred_instance1] - ) - - for origin_ins, script_ins in zip(origin_outputs, script_outputs): - assert_instances_allclose(origin_ins, script_ins, rtol=0) - - def test_StandardROIHeads_scriptability(self): - cfg = get_cfg() - cfg.MODEL.ROI_BOX_HEAD.NAME = "FastRCNNConvFCHead" - cfg.MODEL.ROI_BOX_HEAD.NUM_FC = 2 - cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE = "ROIAlignV2" - cfg.MODEL.ROI_BOX_HEAD.BBOX_REG_WEIGHTS = (10, 10, 5, 5) - cfg.MODEL.MASK_ON = True - cfg.MODEL.ROI_HEADS.NMS_THRESH_TEST = 0.01 - cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.01 - num_images = 2 - images_tensor = torch.rand(num_images, 20, 30) - image_sizes = [(10, 10), (20, 30)] - images = ImageList(images_tensor, image_sizes) - num_channels = 1024 - features = {"res4": torch.rand(num_images, num_channels, 1, 2)} - feature_shape = {"res4": ShapeSpec(channels=num_channels, stride=16)} - - roi_heads = StandardROIHeads(cfg, feature_shape).eval() - - proposal0 = Instances(image_sizes[0]) - proposal_boxes0 = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) - proposal0.proposal_boxes = Boxes(proposal_boxes0) - proposal0.objectness_logits = torch.tensor([0.5, 0.7], dtype=torch.float32) - - proposal1 = Instances(image_sizes[1]) - proposal_boxes1 = torch.tensor([[1, 5, 2, 8], [7, 3, 10, 5]], dtype=torch.float32) - proposal1.proposal_boxes = Boxes(proposal_boxes1) - proposal1.objectness_logits = torch.tensor([0.1, 0.9], dtype=torch.float32) - proposals = [proposal0, proposal1] - - pred_instances, _ = roi_heads(images, features, proposals) - fields = { - "objectness_logits": torch.Tensor, - "proposal_boxes": Boxes, - "pred_classes": torch.Tensor, - "scores": torch.Tensor, - "pred_masks": torch.Tensor, - "pred_boxes": Boxes, - "pred_keypoints": torch.Tensor, - "pred_keypoint_heatmaps": torch.Tensor, - } - with freeze_training_mode(roi_heads), patch_instances(fields) as new_instances: - proposal0 = new_instances.from_instances(proposal0) - proposal1 = new_instances.from_instances(proposal1) - proposals = [proposal0, proposal1] - scripted_rot_heads = torch.jit.script(roi_heads) - scripted_pred_instances, _ = scripted_rot_heads(images, features, proposals) - - for instance, scripted_instance in zip(pred_instances, scripted_pred_instances): - assert_instances_allclose(instance, scripted_instance, rtol=0) - - def test_PointRend_mask_head_tracing(self): - cfg = model_zoo.get_config("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml") - point_rend.add_pointrend_config(cfg) - cfg.MODEL.ROI_HEADS.IN_FEATURES = ["p2", "p3"] - cfg.MODEL.ROI_MASK_HEAD.NAME = "PointRendMaskHead" - cfg.MODEL.ROI_MASK_HEAD.POOLER_TYPE = "" - cfg.MODEL.ROI_MASK_HEAD.POINT_HEAD_ON = True - chan = 256 - head = point_rend.PointRendMaskHead( - cfg, - { - "p2": ShapeSpec(channels=chan, stride=4), - "p3": ShapeSpec(channels=chan, stride=8), - }, - ) - - def gen_inputs(h, w, N): - p2 = torch.rand(1, chan, h, w) - p3 = torch.rand(1, chan, h // 2, w // 2) - boxes = random_boxes(N, max_coord=h) - return p2, p3, boxes - - class Wrap(nn.ModuleDict): - def forward(self, p2, p3, boxes): - features = { - "p2": p2, - "p3": p3, - } - inst = Instances((p2.shape[2] * 4, p2.shape[3] * 4)) - inst.pred_boxes = Boxes(boxes) - inst.pred_classes = torch.zeros(inst.__len__(), dtype=torch.long) - out = self.head(features, [inst])[0] - return out.pred_masks - - model = Wrap({"head": head}) - model.eval() - with torch.no_grad(), patch_builtin_len(): - traced = torch.jit.trace(model, gen_inputs(302, 208, 20)) - inputs = gen_inputs(100, 120, 30) - out_eager = model(*inputs) - out_trace = traced(*inputs) - self.assertTrue(torch.allclose(out_eager, out_trace)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_roi_pooler.py b/preprocess/detectron2/tests/modeling/test_roi_pooler.py deleted file mode 100644 index e1d7c1c689cad32d8b8566e5d497341a5f3f5a36..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_roi_pooler.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import torch - -from detectron2.modeling.poolers import ROIPooler -from detectron2.structures import Boxes, RotatedBoxes -from detectron2.utils.testing import random_boxes - -logger = logging.getLogger(__name__) - - -class TestROIPooler(unittest.TestCase): - def _test_roialignv2_roialignrotated_match(self, device): - pooler_resolution = 14 - canonical_level = 4 - canonical_scale_factor = 2**canonical_level - pooler_scales = (1.0 / canonical_scale_factor,) - sampling_ratio = 0 - - N, C, H, W = 2, 4, 10, 8 - N_rois = 10 - std = 11 - mean = 0 - feature = (torch.rand(N, C, H, W) - 0.5) * 2 * std + mean - - features = [feature.to(device)] - - rois = [] - rois_rotated = [] - for _ in range(N): - boxes = random_boxes(N_rois, W * canonical_scale_factor) - rotated_boxes = torch.zeros(N_rois, 5) - rotated_boxes[:, 0] = (boxes[:, 0] + boxes[:, 2]) / 2.0 - rotated_boxes[:, 1] = (boxes[:, 1] + boxes[:, 3]) / 2.0 - rotated_boxes[:, 2] = boxes[:, 2] - boxes[:, 0] - rotated_boxes[:, 3] = boxes[:, 3] - boxes[:, 1] - rois.append(Boxes(boxes).to(device)) - rois_rotated.append(RotatedBoxes(rotated_boxes).to(device)) - - roialignv2_pooler = ROIPooler( - output_size=pooler_resolution, - scales=pooler_scales, - sampling_ratio=sampling_ratio, - pooler_type="ROIAlignV2", - ) - - roialignv2_out = roialignv2_pooler(features, rois) - - roialignrotated_pooler = ROIPooler( - output_size=pooler_resolution, - scales=pooler_scales, - sampling_ratio=sampling_ratio, - pooler_type="ROIAlignRotated", - ) - - roialignrotated_out = roialignrotated_pooler(features, rois_rotated) - - self.assertTrue(torch.allclose(roialignv2_out, roialignrotated_out, atol=1e-4)) - - def test_roialignv2_roialignrotated_match_cpu(self): - self._test_roialignv2_roialignrotated_match(device="cpu") - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_roialignv2_roialignrotated_match_cuda(self): - self._test_roialignv2_roialignrotated_match(device="cuda") - - def _test_scriptability(self, device): - pooler_resolution = 14 - canonical_level = 4 - canonical_scale_factor = 2**canonical_level - pooler_scales = (1.0 / canonical_scale_factor,) - sampling_ratio = 0 - - N, C, H, W = 2, 4, 10, 8 - N_rois = 10 - std = 11 - mean = 0 - feature = (torch.rand(N, C, H, W) - 0.5) * 2 * std + mean - - features = [feature.to(device)] - - rois = [] - for _ in range(N): - boxes = random_boxes(N_rois, W * canonical_scale_factor) - - rois.append(Boxes(boxes).to(device)) - - roialignv2_pooler = ROIPooler( - output_size=pooler_resolution, - scales=pooler_scales, - sampling_ratio=sampling_ratio, - pooler_type="ROIAlignV2", - ) - - roialignv2_out = roialignv2_pooler(features, rois) - scripted_roialignv2_out = torch.jit.script(roialignv2_pooler)(features, rois) - self.assertTrue(torch.equal(roialignv2_out, scripted_roialignv2_out)) - - def test_scriptability_cpu(self): - self._test_scriptability(device="cpu") - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_scriptability_gpu(self): - self._test_scriptability(device="cuda") - - def test_no_images(self): - N, C, H, W = 0, 32, 32, 32 - feature = torch.rand(N, C, H, W) - 0.5 - features = [feature] - pooler = ROIPooler( - output_size=14, scales=(1.0,), sampling_ratio=0.0, pooler_type="ROIAlignV2" - ) - output = pooler.forward(features, []) - self.assertEqual(output.shape, (0, C, 14, 14)) - - def test_roi_pooler_tracing(self): - class Model(torch.nn.Module): - def __init__(self, roi): - super(Model, self).__init__() - self.roi = roi - - def forward(self, x, boxes): - return self.roi(x, [Boxes(boxes)]) - - pooler_resolution = 14 - canonical_level = 4 - canonical_scale_factor = 2**canonical_level - pooler_scales = (1.0 / canonical_scale_factor, 0.5 / canonical_scale_factor) - sampling_ratio = 0 - - N, C, H, W = 1, 4, 10, 8 - N_rois = 10 - std = 11 - mean = 0 - feature = (torch.rand(N, C, H, W) - 0.5) * 2 * std + mean - feature = [feature, feature] - - rois = random_boxes(N_rois, W * canonical_scale_factor) - # Add one larger box so that this level has only one box. - # This may trigger the bug https://github.com/pytorch/pytorch/issues/49852 - # that we shall workaround. - rois = torch.cat([rois, torch.tensor([[0, 0, 448, 448]])]) - - model = Model( - ROIPooler( - output_size=pooler_resolution, - scales=pooler_scales, - sampling_ratio=sampling_ratio, - pooler_type="ROIAlign", - ) - ) - - with torch.no_grad(): - func = torch.jit.trace(model, (feature, rois)) - o = func(feature, rois) - self.assertEqual(o.shape, (11, 4, 14, 14)) - o = func(feature, rois[:5]) - self.assertEqual(o.shape, (5, 4, 14, 14)) - o = func(feature, random_boxes(20, W * canonical_scale_factor)) - self.assertEqual(o.shape, (20, 4, 14, 14)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/modeling/test_rpn.py b/preprocess/detectron2/tests/modeling/test_rpn.py deleted file mode 100644 index f14faae56e580d3d4762d31273b9f65c5774346b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/modeling/test_rpn.py +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest -import torch - -from detectron2.config import get_cfg -from detectron2.export import scripting_with_instances -from detectron2.layers import ShapeSpec -from detectron2.modeling.backbone import build_backbone -from detectron2.modeling.proposal_generator import RPN, build_proposal_generator -from detectron2.modeling.proposal_generator.proposal_utils import ( - add_ground_truth_to_proposals, - find_top_rpn_proposals, -) -from detectron2.structures import Boxes, ImageList, Instances, RotatedBoxes -from detectron2.utils.events import EventStorage - -logger = logging.getLogger(__name__) - - -class RPNTest(unittest.TestCase): - def get_gt_and_features(self): - num_images = 2 - images_tensor = torch.rand(num_images, 20, 30) - image_sizes = [(10, 10), (20, 30)] - images = ImageList(images_tensor, image_sizes) - image_shape = (15, 15) - num_channels = 1024 - features = {"res4": torch.rand(num_images, num_channels, 1, 2)} - gt_boxes = torch.tensor([[1, 1, 3, 3], [2, 2, 6, 6]], dtype=torch.float32) - gt_instances = Instances(image_shape) - gt_instances.gt_boxes = Boxes(gt_boxes) - return (gt_instances, features, images, image_sizes) - - def test_rpn(self): - torch.manual_seed(121) - cfg = get_cfg() - backbone = build_backbone(cfg) - proposal_generator = RPN(cfg, backbone.output_shape()) - (gt_instances, features, images, image_sizes) = self.get_gt_and_features() - with EventStorage(): # capture events in a new storage to discard them - proposals, proposal_losses = proposal_generator( - images, features, [gt_instances[0], gt_instances[1]] - ) - - expected_losses = { - "loss_rpn_cls": torch.tensor(0.08011703193), - "loss_rpn_loc": torch.tensor(0.101470276), - } - for name in expected_losses.keys(): - err_msg = "proposal_losses[{}] = {}, expected losses = {}".format( - name, proposal_losses[name], expected_losses[name] - ) - self.assertTrue(torch.allclose(proposal_losses[name], expected_losses[name]), err_msg) - - self.assertEqual(len(proposals), len(image_sizes)) - for proposal, im_size in zip(proposals, image_sizes): - self.assertEqual(proposal.image_size, im_size) - - expected_proposal_box = torch.tensor([[0, 0, 10, 10], [7.2702, 0, 10, 10]]) - expected_objectness_logit = torch.tensor([0.1596, -0.0007]) - self.assertTrue( - torch.allclose(proposals[0].proposal_boxes.tensor, expected_proposal_box, atol=1e-4) - ) - self.assertTrue( - torch.allclose(proposals[0].objectness_logits, expected_objectness_logit, atol=1e-4) - ) - - def verify_rpn(self, conv_dims, expected_conv_dims): - torch.manual_seed(121) - cfg = get_cfg() - cfg.MODEL.RPN.CONV_DIMS = conv_dims - backbone = build_backbone(cfg) - proposal_generator = RPN(cfg, backbone.output_shape()) - for k, conv in enumerate(proposal_generator.rpn_head.conv): - self.assertEqual(expected_conv_dims[k], conv.out_channels) - return proposal_generator - - def test_rpn_larger_num_convs(self): - conv_dims = [64, 64, 64, 64, 64] - proposal_generator = self.verify_rpn(conv_dims, conv_dims) - (gt_instances, features, images, image_sizes) = self.get_gt_and_features() - with EventStorage(): # capture events in a new storage to discard them - proposals, proposal_losses = proposal_generator( - images, features, [gt_instances[0], gt_instances[1]] - ) - expected_losses = { - "loss_rpn_cls": torch.tensor(0.08122821152), - "loss_rpn_loc": torch.tensor(0.10064548254), - } - for name in expected_losses.keys(): - err_msg = "proposal_losses[{}] = {}, expected losses = {}".format( - name, proposal_losses[name], expected_losses[name] - ) - self.assertTrue(torch.allclose(proposal_losses[name], expected_losses[name]), err_msg) - - def test_rpn_conv_dims_not_set(self): - conv_dims = [-1, -1, -1] - expected_conv_dims = [1024, 1024, 1024] - self.verify_rpn(conv_dims, expected_conv_dims) - - def test_rpn_scriptability(self): - cfg = get_cfg() - proposal_generator = RPN(cfg, {"res4": ShapeSpec(channels=1024, stride=16)}).eval() - num_images = 2 - images_tensor = torch.rand(num_images, 30, 40) - image_sizes = [(32, 32), (30, 40)] - images = ImageList(images_tensor, image_sizes) - features = {"res4": torch.rand(num_images, 1024, 1, 2)} - - fields = {"proposal_boxes": Boxes, "objectness_logits": torch.Tensor} - proposal_generator_ts = scripting_with_instances(proposal_generator, fields) - - proposals, _ = proposal_generator(images, features) - proposals_ts, _ = proposal_generator_ts(images, features) - - for proposal, proposal_ts in zip(proposals, proposals_ts): - self.assertEqual(proposal.image_size, proposal_ts.image_size) - self.assertTrue( - torch.equal(proposal.proposal_boxes.tensor, proposal_ts.proposal_boxes.tensor) - ) - self.assertTrue(torch.equal(proposal.objectness_logits, proposal_ts.objectness_logits)) - - def test_rrpn(self): - torch.manual_seed(121) - cfg = get_cfg() - cfg.MODEL.PROPOSAL_GENERATOR.NAME = "RRPN" - cfg.MODEL.ANCHOR_GENERATOR.NAME = "RotatedAnchorGenerator" - cfg.MODEL.ANCHOR_GENERATOR.SIZES = [[32, 64]] - cfg.MODEL.ANCHOR_GENERATOR.ASPECT_RATIOS = [[0.25, 1]] - cfg.MODEL.ANCHOR_GENERATOR.ANGLES = [[0, 60]] - cfg.MODEL.RPN.BBOX_REG_WEIGHTS = (1, 1, 1, 1, 1) - cfg.MODEL.RPN.HEAD_NAME = "StandardRPNHead" - backbone = build_backbone(cfg) - proposal_generator = build_proposal_generator(cfg, backbone.output_shape()) - num_images = 2 - images_tensor = torch.rand(num_images, 20, 30) - image_sizes = [(10, 10), (20, 30)] - images = ImageList(images_tensor, image_sizes) - image_shape = (15, 15) - num_channels = 1024 - features = {"res4": torch.rand(num_images, num_channels, 1, 2)} - gt_boxes = torch.tensor([[2, 2, 2, 2, 0], [4, 4, 4, 4, 0]], dtype=torch.float32) - gt_instances = Instances(image_shape) - gt_instances.gt_boxes = RotatedBoxes(gt_boxes) - with EventStorage(): # capture events in a new storage to discard them - proposals, proposal_losses = proposal_generator( - images, features, [gt_instances[0], gt_instances[1]] - ) - - expected_losses = { - "loss_rpn_cls": torch.tensor(0.04291602224), - "loss_rpn_loc": torch.tensor(0.145077362), - } - for name in expected_losses.keys(): - err_msg = "proposal_losses[{}] = {}, expected losses = {}".format( - name, proposal_losses[name], expected_losses[name] - ) - self.assertTrue(torch.allclose(proposal_losses[name], expected_losses[name]), err_msg) - - expected_proposal_box = torch.tensor( - [ - [-1.77999556, 0.78155339, 68.04367828, 14.78156471, 60.59333801], - [13.82740974, -1.50282836, 34.67269897, 29.19676590, -3.81942749], - [8.10392570, -0.99071521, 145.39100647, 32.13126373, 3.67242432], - [5.00000000, 4.57370186, 10.00000000, 9.14740372, 0.89196777], - ] - ) - - expected_objectness_logit = torch.tensor([0.10924313, 0.09881870, 0.07649877, 0.05858029]) - - torch.set_printoptions(precision=8, sci_mode=False) - - self.assertEqual(len(proposals), len(image_sizes)) - - proposal = proposals[0] - # It seems that there's some randomness in the result across different machines: - # This test can be run on a local machine for 100 times with exactly the same result, - # However, a different machine might produce slightly different results, - # thus the atol here. - err_msg = "computed proposal boxes = {}, expected {}".format( - proposal.proposal_boxes.tensor, expected_proposal_box - ) - self.assertTrue( - torch.allclose(proposal.proposal_boxes.tensor[:4], expected_proposal_box, atol=1e-5), - err_msg, - ) - - err_msg = "computed objectness logits = {}, expected {}".format( - proposal.objectness_logits, expected_objectness_logit - ) - self.assertTrue( - torch.allclose(proposal.objectness_logits[:4], expected_objectness_logit, atol=1e-5), - err_msg, - ) - - def test_find_rpn_proposals_inf(self): - N, Hi, Wi, A = 3, 3, 3, 3 - proposals = [torch.rand(N, Hi * Wi * A, 4)] - pred_logits = [torch.rand(N, Hi * Wi * A)] - pred_logits[0][1][3:5].fill_(float("inf")) - find_top_rpn_proposals(proposals, pred_logits, [(10, 10)], 0.5, 1000, 1000, 0, False) - - def test_find_rpn_proposals_tracing(self): - N, Hi, Wi, A = 3, 50, 50, 9 - proposal = torch.rand(N, Hi * Wi * A, 4) - pred_logit = torch.rand(N, Hi * Wi * A) - - def func(proposal, logit, image_size): - r = find_top_rpn_proposals( - [proposal], [logit], [image_size], 0.7, 1000, 1000, 0, False - )[0] - size = r.image_size - if not isinstance(size, torch.Tensor): - size = torch.tensor(size) - return (size, r.proposal_boxes.tensor, r.objectness_logits) - - other_inputs = [] - # test that it generalizes to other shapes - for Hi, Wi, shp in [(30, 30, 60), (10, 10, 800)]: - other_inputs.append( - ( - torch.rand(N, Hi * Wi * A, 4), - torch.rand(N, Hi * Wi * A), - torch.tensor([shp, shp]), - ) - ) - torch.jit.trace( - func, (proposal, pred_logit, torch.tensor([100, 100])), check_inputs=other_inputs - ) - - def test_append_gt_to_proposal(self): - proposals = Instances( - (10, 10), - **{ - "proposal_boxes": Boxes(torch.empty((0, 4))), - "objectness_logits": torch.tensor([]), - "custom_attribute": torch.tensor([]), - } - ) - gt_boxes = Boxes(torch.tensor([[0, 0, 1, 1]])) - - self.assertRaises(AssertionError, add_ground_truth_to_proposals, [gt_boxes], [proposals]) - - gt_instances = Instances((10, 10)) - gt_instances.gt_boxes = gt_boxes - - self.assertRaises( - AssertionError, add_ground_truth_to_proposals, [gt_instances], [proposals] - ) - - gt_instances.custom_attribute = torch.tensor([1]) - gt_instances.custom_attribute2 = torch.tensor([1]) - new_proposals = add_ground_truth_to_proposals([gt_instances], [proposals])[0] - - self.assertEqual(new_proposals.custom_attribute[0], 1) - # new proposals should only include the attributes in proposals - self.assertRaises(AttributeError, lambda: new_proposals.custom_attribute2) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/__init__.py b/preprocess/detectron2/tests/structures/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tests/structures/test_boxes.py b/preprocess/detectron2/tests/structures/test_boxes.py deleted file mode 100644 index 101191818c511cf90c3c8f2cbc55aa49295697fa..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_boxes.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import json -import math -import numpy as np -import unittest -import torch - -from detectron2.structures import Boxes, BoxMode, pairwise_ioa, pairwise_iou -from detectron2.utils.testing import reload_script_model - - -class TestBoxMode(unittest.TestCase): - def _convert_xy_to_wh(self, x): - return BoxMode.convert(x, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS) - - def _convert_xywha_to_xyxy(self, x): - return BoxMode.convert(x, BoxMode.XYWHA_ABS, BoxMode.XYXY_ABS) - - def _convert_xywh_to_xywha(self, x): - return BoxMode.convert(x, BoxMode.XYWH_ABS, BoxMode.XYWHA_ABS) - - def test_convert_int_mode(self): - BoxMode.convert([1, 2, 3, 4], 0, 1) - - def test_box_convert_list(self): - for tp in [list, tuple]: - box = tp([5.0, 5.0, 10.0, 10.0]) - output = self._convert_xy_to_wh(box) - self.assertIsInstance(output, tp) - self.assertIsInstance(output[0], float) - self.assertEqual(output, tp([5.0, 5.0, 5.0, 5.0])) - - with self.assertRaises(Exception): - self._convert_xy_to_wh([box]) - - def test_box_convert_array(self): - box = np.asarray([[5, 5, 10, 10], [1, 1, 2, 3]]) - output = self._convert_xy_to_wh(box) - self.assertEqual(output.dtype, box.dtype) - self.assertEqual(output.shape, box.shape) - self.assertTrue((output[0] == [5, 5, 5, 5]).all()) - self.assertTrue((output[1] == [1, 1, 1, 2]).all()) - - def test_box_convert_cpu_tensor(self): - box = torch.tensor([[5, 5, 10, 10], [1, 1, 2, 3]]) - output = self._convert_xy_to_wh(box) - self.assertEqual(output.dtype, box.dtype) - self.assertEqual(output.shape, box.shape) - output = output.numpy() - self.assertTrue((output[0] == [5, 5, 5, 5]).all()) - self.assertTrue((output[1] == [1, 1, 1, 2]).all()) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_box_convert_cuda_tensor(self): - box = torch.tensor([[5, 5, 10, 10], [1, 1, 2, 3]]).cuda() - output = self._convert_xy_to_wh(box) - self.assertEqual(output.dtype, box.dtype) - self.assertEqual(output.shape, box.shape) - self.assertEqual(output.device, box.device) - output = output.cpu().numpy() - self.assertTrue((output[0] == [5, 5, 5, 5]).all()) - self.assertTrue((output[1] == [1, 1, 1, 2]).all()) - - def test_box_convert_xywha_to_xyxy_list(self): - for tp in [list, tuple]: - box = tp([50, 50, 30, 20, 0]) - output = self._convert_xywha_to_xyxy(box) - self.assertIsInstance(output, tp) - self.assertEqual(output, tp([35, 40, 65, 60])) - - with self.assertRaises(Exception): - self._convert_xywha_to_xyxy([box]) - - def test_box_convert_xywha_to_xyxy_array(self): - for dtype in [np.float64, np.float32]: - box = np.asarray( - [ - [50, 50, 30, 20, 0], - [50, 50, 30, 20, 90], - [1, 1, math.sqrt(2), math.sqrt(2), -45], - ], - dtype=dtype, - ) - output = self._convert_xywha_to_xyxy(box) - self.assertEqual(output.dtype, box.dtype) - expected = np.asarray([[35, 40, 65, 60], [40, 35, 60, 65], [0, 0, 2, 2]], dtype=dtype) - self.assertTrue(np.allclose(output, expected, atol=1e-6), "output={}".format(output)) - - def test_box_convert_xywha_to_xyxy_tensor(self): - for dtype in [torch.float32, torch.float64]: - box = torch.tensor( - [ - [50, 50, 30, 20, 0], - [50, 50, 30, 20, 90], - [1, 1, math.sqrt(2), math.sqrt(2), -45], - ], - dtype=dtype, - ) - output = self._convert_xywha_to_xyxy(box) - self.assertEqual(output.dtype, box.dtype) - expected = torch.tensor([[35, 40, 65, 60], [40, 35, 60, 65], [0, 0, 2, 2]], dtype=dtype) - - self.assertTrue(torch.allclose(output, expected, atol=1e-6), "output={}".format(output)) - - def test_box_convert_xywh_to_xywha_list(self): - for tp in [list, tuple]: - box = tp([50, 50, 30, 20]) - output = self._convert_xywh_to_xywha(box) - self.assertIsInstance(output, tp) - self.assertEqual(output, tp([65, 60, 30, 20, 0])) - - with self.assertRaises(Exception): - self._convert_xywh_to_xywha([box]) - - def test_box_convert_xywh_to_xywha_array(self): - for dtype in [np.float64, np.float32]: - box = np.asarray([[30, 40, 70, 60], [30, 40, 60, 70], [-1, -1, 2, 2]], dtype=dtype) - output = self._convert_xywh_to_xywha(box) - self.assertEqual(output.dtype, box.dtype) - expected = np.asarray( - [[65, 70, 70, 60, 0], [60, 75, 60, 70, 0], [0, 0, 2, 2, 0]], dtype=dtype - ) - self.assertTrue(np.allclose(output, expected, atol=1e-6), "output={}".format(output)) - - def test_box_convert_xywh_to_xywha_tensor(self): - for dtype in [torch.float32, torch.float64]: - box = torch.tensor([[30, 40, 70, 60], [30, 40, 60, 70], [-1, -1, 2, 2]], dtype=dtype) - output = self._convert_xywh_to_xywha(box) - self.assertEqual(output.dtype, box.dtype) - expected = torch.tensor( - [[65, 70, 70, 60, 0], [60, 75, 60, 70, 0], [0, 0, 2, 2, 0]], dtype=dtype - ) - - self.assertTrue(torch.allclose(output, expected, atol=1e-6), "output={}".format(output)) - - def test_json_serializable(self): - payload = {"box_mode": BoxMode.XYWH_REL} - try: - json.dumps(payload) - except Exception: - self.fail("JSON serialization failed") - - def test_json_deserializable(self): - payload = '{"box_mode": 2}' - obj = json.loads(payload) - try: - obj["box_mode"] = BoxMode(obj["box_mode"]) - except Exception: - self.fail("JSON deserialization failed") - - -class TestBoxIOU(unittest.TestCase): - def create_boxes(self): - boxes1 = torch.tensor([[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]]) - - boxes2 = torch.tensor( - [ - [0.0, 0.0, 1.0, 1.0], - [0.0, 0.0, 0.5, 1.0], - [0.0, 0.0, 1.0, 0.5], - [0.0, 0.0, 0.5, 0.5], - [0.5, 0.5, 1.0, 1.0], - [0.5, 0.5, 1.5, 1.5], - ] - ) - return boxes1, boxes2 - - def test_pairwise_iou(self): - boxes1, boxes2 = self.create_boxes() - expected_ious = torch.tensor( - [ - [1.0, 0.5, 0.5, 0.25, 0.25, 0.25 / (2 - 0.25)], - [1.0, 0.5, 0.5, 0.25, 0.25, 0.25 / (2 - 0.25)], - ] - ) - - ious = pairwise_iou(Boxes(boxes1), Boxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_ioa(self): - boxes1, boxes2 = self.create_boxes() - expected_ioas = torch.tensor( - [[1.0, 1.0, 1.0, 1.0, 1.0, 0.25], [1.0, 1.0, 1.0, 1.0, 1.0, 0.25]] - ) - ioas = pairwise_ioa(Boxes(boxes1), Boxes(boxes2)) - self.assertTrue(torch.allclose(ioas, expected_ioas)) - - -class TestBoxes(unittest.TestCase): - def test_empty_cat(self): - x = Boxes.cat([]) - self.assertTrue(x.tensor.shape, (0, 4)) - - def test_to(self): - x = Boxes(torch.rand(3, 4)) - self.assertEqual(x.to(device="cpu").tensor.device.type, "cpu") - - def test_scriptability(self): - def func(x): - boxes = Boxes(x) - test = boxes.to(torch.device("cpu")).tensor - return boxes.area(), test - - f = torch.jit.script(func) - f = reload_script_model(f) - f(torch.rand((3, 4))) - - data = torch.rand((3, 4)) - - def func_cat(x: torch.Tensor): - boxes1 = Boxes(x) - boxes2 = Boxes(x) - # boxes3 = Boxes.cat([boxes1, boxes2]) # this is not supported by torchsript for now. - boxes3 = boxes1.cat([boxes1, boxes2]) - return boxes3 - - f = torch.jit.script(func_cat) - script_box = f(data) - self.assertTrue(torch.equal(torch.cat([data, data]), script_box.tensor)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/test_imagelist.py b/preprocess/detectron2/tests/structures/test_imagelist.py deleted file mode 100644 index e446e44a37f5d8f9a68362e4b93a291d314d5d68..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_imagelist.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import unittest -from typing import List, Sequence, Tuple -import torch - -from detectron2.structures import ImageList - - -class TestImageList(unittest.TestCase): - def test_imagelist_padding_tracing(self): - # test that the trace does not contain hard-coded constant sizes - def to_imagelist(tensors: Sequence[torch.Tensor]): - image_list = ImageList.from_tensors(tensors, 4) - return image_list.tensor, image_list.image_sizes - - def _tensor(*shape): - return torch.ones(shape, dtype=torch.float32) - - # test CHW (inputs needs padding vs. no padding) - for shape in [(3, 10, 10), (3, 12, 12)]: - func = torch.jit.trace(to_imagelist, ([_tensor(*shape)],)) - tensor, image_sizes = func([_tensor(3, 15, 20)]) - self.assertEqual(tensor.shape, (1, 3, 16, 20), tensor.shape) - self.assertEqual(image_sizes[0].tolist(), [15, 20], image_sizes[0]) - - # test HW - func = torch.jit.trace(to_imagelist, ([_tensor(10, 10)],)) - tensor, image_sizes = func([_tensor(15, 20)]) - self.assertEqual(tensor.shape, (1, 16, 20), tensor.shape) - self.assertEqual(image_sizes[0].tolist(), [15, 20], image_sizes[0]) - - # test 2x CHW - func = torch.jit.trace( - to_imagelist, - ([_tensor(3, 16, 10), _tensor(3, 13, 11)],), - ) - tensor, image_sizes = func([_tensor(3, 25, 20), _tensor(3, 10, 10)]) - self.assertEqual(tensor.shape, (2, 3, 28, 20), tensor.shape) - self.assertEqual(image_sizes[0].tolist(), [25, 20], image_sizes[0]) - self.assertEqual(image_sizes[1].tolist(), [10, 10], image_sizes[1]) - # support calling with different spatial sizes, but not with different #images - - def test_imagelist_scriptability(self): - image_nums = 2 - image_tensor = torch.randn((image_nums, 10, 20), dtype=torch.float32) - image_shape = [(10, 20)] * image_nums - - def f(image_tensor, image_shape: List[Tuple[int, int]]): - return ImageList(image_tensor, image_shape) - - ret = f(image_tensor, image_shape) - ret_script = torch.jit.script(f)(image_tensor, image_shape) - - self.assertEqual(len(ret), len(ret_script)) - for i in range(image_nums): - self.assertTrue(torch.equal(ret[i], ret_script[i])) - - def test_imagelist_from_tensors_scriptability(self): - image_tensor_0 = torch.randn(10, 20, dtype=torch.float32) - image_tensor_1 = torch.randn(12, 22, dtype=torch.float32) - inputs = [image_tensor_0, image_tensor_1] - - def f(image_tensor: List[torch.Tensor]): - return ImageList.from_tensors(image_tensor, 10) - - ret = f(inputs) - ret_script = torch.jit.script(f)(inputs) - - self.assertEqual(len(ret), len(ret_script)) - self.assertTrue(torch.equal(ret.tensor, ret_script.tensor)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/test_instances.py b/preprocess/detectron2/tests/structures/test_instances.py deleted file mode 100644 index a352f74313ae9b2b7a42398f0ef4606fcb4a610c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_instances.py +++ /dev/null @@ -1,219 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest -import torch -from torch import Tensor - -from detectron2.export.torchscript import patch_instances -from detectron2.structures import Boxes, Instances -from detectron2.utils.testing import convert_scripted_instances - - -class TestInstances(unittest.TestCase): - def test_int_indexing(self): - attr1 = torch.tensor([[0.0, 0.0, 1.0], [0.0, 0.0, 0.5], [0.0, 0.0, 1.0], [0.0, 0.5, 0.5]]) - attr2 = torch.tensor([0.1, 0.2, 0.3, 0.4]) - instances = Instances((100, 100)) - instances.attr1 = attr1 - instances.attr2 = attr2 - for i in range(-len(instances), len(instances)): - inst = instances[i] - self.assertEqual((inst.attr1 == attr1[i]).all(), True) - self.assertEqual((inst.attr2 == attr2[i]).all(), True) - - self.assertRaises(IndexError, lambda: instances[len(instances)]) - self.assertRaises(IndexError, lambda: instances[-len(instances) - 1]) - - def test_script_new_fields(self): - def get_mask(x: Instances) -> torch.Tensor: - return x.mask - - class f(torch.nn.Module): - def forward(self, x: Instances): - proposal_boxes = x.proposal_boxes # noqa F841 - objectness_logits = x.objectness_logits # noqa F841 - return x - - class g(torch.nn.Module): - def forward(self, x: Instances): - return get_mask(x) - - class g2(torch.nn.Module): - def __init__(self): - super().__init__() - self.g = g() - - def forward(self, x: Instances): - proposal_boxes = x.proposal_boxes # noqa F841 - return x, self.g(x) - - fields = {"proposal_boxes": Boxes, "objectness_logits": Tensor} - with patch_instances(fields): - torch.jit.script(f()) - - # can't script anymore after exiting the context - with self.assertRaises(Exception): - # will create a ConcreteType for g - torch.jit.script(g2()) - - new_fields = {"mask": Tensor} - with patch_instances(new_fields): - # will compile g with a different Instances; this should pass - torch.jit.script(g()) - with self.assertRaises(Exception): - torch.jit.script(g2()) - - new_fields = {"mask": Tensor, "proposal_boxes": Boxes} - with patch_instances(new_fields) as NewInstances: - # get_mask will be compiled with a different Instances; this should pass - scripted_g2 = torch.jit.script(g2()) - x = NewInstances((3, 4)) - x.mask = torch.rand(3) - x.proposal_boxes = Boxes(torch.rand(3, 4)) - scripted_g2(x) # it should accept the new Instances object and run successfully - - def test_script_access_fields(self): - class f(torch.nn.Module): - def forward(self, x: Instances): - proposal_boxes = x.proposal_boxes - objectness_logits = x.objectness_logits - return proposal_boxes.tensor + objectness_logits - - fields = {"proposal_boxes": Boxes, "objectness_logits": Tensor} - with patch_instances(fields): - torch.jit.script(f()) - - def test_script_len(self): - class f(torch.nn.Module): - def forward(self, x: Instances): - return len(x) - - class g(torch.nn.Module): - def forward(self, x: Instances): - return len(x) - - image_shape = (15, 15) - - fields = {"proposal_boxes": Boxes} - with patch_instances(fields) as new_instance: - script_module = torch.jit.script(f()) - x = new_instance(image_shape) - with self.assertRaises(Exception): - script_module(x) - box_tensors = torch.tensor([[5, 5, 10, 10], [1, 1, 2, 3]]) - x.proposal_boxes = Boxes(box_tensors) - length = script_module(x) - self.assertEqual(length, 2) - - fields = {"objectness_logits": Tensor} - with patch_instances(fields) as new_instance: - script_module = torch.jit.script(g()) - x = new_instance(image_shape) - objectness_logits = torch.tensor([1.0]).reshape(1, 1) - x.objectness_logits = objectness_logits - length = script_module(x) - self.assertEqual(length, 1) - - def test_script_has(self): - class f(torch.nn.Module): - def forward(self, x: Instances): - return x.has("proposal_boxes") - - image_shape = (15, 15) - fields = {"proposal_boxes": Boxes} - with patch_instances(fields) as new_instance: - script_module = torch.jit.script(f()) - x = new_instance(image_shape) - self.assertFalse(script_module(x)) - - box_tensors = torch.tensor([[5, 5, 10, 10], [1, 1, 2, 3]]) - x.proposal_boxes = Boxes(box_tensors) - self.assertTrue(script_module(x)) - - def test_script_to(self): - class f(torch.nn.Module): - def forward(self, x: Instances): - return x.to(torch.device("cpu")) - - image_shape = (15, 15) - fields = {"proposal_boxes": Boxes, "a": Tensor} - with patch_instances(fields) as new_instance: - script_module = torch.jit.script(f()) - x = new_instance(image_shape) - script_module(x) - - box_tensors = torch.tensor([[5, 5, 10, 10], [1, 1, 2, 3]]) - x.proposal_boxes = Boxes(box_tensors) - x.a = box_tensors - script_module(x) - - def test_script_getitem(self): - class f(torch.nn.Module): - def forward(self, x: Instances, idx): - return x[idx] - - image_shape = (15, 15) - fields = {"proposal_boxes": Boxes, "a": Tensor} - inst = Instances(image_shape) - inst.proposal_boxes = Boxes(torch.rand(4, 4)) - inst.a = torch.rand(4, 10) - idx = torch.tensor([True, False, True, False]) - with patch_instances(fields) as new_instance: - script_module = torch.jit.script(f()) - - out = f()(inst, idx) - out_scripted = script_module(new_instance.from_instances(inst), idx) - self.assertTrue( - torch.equal(out.proposal_boxes.tensor, out_scripted.proposal_boxes.tensor) - ) - self.assertTrue(torch.equal(out.a, out_scripted.a)) - - def test_from_to_instances(self): - orig = Instances((30, 30)) - orig.proposal_boxes = Boxes(torch.rand(3, 4)) - - fields = {"proposal_boxes": Boxes, "a": Tensor} - with patch_instances(fields) as NewInstances: - # convert to NewInstances and back - new1 = NewInstances.from_instances(orig) - new2 = convert_scripted_instances(new1) - self.assertTrue(torch.equal(orig.proposal_boxes.tensor, new1.proposal_boxes.tensor)) - self.assertTrue(torch.equal(orig.proposal_boxes.tensor, new2.proposal_boxes.tensor)) - - def test_script_init_args(self): - def f(x: Tensor): - image_shape = (15, 15) - # __init__ can take arguments - inst = Instances(image_shape, a=x, proposal_boxes=Boxes(x)) - inst2 = Instances(image_shape, a=x) - return inst.a, inst2.a - - fields = {"proposal_boxes": Boxes, "a": Tensor} - with patch_instances(fields): - script_f = torch.jit.script(f) - x = torch.randn(3, 4) - outputs = script_f(x) - self.assertTrue(torch.equal(outputs[0], x)) - self.assertTrue(torch.equal(outputs[1], x)) - - def test_script_cat(self): - def f(x: Tensor): - image_shape = (15, 15) - # __init__ can take arguments - inst = Instances(image_shape, a=x) - inst2 = Instances(image_shape, a=x) - - inst3 = Instances(image_shape, proposal_boxes=Boxes(x)) - return inst.cat([inst, inst2]), inst3.cat([inst3, inst3]) - - fields = {"proposal_boxes": Boxes, "a": Tensor} - with patch_instances(fields): - script_f = torch.jit.script(f) - x = torch.randn(3, 4) - output, output2 = script_f(x) - self.assertTrue(torch.equal(output.a, torch.cat([x, x]))) - self.assertFalse(output.has("proposal_boxes")) - self.assertTrue(torch.equal(output2.proposal_boxes.tensor, torch.cat([x, x]))) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/test_keypoints.py b/preprocess/detectron2/tests/structures/test_keypoints.py deleted file mode 100644 index adc616e42341343e503afcbe181dbfae3f8ea063..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_keypoints.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest -import torch - -from detectron2.structures.keypoints import Keypoints - - -class TestKeypoints(unittest.TestCase): - def test_cat_keypoints(self): - keypoints1 = Keypoints(torch.rand(2, 21, 3)) - keypoints2 = Keypoints(torch.rand(4, 21, 3)) - - cat_keypoints = keypoints1.cat([keypoints1, keypoints2]) - self.assertTrue(torch.all(cat_keypoints.tensor[:2] == keypoints1.tensor).item()) - self.assertTrue(torch.all(cat_keypoints.tensor[2:] == keypoints2.tensor).item()) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/test_masks.py b/preprocess/detectron2/tests/structures/test_masks.py deleted file mode 100644 index 7991eb0b35724f2f2f402d788a273d68b7cad5f2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_masks.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest -import torch - -from detectron2.structures.masks import BitMasks, PolygonMasks, polygons_to_bitmask - - -class TestBitMask(unittest.TestCase): - def test_get_bounding_box(self): - masks = torch.tensor( - [ - [ - [False, False, False, True], - [False, False, True, True], - [False, True, True, False], - [False, True, True, False], - ], - [ - [False, False, False, False], - [False, False, True, False], - [False, True, True, False], - [False, True, True, False], - ], - torch.zeros(4, 4), - ] - ) - bitmask = BitMasks(masks) - box_true = torch.tensor([[1, 0, 4, 4], [1, 1, 3, 4], [0, 0, 0, 0]], dtype=torch.float32) - box = bitmask.get_bounding_boxes() - self.assertTrue(torch.all(box.tensor == box_true).item()) - - for box in box_true: - poly = box[[0, 1, 2, 1, 2, 3, 0, 3]].numpy() - mask = polygons_to_bitmask([poly], 4, 4) - reconstruct_box = BitMasks(mask[None, :, :]).get_bounding_boxes()[0].tensor - self.assertTrue(torch.all(box == reconstruct_box).item()) - - reconstruct_box = PolygonMasks([[poly]]).get_bounding_boxes()[0].tensor - self.assertTrue(torch.all(box == reconstruct_box).item()) - - def test_from_empty_polygons(self): - masks = BitMasks.from_polygon_masks([], 100, 100) - self.assertEqual(masks.tensor.shape, (0, 100, 100)) - - def test_getitem(self): - masks = BitMasks(torch.ones(3, 10, 10)) - self.assertEqual(masks[1].tensor.shape, (1, 10, 10)) - self.assertEqual(masks[1:3].tensor.shape, (2, 10, 10)) - self.assertEqual(masks[torch.tensor([True, False, False])].tensor.shape, (1, 10, 10)) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/structures/test_rotated_boxes.py b/preprocess/detectron2/tests/structures/test_rotated_boxes.py deleted file mode 100644 index 478f034a4b8e1b48a1ace5c0a4823ecdf15c8536..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/structures/test_rotated_boxes.py +++ /dev/null @@ -1,441 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -from __future__ import absolute_import, division, print_function, unicode_literals -import logging -import math -import random -import unittest -import torch -from fvcore.common.benchmark import benchmark - -from detectron2.layers.rotated_boxes import pairwise_iou_rotated -from detectron2.structures.boxes import Boxes -from detectron2.structures.rotated_boxes import RotatedBoxes, pairwise_iou -from detectron2.utils.testing import reload_script_model - -logger = logging.getLogger(__name__) - - -class TestRotatedBoxesLayer(unittest.TestCase): - def test_iou_0_dim_cpu(self): - boxes1 = torch.rand(0, 5, dtype=torch.float32) - boxes2 = torch.rand(10, 5, dtype=torch.float32) - expected_ious = torch.zeros(0, 10, dtype=torch.float32) - ious = pairwise_iou_rotated(boxes1, boxes2) - self.assertTrue(torch.allclose(ious, expected_ious)) - - boxes1 = torch.rand(10, 5, dtype=torch.float32) - boxes2 = torch.rand(0, 5, dtype=torch.float32) - expected_ious = torch.zeros(10, 0, dtype=torch.float32) - ious = pairwise_iou_rotated(boxes1, boxes2) - self.assertTrue(torch.allclose(ious, expected_ious)) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_iou_0_dim_cuda(self): - boxes1 = torch.rand(0, 5, dtype=torch.float32) - boxes2 = torch.rand(10, 5, dtype=torch.float32) - expected_ious = torch.zeros(0, 10, dtype=torch.float32) - ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) - self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious)) - - boxes1 = torch.rand(10, 5, dtype=torch.float32) - boxes2 = torch.rand(0, 5, dtype=torch.float32) - expected_ious = torch.zeros(10, 0, dtype=torch.float32) - ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) - self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious)) - - def test_iou_half_overlap_cpu(self): - boxes1 = torch.tensor([[0.5, 0.5, 1.0, 1.0, 0.0]], dtype=torch.float32) - boxes2 = torch.tensor([[0.25, 0.5, 0.5, 1.0, 0.0]], dtype=torch.float32) - expected_ious = torch.tensor([[0.5]], dtype=torch.float32) - ious = pairwise_iou_rotated(boxes1, boxes2) - self.assertTrue(torch.allclose(ious, expected_ious)) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_iou_half_overlap_cuda(self): - boxes1 = torch.tensor([[0.5, 0.5, 1.0, 1.0, 0.0]], dtype=torch.float32) - boxes2 = torch.tensor([[0.25, 0.5, 0.5, 1.0, 0.0]], dtype=torch.float32) - expected_ious = torch.tensor([[0.5]], dtype=torch.float32) - ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) - self.assertTrue(torch.allclose(ious_cuda.cpu(), expected_ious)) - - def test_iou_precision(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor([[565, 565, 10, 10.0, 0]], dtype=torch.float32, device=device) - boxes2 = torch.tensor([[565, 565, 10, 8.3, 0]], dtype=torch.float32, device=device) - iou = 8.3 / 10.0 - expected_ious = torch.tensor([[iou]], dtype=torch.float32) - ious = pairwise_iou_rotated(boxes1, boxes2) - self.assertTrue(torch.allclose(ious.cpu(), expected_ious)) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_iou_too_many_boxes_cuda(self): - s1, s2 = 5, 1289035 - boxes1 = torch.zeros(s1, 5) - boxes2 = torch.zeros(s2, 5) - ious_cuda = pairwise_iou_rotated(boxes1.cuda(), boxes2.cuda()) - self.assertTupleEqual(tuple(ious_cuda.shape), (s1, s2)) - - def test_iou_extreme(self): - # Cause floating point issues in cuda kernels (#1266) - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor([[160.0, 153.0, 230.0, 23.0, -37.0]], device=device) - boxes2 = torch.tensor( - [ - [ - -1.117407639806935e17, - 1.3858420478349148e18, - 1000.0000610351562, - 1000.0000610351562, - 1612.0, - ] - ], - device=device, - ) - ious = pairwise_iou_rotated(boxes1, boxes2) - self.assertTrue(ious.min() >= 0, ious) - - def test_iou_issue_2154(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor( - [ - [ - 296.6620178222656, - 458.73883056640625, - 23.515729904174805, - 47.677001953125, - 0.08795166015625, - ] - ], - device=device, - ) - boxes2 = torch.tensor( - [[296.66201, 458.73882000000003, 23.51573, 47.67702, 0.087951]], - device=device, - ) - ious = pairwise_iou_rotated(boxes1, boxes2) - expected_ious = torch.tensor([[1.0]], dtype=torch.float32) - self.assertTrue(torch.allclose(ious.cpu(), expected_ious)) - - def test_iou_issue_2167(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor( - [ - [ - 2563.74462890625000000000, - 1436.79016113281250000000, - 2174.70336914062500000000, - 214.09500122070312500000, - 115.11834716796875000000, - ] - ], - device=device, - ) - boxes2 = torch.tensor( - [ - [ - 2563.74462890625000000000, - 1436.79028320312500000000, - 2174.70288085937500000000, - 214.09495544433593750000, - 115.11835479736328125000, - ] - ], - device=device, - ) - ious = pairwise_iou_rotated(boxes1, boxes2) - expected_ious = torch.tensor([[1.0]], dtype=torch.float32) - self.assertTrue(torch.allclose(ious.cpu(), expected_ious)) - - -class TestRotatedBoxesStructure(unittest.TestCase): - def test_clip_area_0_degree(self): - for _ in range(50): - num_boxes = 100 - boxes_5d = torch.zeros(num_boxes, 5) - boxes_5d[:, 0] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 1] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 2] = torch.FloatTensor(num_boxes).uniform_(0, 500) - boxes_5d[:, 3] = torch.FloatTensor(num_boxes).uniform_(0, 500) - # Convert from (x_ctr, y_ctr, w, h, 0) to (x1, y1, x2, y2) - boxes_4d = torch.zeros(num_boxes, 4) - boxes_4d[:, 0] = boxes_5d[:, 0] - boxes_5d[:, 2] / 2.0 - boxes_4d[:, 1] = boxes_5d[:, 1] - boxes_5d[:, 3] / 2.0 - boxes_4d[:, 2] = boxes_5d[:, 0] + boxes_5d[:, 2] / 2.0 - boxes_4d[:, 3] = boxes_5d[:, 1] + boxes_5d[:, 3] / 2.0 - - image_size = (500, 600) - test_boxes_4d = Boxes(boxes_4d) - test_boxes_5d = RotatedBoxes(boxes_5d) - # Before clip - areas_4d = test_boxes_4d.area() - areas_5d = test_boxes_5d.area() - self.assertTrue(torch.allclose(areas_4d, areas_5d, atol=1e-1, rtol=1e-5)) - # After clip - test_boxes_4d.clip(image_size) - test_boxes_5d.clip(image_size) - areas_4d = test_boxes_4d.area() - areas_5d = test_boxes_5d.area() - self.assertTrue(torch.allclose(areas_4d, areas_5d, atol=1e-1, rtol=1e-5)) - - def test_clip_area_arbitrary_angle(self): - num_boxes = 100 - boxes_5d = torch.zeros(num_boxes, 5) - boxes_5d[:, 0] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 1] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 2] = torch.FloatTensor(num_boxes).uniform_(0, 500) - boxes_5d[:, 3] = torch.FloatTensor(num_boxes).uniform_(0, 500) - boxes_5d[:, 4] = torch.FloatTensor(num_boxes).uniform_(-1800, 1800) - clip_angle_threshold = random.uniform(0, 180) - - image_size = (500, 600) - test_boxes_5d = RotatedBoxes(boxes_5d) - # Before clip - areas_before = test_boxes_5d.area() - # After clip - test_boxes_5d.clip(image_size, clip_angle_threshold) - areas_diff = test_boxes_5d.area() - areas_before - - # the areas should only decrease after clipping - self.assertTrue(torch.all(areas_diff <= 0)) - # whenever the box is clipped (thus the area shrinks), - # the angle for the box must be within the clip_angle_threshold - # Note that the clip function will normalize the angle range - # to be within (-180, 180] - - self.assertTrue( - torch.all( - torch.abs(test_boxes_5d.tensor[:, 4][torch.where(areas_diff < 0)]) - < clip_angle_threshold - ) - ) - - def test_normalize_angles(self): - # torch.manual_seed(0) - for _ in range(50): - num_boxes = 100 - boxes_5d = torch.zeros(num_boxes, 5) - boxes_5d[:, 0] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 1] = torch.FloatTensor(num_boxes).uniform_(-100, 500) - boxes_5d[:, 2] = torch.FloatTensor(num_boxes).uniform_(0, 500) - boxes_5d[:, 3] = torch.FloatTensor(num_boxes).uniform_(0, 500) - boxes_5d[:, 4] = torch.FloatTensor(num_boxes).uniform_(-1800, 1800) - rotated_boxes = RotatedBoxes(boxes_5d) - normalized_boxes = rotated_boxes.clone() - normalized_boxes.normalize_angles() - self.assertTrue(torch.all(normalized_boxes.tensor[:, 4] >= -180)) - self.assertTrue(torch.all(normalized_boxes.tensor[:, 4] < 180)) - # x, y, w, h should not change - self.assertTrue(torch.allclose(boxes_5d[:, :4], normalized_boxes.tensor[:, :4])) - # the cos/sin values of the angles should stay the same - - self.assertTrue( - torch.allclose( - torch.cos(boxes_5d[:, 4] * math.pi / 180), - torch.cos(normalized_boxes.tensor[:, 4] * math.pi / 180), - atol=1e-5, - ) - ) - - self.assertTrue( - torch.allclose( - torch.sin(boxes_5d[:, 4] * math.pi / 180), - torch.sin(normalized_boxes.tensor[:, 4] * math.pi / 180), - atol=1e-5, - ) - ) - - def test_pairwise_iou_0_degree(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor( - [[0.5, 0.5, 1.0, 1.0, 0.0], [0.5, 0.5, 1.0, 1.0, 0.0]], - dtype=torch.float32, - device=device, - ) - boxes2 = torch.tensor( - [ - [0.5, 0.5, 1.0, 1.0, 0.0], - [0.25, 0.5, 0.5, 1.0, 0.0], - [0.5, 0.25, 1.0, 0.5, 0.0], - [0.25, 0.25, 0.5, 0.5, 0.0], - [0.75, 0.75, 0.5, 0.5, 0.0], - [1.0, 1.0, 1.0, 1.0, 0.0], - ], - dtype=torch.float32, - device=device, - ) - expected_ious = torch.tensor( - [ - [1.0, 0.5, 0.5, 0.25, 0.25, 0.25 / (2 - 0.25)], - [1.0, 0.5, 0.5, 0.25, 0.25, 0.25 / (2 - 0.25)], - ], - dtype=torch.float32, - device=device, - ) - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_45_degrees(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor( - [ - [1, 1, math.sqrt(2), math.sqrt(2), 45], - [1, 1, 2 * math.sqrt(2), 2 * math.sqrt(2), -45], - ], - dtype=torch.float32, - device=device, - ) - boxes2 = torch.tensor([[1, 1, 2, 2, 0]], dtype=torch.float32, device=device) - expected_ious = torch.tensor([[0.5], [0.5]], dtype=torch.float32, device=device) - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_orthogonal(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor([[5, 5, 10, 6, 55]], dtype=torch.float32, device=device) - boxes2 = torch.tensor([[5, 5, 10, 6, -35]], dtype=torch.float32, device=device) - iou = (6.0 * 6.0) / (6.0 * 6.0 + 4.0 * 6.0 + 4.0 * 6.0) - expected_ious = torch.tensor([[iou]], dtype=torch.float32, device=device) - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_large_close_boxes(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - boxes1 = torch.tensor( - [[299.500000, 417.370422, 600.000000, 364.259186, 27.1828]], - dtype=torch.float32, - device=device, - ) - boxes2 = torch.tensor( - [[299.500000, 417.370422, 600.000000, 364.259155, 27.1828]], - dtype=torch.float32, - device=device, - ) - iou = 364.259155 / 364.259186 - expected_ious = torch.tensor([[iou]], dtype=torch.float32, device=device) - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_many_boxes(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - num_boxes1 = 100 - num_boxes2 = 200 - boxes1 = torch.stack( - [ - torch.tensor( - [5 + 20 * i, 5 + 20 * i, 10, 10, 0], - dtype=torch.float32, - device=device, - ) - for i in range(num_boxes1) - ] - ) - boxes2 = torch.stack( - [ - torch.tensor( - [5 + 20 * i, 5 + 20 * i, 10, 1 + 9 * i / num_boxes2, 0], - dtype=torch.float32, - device=device, - ) - for i in range(num_boxes2) - ] - ) - expected_ious = torch.zeros(num_boxes1, num_boxes2, dtype=torch.float32, device=device) - for i in range(min(num_boxes1, num_boxes2)): - expected_ious[i][i] = (1 + 9 * i / num_boxes2) / 10.0 - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_issue1207_simplified(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - # Simplified test case of D2-issue-1207 - boxes1 = torch.tensor([[3, 3, 8, 2, -45.0]], device=device) - boxes2 = torch.tensor([[6, 0, 8, 2, -45.0]], device=device) - iou = 0.0 - expected_ious = torch.tensor([[iou]], dtype=torch.float32, device=device) - - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_pairwise_iou_issue1207(self): - for device in ["cpu"] + (["cuda"] if torch.cuda.is_available() else []): - # The original test case in D2-issue-1207 - boxes1 = torch.tensor([[160.0, 153.0, 230.0, 23.0, -37.0]], device=device) - boxes2 = torch.tensor([[190.0, 127.0, 80.0, 21.0, -46.0]], device=device) - - iou = 0.0 - expected_ious = torch.tensor([[iou]], dtype=torch.float32, device=device) - - ious = pairwise_iou(RotatedBoxes(boxes1), RotatedBoxes(boxes2)) - self.assertTrue(torch.allclose(ious, expected_ious)) - - def test_empty_cat(self): - x = RotatedBoxes.cat([]) - self.assertTrue(x.tensor.shape, (0, 5)) - - def test_scriptability(self): - def func(x): - boxes = RotatedBoxes(x) - test = boxes.to(torch.device("cpu")).tensor - return boxes.area(), test - - f = torch.jit.script(func) - f = reload_script_model(f) - f(torch.rand((3, 5))) - - data = torch.rand((3, 5)) - - def func_cat(x: torch.Tensor): - boxes1 = RotatedBoxes(x) - boxes2 = RotatedBoxes(x) - # this is not supported by torchscript for now. - # boxes3 = RotatedBoxes.cat([boxes1, boxes2]) - boxes3 = boxes1.cat([boxes1, boxes2]) - return boxes3 - - f = torch.jit.script(func_cat) - script_box = f(data) - self.assertTrue(torch.equal(torch.cat([data, data]), script_box.tensor)) - - -def benchmark_rotated_iou(): - num_boxes1 = 200 - num_boxes2 = 500 - boxes1 = torch.stack( - [ - torch.tensor([5 + 20 * i, 5 + 20 * i, 10, 10, 0], dtype=torch.float32) - for i in range(num_boxes1) - ] - ) - boxes2 = torch.stack( - [ - torch.tensor( - [5 + 20 * i, 5 + 20 * i, 10, 1 + 9 * i / num_boxes2, 0], - dtype=torch.float32, - ) - for i in range(num_boxes2) - ] - ) - - def func(dev, n=1): - b1 = boxes1.to(device=dev) - b2 = boxes2.to(device=dev) - - def bench(): - for _ in range(n): - pairwise_iou_rotated(b1, b2) - if dev.type == "cuda": - torch.cuda.synchronize() - - return bench - - # only run it once per timed loop, since it's slow - args = [{"dev": torch.device("cpu"), "n": 1}] - if torch.cuda.is_available(): - args.append({"dev": torch.device("cuda"), "n": 10}) - - benchmark(func, "rotated_iou", args, warmup_iters=3) - - -if __name__ == "__main__": - unittest.main() - benchmark_rotated_iou() diff --git a/preprocess/detectron2/tests/test_checkpoint.py b/preprocess/detectron2/tests/test_checkpoint.py deleted file mode 100644 index 6c0b1c1ca85e63e0848a4d4de2386c8c89fb6f76..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_checkpoint.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import os -import tempfile -import unittest -from collections import OrderedDict -import torch -from iopath.common.file_io import PathHandler, PathManager -from torch import nn - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.checkpoint.c2_model_loading import ( - _longest_common_prefix_str, - align_and_update_state_dicts, -) -from detectron2.utils.logger import setup_logger - - -class TestCheckpointer(unittest.TestCase): - def setUp(self): - setup_logger() - - def create_complex_model(self): - m = nn.Module() - m.block1 = nn.Module() - m.block1.layer1 = nn.Linear(2, 3) - m.layer2 = nn.Linear(3, 2) - m.res = nn.Module() - m.res.layer2 = nn.Linear(3, 2) - - state_dict = OrderedDict() - state_dict["layer1.weight"] = torch.rand(3, 2) - state_dict["layer1.bias"] = torch.rand(3) - state_dict["layer2.weight"] = torch.rand(2, 3) - state_dict["layer2.bias"] = torch.rand(2) - state_dict["res.layer2.weight"] = torch.rand(2, 3) - state_dict["res.layer2.bias"] = torch.rand(2) - return m, state_dict - - def test_complex_model_loaded(self): - for add_data_parallel in [False, True]: - model, state_dict = self.create_complex_model() - if add_data_parallel: - model = nn.DataParallel(model) - model_sd = model.state_dict() - - sd_to_load = align_and_update_state_dicts(model_sd, state_dict) - model.load_state_dict(sd_to_load) - for loaded, stored in zip(model_sd.values(), state_dict.values()): - # different tensor references - self.assertFalse(id(loaded) == id(stored)) - # same content - self.assertTrue(loaded.to(stored).equal(stored)) - - def test_load_with_matching_heuristics(self): - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - model, state_dict = self.create_complex_model() - torch.save({"model": state_dict}, os.path.join(d, "checkpoint.pth")) - checkpointer = DetectionCheckpointer(model, save_dir=d) - - with torch.no_grad(): - # use a different weight from the `state_dict`, since torch.rand is less than 1 - model.block1.layer1.weight.fill_(1) - - # load checkpoint without matching_heuristics - checkpointer.load(os.path.join(d, "checkpoint.pth")) - self.assertTrue(model.block1.layer1.weight.equal(torch.ones(3, 2))) - - # load checkpoint with matching_heuristics - checkpointer.load(os.path.join(d, "checkpoint.pth?matching_heuristics=True")) - self.assertFalse(model.block1.layer1.weight.equal(torch.ones(3, 2))) - - def test_custom_path_manager_handler(self): - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - - class CustomPathManagerHandler(PathHandler): - PREFIX = "detectron2_test://" - - def _get_supported_prefixes(self): - return [self.PREFIX] - - def _get_local_path(self, path, **kwargs): - name = path[len(self.PREFIX) :] - return os.path.join(d, name) - - def _open(self, path, mode="r", **kwargs): - return open(self._get_local_path(path), mode, **kwargs) - - pathmgr = PathManager() - pathmgr.register_handler(CustomPathManagerHandler()) - - model, state_dict = self.create_complex_model() - torch.save({"model": state_dict}, os.path.join(d, "checkpoint.pth")) - checkpointer = DetectionCheckpointer(model, save_dir=d) - checkpointer.path_manager = pathmgr - checkpointer.load("detectron2_test://checkpoint.pth") - checkpointer.load("detectron2_test://checkpoint.pth?matching_heuristics=True") - - def test_lcp(self): - self.assertEqual(_longest_common_prefix_str(["class", "dlaps_model"]), "") - self.assertEqual(_longest_common_prefix_str(["classA", "classB"]), "class") - self.assertEqual(_longest_common_prefix_str(["classA", "classB", "clab"]), "cla") - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/test_engine.py b/preprocess/detectron2/tests/test_engine.py deleted file mode 100644 index c97c11bc20e57bebfad1830d8d035c53c8006756..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_engine.py +++ /dev/null @@ -1,264 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import json -import math -import os -import tempfile -import time -import unittest -from unittest import mock -import torch -from fvcore.common.checkpoint import Checkpointer -from torch import nn - -from detectron2 import model_zoo -from detectron2.config import configurable, get_cfg -from detectron2.engine import DefaultTrainer, SimpleTrainer, default_setup, hooks -from detectron2.modeling.meta_arch import META_ARCH_REGISTRY -from detectron2.utils.events import CommonMetricPrinter, JSONWriter - - -@META_ARCH_REGISTRY.register() -class _SimpleModel(nn.Module): - @configurable - def __init__(self, sleep_sec=0): - super().__init__() - self.mod = nn.Linear(10, 20) - self.sleep_sec = sleep_sec - - @classmethod - def from_config(cls, cfg): - return {} - - def forward(self, x): - if self.sleep_sec > 0: - time.sleep(self.sleep_sec) - return {"loss": x.sum() + sum([x.mean() for x in self.parameters()])} - - -class TestTrainer(unittest.TestCase): - def _data_loader(self, device): - device = torch.device(device) - while True: - yield torch.rand(3, 3).to(device) - - def test_simple_trainer(self, device="cpu"): - model = _SimpleModel().to(device=device) - trainer = SimpleTrainer( - model, self._data_loader(device), torch.optim.SGD(model.parameters(), 0.1) - ) - trainer.train(0, 10) - - def test_simple_trainer_reset_dataloader(self, device="cpu"): - model = _SimpleModel().to(device=device) - trainer = SimpleTrainer( - model, self._data_loader(device), torch.optim.SGD(model.parameters(), 0.1) - ) - trainer.train(0, 10) - trainer.reset_data_loader(lambda: self._data_loader(device)) - trainer.train(0, 10) - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def test_simple_trainer_cuda(self): - self.test_simple_trainer(device="cuda") - - def test_writer_hooks(self): - model = _SimpleModel(sleep_sec=0.1) - trainer = SimpleTrainer( - model, self._data_loader("cpu"), torch.optim.SGD(model.parameters(), 0.1) - ) - - max_iter = 50 - - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - json_file = os.path.join(d, "metrics.json") - writers = [CommonMetricPrinter(max_iter), JSONWriter(json_file)] - - trainer.register_hooks( - [hooks.EvalHook(0, lambda: {"metric": 100}), hooks.PeriodicWriter(writers)] - ) - with self.assertLogs(writers[0].logger) as logs: - trainer.train(0, max_iter) - - with open(json_file, "r") as f: - data = [json.loads(line.strip()) for line in f] - self.assertEqual([x["iteration"] for x in data], [19, 39, 49, 50]) - # the eval metric is in the last line with iter 50 - self.assertIn("metric", data[-1], "Eval metric must be in last line of JSON!") - - # test logged messages from CommonMetricPrinter - self.assertEqual(len(logs.output), 3) - for log, iter in zip(logs.output, [19, 39, 49]): - self.assertIn(f"iter: {iter}", log) - - self.assertIn("eta: 0:00:00", logs.output[-1], "Last ETA must be 0!") - - def test_metric_gather_and_write(self): - gather_metric_period = 5 - writer_period = 10 - - model = _SimpleModel(sleep_sec=0.1) - trainer = SimpleTrainer( - model, - self._data_loader("cpu"), - torch.optim.SGD(model.parameters(), 0.1), - gather_metric_period=gather_metric_period, - ) - - max_iter = 50 - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - json_file = os.path.join(d, "metrics.json") - writers = [JSONWriter(json_file, window_size=writer_period)] - - trainer.register_hooks( - [ - hooks.IterationTimer(), - hooks.PeriodicWriter(writers, period=writer_period), - ] - ) - trainer.train(0, max_iter) - - with open(json_file, "r") as f: - data = [json.loads(line.strip()) for line in f] - self.assertEqual([x["iteration"] for x in data], [9, 19, 29, 39, 49]) - self.assertEqual(len(trainer.storage.history("time").values()), 48) - for key in ["data_time", "total_loss"]: - history = trainer.storage.history(key).values() - history_iters = [h[1] for h in history] - self.assertEqual(history_iters, [4, 9, 14, 19, 24, 29, 34, 39, 44, 49]) - for i in range(len(data)): - # written metric should equal to the median of 2 most recent logged metrics - logged1, logged2 = history[2 * i][0], history[2 * i + 1][0] - gt = data[i][key] - self.assertEqual(gt, (logged1 + logged2) / 2.0) - - def test_async_write_metrics(self): - writer_period = 1 - - model = _SimpleModel(sleep_sec=0.1) - trainer = SimpleTrainer( - model, - self._data_loader("cpu"), - torch.optim.SGD(model.parameters(), 0.1), - async_write_metrics=True, - ) - - max_iter = 50 - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - json_file = os.path.join(d, "metrics.json") - writers = [JSONWriter(json_file, window_size=writer_period)] - - trainer.register_hooks( - [ - hooks.IterationTimer(), - hooks.PeriodicWriter(writers, period=writer_period), - ] - ) - trainer.train(0, max_iter) - - self.assertEqual(len(trainer.storage.history("time").values()), 48) - for key in ["data_time", "total_loss"]: - history = trainer.storage.history(key).values() - history_iters = [h[1] for h in history] - self.assertEqual(history_iters, list(range(50))) - - def test_default_trainer(self): - # TODO: this test requires manifold access, so changed device to CPU. see: T88318502 - cfg = get_cfg() - cfg.MODEL.DEVICE = "cpu" - cfg.MODEL.META_ARCHITECTURE = "_SimpleModel" - cfg.DATASETS.TRAIN = ("coco_2017_val_100",) - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - cfg.OUTPUT_DIR = d - trainer = DefaultTrainer(cfg) - - # test property - self.assertIs(trainer.model, trainer._trainer.model) - trainer.model = _SimpleModel() - self.assertIs(trainer.model, trainer._trainer.model) - - def test_checkpoint_resume(self): - model = _SimpleModel() - dataloader = self._data_loader("cpu") - opt = torch.optim.SGD(model.parameters(), 0.1) - scheduler = torch.optim.lr_scheduler.StepLR(opt, 3) - - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - trainer = SimpleTrainer(model, dataloader, opt) - checkpointer = Checkpointer(model, d, opt=opt, trainer=trainer) - - trainer.register_hooks( - [ - hooks.LRScheduler(scheduler=scheduler), - # checkpoint after scheduler to properly save the state of scheduler - hooks.PeriodicCheckpointer(checkpointer, 10), - ] - ) - - trainer.train(0, 12) - self.assertAlmostEqual(opt.param_groups[0]["lr"], 1e-5) - self.assertEqual(scheduler.last_epoch, 12) - del trainer - - opt = torch.optim.SGD(model.parameters(), 999) # lr will be loaded - trainer = SimpleTrainer(model, dataloader, opt) - scheduler = torch.optim.lr_scheduler.StepLR(opt, 3) - trainer.register_hooks( - [ - hooks.LRScheduler(scheduler=scheduler), - ] - ) - checkpointer = Checkpointer(model, d, opt=opt, trainer=trainer) - checkpointer.resume_or_load("non_exist.pth") - self.assertEqual(trainer.iter, 11) # last finished iter number (0-based in Trainer) - # number of times `scheduler.step()` was called (1-based) - self.assertEqual(scheduler.last_epoch, 12) - self.assertAlmostEqual(opt.param_groups[0]["lr"], 1e-5) - - def test_eval_hook(self): - model = _SimpleModel() - dataloader = self._data_loader("cpu") - opt = torch.optim.SGD(model.parameters(), 0.1) - - for total_iter, period, eval_count in [(30, 15, 2), (31, 15, 3), (20, 0, 1)]: - test_func = mock.Mock(return_value={"metric": 3.0}) - trainer = SimpleTrainer(model, dataloader, opt) - trainer.register_hooks([hooks.EvalHook(period, test_func)]) - trainer.train(0, total_iter) - self.assertEqual(test_func.call_count, eval_count) - - def test_best_checkpointer(self): - model = _SimpleModel() - dataloader = self._data_loader("cpu") - opt = torch.optim.SGD(model.parameters(), 0.1) - metric_name = "metric" - total_iter = 40 - test_period = 10 - test_cases = [ - ("max", iter([0.3, 0.4, 0.35, 0.5]), 3), - ("min", iter([1.0, 0.8, 0.9, 0.9]), 2), - ("min", iter([math.nan, 0.8, 0.9, 0.9]), 1), - ] - for mode, metrics, call_count in test_cases: - trainer = SimpleTrainer(model, dataloader, opt) - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - checkpointer = Checkpointer(model, d, opt=opt, trainer=trainer) - trainer.register_hooks( - [ - hooks.EvalHook(test_period, lambda: {metric_name: next(metrics)}), - hooks.BestCheckpointer(test_period, checkpointer, metric_name, mode=mode), - ] - ) - with mock.patch.object(checkpointer, "save") as mock_save_method: - trainer.train(0, total_iter) - self.assertEqual(mock_save_method.call_count, call_count) - - def test_setup_config(self): - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - cfg = get_cfg() - cfg.OUTPUT_DIR = os.path.join(d, "yacs") - default_setup(cfg, {}) - - cfg = model_zoo.get_config("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.py") - cfg.train.output_dir = os.path.join(d, "omegaconf") - default_setup(cfg, {}) diff --git a/preprocess/detectron2/tests/test_events.py b/preprocess/detectron2/tests/test_events.py deleted file mode 100644 index 174ca978de21fa09fdf79eca62936ef497aaf2e8..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_events.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import json -import os -import tempfile -import unittest - -from detectron2.utils.events import ( - CommonMetricPrinter, - EventStorage, - JSONWriter, - get_event_storage, - has_event_storage, -) - - -class TestEventWriter(unittest.TestCase): - def testScalar(self): - with tempfile.TemporaryDirectory( - prefix="detectron2_tests" - ) as dir, EventStorage() as storage: - json_file = os.path.join(dir, "test.json") - writer = JSONWriter(json_file) - for k in range(60): - storage.put_scalar("key", k, smoothing_hint=False) - if (k + 1) % 20 == 0: - writer.write() - storage.step() - writer.close() - with open(json_file) as f: - data = [json.loads(l) for l in f] - self.assertTrue([int(k["key"]) for k in data] == [19, 39, 59]) - - def testScalarMismatchedPeriod(self): - with tempfile.TemporaryDirectory( - prefix="detectron2_tests" - ) as dir, EventStorage() as storage: - json_file = os.path.join(dir, "test.json") - - writer = JSONWriter(json_file) - for k in range(60): - if k % 17 == 0: # write in a differnt period - storage.put_scalar("key2", k, smoothing_hint=False) - storage.put_scalar("key", k, smoothing_hint=False) - if (k + 1) % 20 == 0: - writer.write() - storage.step() - writer.close() - with open(json_file) as f: - data = [json.loads(l) for l in f] - self.assertTrue([int(k.get("key2", 0)) for k in data] == [17, 0, 34, 0, 51, 0]) - self.assertTrue([int(k.get("key", 0)) for k in data] == [0, 19, 0, 39, 0, 59]) - self.assertTrue([int(k["iteration"]) for k in data] == [17, 19, 34, 39, 51, 59]) - - def testPrintETA(self): - with EventStorage() as s: - p1 = CommonMetricPrinter(10) - p2 = CommonMetricPrinter() - - s.put_scalar("time", 1.0) - s.step() - s.put_scalar("time", 1.0) - s.step() - - with self.assertLogs("detectron2.utils.events") as logs: - p1.write() - self.assertIn("eta", logs.output[0]) - - with self.assertLogs("detectron2.utils.events") as logs: - p2.write() - self.assertNotIn("eta", logs.output[0]) - - def testPrintNonLosses(self): - with EventStorage() as s: - p1 = CommonMetricPrinter(10) - p2 = CommonMetricPrinter() - - s.put_scalar("time", 1.0) - s.put_scalar("[metric]bn_stat", 1.0) - s.step() - s.put_scalar("time", 1.0) - s.put_scalar("[metric]bn_stat", 1.0) - s.step() - - with self.assertLogs("detectron2.utils.events") as logs: - p1.write() - self.assertIn("[metric]bn_stat", logs.output[0]) - - with self.assertLogs("detectron2.utils.events") as logs: - p2.write() - self.assertIn("[metric]bn_stat", logs.output[0]) - - def testSmoothingWithWindowSize(self): - with tempfile.TemporaryDirectory( - prefix="detectron2_tests" - ) as dir, EventStorage() as storage: - json_file = os.path.join(dir, "test.json") - writer = JSONWriter(json_file, window_size=10) - for k in range(20): - storage.put_scalar("key1", k, smoothing_hint=True) - if (k + 1) % 2 == 0: - storage.put_scalar("key2", k, smoothing_hint=True) - if (k + 1) % 5 == 0: - storage.put_scalar("key3", k, smoothing_hint=True) - if (k + 1) % 10 == 0: - writer.write() - storage.step() - - num_samples = {k: storage.count_samples(k, 10) for k in ["key1", "key2", "key3"]} - self.assertEqual(num_samples, {"key1": 10, "key2": 5, "key3": 2}) - writer.close() - with open(json_file) as f: - data = [json.loads(l) for l in f] - self.assertEqual([k["key1"] for k in data], [4.5, 14.5]) - self.assertEqual([k["key2"] for k in data], [5, 15]) - self.assertEqual([k["key3"] for k in data], [6.5, 16.5]) - - def testEventStorage(self): - self.assertFalse(has_event_storage()) - with EventStorage() as storage: - self.assertTrue(has_event_storage()) - self.assertEqual(storage, get_event_storage()) - self.assertFalse(has_event_storage()) diff --git a/preprocess/detectron2/tests/test_export_caffe2.py b/preprocess/detectron2/tests/test_export_caffe2.py deleted file mode 100644 index 58e9f681c356d05e3d03b06b603721ed51840c5c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_export_caffe2.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -*- coding: utf-8 -*- - -import copy -import os -import tempfile -import unittest -import torch -from torch.hub import _check_module_exists - -from detectron2 import model_zoo -from detectron2.utils.logger import setup_logger -from detectron2.utils.testing import get_sample_coco_image - -try: - # Caffe2 used to be included in PyTorch, but since PyTorch 1.10+, - # Caffe2 is not included in pre-built packages. This is a safety BC check - from detectron2.export import Caffe2Model, Caffe2Tracer -except ImportError: - raise unittest.SkipTest( - f"PyTorch does not have Caffe2 support. Skipping all tests in {__name__}" - ) from None - - -# TODO: this test requires manifold access, see: T88318502 -# Running it on CircleCI causes crash, not sure why. -@unittest.skipIf(os.environ.get("CIRCLECI"), "Caffe2 tests crash on CircleCI.") -@unittest.skipIf(not _check_module_exists("onnx"), "ONNX not installed.") -class TestCaffe2Export(unittest.TestCase): - def setUp(self): - setup_logger() - - def _test_model(self, config_path, device="cpu"): - cfg = model_zoo.get_config(config_path) - cfg.MODEL.DEVICE = device - model = model_zoo.get(config_path, trained=True, device=device) - - inputs = [{"image": get_sample_coco_image()}] - tracer = Caffe2Tracer(cfg, model, copy.deepcopy(inputs)) - - with tempfile.TemporaryDirectory(prefix="detectron2_unittest") as d: - if not os.environ.get("CI"): - # This requires onnx, which is not yet available on public CI - c2_model = tracer.export_caffe2() - c2_model.save_protobuf(d) - c2_model.save_graph(os.path.join(d, "test.svg"), inputs=copy.deepcopy(inputs)) - - c2_model = Caffe2Model.load_protobuf(d) - c2_model(inputs)[0]["instances"] - - ts_model = tracer.export_torchscript() - ts_model.save(os.path.join(d, "model.ts")) - - def testMaskRCNN(self): - self._test_model("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") - - @unittest.skipIf(not torch.cuda.is_available(), "CUDA not available") - def testMaskRCNNGPU(self): - self._test_model("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", device="cuda") - - def testRetinaNet(self): - self._test_model("COCO-Detection/retinanet_R_50_FPN_3x.yaml") diff --git a/preprocess/detectron2/tests/test_export_onnx.py b/preprocess/detectron2/tests/test_export_onnx.py deleted file mode 100644 index aa15e1a40696e34e6792d1dedd75b6e5bb62b236..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_export_onnx.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import io -import unittest -import warnings -import torch -from torch.hub import _check_module_exists - -from detectron2 import model_zoo -from detectron2.config import get_cfg -from detectron2.export import STABLE_ONNX_OPSET_VERSION -from detectron2.export.flatten import TracingAdapter -from detectron2.export.torchscript_patch import patch_builtin_len -from detectron2.layers import ShapeSpec -from detectron2.modeling import build_model -from detectron2.modeling.roi_heads import KRCNNConvDeconvUpsampleHead -from detectron2.structures import Boxes, Instances -from detectron2.utils.testing import ( - _pytorch1111_symbolic_opset9_repeat_interleave, - _pytorch1111_symbolic_opset9_to, - get_sample_coco_image, - has_dynamic_axes, - random_boxes, - register_custom_op_onnx_export, - skipIfOnCPUCI, - skipIfUnsupportedMinOpsetVersion, - skipIfUnsupportedMinTorchVersion, - unregister_custom_op_onnx_export, -) - - -@unittest.skipIf(not _check_module_exists("onnx"), "ONNX not installed.") -@skipIfUnsupportedMinTorchVersion("1.10") -class TestONNXTracingExport(unittest.TestCase): - opset_version = STABLE_ONNX_OPSET_VERSION - - def testMaskRCNNFPN(self): - def inference_func(model, images): - with warnings.catch_warnings(record=True): - inputs = [{"image": image} for image in images] - inst = model.inference(inputs, do_postprocess=False)[0] - return [{"instances": inst}] - - self._test_model_zoo_from_config_path( - "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", inference_func - ) - - @skipIfOnCPUCI - def testMaskRCNNC4(self): - def inference_func(model, image): - inputs = [{"image": image}] - return model.inference(inputs, do_postprocess=False)[0] - - self._test_model_zoo_from_config_path( - "COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml", inference_func - ) - - @skipIfOnCPUCI - def testCascadeRCNN(self): - def inference_func(model, image): - inputs = [{"image": image}] - return model.inference(inputs, do_postprocess=False)[0] - - self._test_model_zoo_from_config_path( - "Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml", inference_func - ) - - def testRetinaNet(self): - def inference_func(model, image): - return model.forward([{"image": image}])[0]["instances"] - - self._test_model_zoo_from_config_path( - "COCO-Detection/retinanet_R_50_FPN_3x.yaml", inference_func - ) - - @skipIfOnCPUCI - def testMaskRCNNFPN_batched(self): - def inference_func(model, image1, image2): - inputs = [{"image": image1}, {"image": image2}] - return model.inference(inputs, do_postprocess=False) - - self._test_model_zoo_from_config_path( - "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", inference_func, batch=2 - ) - - @skipIfUnsupportedMinOpsetVersion(16, STABLE_ONNX_OPSET_VERSION) - @skipIfUnsupportedMinTorchVersion("1.11.1") - def testMaskRCNNFPN_with_postproc(self): - def inference_func(model, image): - inputs = [{"image": image, "height": image.shape[1], "width": image.shape[2]}] - return model.inference(inputs, do_postprocess=True)[0]["instances"] - - self._test_model_zoo_from_config_path( - "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", - inference_func, - ) - - def testKeypointHead(self): - class M(torch.nn.Module): - def __init__(self): - super().__init__() - self.model = KRCNNConvDeconvUpsampleHead( - ShapeSpec(channels=4, height=14, width=14), num_keypoints=17, conv_dims=(4,) - ) - - def forward(self, x, predbox1, predbox2): - inst = [ - Instances((100, 100), pred_boxes=Boxes(predbox1)), - Instances((100, 100), pred_boxes=Boxes(predbox2)), - ] - ret = self.model(x, inst) - return tuple(x.pred_keypoints for x in ret) - - model = M() - model.eval() - - def gen_input(num1, num2): - feat = torch.randn((num1 + num2, 4, 14, 14)) - box1 = random_boxes(num1) - box2 = random_boxes(num2) - return feat, box1, box2 - - with patch_builtin_len(): - onnx_model = self._test_model( - model, - gen_input(1, 2), - input_names=["features", "pred_boxes", "pred_classes"], - output_names=["box1", "box2"], - dynamic_axes={ - "features": {0: "batch", 1: "static_four", 2: "height", 3: "width"}, - "pred_boxes": {0: "batch", 1: "static_four"}, - "pred_classes": {0: "batch", 1: "static_four"}, - "box1": {0: "num_instance", 1: "K", 2: "static_three"}, - "box2": {0: "num_instance", 1: "K", 2: "static_three"}, - }, - ) - - # Although ONNX models are not executable by PyTorch to verify - # support of batches with different sizes, we can verify model's IR - # does not hard-code input and/or output shapes. - # TODO: Add tests with different batch sizes when detectron2's CI - # support ONNX Runtime backend. - assert has_dynamic_axes(onnx_model) - - ################################################################################ - # Testcase internals - DO NOT add tests below this point - ################################################################################ - - def setUp(self): - register_custom_op_onnx_export("::to", _pytorch1111_symbolic_opset9_to, 9, "1.11.1") - register_custom_op_onnx_export( - "::repeat_interleave", - _pytorch1111_symbolic_opset9_repeat_interleave, - 9, - "1.11.1", - ) - - def tearDown(self): - unregister_custom_op_onnx_export("::to", 9, "1.11.1") - unregister_custom_op_onnx_export("::repeat_interleave", 9, "1.11.1") - - def _test_model( - self, - model, - inputs, - inference_func=None, - opset_version=STABLE_ONNX_OPSET_VERSION, - save_onnx_graph_path=None, - **export_kwargs, - ): - # Not imported in the beginning of file to prevent runtime errors - # for environments without ONNX. - # This testcase checks dependencies before running - import onnx # isort:skip - - f = io.BytesIO() - adapter_model = TracingAdapter(model, inputs, inference_func) - adapter_model.eval() - with torch.no_grad(): - try: - torch.onnx.enable_log() - except AttributeError: - # Older ONNX versions does not have this API - pass - torch.onnx.export( - adapter_model, - adapter_model.flattened_inputs, - f, - training=torch.onnx.TrainingMode.EVAL, - opset_version=opset_version, - verbose=True, - **export_kwargs, - ) - onnx_model = onnx.load_from_string(f.getvalue()) - assert onnx_model is not None - if save_onnx_graph_path: - onnx.save(onnx_model, save_onnx_graph_path) - return onnx_model - - def _test_model_zoo_from_config_path( - self, - config_path, - inference_func, - batch=1, - opset_version=STABLE_ONNX_OPSET_VERSION, - save_onnx_graph_path=None, - **export_kwargs, - ): - model = model_zoo.get(config_path, trained=True) - image = get_sample_coco_image() - inputs = tuple(image.clone() for _ in range(batch)) - return self._test_model( - model, inputs, inference_func, opset_version, save_onnx_graph_path, **export_kwargs - ) - - def _test_model_from_config_path( - self, - config_path, - inference_func, - batch=1, - opset_version=STABLE_ONNX_OPSET_VERSION, - save_onnx_graph_path=None, - **export_kwargs, - ): - from projects.PointRend import point_rend # isort:skip - - cfg = get_cfg() - cfg.DATALOADER.NUM_WORKERS = 0 - point_rend.add_pointrend_config(cfg) - cfg.merge_from_file(config_path) - cfg.freeze() - model = build_model(cfg) - image = get_sample_coco_image() - inputs = tuple(image.clone() for _ in range(batch)) - return self._test_model( - model, inputs, inference_func, opset_version, save_onnx_graph_path, **export_kwargs - ) diff --git a/preprocess/detectron2/tests/test_export_torchscript.py b/preprocess/detectron2/tests/test_export_torchscript.py deleted file mode 100644 index f4dcfc25001254029b3b656487159585e76e687d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_export_torchscript.py +++ /dev/null @@ -1,338 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import copy -import glob -import json -import os -import random -import tempfile -import unittest -import zipfile -import torch -from torch import Tensor, nn - -from detectron2 import model_zoo -from detectron2.config import get_cfg -from detectron2.config.instantiate import dump_dataclass, instantiate -from detectron2.export import dump_torchscript_IR, scripting_with_instances -from detectron2.export.flatten import TracingAdapter, flatten_to_tuple -from detectron2.export.torchscript_patch import patch_builtin_len -from detectron2.layers import ShapeSpec -from detectron2.modeling import build_backbone -from detectron2.modeling.postprocessing import detector_postprocess -from detectron2.modeling.roi_heads import KRCNNConvDeconvUpsampleHead -from detectron2.structures import Boxes, Instances -from detectron2.utils.env import TORCH_VERSION -from detectron2.utils.testing import ( - assert_instances_allclose, - convert_scripted_instances, - get_sample_coco_image, - random_boxes, - reload_script_model, - skipIfOnCPUCI, -) - - -""" -https://detectron2.readthedocs.io/tutorials/deployment.html -contains some explanations of this file. -""" - - -class TestScripting(unittest.TestCase): - def testMaskRCNNFPN(self): - self._test_rcnn_model("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") - - @skipIfOnCPUCI - def testMaskRCNNC4(self): - self._test_rcnn_model("COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml") - - def testRetinaNet(self): - self._test_retinanet_model("COCO-Detection/retinanet_R_50_FPN_3x.yaml") - - def _test_rcnn_model(self, config_path): - model = model_zoo.get(config_path, trained=True) - model.eval() - - fields = { - "proposal_boxes": Boxes, - "objectness_logits": Tensor, - "pred_boxes": Boxes, - "scores": Tensor, - "pred_classes": Tensor, - "pred_masks": Tensor, - } - script_model = scripting_with_instances(model, fields) - script_model = reload_script_model(script_model) - - # Test that batch inference with different shapes are supported - image = get_sample_coco_image() - small_image = nn.functional.interpolate(image, scale_factor=0.5) - inputs = [{"image": image}, {"image": small_image}] - with torch.no_grad(): - instance = model.inference(inputs, do_postprocess=False)[0] - scripted_instance = script_model.inference(inputs, do_postprocess=False)[0] - assert_instances_allclose(instance, scripted_instance) - - def _test_retinanet_model(self, config_path): - model = model_zoo.get(config_path, trained=True) - model.eval() - - fields = { - "pred_boxes": Boxes, - "scores": Tensor, - "pred_classes": Tensor, - } - script_model = scripting_with_instances(model, fields) - - img = get_sample_coco_image() - inputs = [{"image": img}] * 2 - with torch.no_grad(): - instance = model(inputs)[0]["instances"] - scripted_instance = convert_scripted_instances(script_model(inputs)[0]) - scripted_instance = detector_postprocess(scripted_instance, img.shape[1], img.shape[2]) - assert_instances_allclose(instance, scripted_instance) - # Note that the model currently cannot be saved and loaded into a new process: - # https://github.com/pytorch/pytorch/issues/46944 - - -# TODO: this test requires manifold access, see: T88318502 -class TestTracing(unittest.TestCase): - def testMaskRCNNFPN(self): - def inference_func(model, image): - inputs = [{"image": image}] - return model.inference(inputs, do_postprocess=False)[0] - - self._test_model("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", inference_func) - - def testMaskRCNNFPN_with_postproc(self): - def inference_func(model, image): - inputs = [{"image": image, "height": image.shape[1], "width": image.shape[2]}] - return model.inference(inputs, do_postprocess=True)[0]["instances"] - - self._test_model("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", inference_func) - - @skipIfOnCPUCI - def testMaskRCNNC4(self): - def inference_func(model, image): - inputs = [{"image": image}] - return model.inference(inputs, do_postprocess=False)[0] - - self._test_model("COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml", inference_func) - - @skipIfOnCPUCI - def testCascadeRCNN(self): - def inference_func(model, image): - inputs = [{"image": image}] - return model.inference(inputs, do_postprocess=False)[0] - - self._test_model("Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml", inference_func) - - # bug fixed by https://github.com/pytorch/pytorch/pull/67734 - @unittest.skipIf(TORCH_VERSION == (1, 10) and os.environ.get("CI"), "1.10 has bugs.") - def testRetinaNet(self): - def inference_func(model, image): - return model.forward([{"image": image}])[0]["instances"] - - self._test_model("COCO-Detection/retinanet_R_50_FPN_3x.yaml", inference_func) - - def _check_torchscript_no_hardcoded_device(self, jitfile, extract_dir, device): - zipfile.ZipFile(jitfile).extractall(extract_dir) - dir_path = os.path.join(extract_dir, os.path.splitext(os.path.basename(jitfile))[0]) - error_files = [] - for f in glob.glob(f"{dir_path}/code/**/*.py", recursive=True): - content = open(f).read() - if device in content: - error_files.append((f, content)) - if len(error_files): - msg = "\n".join(f"{f}\n{content}" for f, content in error_files) - raise ValueError(f"Found device '{device}' in following files:\n{msg}") - - def _get_device_casting_test_cases(self, model): - # Indexing operation can causes hardcoded device type before 1.10 - if not TORCH_VERSION >= (1, 10) or torch.cuda.device_count() == 0: - return [None] - - testing_devices = ["cpu", "cuda:0"] - if torch.cuda.device_count() > 1: - testing_devices.append(f"cuda:{torch.cuda.device_count() - 1}") - assert str(model.device) in testing_devices - testing_devices.remove(str(model.device)) - testing_devices = [None] + testing_devices # test no casting first - - return testing_devices - - def _test_model(self, config_path, inference_func, batch=1): - model = model_zoo.get(config_path, trained=True) - image = get_sample_coco_image() - inputs = tuple(image.clone() for _ in range(batch)) - - wrapper = TracingAdapter(model, inputs, inference_func) - wrapper.eval() - with torch.no_grad(): - # trace with smaller images, and the trace must still work - trace_inputs = tuple( - nn.functional.interpolate(image, scale_factor=random.uniform(0.5, 0.7)) - for _ in range(batch) - ) - traced_model = torch.jit.trace(wrapper, trace_inputs) - - testing_devices = self._get_device_casting_test_cases(model) - # save and load back the model in order to show traceback of TorchScript - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - basename = "model" - jitfile = f"{d}/{basename}.jit" - torch.jit.save(traced_model, jitfile) - traced_model = torch.jit.load(jitfile) - - if any(device and "cuda" in device for device in testing_devices): - self._check_torchscript_no_hardcoded_device(jitfile, d, "cuda") - - for device in testing_devices: - print(f"Testing casting to {device} for inference (traced on {model.device}) ...") - with torch.no_grad(): - outputs = inference_func(copy.deepcopy(model).to(device), *inputs) - traced_outputs = wrapper.outputs_schema(traced_model.to(device)(*inputs)) - if batch > 1: - for output, traced_output in zip(outputs, traced_outputs): - assert_instances_allclose(output, traced_output, size_as_tensor=True) - else: - assert_instances_allclose(outputs, traced_outputs, size_as_tensor=True) - - @skipIfOnCPUCI - def testMaskRCNNFPN_batched(self): - def inference_func(model, image1, image2): - inputs = [{"image": image1}, {"image": image2}] - return model.inference(inputs, do_postprocess=False) - - self._test_model( - "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", inference_func, batch=2 - ) - - def testKeypointHead(self): - class M(nn.Module): - def __init__(self): - super().__init__() - self.model = KRCNNConvDeconvUpsampleHead( - ShapeSpec(channels=4, height=14, width=14), num_keypoints=17, conv_dims=(4,) - ) - - def forward(self, x, predbox1, predbox2): - inst = [ - Instances((100, 100), pred_boxes=Boxes(predbox1)), - Instances((100, 100), pred_boxes=Boxes(predbox2)), - ] - ret = self.model(x, inst) - return tuple(x.pred_keypoints for x in ret) - - model = M() - model.eval() - - def gen_input(num1, num2): - feat = torch.randn((num1 + num2, 4, 14, 14)) - box1 = random_boxes(num1) - box2 = random_boxes(num2) - return feat, box1, box2 - - with torch.no_grad(), patch_builtin_len(): - trace = torch.jit.trace(model, gen_input(15, 15), check_trace=False) - - inputs = gen_input(12, 10) - trace_outputs = trace(*inputs) - true_outputs = model(*inputs) - for trace_output, true_output in zip(trace_outputs, true_outputs): - self.assertTrue(torch.allclose(trace_output, true_output)) - - -class TestTorchscriptUtils(unittest.TestCase): - # TODO: add test to dump scripting - def test_dump_IR_tracing(self): - cfg = get_cfg() - cfg.MODEL.RESNETS.DEPTH = 18 - cfg.MODEL.RESNETS.RES2_OUT_CHANNELS = 64 - - class Mod(nn.Module): - def forward(self, x): - return tuple(self.m(x).values()) - - model = Mod() - model.m = build_backbone(cfg) - model.eval() - - with torch.no_grad(): - ts_model = torch.jit.trace(model, (torch.rand(2, 3, 224, 224),)) - - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - dump_torchscript_IR(ts_model, d) - # check that the files are created - for name in ["model_ts_code", "model_ts_IR", "model_ts_IR_inlined", "model"]: - fname = os.path.join(d, name + ".txt") - self.assertTrue(os.stat(fname).st_size > 0, fname) - - def test_dump_IR_function(self): - @torch.jit.script - def gunc(x, y): - return x + y - - def func(x, y): - return x + y + gunc(x, y) - - ts_model = torch.jit.trace(func, (torch.rand(3), torch.rand(3))) - with tempfile.TemporaryDirectory(prefix="detectron2_test") as d: - dump_torchscript_IR(ts_model, d) - for name in ["model_ts_code", "model_ts_IR", "model_ts_IR_inlined"]: - fname = os.path.join(d, name + ".txt") - self.assertTrue(os.stat(fname).st_size > 0, fname) - - def test_flatten_basic(self): - obj = [3, ([5, 6], {"name": [7, 9], "name2": 3})] - res, schema = flatten_to_tuple(obj) - self.assertEqual(res, (3, 5, 6, 7, 9, 3)) - new_obj = schema(res) - self.assertEqual(new_obj, obj) - - _, new_schema = flatten_to_tuple(new_obj) - self.assertEqual(schema, new_schema) # test __eq__ - self._check_schema(schema) - - def _check_schema(self, schema): - dumped_schema = dump_dataclass(schema) - # Check that the schema is json-serializable - # Although in reality you might want to use yaml because it often has many levels - json.dumps(dumped_schema) - - # Check that the schema can be deserialized - new_schema = instantiate(dumped_schema) - self.assertEqual(schema, new_schema) - - def test_flatten_instances_boxes(self): - inst = Instances( - torch.tensor([5, 8]), pred_masks=torch.tensor([3]), pred_boxes=Boxes(torch.ones((1, 4))) - ) - obj = [3, ([5, 6], inst)] - res, schema = flatten_to_tuple(obj) - self.assertEqual(res[:3], (3, 5, 6)) - for r, expected in zip(res[3:], (inst.pred_boxes.tensor, inst.pred_masks, inst.image_size)): - self.assertIs(r, expected) - new_obj = schema(res) - assert_instances_allclose(new_obj[1][1], inst, rtol=0.0, size_as_tensor=True) - - self._check_schema(schema) - - def test_allow_non_tensor(self): - data = (torch.tensor([5, 8]), 3) # contains non-tensor - - class M(nn.Module): - def forward(self, input, number): - return input - - model = M() - with self.assertRaisesRegex(ValueError, "must only contain tensors"): - adap = TracingAdapter(model, data, allow_non_tensor=False) - - adap = TracingAdapter(model, data, allow_non_tensor=True) - _ = adap(*adap.flattened_inputs) - - newdata = (data[0].clone(),) - with self.assertRaisesRegex(ValueError, "cannot generalize"): - _ = adap(*newdata) diff --git a/preprocess/detectron2/tests/test_model_analysis.py b/preprocess/detectron2/tests/test_model_analysis.py deleted file mode 100644 index c01b7af09703c8dad889dee0118d74fcc12ac4b0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_model_analysis.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - - -import unittest -import torch -from torch import nn - -from detectron2.utils.analysis import find_unused_parameters, flop_count_operators, parameter_count -from detectron2.utils.testing import get_model_no_weights - - -class RetinaNetTest(unittest.TestCase): - def setUp(self): - self.model = get_model_no_weights("COCO-Detection/retinanet_R_50_FPN_1x.yaml") - - def test_flop(self): - # RetinaNet supports flop-counting with random inputs - inputs = [{"image": torch.rand(3, 800, 800), "test_unused": "abcd"}] - res = flop_count_operators(self.model, inputs) - self.assertEqual(int(res["conv"]), 146) # 146B flops - - def test_param_count(self): - res = parameter_count(self.model) - self.assertEqual(res[""], 37915572) - self.assertEqual(res["backbone"], 31452352) - - -class FasterRCNNTest(unittest.TestCase): - def setUp(self): - self.model = get_model_no_weights("COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml") - - def test_flop(self): - # Faster R-CNN supports flop-counting with random inputs - inputs = [{"image": torch.rand(3, 800, 800)}] - res = flop_count_operators(self.model, inputs) - - # This only checks flops for backbone & proposal generator - # Flops for box head is not conv, and depends on #proposals, which is - # almost 0 for random inputs. - self.assertEqual(int(res["conv"]), 117) - - def test_flop_with_output_shape(self): - inputs = [{"image": torch.rand(3, 800, 800), "height": 700, "width": 700}] - res = flop_count_operators(self.model, inputs) - self.assertEqual(int(res["conv"]), 117) - - def test_param_count(self): - res = parameter_count(self.model) - self.assertEqual(res[""], 41699936) - self.assertEqual(res["backbone"], 26799296) - - -class MaskRCNNTest(unittest.TestCase): - def setUp(self): - self.model = get_model_no_weights("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml") - - def test_flop(self): - inputs1 = [{"image": torch.rand(3, 800, 800)}] - inputs2 = [{"image": torch.rand(3, 800, 800), "height": 700, "width": 700}] - - for inputs in [inputs1, inputs2]: - res = flop_count_operators(self.model, inputs) - # The mask head could have extra conv flops, so total >= 117 - self.assertGreaterEqual(int(res["conv"]), 117) - - -class UnusedParamTest(unittest.TestCase): - def test_unused(self): - class TestMod(nn.Module): - def __init__(self): - super().__init__() - self.fc1 = nn.Linear(10, 10) - self.t = nn.Linear(10, 10) - - def forward(self, x): - return self.fc1(x).mean() - - m = TestMod() - ret = find_unused_parameters(m, torch.randn(10, 10)) - self.assertEqual(set(ret), {"t.weight", "t.bias"}) diff --git a/preprocess/detectron2/tests/test_model_zoo.py b/preprocess/detectron2/tests/test_model_zoo.py deleted file mode 100644 index e3360a74864e0c00ed92ffbc8531c8d36e8be379..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_model_zoo.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import unittest - -from detectron2 import model_zoo -from detectron2.config import instantiate -from detectron2.modeling import FPN, GeneralizedRCNN - -logger = logging.getLogger(__name__) - - -class TestModelZoo(unittest.TestCase): - def test_get_returns_model(self): - model = model_zoo.get("Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml", trained=False) - self.assertIsInstance(model, GeneralizedRCNN) - self.assertIsInstance(model.backbone, FPN) - - def test_get_invalid_model(self): - self.assertRaises(RuntimeError, model_zoo.get, "Invalid/config.yaml") - - def test_get_url(self): - url = model_zoo.get_checkpoint_url("Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml") - self.assertEqual( - url, - "https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn/138602908/model_final_01ca85.pkl", # noqa - ) - url2 = model_zoo.get_checkpoint_url("Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.py") - self.assertEqual(url, url2) - - def _build_lazy_model(self, name): - cfg = model_zoo.get_config("common/models/" + name) - instantiate(cfg.model) - - def test_mask_rcnn_fpn(self): - self._build_lazy_model("mask_rcnn_fpn.py") - - def test_mask_rcnn_c4(self): - self._build_lazy_model("mask_rcnn_c4.py") - - def test_panoptic_fpn(self): - self._build_lazy_model("panoptic_fpn.py") - - def test_schedule(self): - cfg = model_zoo.get_config("common/coco_schedule.py") - for _, v in cfg.items(): - instantiate(v) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/test_packaging.py b/preprocess/detectron2/tests/test_packaging.py deleted file mode 100644 index a5b1661e8f341fe66a6e02c59fe172bce445782b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_packaging.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest - -from detectron2.utils.collect_env import collect_env_info - - -class TestProjects(unittest.TestCase): - def test_import(self): - from detectron2.projects import point_rend - - _ = point_rend.add_pointrend_config - - import detectron2.projects.deeplab as deeplab - - _ = deeplab.add_deeplab_config - - # import detectron2.projects.panoptic_deeplab as panoptic_deeplab - - # _ = panoptic_deeplab.add_panoptic_deeplab_config - - -class TestCollectEnv(unittest.TestCase): - def test(self): - _ = collect_env_info() diff --git a/preprocess/detectron2/tests/test_registry.py b/preprocess/detectron2/tests/test_registry.py deleted file mode 100644 index 4e425a6ec44c7c47a5a106bfdf5ce8062c2110c9..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_registry.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import unittest -import torch - -from detectron2.modeling.meta_arch import GeneralizedRCNN -from detectron2.utils.registry import _convert_target_to_string, locate - - -class A: - class B: - pass - - -class TestLocate(unittest.TestCase): - def _test_obj(self, obj): - name = _convert_target_to_string(obj) - newobj = locate(name) - self.assertIs(obj, newobj) - - def test_basic(self): - self._test_obj(GeneralizedRCNN) - - def test_inside_class(self): - # requires using __qualname__ instead of __name__ - self._test_obj(A.B) - - def test_builtin(self): - self._test_obj(len) - self._test_obj(dict) - - def test_pytorch_optim(self): - # pydoc.locate does not work for it - self._test_obj(torch.optim.SGD) - - def test_failure(self): - with self.assertRaises(ImportError): - locate("asdf") - - def test_compress_target(self): - from detectron2.data.transforms import RandomCrop - - name = _convert_target_to_string(RandomCrop) - # name shouldn't contain 'augmentation_impl' - self.assertEqual(name, "detectron2.data.transforms.RandomCrop") - self.assertIs(RandomCrop, locate(name)) diff --git a/preprocess/detectron2/tests/test_scheduler.py b/preprocess/detectron2/tests/test_scheduler.py deleted file mode 100644 index 5649a4a2e167f44a734cfcc3ec86ab3a22bfc1b0..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_scheduler.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. - -import math -import numpy as np -from unittest import TestCase -import torch -from fvcore.common.param_scheduler import ( - CosineParamScheduler, - MultiStepParamScheduler, - StepWithFixedGammaParamScheduler, -) -from torch import nn - -from detectron2.solver import LRMultiplier, WarmupParamScheduler, build_lr_scheduler - - -class TestScheduler(TestCase): - def test_warmup_multistep(self): - p = nn.Parameter(torch.zeros(0)) - opt = torch.optim.SGD([p], lr=5) - - multiplier = WarmupParamScheduler( - MultiStepParamScheduler( - [1, 0.1, 0.01, 0.001], - milestones=[10, 15, 20], - num_updates=30, - ), - 0.001, - 5 / 30, - ) - sched = LRMultiplier(opt, multiplier, 30) - # This is an equivalent of: - # sched = WarmupMultiStepLR( - # opt, milestones=[10, 15, 20], gamma=0.1, warmup_factor=0.001, warmup_iters=5) - - p.sum().backward() - opt.step() - - lrs = [0.005] - for _ in range(30): - sched.step() - lrs.append(opt.param_groups[0]["lr"]) - self.assertTrue(np.allclose(lrs[:5], [0.005, 1.004, 2.003, 3.002, 4.001])) - self.assertTrue(np.allclose(lrs[5:10], 5.0)) - self.assertTrue(np.allclose(lrs[10:15], 0.5)) - self.assertTrue(np.allclose(lrs[15:20], 0.05)) - self.assertTrue(np.allclose(lrs[20:], 0.005)) - - def test_warmup_cosine(self): - p = nn.Parameter(torch.zeros(0)) - opt = torch.optim.SGD([p], lr=5) - multiplier = WarmupParamScheduler( - CosineParamScheduler(1, 0), - 0.001, - 5 / 30, - ) - sched = LRMultiplier(opt, multiplier, 30) - - p.sum().backward() - opt.step() - self.assertEqual(opt.param_groups[0]["lr"], 0.005) - lrs = [0.005] - - for _ in range(30): - sched.step() - lrs.append(opt.param_groups[0]["lr"]) - for idx, lr in enumerate(lrs): - expected_cosine = 2.5 * (1.0 + math.cos(math.pi * idx / 30)) - if idx >= 5: - self.assertAlmostEqual(lr, expected_cosine) - else: - self.assertNotAlmostEqual(lr, expected_cosine) - - def test_warmup_cosine_end_value(self): - from detectron2.config import CfgNode, get_cfg - - def _test_end_value(cfg_dict): - cfg = get_cfg() - cfg.merge_from_other_cfg(CfgNode(cfg_dict)) - - p = nn.Parameter(torch.zeros(0)) - opt = torch.optim.SGD([p], lr=cfg.SOLVER.BASE_LR) - - scheduler = build_lr_scheduler(cfg, opt) - - p.sum().backward() - opt.step() - self.assertEqual( - opt.param_groups[0]["lr"], cfg.SOLVER.BASE_LR * cfg.SOLVER.WARMUP_FACTOR - ) - - lrs = [] - for _ in range(cfg.SOLVER.MAX_ITER): - scheduler.step() - lrs.append(opt.param_groups[0]["lr"]) - - self.assertAlmostEqual(lrs[-1], cfg.SOLVER.BASE_LR_END) - - _test_end_value( - { - "SOLVER": { - "LR_SCHEDULER_NAME": "WarmupCosineLR", - "MAX_ITER": 100, - "WARMUP_ITERS": 10, - "WARMUP_FACTOR": 0.1, - "BASE_LR": 5.0, - "BASE_LR_END": 0.0, - } - } - ) - - _test_end_value( - { - "SOLVER": { - "LR_SCHEDULER_NAME": "WarmupCosineLR", - "MAX_ITER": 100, - "WARMUP_ITERS": 10, - "WARMUP_FACTOR": 0.1, - "BASE_LR": 5.0, - "BASE_LR_END": 0.5, - } - } - ) - - def test_warmup_stepwithfixedgamma(self): - p = nn.Parameter(torch.zeros(0)) - opt = torch.optim.SGD([p], lr=5) - - multiplier = WarmupParamScheduler( - StepWithFixedGammaParamScheduler( - base_value=1.0, - gamma=0.1, - num_decays=4, - num_updates=30, - ), - 0.001, - 5 / 30, - rescale_interval=True, - ) - sched = LRMultiplier(opt, multiplier, 30) - - p.sum().backward() - opt.step() - - lrs = [0.005] - for _ in range(29): - sched.step() - lrs.append(opt.param_groups[0]["lr"]) - self.assertTrue(np.allclose(lrs[:5], [0.005, 1.004, 2.003, 3.002, 4.001])) - self.assertTrue(np.allclose(lrs[5:10], 5.0)) - self.assertTrue(np.allclose(lrs[10:15], 0.5)) - self.assertTrue(np.allclose(lrs[15:20], 0.05)) - self.assertTrue(np.allclose(lrs[20:25], 0.005)) - self.assertTrue(np.allclose(lrs[25:], 0.0005)) - - # Calling sche.step() after the last training iteration is done will trigger IndexError - with self.assertRaises(IndexError, msg="list index out of range"): - sched.step() diff --git a/preprocess/detectron2/tests/test_solver.py b/preprocess/detectron2/tests/test_solver.py deleted file mode 100644 index 6b3ae84c00b789df071ab5d12bae42d991df1d0b..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_solver.py +++ /dev/null @@ -1,66 +0,0 @@ -import unittest - -from detectron2.solver.build import _expand_param_groups, reduce_param_groups - - -class TestOptimizer(unittest.TestCase): - def testExpandParamsGroups(self): - params = [ - { - "params": ["p1", "p2", "p3", "p4"], - "lr": 1.0, - "weight_decay": 3.0, - }, - { - "params": ["p2", "p3", "p5"], - "lr": 2.0, - "momentum": 2.0, - }, - { - "params": ["p1"], - "weight_decay": 4.0, - }, - ] - out = _expand_param_groups(params) - gt = [ - dict(params=["p1"], lr=1.0, weight_decay=4.0), # noqa - dict(params=["p2"], lr=2.0, weight_decay=3.0, momentum=2.0), # noqa - dict(params=["p3"], lr=2.0, weight_decay=3.0, momentum=2.0), # noqa - dict(params=["p4"], lr=1.0, weight_decay=3.0), # noqa - dict(params=["p5"], lr=2.0, momentum=2.0), # noqa - ] - self.assertEqual(out, gt) - - def testReduceParamGroups(self): - params = [ - dict(params=["p1"], lr=1.0, weight_decay=4.0), # noqa - dict(params=["p2", "p6"], lr=2.0, weight_decay=3.0, momentum=2.0), # noqa - dict(params=["p3"], lr=2.0, weight_decay=3.0, momentum=2.0), # noqa - dict(params=["p4"], lr=1.0, weight_decay=3.0), # noqa - dict(params=["p5"], lr=2.0, momentum=2.0), # noqa - ] - gt_groups = [ - { - "lr": 1.0, - "weight_decay": 4.0, - "params": ["p1"], - }, - { - "lr": 2.0, - "weight_decay": 3.0, - "momentum": 2.0, - "params": ["p2", "p6", "p3"], - }, - { - "lr": 1.0, - "weight_decay": 3.0, - "params": ["p4"], - }, - { - "lr": 2.0, - "momentum": 2.0, - "params": ["p5"], - }, - ] - out = reduce_param_groups(params) - self.assertEqual(out, gt_groups) diff --git a/preprocess/detectron2/tests/test_visualizer.py b/preprocess/detectron2/tests/test_visualizer.py deleted file mode 100644 index 646e5f32b5c570bd8024c13b417a45c07aad8453..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/test_visualizer.py +++ /dev/null @@ -1,278 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import numpy as np -import os -import tempfile -import unittest -import cv2 -import torch - -from detectron2.data import MetadataCatalog -from detectron2.structures import BoxMode, Instances, RotatedBoxes -from detectron2.utils.visualizer import ColorMode, Visualizer - - -class TestVisualizer(unittest.TestCase): - def _random_data(self): - H, W = 100, 100 - N = 10 - img = np.random.rand(H, W, 3) * 255 - boxxy = np.random.rand(N, 2) * (H // 2) - boxes = np.concatenate((boxxy, boxxy + H // 2), axis=1) - - def _rand_poly(): - return np.random.rand(3, 2).flatten() * H - - polygons = [[_rand_poly() for _ in range(np.random.randint(1, 5))] for _ in range(N)] - - mask = np.zeros_like(img[:, :, 0], dtype=bool) - mask[:40, 10:20] = 1 - - labels = [str(i) for i in range(N)] - return img, boxes, labels, polygons, [mask] * N - - @property - def metadata(self): - return MetadataCatalog.get("coco_2017_train") - - def test_draw_dataset_dict(self): - img = np.random.rand(512, 512, 3) * 255 - dic = { - "annotations": [ - { - "bbox": [ - 368.9946492271106, - 330.891438763377, - 13.148537455410235, - 13.644708680142685, - ], - "bbox_mode": BoxMode.XYWH_ABS, - "category_id": 0, - "iscrowd": 1, - "segmentation": { - "counts": "_jh52m?2N2N2N2O100O10O001N1O2MceP2", - "size": [512, 512], - }, - } - ], - "height": 512, - "image_id": 1, - "width": 512, - } - v = Visualizer(img) - v.draw_dataset_dict(dic) - - v = Visualizer(img, self.metadata) - v.draw_dataset_dict(dic) - - def test_draw_rotated_dataset_dict(self): - img = np.random.rand(512, 512, 3) * 255 - dic = { - "annotations": [ - { - "bbox": [ - 368.9946492271106, - 330.891438763377, - 13.148537455410235, - 13.644708680142685, - 45.0, - ], - "bbox_mode": BoxMode.XYWHA_ABS, - "category_id": 0, - "iscrowd": 1, - } - ], - "height": 512, - "image_id": 1, - "width": 512, - } - v = Visualizer(img, self.metadata) - v.draw_dataset_dict(dic) - - def test_overlay_instances(self): - img, boxes, labels, polygons, masks = self._random_data() - - v = Visualizer(img, self.metadata) - output = v.overlay_instances(masks=polygons, boxes=boxes, labels=labels).get_image() - self.assertEqual(output.shape, img.shape) - - # Test 2x scaling - v = Visualizer(img, self.metadata, scale=2.0) - output = v.overlay_instances(masks=polygons, boxes=boxes, labels=labels).get_image() - self.assertEqual(output.shape[0], img.shape[0] * 2) - - # Test overlay masks - v = Visualizer(img, self.metadata) - output = v.overlay_instances(masks=masks, boxes=boxes, labels=labels).get_image() - self.assertEqual(output.shape, img.shape) - - def test_overlay_instances_no_boxes(self): - img, boxes, labels, polygons, _ = self._random_data() - v = Visualizer(img, self.metadata) - v.overlay_instances(masks=polygons, boxes=None, labels=labels).get_image() - - def test_draw_instance_predictions(self): - img, boxes, _, _, masks = self._random_data() - num_inst = len(boxes) - inst = Instances((img.shape[0], img.shape[1])) - inst.pred_classes = torch.randint(0, 80, size=(num_inst,)) - inst.scores = torch.rand(num_inst) - inst.pred_boxes = torch.from_numpy(boxes) - inst.pred_masks = torch.from_numpy(np.asarray(masks)) - - v = Visualizer(img) - v.draw_instance_predictions(inst) - - v = Visualizer(img, self.metadata) - v.draw_instance_predictions(inst) - - def test_BWmode_nomask(self): - img, boxes, _, _, masks = self._random_data() - num_inst = len(boxes) - inst = Instances((img.shape[0], img.shape[1])) - inst.pred_classes = torch.randint(0, 80, size=(num_inst,)) - inst.scores = torch.rand(num_inst) - inst.pred_boxes = torch.from_numpy(boxes) - - v = Visualizer(img, self.metadata, instance_mode=ColorMode.IMAGE_BW) - v.draw_instance_predictions(inst) - - # check that output is grayscale - inst = inst[:0] - v = Visualizer(img, self.metadata, instance_mode=ColorMode.IMAGE_BW) - output = v.draw_instance_predictions(inst).get_image() - self.assertTrue(np.allclose(output[:, :, 0], output[:, :, 1])) - self.assertTrue(np.allclose(output[:, :, 0], output[:, :, 2])) - - def test_draw_empty_mask_predictions(self): - img, boxes, _, _, masks = self._random_data() - num_inst = len(boxes) - inst = Instances((img.shape[0], img.shape[1])) - inst.pred_classes = torch.randint(0, 80, size=(num_inst,)) - inst.scores = torch.rand(num_inst) - inst.pred_boxes = torch.from_numpy(boxes) - inst.pred_masks = torch.from_numpy(np.zeros_like(np.asarray(masks))) - - v = Visualizer(img, self.metadata) - v.draw_instance_predictions(inst) - - def test_correct_output_shape(self): - img = np.random.rand(928, 928, 3) * 255 - v = Visualizer(img, self.metadata) - out = v.output.get_image() - self.assertEqual(out.shape, img.shape) - - def test_overlay_rotated_instances(self): - H, W = 100, 150 - img = np.random.rand(H, W, 3) * 255 - num_boxes = 50 - boxes_5d = torch.zeros(num_boxes, 5) - boxes_5d[:, 0] = torch.FloatTensor(num_boxes).uniform_(-0.1 * W, 1.1 * W) - boxes_5d[:, 1] = torch.FloatTensor(num_boxes).uniform_(-0.1 * H, 1.1 * H) - boxes_5d[:, 2] = torch.FloatTensor(num_boxes).uniform_(0, max(W, H)) - boxes_5d[:, 3] = torch.FloatTensor(num_boxes).uniform_(0, max(W, H)) - boxes_5d[:, 4] = torch.FloatTensor(num_boxes).uniform_(-1800, 1800) - rotated_boxes = RotatedBoxes(boxes_5d) - labels = [str(i) for i in range(num_boxes)] - - v = Visualizer(img, self.metadata) - output = v.overlay_instances(boxes=rotated_boxes, labels=labels).get_image() - self.assertEqual(output.shape, img.shape) - - def test_draw_no_metadata(self): - img, boxes, _, _, masks = self._random_data() - num_inst = len(boxes) - inst = Instances((img.shape[0], img.shape[1])) - inst.pred_classes = torch.randint(0, 80, size=(num_inst,)) - inst.scores = torch.rand(num_inst) - inst.pred_boxes = torch.from_numpy(boxes) - inst.pred_masks = torch.from_numpy(np.asarray(masks)) - - v = Visualizer(img, MetadataCatalog.get("asdfasdf")) - v.draw_instance_predictions(inst) - - def test_draw_binary_mask(self): - img, boxes, _, _, masks = self._random_data() - img[:, :, 0] = 0 # remove red color - mask = masks[0] - mask_with_hole = np.zeros_like(mask).astype("uint8") - mask_with_hole = cv2.rectangle(mask_with_hole, (10, 10), (50, 50), 1, 5) - - for m in [mask, mask_with_hole]: - for save in [True, False]: - v = Visualizer(img) - o = v.draw_binary_mask(m, color="red", text="test") - if save: - with tempfile.TemporaryDirectory(prefix="detectron2_viz") as d: - path = os.path.join(d, "output.png") - o.save(path) - o = cv2.imread(path)[:, :, ::-1] - else: - o = o.get_image().astype("float32") - # red color is drawn on the image - self.assertTrue(o[:, :, 0].sum() > 0) - - def test_draw_soft_mask(self): - img = np.random.rand(100, 100, 3) * 255 - img[:, :, 0] = 0 # remove red color - mask = np.zeros((100, 100), dtype=np.float32) - mask[30:50, 40:50] = 1.0 - cv2.GaussianBlur(mask, (21, 21), 10) - - v = Visualizer(img) - o = v.draw_soft_mask(mask, color="red", text="test") - o = o.get_image().astype("float32") - # red color is drawn on the image - self.assertTrue(o[:, :, 0].sum() > 0) - - # test draw empty mask - v = Visualizer(img) - o = v.draw_soft_mask(np.zeros((100, 100), dtype=np.float32), color="red", text="test") - o = o.get_image().astype("float32") - - def test_border_mask_with_holes(self): - H, W = 200, 200 - img = np.zeros((H, W, 3)) - img[:, :, 0] = 255.0 - v = Visualizer(img, scale=3) - - mask = np.zeros((H, W)) - mask[:, 100:150] = 1 - # create a hole, to trigger imshow - mask = cv2.rectangle(mask, (110, 110), (130, 130), 0, thickness=-1) - output = v.draw_binary_mask(mask, color="blue") - output = output.get_image()[:, :, ::-1] - - first_row = {tuple(x.tolist()) for x in output[0]} - last_row = {tuple(x.tolist()) for x in output[-1]} - # Check quantization / off-by-1 error: the first and last row must have two colors - self.assertEqual(len(last_row), 2) - self.assertEqual(len(first_row), 2) - self.assertIn((0, 0, 255), last_row) - self.assertIn((0, 0, 255), first_row) - - def test_border_polygons(self): - H, W = 200, 200 - img = np.zeros((H, W, 3)) - img[:, :, 0] = 255.0 - v = Visualizer(img, scale=3) - mask = np.zeros((H, W)) - mask[:, 100:150] = 1 - - output = v.draw_binary_mask(mask, color="blue") - output = output.get_image()[:, :, ::-1] - - first_row = {tuple(x.tolist()) for x in output[0]} - last_row = {tuple(x.tolist()) for x in output[-1]} - # Check quantization / off-by-1 error: - # the first and last row must have >=2 colors, because the polygon - # touches both rows - self.assertGreaterEqual(len(last_row), 2) - self.assertGreaterEqual(len(first_row), 2) - self.assertIn((0, 0, 255), last_row) - self.assertIn((0, 0, 255), first_row) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/tracking/__init__.py b/preprocess/detectron2/tests/tracking/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tests/tracking/test_bbox_iou_tracker.py b/preprocess/detectron2/tests/tracking/test_bbox_iou_tracker.py deleted file mode 100644 index e720b2eb98788670c7daf2a694eff1fdc7b9f1bd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/tracking/test_bbox_iou_tracker.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest -from copy import deepcopy -from typing import Dict -import torch - -from detectron2.config import CfgNode as CfgNode_ -from detectron2.config import instantiate -from detectron2.structures import Boxes, Instances -from detectron2.tracking.base_tracker import build_tracker_head -from detectron2.tracking.bbox_iou_tracker import BBoxIOUTracker # noqa - - -class TestBBoxIOUTracker(unittest.TestCase): - def setUp(self): - self._img_size = np.array([600, 800]) - self._prev_boxes = np.array( - [ - [101, 101, 200, 200], - [301, 301, 450, 450], - ] - ).astype(np.float32) - self._prev_scores = np.array([0.9, 0.9]) - self._prev_classes = np.array([1, 1]) - self._prev_masks = np.ones((2, 600, 800)).astype("uint8") - self._curr_boxes = np.array( - [ - [302, 303, 451, 452], - [101, 102, 201, 203], - ] - ).astype(np.float32) - self._curr_scores = np.array([0.95, 0.85]) - self._curr_classes = np.array([1, 1]) - self._curr_masks = np.ones((2, 600, 800)).astype("uint8") - - self._prev_instances = { - "image_size": self._img_size, - "pred_boxes": self._prev_boxes, - "scores": self._prev_scores, - "pred_classes": self._prev_classes, - "pred_masks": self._prev_masks, - } - self._prev_instances = self._convertDictPredictionToInstance(self._prev_instances) - self._curr_instances = { - "image_size": self._img_size, - "pred_boxes": self._curr_boxes, - "scores": self._curr_scores, - "pred_classes": self._curr_classes, - "pred_masks": self._curr_masks, - } - self._curr_instances = self._convertDictPredictionToInstance(self._curr_instances) - - self._max_num_instances = 200 - self._max_lost_frame_count = 0 - self._min_box_rel_dim = 0.02 - self._min_instance_period = 1 - self._track_iou_threshold = 0.5 - - def _convertDictPredictionToInstance(self, prediction: Dict) -> Instances: - """ - convert prediction from Dict to D2 Instances format - """ - res = Instances( - image_size=torch.IntTensor(prediction["image_size"]), - pred_boxes=Boxes(torch.FloatTensor(prediction["pred_boxes"])), - pred_masks=torch.IntTensor(prediction["pred_masks"]), - pred_classes=torch.IntTensor(prediction["pred_classes"]), - scores=torch.FloatTensor(prediction["scores"]), - ) - return res - - def test_init(self): - cfg = { - "_target_": "detectron2.tracking.bbox_iou_tracker.BBoxIOUTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_from_config(self): - cfg = CfgNode_() - cfg.TRACKER_HEADS = CfgNode_() - cfg.TRACKER_HEADS.TRACKER_NAME = "BBoxIOUTracker" - cfg.TRACKER_HEADS.VIDEO_HEIGHT = int(self._img_size[0]) - cfg.TRACKER_HEADS.VIDEO_WIDTH = int(self._img_size[1]) - cfg.TRACKER_HEADS.MAX_NUM_INSTANCES = self._max_num_instances - cfg.TRACKER_HEADS.MAX_LOST_FRAME_COUNT = self._max_lost_frame_count - cfg.TRACKER_HEADS.MIN_BOX_REL_DIM = self._min_box_rel_dim - cfg.TRACKER_HEADS.MIN_INSTANCE_PERIOD = self._min_instance_period - cfg.TRACKER_HEADS.TRACK_IOU_THRESHOLD = self._track_iou_threshold - tracker = build_tracker_head(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_initialize_extra_fields(self): - cfg = { - "_target_": "detectron2.tracking.bbox_iou_tracker.BBoxIOUTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - instances = tracker._initialize_extra_fields(self._curr_instances) - self.assertTrue(instances.has("ID")) - self.assertTrue(instances.has("ID_period")) - self.assertTrue(instances.has("lost_frame_count")) - - def test_assign_new_id(self): - cfg = { - "_target_": "detectron2.tracking.bbox_iou_tracker.BBoxIOUTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - instances = deepcopy(self._curr_instances) - instances = tracker._initialize_extra_fields(instances) - instances = tracker._assign_new_id(instances) - self.assertTrue(len(instances.ID) == 2) - self.assertTrue(instances.ID[0] == 2) - self.assertTrue(instances.ID[1] == 3) - - def test_update(self): - cfg = { - "_target_": "detectron2.tracking.bbox_iou_tracker.BBoxIOUTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker.update(self._prev_instances) - self.assertTrue(len(prev_instances.ID) == 2) - self.assertTrue(prev_instances.ID[0] == 0) - self.assertTrue(prev_instances.ID[1] == 1) - curr_instances = tracker.update(self._curr_instances) - self.assertTrue(len(curr_instances.ID) == 2) - self.assertTrue(curr_instances.ID[0] == 1) - self.assertTrue(curr_instances.ID[1] == 0) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/tracking/test_hungarian_tracker.py b/preprocess/detectron2/tests/tracking/test_hungarian_tracker.py deleted file mode 100644 index 660c635990a3370945e7f14422dcd978320e4782..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/tracking/test_hungarian_tracker.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import numpy as np -import unittest -from typing import Dict -import torch - -from detectron2.config import instantiate -from detectron2.structures import Boxes, Instances - - -class TestBaseHungarianTracker(unittest.TestCase): - def setUp(self): - self._img_size = np.array([600, 800]) - self._prev_boxes = np.array( - [ - [101, 101, 200, 200], - [301, 301, 450, 450], - ] - ).astype(np.float32) - self._prev_scores = np.array([0.9, 0.9]) - self._prev_classes = np.array([1, 1]) - self._prev_masks = np.ones((2, 600, 800)).astype("uint8") - self._curr_boxes = np.array( - [ - [302, 303, 451, 452], - [101, 102, 201, 203], - ] - ).astype(np.float32) - self._curr_scores = np.array([0.95, 0.85]) - self._curr_classes = np.array([1, 1]) - self._curr_masks = np.ones((2, 600, 800)).astype("uint8") - - self._prev_instances = { - "image_size": self._img_size, - "pred_boxes": self._prev_boxes, - "scores": self._prev_scores, - "pred_classes": self._prev_classes, - "pred_masks": self._prev_masks, - } - self._prev_instances = self._convertDictPredictionToInstance(self._prev_instances) - self._curr_instances = { - "image_size": self._img_size, - "pred_boxes": self._curr_boxes, - "scores": self._curr_scores, - "pred_classes": self._curr_classes, - "pred_masks": self._curr_masks, - } - self._curr_instances = self._convertDictPredictionToInstance(self._curr_instances) - - self._max_num_instances = 200 - self._max_lost_frame_count = 0 - self._min_box_rel_dim = 0.02 - self._min_instance_period = 1 - self._track_iou_threshold = 0.5 - - def _convertDictPredictionToInstance(self, prediction: Dict) -> Instances: - """ - convert prediction from Dict to D2 Instances format - """ - res = Instances( - image_size=torch.IntTensor(prediction["image_size"]), - pred_boxes=Boxes(torch.FloatTensor(prediction["pred_boxes"])), - pred_masks=torch.IntTensor(prediction["pred_masks"]), - pred_classes=torch.IntTensor(prediction["pred_classes"]), - scores=torch.FloatTensor(prediction["scores"]), - ) - return res - - def test_init(self): - cfg = { - "_target_": "detectron2.tracking.hungarian_tracker.BaseHungarianTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_initialize_extra_fields(self): - cfg = { - "_target_": "detectron2.tracking.hungarian_tracker.BaseHungarianTracker", - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - instances = tracker._initialize_extra_fields(self._curr_instances) - self.assertTrue(instances.has("ID")) - self.assertTrue(instances.has("ID_period")) - self.assertTrue(instances.has("lost_frame_count")) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/tracking/test_iou_weighted_hungarian_bbox_iou_tracker.py b/preprocess/detectron2/tests/tracking/test_iou_weighted_hungarian_bbox_iou_tracker.py deleted file mode 100644 index 6947399fc4bd356a5c0e8168334e490ab651ae27..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/tracking/test_iou_weighted_hungarian_bbox_iou_tracker.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import copy -import numpy as np -import unittest -from typing import Dict -import torch - -from detectron2.config import CfgNode as CfgNode_ -from detectron2.config import instantiate -from detectron2.structures import Boxes, Instances -from detectron2.tracking.base_tracker import build_tracker_head -from detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker import ( # noqa - IOUWeightedHungarianBBoxIOUTracker, -) - - -class TestIOUWeightedHungarianBBoxIOUTracker(unittest.TestCase): - def setUp(self): - self._img_size = np.array([600, 800]) - self._prev_boxes = np.array( - [ - [101, 101, 200, 200], - [301, 301, 450, 450], - ] - ).astype(np.float32) - self._prev_scores = np.array([0.9, 0.9]) - self._prev_classes = np.array([1, 1]) - self._prev_masks = np.ones((2, 600, 800)).astype("uint8") - self._curr_boxes = np.array( - [ - [302, 303, 451, 452], - [101, 102, 201, 203], - ] - ).astype(np.float32) - self._curr_scores = np.array([0.95, 0.85]) - self._curr_classes = np.array([1, 1]) - self._curr_masks = np.ones((2, 600, 800)).astype("uint8") - - self._prev_instances = { - "image_size": self._img_size, - "pred_boxes": self._prev_boxes, - "scores": self._prev_scores, - "pred_classes": self._prev_classes, - "pred_masks": self._prev_masks, - } - self._prev_instances = self._convertDictPredictionToInstance(self._prev_instances) - self._curr_instances = { - "image_size": self._img_size, - "pred_boxes": self._curr_boxes, - "scores": self._curr_scores, - "pred_classes": self._curr_classes, - "pred_masks": self._curr_masks, - } - self._curr_instances = self._convertDictPredictionToInstance(self._curr_instances) - - self._max_num_instances = 10 - self._max_lost_frame_count = 3 - self._min_box_rel_dim = 0.02 - self._min_instance_period = 1 - self._track_iou_threshold = 0.5 - - def _convertDictPredictionToInstance(self, prediction: Dict) -> Instances: - """ - convert prediction from Dict to D2 Instances format - """ - res = Instances( - image_size=torch.IntTensor(prediction["image_size"]), - pred_boxes=Boxes(torch.FloatTensor(prediction["pred_boxes"])), - pred_masks=torch.IntTensor(prediction["pred_masks"]), - pred_classes=torch.IntTensor(prediction["pred_classes"]), - scores=torch.FloatTensor(prediction["scores"]), - ) - return res - - def test_init(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_from_config(self): - cfg = CfgNode_() - cfg.TRACKER_HEADS = CfgNode_() - cfg.TRACKER_HEADS.TRACKER_NAME = "IOUWeightedHungarianBBoxIOUTracker" - cfg.TRACKER_HEADS.VIDEO_HEIGHT = int(self._img_size[0]) - cfg.TRACKER_HEADS.VIDEO_WIDTH = int(self._img_size[1]) - cfg.TRACKER_HEADS.MAX_NUM_INSTANCES = self._max_num_instances - cfg.TRACKER_HEADS.MAX_LOST_FRAME_COUNT = self._max_lost_frame_count - cfg.TRACKER_HEADS.MIN_BOX_REL_DIM = self._min_box_rel_dim - cfg.TRACKER_HEADS.MIN_INSTANCE_PERIOD = self._min_instance_period - cfg.TRACKER_HEADS.TRACK_IOU_THRESHOLD = self._track_iou_threshold - tracker = build_tracker_head(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_initialize_extra_fields(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - instances = tracker._initialize_extra_fields(self._curr_instances) - self.assertTrue(instances.has("ID")) - self.assertTrue(instances.has("ID_period")) - self.assertTrue(instances.has("lost_frame_count")) - - def test_process_matched_idx(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - self.assertTrue(curr_instances.ID[0] == 1) - - def test_process_unmatched_idx(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - curr_instances = tracker._process_unmatched_idx(curr_instances, matched_idx) - self.assertTrue(curr_instances.ID[1] == 2) - - def test_process_unmatched_prev_idx(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - prev_instances.ID_period = [3, 3] - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - curr_instances = tracker._process_unmatched_idx(curr_instances, matched_idx) - curr_instances = tracker._process_unmatched_prev_idx(curr_instances, matched_prev_idx) - self.assertTrue(curr_instances.ID[2] == 0) - - def test_assign_cost_matrix_values(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - pair1 = {"idx": 0, "prev_idx": 1, "IoU": 0.6} - pair2 = {"idx": 1, "prev_idx": 0, "IoU": 0.8} - bbox_pairs = [pair1, pair2] - cost_matrix = np.full((2, 2), np.inf) - target_matrix = copy.deepcopy(cost_matrix) - target_matrix[0, 1] = -0.6 - target_matrix[1, 0] = -0.8 - cost_matrix = tracker.assign_cost_matrix_values(cost_matrix, bbox_pairs) - self.assertTrue(np.allclose(cost_matrix, target_matrix)) - - def test_update(self): - cfg = { - "_target_": "detectron2.tracking.iou_weighted_hungarian_bbox_iou_tracker.IOUWeightedHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - _ = tracker.update(self._prev_instances) - curr_instances = tracker.update(self._curr_instances) - self.assertTrue(curr_instances.ID[0] == 1) - self.assertTrue(curr_instances.ID[1] == 0) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/tracking/test_vanilla_hungarian_bbox_iou_tracker.py b/preprocess/detectron2/tests/tracking/test_vanilla_hungarian_bbox_iou_tracker.py deleted file mode 100644 index c33e3d971583c52e29284ab9538e4a2ba4e5d8d5..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/tracking/test_vanilla_hungarian_bbox_iou_tracker.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import copy -import numpy as np -import unittest -from typing import Dict -import torch - -from detectron2.config import CfgNode as CfgNode_ -from detectron2.config import instantiate -from detectron2.structures import Boxes, Instances -from detectron2.tracking.base_tracker import build_tracker_head -from detectron2.tracking.vanilla_hungarian_bbox_iou_tracker import ( # noqa - VanillaHungarianBBoxIOUTracker, -) - - -class TestVanillaHungarianBBoxIOUTracker(unittest.TestCase): - def setUp(self): - self._img_size = np.array([600, 800]) - self._prev_boxes = np.array( - [ - [101, 101, 200, 200], - [301, 301, 450, 450], - ] - ).astype(np.float32) - self._prev_scores = np.array([0.9, 0.9]) - self._prev_classes = np.array([1, 1]) - self._prev_masks = np.ones((2, 600, 800)).astype("uint8") - self._curr_boxes = np.array( - [ - [302, 303, 451, 452], - [101, 102, 201, 203], - ] - ).astype(np.float32) - self._curr_scores = np.array([0.95, 0.85]) - self._curr_classes = np.array([1, 1]) - self._curr_masks = np.ones((2, 600, 800)).astype("uint8") - - self._prev_instances = { - "image_size": self._img_size, - "pred_boxes": self._prev_boxes, - "scores": self._prev_scores, - "pred_classes": self._prev_classes, - "pred_masks": self._prev_masks, - } - self._prev_instances = self._convertDictPredictionToInstance(self._prev_instances) - self._curr_instances = { - "image_size": self._img_size, - "pred_boxes": self._curr_boxes, - "scores": self._curr_scores, - "pred_classes": self._curr_classes, - "pred_masks": self._curr_masks, - } - self._curr_instances = self._convertDictPredictionToInstance(self._curr_instances) - - self._max_num_instances = 10 - self._max_lost_frame_count = 3 - self._min_box_rel_dim = 0.02 - self._min_instance_period = 1 - self._track_iou_threshold = 0.5 - - def _convertDictPredictionToInstance(self, prediction: Dict) -> Instances: - """ - convert prediction from Dict to D2 Instances format - """ - res = Instances( - image_size=torch.IntTensor(prediction["image_size"]), - pred_boxes=Boxes(torch.FloatTensor(prediction["pred_boxes"])), - pred_masks=torch.IntTensor(prediction["pred_masks"]), - pred_classes=torch.IntTensor(prediction["pred_classes"]), - scores=torch.FloatTensor(prediction["scores"]), - ) - return res - - def test_init(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_from_config(self): - cfg = CfgNode_() - cfg.TRACKER_HEADS = CfgNode_() - cfg.TRACKER_HEADS.TRACKER_NAME = "VanillaHungarianBBoxIOUTracker" - cfg.TRACKER_HEADS.VIDEO_HEIGHT = int(self._img_size[0]) - cfg.TRACKER_HEADS.VIDEO_WIDTH = int(self._img_size[1]) - cfg.TRACKER_HEADS.MAX_NUM_INSTANCES = self._max_num_instances - cfg.TRACKER_HEADS.MAX_LOST_FRAME_COUNT = self._max_lost_frame_count - cfg.TRACKER_HEADS.MIN_BOX_REL_DIM = self._min_box_rel_dim - cfg.TRACKER_HEADS.MIN_INSTANCE_PERIOD = self._min_instance_period - cfg.TRACKER_HEADS.TRACK_IOU_THRESHOLD = self._track_iou_threshold - tracker = build_tracker_head(cfg) - self.assertTrue(tracker._video_height == self._img_size[0]) - - def test_initialize_extra_fields(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - instances = tracker._initialize_extra_fields(self._curr_instances) - self.assertTrue(instances.has("ID")) - self.assertTrue(instances.has("ID_period")) - self.assertTrue(instances.has("lost_frame_count")) - - def test_process_matched_idx(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - self.assertTrue(curr_instances.ID[0] == 1) - - def test_process_unmatched_idx(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - curr_instances = tracker._process_unmatched_idx(curr_instances, matched_idx) - self.assertTrue(curr_instances.ID[1] == 2) - - def test_process_unmatched_prev_idx(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - prev_instances = tracker._initialize_extra_fields(self._prev_instances) - prev_instances.ID_period = [3, 3] - tracker._prev_instances = prev_instances - curr_instances = tracker._initialize_extra_fields(self._curr_instances) - matched_idx = np.array([0]) - matched_prev_idx = np.array([1]) - curr_instances = tracker._process_matched_idx(curr_instances, matched_idx, matched_prev_idx) - curr_instances = tracker._process_unmatched_idx(curr_instances, matched_idx) - curr_instances = tracker._process_unmatched_prev_idx(curr_instances, matched_prev_idx) - self.assertTrue(curr_instances.ID[2] == 0) - - def test_assign_cost_matrix_values(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - pair1 = {"idx": 0, "prev_idx": 1} - pair2 = {"idx": 1, "prev_idx": 0} - bbox_pairs = [pair1, pair2] - cost_matrix = np.full((2, 2), np.inf) - target_matrix = copy.deepcopy(cost_matrix) - target_matrix[0, 1] = -1 - target_matrix[1, 0] = -1 - cost_matrix = tracker.assign_cost_matrix_values(cost_matrix, bbox_pairs) - self.assertTrue(np.allclose(cost_matrix, target_matrix)) - - def test_update(self): - cfg = { - "_target_": "detectron2.tracking.vanilla_hungarian_bbox_iou_tracker.VanillaHungarianBBoxIOUTracker", # noqa - "video_height": self._img_size[0], - "video_width": self._img_size[1], - "max_num_instances": self._max_num_instances, - "max_lost_frame_count": self._max_lost_frame_count, - "min_box_rel_dim": self._min_box_rel_dim, - "min_instance_period": self._min_instance_period, - "track_iou_threshold": self._track_iou_threshold, - } - tracker = instantiate(cfg) - _ = tracker.update(self._prev_instances) - curr_instances = tracker.update(self._curr_instances) - self.assertTrue(curr_instances.ID[0] == 1) - self.assertTrue(curr_instances.ID[1] == 0) - - -if __name__ == "__main__": - unittest.main() diff --git a/preprocess/detectron2/tests/utils/test_tensorboardx.py b/preprocess/detectron2/tests/utils/test_tensorboardx.py deleted file mode 100644 index 885fb8d3576ff598b988427137c421bc17a41aaf..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tests/utils/test_tensorboardx.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import tempfile -import unittest - -from detectron2.utils.events import TensorboardXWriter - - -# TODO Fix up capitalization -class TestTensorboardXWriter(unittest.TestCase): - def test_no_files_created(self) -> None: - with tempfile.TemporaryDirectory() as tmp_dir: - writer = TensorboardXWriter(tmp_dir) - writer.close() - - self.assertFalse(os.listdir(tmp_dir)) - - def test_single_write(self) -> None: - with tempfile.TemporaryDirectory() as tmp_dir: - writer = TensorboardXWriter(tmp_dir) - writer._writer.add_scalar("testing", 1, 1) - writer.close() - - self.assertTrue(os.listdir(tmp_dir)) diff --git a/preprocess/detectron2/tools/README.md b/preprocess/detectron2/tools/README.md deleted file mode 100644 index 0b40d5319c0838fdaa22bc6a10ef0d88bc6578ed..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/README.md +++ /dev/null @@ -1,49 +0,0 @@ - -This directory contains a few example scripts that demonstrate features of detectron2. - - -* `train_net.py` - -An example training script that's made to train builtin models of detectron2. - -For usage, see [GETTING_STARTED.md](../GETTING_STARTED.md). - -* `plain_train_net.py` - -Similar to `train_net.py`, but implements a training loop instead of using `Trainer`. -This script includes fewer features but it may be more friendly to hackers. - -* `benchmark.py` - -Benchmark the training speed, inference speed or data loading speed of a given config. - -Usage: -``` -python benchmark.py --config-file config.yaml --task train/eval/data [optional DDP flags] -``` - -* `analyze_model.py` - -Analyze FLOPs, parameters, activations of a detectron2 model. See its `--help` for usage. - -* `visualize_json_results.py` - -Visualize the json instance detection/segmentation results dumped by `COCOEvalutor` or `LVISEvaluator` - -Usage: -``` -python visualize_json_results.py --input x.json --output dir/ --dataset coco_2017_val -``` -If not using a builtin dataset, you'll need your own script or modify this script. - -* `visualize_data.py` - -Visualize ground truth raw annotations or training data (after preprocessing/augmentations). - -Usage: -``` -python visualize_data.py --config-file config.yaml --source annotation/dataloader --output-dir dir/ [--show] -``` - -NOTE: the script does not stop by itself when using `--source dataloader` because a training -dataloader is usually infinite. diff --git a/preprocess/detectron2/tools/__init__.py b/preprocess/detectron2/tools/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/preprocess/detectron2/tools/analyze_model.py b/preprocess/detectron2/tools/analyze_model.py deleted file mode 100755 index 543b14e80bf4d3f8ce1426a0e36ca95a8d5fc46c..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/analyze_model.py +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) Facebook, Inc. and its affiliates. - -import logging -from collections import Counter - -import numpy as np -import tqdm - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import CfgNode, get_cfg, instantiate, LazyConfig -from detectron2.data import build_detection_test_loader -from detectron2.engine import default_argument_parser -from detectron2.modeling import build_model -from detectron2.utils.analysis import ( - activation_count_operators, - FlopCountAnalysis, - parameter_count_table, -) -from detectron2.utils.logger import setup_logger -from fvcore.nn import flop_count_table # can also try flop_count_str - -logger = logging.getLogger("detectron2") - - -def setup(args): - if args.config_file.endswith(".yaml"): - cfg = get_cfg() - cfg.merge_from_file(args.config_file) - cfg.DATALOADER.NUM_WORKERS = 0 - cfg.merge_from_list(args.opts) - cfg.freeze() - else: - cfg = LazyConfig.load(args.config_file) - cfg = LazyConfig.apply_overrides(cfg, args.opts) - setup_logger(name="fvcore") - setup_logger() - return cfg - - -def do_flop(cfg): - if isinstance(cfg, CfgNode): - data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) - model = build_model(cfg) - DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) - else: - data_loader = instantiate(cfg.dataloader.test) - model = instantiate(cfg.model) - model.to(cfg.train.device) - DetectionCheckpointer(model).load(cfg.train.init_checkpoint) - model.eval() - - counts = Counter() - total_flops = [] - for idx, data in zip(tqdm.trange(args.num_inputs), data_loader): # noqa - flops = FlopCountAnalysis(model, data) - if idx > 0: - flops.unsupported_ops_warnings(False).uncalled_modules_warnings(False) - counts += flops.by_operator() - total_flops.append(flops.total()) - - logger.info( - "Flops table computed from only one input sample:\n" + flop_count_table(flops) - ) - logger.info( - "Average GFlops for each type of operators:\n" - + str([(k, v / (idx + 1) / 1e9) for k, v in counts.items()]) - ) - logger.info( - "Total GFlops: {:.1f}±{:.1f}".format( - np.mean(total_flops) / 1e9, np.std(total_flops) / 1e9 - ) - ) - - -def do_activation(cfg): - if isinstance(cfg, CfgNode): - data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) - model = build_model(cfg) - DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) - else: - data_loader = instantiate(cfg.dataloader.test) - model = instantiate(cfg.model) - model.to(cfg.train.device) - DetectionCheckpointer(model).load(cfg.train.init_checkpoint) - model.eval() - - counts = Counter() - total_activations = [] - for idx, data in zip(tqdm.trange(args.num_inputs), data_loader): # noqa - count = activation_count_operators(model, data) - counts += count - total_activations.append(sum(count.values())) - logger.info( - "(Million) Activations for Each Type of Operators:\n" - + str([(k, v / idx) for k, v in counts.items()]) - ) - logger.info( - "Total (Million) Activations: {}±{}".format( - np.mean(total_activations), np.std(total_activations) - ) - ) - - -def do_parameter(cfg): - if isinstance(cfg, CfgNode): - model = build_model(cfg) - else: - model = instantiate(cfg.model) - logger.info("Parameter Count:\n" + parameter_count_table(model, max_depth=5)) - - -def do_structure(cfg): - if isinstance(cfg, CfgNode): - model = build_model(cfg) - else: - model = instantiate(cfg.model) - logger.info("Model Structure:\n" + str(model)) - - -def main() -> None: - global cfg, args - parser = default_argument_parser( - epilog=""" -Examples: - -To show parameters of a model: -$ ./analyze_model.py --tasks parameter \\ - --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml - -Flops and activations are data-dependent, therefore inputs and model weights -are needed to count them: - -$ ./analyze_model.py --num-inputs 100 --tasks flop \\ - --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \\ - MODEL.WEIGHTS /path/to/model.pkl -""" - ) - parser.add_argument( - "--tasks", - choices=["flop", "activation", "parameter", "structure"], - required=True, - nargs="+", - ) - parser.add_argument( - "-n", - "--num-inputs", - default=100, - type=int, - help="number of inputs used to compute statistics for flops/activations, " - "both are data dependent.", - ) - args = parser.parse_args() - assert not args.eval_only - assert args.num_gpus == 1 - - cfg = setup(args) - - for task in args.tasks: - { - "flop": do_flop, - "activation": do_activation, - "parameter": do_parameter, - "structure": do_structure, - }[task](cfg) - - -if __name__ == "__main__": - main() # pragma: no cover diff --git a/preprocess/detectron2/tools/benchmark.py b/preprocess/detectron2/tools/benchmark.py deleted file mode 100755 index 418a723f64a5e5804f1f01105421156c85a483fd..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/benchmark.py +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -""" -A script to benchmark builtin models. - -Note: this script has an extra dependency of psutil. -""" - -import itertools -import logging - -import psutil -import torch -import tqdm - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg, instantiate, LazyConfig -from detectron2.data import ( - build_detection_test_loader, - build_detection_train_loader, - DatasetFromList, -) -from detectron2.data.benchmark import DataLoaderBenchmark -from detectron2.engine import ( - AMPTrainer, - default_argument_parser, - hooks, - launch, - SimpleTrainer, -) -from detectron2.modeling import build_model -from detectron2.solver import build_optimizer -from detectron2.utils import comm -from detectron2.utils.collect_env import collect_env_info -from detectron2.utils.events import CommonMetricPrinter -from detectron2.utils.logger import setup_logger -from fvcore.common.timer import Timer -from torch.nn.parallel import DistributedDataParallel - -logger = logging.getLogger("detectron2") - - -def setup(args): - if args.config_file.endswith(".yaml"): - cfg = get_cfg() - cfg.merge_from_file(args.config_file) - cfg.SOLVER.BASE_LR = 0.001 # Avoid NaNs. Not useful in this script anyway. - cfg.merge_from_list(args.opts) - cfg.freeze() - else: - cfg = LazyConfig.load(args.config_file) - cfg = LazyConfig.apply_overrides(cfg, args.opts) - setup_logger(distributed_rank=comm.get_rank()) - return cfg - - -def create_data_benchmark(cfg, args): - if args.config_file.endswith(".py"): - dl_cfg = cfg.dataloader.train - dl_cfg._target_ = DataLoaderBenchmark - return instantiate(dl_cfg) - else: - kwargs = build_detection_train_loader.from_config(cfg) - kwargs.pop("aspect_ratio_grouping", None) - kwargs["_target_"] = DataLoaderBenchmark - return instantiate(kwargs) - - -def RAM_msg(): - vram = psutil.virtual_memory() - return "RAM Usage: {:.2f}/{:.2f} GB".format( - (vram.total - vram.available) / 1024**3, vram.total / 1024**3 - ) - - -def benchmark_data(args): - cfg = setup(args) - logger.info("After spawning " + RAM_msg()) - - benchmark = create_data_benchmark(cfg, args) - benchmark.benchmark_distributed(250, 10) - # test for a few more rounds - for k in range(10): - logger.info(f"Iteration {k} " + RAM_msg()) - benchmark.benchmark_distributed(250, 1) - - -def benchmark_data_advanced(args): - # benchmark dataloader with more details to help analyze performance bottleneck - cfg = setup(args) - benchmark = create_data_benchmark(cfg, args) - - if comm.get_rank() == 0: - benchmark.benchmark_dataset(100) - benchmark.benchmark_mapper(100) - benchmark.benchmark_workers(100, warmup=10) - benchmark.benchmark_IPC(100, warmup=10) - if comm.get_world_size() > 1: - benchmark.benchmark_distributed(100) - logger.info("Rerun ...") - benchmark.benchmark_distributed(100) - - -def benchmark_train(args): - cfg = setup(args) - model = build_model(cfg) - logger.info("Model:\n{}".format(model)) - if comm.get_world_size() > 1: - model = DistributedDataParallel( - model, device_ids=[comm.get_local_rank()], broadcast_buffers=False - ) - optimizer = build_optimizer(cfg, model) - checkpointer = DetectionCheckpointer(model, optimizer=optimizer) - checkpointer.load(cfg.MODEL.WEIGHTS) - - cfg.defrost() - cfg.DATALOADER.NUM_WORKERS = 2 - data_loader = build_detection_train_loader(cfg) - dummy_data = list(itertools.islice(data_loader, 100)) - - def f(): - data = DatasetFromList(dummy_data, copy=False, serialize=False) - while True: - yield from data - - max_iter = 400 - trainer = (AMPTrainer if cfg.SOLVER.AMP.ENABLED else SimpleTrainer)( - model, f(), optimizer - ) - trainer.register_hooks( - [ - hooks.IterationTimer(), - hooks.PeriodicWriter([CommonMetricPrinter(max_iter)]), - hooks.TorchProfiler( - lambda trainer: trainer.iter == max_iter - 1, - cfg.OUTPUT_DIR, - save_tensorboard=True, - ), - ] - ) - trainer.train(1, max_iter) - - -@torch.no_grad() -def benchmark_eval(args): - cfg = setup(args) - if args.config_file.endswith(".yaml"): - model = build_model(cfg) - DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) - - cfg.defrost() - cfg.DATALOADER.NUM_WORKERS = 0 - data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) - else: - model = instantiate(cfg.model) - model.to(cfg.train.device) - DetectionCheckpointer(model).load(cfg.train.init_checkpoint) - - cfg.dataloader.num_workers = 0 - data_loader = instantiate(cfg.dataloader.test) - - model.eval() - logger.info("Model:\n{}".format(model)) - dummy_data = DatasetFromList(list(itertools.islice(data_loader, 100)), copy=False) - - def f(): - while True: - yield from dummy_data - - for k in range(5): # warmup - model(dummy_data[k]) - - max_iter = 300 - timer = Timer() - with tqdm.tqdm(total=max_iter) as pbar: - for idx, d in enumerate(f()): - if idx == max_iter: - break - model(d) - pbar.update() - logger.info("{} iters in {} seconds.".format(max_iter, timer.seconds())) - - -def main() -> None: - parser = default_argument_parser() - parser.add_argument( - "--task", choices=["train", "eval", "data", "data_advanced"], required=True - ) - args = parser.parse_args() - assert not args.eval_only - - logger.info("Environment info:\n" + collect_env_info()) - if "data" in args.task: - print("Initial " + RAM_msg()) - if args.task == "data": - f = benchmark_data - if args.task == "data_advanced": - f = benchmark_data_advanced - elif args.task == "train": - """ - Note: training speed may not be representative. - The training cost of a R-CNN model varies with the content of the data - and the quality of the model. - """ - f = benchmark_train - elif args.task == "eval": - f = benchmark_eval - # only benchmark single-GPU inference. - assert args.num_gpus == 1 and args.num_machines == 1 - launch( - f, - args.num_gpus, - args.num_machines, - args.machine_rank, - args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - main() # pragma: no cover diff --git a/preprocess/detectron2/tools/convert-torchvision-to-d2.py b/preprocess/detectron2/tools/convert-torchvision-to-d2.py deleted file mode 100755 index 4b827d960cca69657e98bd89a9aa5623a847099d..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/convert-torchvision-to-d2.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. - -import pickle as pkl -import sys -import torch - -""" -Usage: - # download one of the ResNet{18,34,50,101,152} models from torchvision: - wget https://download.pytorch.org/models/resnet50-19c8e357.pth -O r50.pth - # run the conversion - ./convert-torchvision-to-d2.py r50.pth r50.pkl - - # Then, use r50.pkl with the following changes in config: - -MODEL: - WEIGHTS: "/path/to/r50.pkl" - PIXEL_MEAN: [123.675, 116.280, 103.530] - PIXEL_STD: [58.395, 57.120, 57.375] - RESNETS: - DEPTH: 50 - STRIDE_IN_1X1: False -INPUT: - FORMAT: "RGB" - - These models typically produce slightly worse results than the - pre-trained ResNets we use in official configs, which are the - original ResNet models released by MSRA. -""" - -if __name__ == "__main__": - input = sys.argv[1] - - obj = torch.load(input, map_location="cpu") - - newmodel = {} - for k in list(obj.keys()): - old_k = k - if "layer" not in k: - k = "stem." + k - for t in [1, 2, 3, 4]: - k = k.replace("layer{}".format(t), "res{}".format(t + 1)) - for t in [1, 2, 3]: - k = k.replace("bn{}".format(t), "conv{}.norm".format(t)) - k = k.replace("downsample.0", "shortcut") - k = k.replace("downsample.1", "shortcut.norm") - print(old_k, "->", k) - newmodel[k] = obj.pop(old_k).detach().numpy() - - res = {"model": newmodel, "__author__": "torchvision", "matching_heuristics": True} - - with open(sys.argv[2], "wb") as f: - pkl.dump(res, f) - if obj: - print("Unconverted keys:", obj.keys()) diff --git a/preprocess/detectron2/tools/deploy/CMakeLists.txt b/preprocess/detectron2/tools/deploy/CMakeLists.txt deleted file mode 100644 index 80dae12500af4c7e7e6cfc5b7b3a5800782956c3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/deploy/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# See https://pytorch.org/tutorials/advanced/cpp_frontend.html -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) -project(torchscript_mask_rcnn) - -find_package(Torch REQUIRED) -find_package(OpenCV REQUIRED) -find_package(TorchVision REQUIRED) # needed by export-method=tracing/scripting - -add_executable(torchscript_mask_rcnn torchscript_mask_rcnn.cpp) -target_link_libraries( - torchscript_mask_rcnn - -Wl,--no-as-needed TorchVision::TorchVision -Wl,--as-needed - "${TORCH_LIBRARIES}" ${OpenCV_LIBS}) -set_property(TARGET torchscript_mask_rcnn PROPERTY CXX_STANDARD 14) diff --git a/preprocess/detectron2/tools/deploy/README.md b/preprocess/detectron2/tools/deploy/README.md deleted file mode 100644 index e33cbeb54c003a5738da68c838fdaa4e0d218501..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/deploy/README.md +++ /dev/null @@ -1,66 +0,0 @@ -See [deployment tutorial](https://detectron2.readthedocs.io/tutorials/deployment.html) -for some high-level background about deployment. - -This directory contains the following examples: - -1. An example script `export_model.py` - that exports a detectron2 model for deployment using different methods and formats. - -2. A C++ example that runs inference with Mask R-CNN model in TorchScript format. - -## Build -Deployment depends on libtorch and OpenCV. Some require more dependencies: - -* Running TorchScript-format models produced by `--export-method=caffe2_tracing` requires libtorch - to be built with caffe2 enabled. -* Running TorchScript-format models produced by `--export-method=tracing/scripting` requires libtorchvision (C++ library of torchvision). - -All methods are supported in one C++ file that requires all the above dependencies. -Adjust it and remove code you don't need. -As a reference, we provide a [Dockerfile](../../docker/deploy.Dockerfile) that installs all the above dependencies and builds the C++ example. - -## Use - -We show a few example commands to export and execute a Mask R-CNN model in C++. - -* `export-method=tracing, format=torchscript`: -``` -./export_model.py --config-file ../../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ - --output ./output --export-method tracing --format torchscript \ - MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl \ - MODEL.DEVICE cuda - -./build/torchscript_mask_rcnn output/model.ts input.jpg tracing -``` - -* `export-method=scripting, format=torchscript`: -``` -./export_model.py --config-file ../../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ - --output ./output --export-method scripting --format torchscript \ - MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl \ - -./build/torchscript_mask_rcnn output/model.ts input.jpg scripting -``` - -* `export-method=caffe2_tracing, format=torchscript`: - -``` -./export_model.py --config-file ../../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ - --output ./output --export-method caffe2_tracing --format torchscript \ - MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl \ - -./build/torchscript_mask_rcnn output/model.ts input.jpg caffe2_tracing -``` - - -## Notes: - -1. Tracing/Caffe2-tracing requires valid weights & sample inputs. - Therefore the above commands require pre-trained models and [COCO dataset](https://detectron2.readthedocs.io/tutorials/builtin_datasets.html). - You can modify the script to obtain sample inputs in other ways instead of from COCO. - -2. `--run-eval` is implemented only for tracing mode - to evaluate the exported model using the dataset in the config. - It's recommended to always verify the accuracy in case the conversion is not successful. - Evaluation can be slow if model is exported to CPU or dataset is too large ("coco_2017_val_100" is a small subset of COCO useful for evaluation). - `caffe2_tracing` accuracy may be slightly different (within 0.1 AP) from original model due to numerical precisions between different runtime. diff --git a/preprocess/detectron2/tools/deploy/export_model.py b/preprocess/detectron2/tools/deploy/export_model.py deleted file mode 100755 index 041f9124278f40618e87927822ba98169e758432..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/deploy/export_model.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -import argparse -import os -from typing import Dict, List, Tuple - -import detectron2.data.transforms as T -import torch -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_test_loader, detection_utils -from detectron2.evaluation import COCOEvaluator, inference_on_dataset, print_csv_format -from detectron2.export import ( - dump_torchscript_IR, - scripting_with_instances, - STABLE_ONNX_OPSET_VERSION, - TracingAdapter, -) -from detectron2.modeling import build_model, GeneralizedRCNN, RetinaNet -from detectron2.modeling.postprocessing import detector_postprocess -from detectron2.projects.point_rend import add_pointrend_config -from detectron2.structures import Boxes -from detectron2.utils.env import TORCH_VERSION -from detectron2.utils.file_io import PathManager -from detectron2.utils.logger import setup_logger -from torch import nn, Tensor - - -def setup_cfg(args): - cfg = get_cfg() - # cuda context is initialized before creating dataloader, so we don't fork anymore - cfg.DATALOADER.NUM_WORKERS = 0 - add_pointrend_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - return cfg - - -def export_caffe2_tracing(cfg, torch_model, inputs): - from detectron2.export import Caffe2Tracer - - tracer = Caffe2Tracer(cfg, torch_model, inputs) - if args.format == "caffe2": - caffe2_model = tracer.export_caffe2() - caffe2_model.save_protobuf(args.output) - # draw the caffe2 graph - caffe2_model.save_graph(os.path.join(args.output, "model.svg"), inputs=inputs) - return caffe2_model - elif args.format == "onnx": - import onnx - - onnx_model = tracer.export_onnx() - onnx.save(onnx_model, os.path.join(args.output, "model.onnx")) - elif args.format == "torchscript": - ts_model = tracer.export_torchscript() - with PathManager.open(os.path.join(args.output, "model.ts"), "wb") as f: - torch.jit.save(ts_model, f) - dump_torchscript_IR(ts_model, args.output) - - -# experimental. API not yet final -def export_scripting(torch_model): - assert TORCH_VERSION >= (1, 8) - fields = { - "proposal_boxes": Boxes, - "objectness_logits": Tensor, - "pred_boxes": Boxes, - "scores": Tensor, - "pred_classes": Tensor, - "pred_masks": Tensor, - "pred_keypoints": torch.Tensor, - "pred_keypoint_heatmaps": torch.Tensor, - } - assert args.format == "torchscript", "Scripting only supports torchscript format." - - class ScriptableAdapterBase(nn.Module): - # Use this adapter to workaround https://github.com/pytorch/pytorch/issues/46944 - # by not retuning instances but dicts. Otherwise the exported model is not deployable - def __init__(self): - super().__init__() - self.model = torch_model - self.eval() - - if isinstance(torch_model, GeneralizedRCNN): - - class ScriptableAdapter(ScriptableAdapterBase): - def forward( - self, inputs: Tuple[Dict[str, torch.Tensor]] - ) -> List[Dict[str, Tensor]]: - instances = self.model.inference(inputs, do_postprocess=False) - return [i.get_fields() for i in instances] - - else: - - class ScriptableAdapter(ScriptableAdapterBase): - def forward( - self, inputs: Tuple[Dict[str, torch.Tensor]] - ) -> List[Dict[str, Tensor]]: - instances = self.model(inputs) - return [i.get_fields() for i in instances] - - ts_model = scripting_with_instances(ScriptableAdapter(), fields) - with PathManager.open(os.path.join(args.output, "model.ts"), "wb") as f: - torch.jit.save(ts_model, f) - dump_torchscript_IR(ts_model, args.output) - # TODO inference in Python now missing postprocessing glue code - return None - - -# experimental. API not yet final -def export_tracing(torch_model, inputs): - assert TORCH_VERSION >= (1, 8) - image = inputs[0]["image"] - inputs = [{"image": image}] # remove other unused keys - - if isinstance(torch_model, GeneralizedRCNN): - - def inference(model, inputs): - # use do_postprocess=False so it returns ROI mask - inst = model.inference(inputs, do_postprocess=False)[0] - return [{"instances": inst}] - - else: - inference = None # assume that we just call the model directly - - traceable_model = TracingAdapter(torch_model, inputs, inference) - - if args.format == "torchscript": - ts_model = torch.jit.trace(traceable_model, (image,)) - with PathManager.open(os.path.join(args.output, "model.ts"), "wb") as f: - torch.jit.save(ts_model, f) - dump_torchscript_IR(ts_model, args.output) - elif args.format == "onnx": - with PathManager.open(os.path.join(args.output, "model.onnx"), "wb") as f: - torch.onnx.export( - traceable_model, (image,), f, opset_version=STABLE_ONNX_OPSET_VERSION - ) - logger.info("Inputs schema: " + str(traceable_model.inputs_schema)) - logger.info("Outputs schema: " + str(traceable_model.outputs_schema)) - - if args.format != "torchscript": - return None - if not isinstance(torch_model, (GeneralizedRCNN, RetinaNet)): - return None - - def eval_wrapper(inputs): - """ - The exported model does not contain the final resize step, which is typically - unused in deployment but needed for evaluation. We add it manually here. - """ - input = inputs[0] - instances = traceable_model.outputs_schema(ts_model(input["image"]))[0][ - "instances" - ] - postprocessed = detector_postprocess(instances, input["height"], input["width"]) - return [{"instances": postprocessed}] - - return eval_wrapper - - -def get_sample_inputs(args): - - if args.sample_image is None: - # get a first batch from dataset - data_loader = build_detection_test_loader(cfg, cfg.DATASETS.TEST[0]) - first_batch = next(iter(data_loader)) - return first_batch - else: - # get a sample data - original_image = detection_utils.read_image( - args.sample_image, format=cfg.INPUT.FORMAT - ) - # Do same preprocessing as DefaultPredictor - aug = T.ResizeShortestEdge( - [cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST - ) - height, width = original_image.shape[:2] - image = aug.get_transform(original_image).apply_image(original_image) - image = torch.as_tensor(image.astype("float32").transpose(2, 0, 1)) - - inputs = {"image": image, "height": height, "width": width} - - # Sample ready - sample_inputs = [inputs] - return sample_inputs - - -def main() -> None: - global logger, cfg, args - parser = argparse.ArgumentParser(description="Export a model for deployment.") - parser.add_argument( - "--format", - choices=["caffe2", "onnx", "torchscript"], - help="output format", - default="torchscript", - ) - parser.add_argument( - "--export-method", - choices=["caffe2_tracing", "tracing", "scripting"], - help="Method to export models", - default="tracing", - ) - parser.add_argument( - "--config-file", default="", metavar="FILE", help="path to config file" - ) - parser.add_argument( - "--sample-image", default=None, type=str, help="sample image for input" - ) - parser.add_argument("--run-eval", action="store_true") - parser.add_argument("--output", help="output directory for the converted model") - parser.add_argument( - "opts", - help="Modify config options using the command-line", - default=None, - nargs=argparse.REMAINDER, - ) - args = parser.parse_args() - logger = setup_logger() - logger.info("Command line arguments: " + str(args)) - PathManager.mkdirs(args.output) - # Disable re-specialization on new shapes. Otherwise --run-eval will be slow - torch._C._jit_set_bailout_depth(1) - - cfg = setup_cfg(args) - - # create a torch model - torch_model = build_model(cfg) - DetectionCheckpointer(torch_model).resume_or_load(cfg.MODEL.WEIGHTS) - torch_model.eval() - - # convert and save model - if args.export_method == "caffe2_tracing": - sample_inputs = get_sample_inputs(args) - exported_model = export_caffe2_tracing(cfg, torch_model, sample_inputs) - elif args.export_method == "scripting": - exported_model = export_scripting(torch_model) - elif args.export_method == "tracing": - sample_inputs = get_sample_inputs(args) - exported_model = export_tracing(torch_model, sample_inputs) - - # run evaluation with the converted model - if args.run_eval: - assert exported_model is not None, ( - "Python inference is not yet implemented for " - f"export_method={args.export_method}, format={args.format}." - ) - logger.info( - "Running evaluation ... this takes a long time if you export to CPU." - ) - dataset = cfg.DATASETS.TEST[0] - data_loader = build_detection_test_loader(cfg, dataset) - # NOTE: hard-coded evaluator. change to the evaluator for your dataset - evaluator = COCOEvaluator(dataset, output_dir=args.output) - metrics = inference_on_dataset(exported_model, data_loader, evaluator) - print_csv_format(metrics) - logger.info("Success.") - - -if __name__ == "__main__": - main() # pragma: no cover diff --git a/preprocess/detectron2/tools/deploy/torchscript_mask_rcnn.cpp b/preprocess/detectron2/tools/deploy/torchscript_mask_rcnn.cpp deleted file mode 100644 index fd6e1e9f82652a1d4d221447cd140ab675f312b2..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/deploy/torchscript_mask_rcnn.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// @lint-ignore-every CLANGTIDY -// This is an example code that demonstrates how to run inference -// with a torchscript format Mask R-CNN model exported by ./export_model.py -// using export method=tracing, caffe2_tracing & scripting. - -#include -#include -#include - -#include -#include -#include -#include - -// only needed for export_method=tracing -#include // @oss-only -// @fb-only: #include - -using namespace std; - -c10::IValue get_caffe2_tracing_inputs(cv::Mat& img, c10::Device device) { - const int height = img.rows; - const int width = img.cols; - // FPN models require divisibility of 32. - // Tracing mode does padding inside the graph, but caffe2_tracing does not. - assert(height % 32 == 0 && width % 32 == 0); - const int channels = 3; - - auto input = - torch::from_blob(img.data, {1, height, width, channels}, torch::kUInt8); - // NHWC to NCHW - input = input.to(device, torch::kFloat).permute({0, 3, 1, 2}).contiguous(); - - std::array im_info_data{height * 1.0f, width * 1.0f, 1.0f}; - auto im_info = - torch::from_blob(im_info_data.data(), {1, 3}).clone().to(device); - return std::make_tuple(input, im_info); -} - -c10::IValue get_tracing_inputs(cv::Mat& img, c10::Device device) { - const int height = img.rows; - const int width = img.cols; - const int channels = 3; - - auto input = - torch::from_blob(img.data, {height, width, channels}, torch::kUInt8); - // HWC to CHW - input = input.to(device, torch::kFloat).permute({2, 0, 1}).contiguous(); - return input; -} - -// create a Tuple[Dict[str, Tensor]] which is the input type of scripted model -c10::IValue get_scripting_inputs(cv::Mat& img, c10::Device device) { - const int height = img.rows; - const int width = img.cols; - const int channels = 3; - - auto img_tensor = - torch::from_blob(img.data, {height, width, channels}, torch::kUInt8); - // HWC to CHW - img_tensor = - img_tensor.to(device, torch::kFloat).permute({2, 0, 1}).contiguous(); - auto dic = c10::Dict(); - dic.insert("image", img_tensor); - return std::make_tuple(dic); -} - -c10::IValue -get_inputs(std::string export_method, cv::Mat& img, c10::Device device) { - // Given an image, create inputs in the format required by the model. - if (export_method == "tracing") - return get_tracing_inputs(img, device); - if (export_method == "caffe2_tracing") - return get_caffe2_tracing_inputs(img, device); - if (export_method == "scripting") - return get_scripting_inputs(img, device); - abort(); -} - -struct MaskRCNNOutputs { - at::Tensor pred_boxes, pred_classes, pred_masks, scores; - int num_instances() const { - return pred_boxes.sizes()[0]; - } -}; - -MaskRCNNOutputs get_outputs(std::string export_method, c10::IValue outputs) { - // Given outputs of the model, extract tensors from it to turn into a - // common MaskRCNNOutputs format. - if (export_method == "tracing") { - auto out_tuple = outputs.toTuple()->elements(); - // They are ordered alphabetically by their field name in Instances - return MaskRCNNOutputs{ - out_tuple[0].toTensor(), - out_tuple[1].toTensor(), - out_tuple[2].toTensor(), - out_tuple[3].toTensor()}; - } - if (export_method == "caffe2_tracing") { - auto out_tuple = outputs.toTuple()->elements(); - // A legacy order used by caffe2 models - return MaskRCNNOutputs{ - out_tuple[0].toTensor(), - out_tuple[2].toTensor(), - out_tuple[3].toTensor(), - out_tuple[1].toTensor()}; - } - if (export_method == "scripting") { - // With the ScriptableAdapter defined in export_model.py, the output is - // List[Dict[str, Any]]. - auto out_dict = outputs.toList().get(0).toGenericDict(); - return MaskRCNNOutputs{ - out_dict.at("pred_boxes").toTensor(), - out_dict.at("pred_classes").toTensor(), - out_dict.at("pred_masks").toTensor(), - out_dict.at("scores").toTensor()}; - } - abort(); -} - -int main(int argc, const char* argv[]) { - if (argc != 4) { - cerr << R"xx( -Usage: - ./torchscript_mask_rcnn model.ts input.jpg EXPORT_METHOD - - EXPORT_METHOD can be "tracing", "caffe2_tracing" or "scripting". -)xx"; - return 1; - } - std::string image_file = argv[2]; - std::string export_method = argv[3]; - assert( - export_method == "caffe2_tracing" || export_method == "tracing" || - export_method == "scripting"); - - torch::jit::FusionStrategy strat = {{torch::jit::FusionBehavior::DYNAMIC, 1}}; - torch::jit::setFusionStrategy(strat); - torch::autograd::AutoGradMode guard(false); - auto module = torch::jit::load(argv[1]); - - assert(module.buffers().size() > 0); - // Assume that the entire model is on the same device. - // We just put input to this device. - auto device = (*begin(module.buffers())).device(); - - cv::Mat input_img = cv::imread(image_file, cv::IMREAD_COLOR); - auto inputs = get_inputs(export_method, input_img, device); - - // Run the network - auto output = module.forward({inputs}); - if (device.is_cuda()) - c10::cuda::getCurrentCUDAStream().synchronize(); - - // run 3 more times to benchmark - int N_benchmark = 3, N_warmup = 1; - auto start_time = chrono::high_resolution_clock::now(); - for (int i = 0; i < N_benchmark + N_warmup; ++i) { - if (i == N_warmup) - start_time = chrono::high_resolution_clock::now(); - output = module.forward({inputs}); - if (device.is_cuda()) - c10::cuda::getCurrentCUDAStream().synchronize(); - } - auto end_time = chrono::high_resolution_clock::now(); - auto ms = chrono::duration_cast(end_time - start_time) - .count(); - cout << "Latency (should vary with different inputs): " - << ms * 1.0 / 1e6 / N_benchmark << " seconds" << endl; - - // Parse Mask R-CNN outputs - auto rcnn_outputs = get_outputs(export_method, output); - cout << "Number of detected objects: " << rcnn_outputs.num_instances() - << endl; - - cout << "pred_boxes: " << rcnn_outputs.pred_boxes.toString() << " " - << rcnn_outputs.pred_boxes.sizes() << endl; - cout << "scores: " << rcnn_outputs.scores.toString() << " " - << rcnn_outputs.scores.sizes() << endl; - cout << "pred_classes: " << rcnn_outputs.pred_classes.toString() << " " - << rcnn_outputs.pred_classes.sizes() << endl; - cout << "pred_masks: " << rcnn_outputs.pred_masks.toString() << " " - << rcnn_outputs.pred_masks.sizes() << endl; - - cout << rcnn_outputs.pred_boxes << endl; - return 0; -} diff --git a/preprocess/detectron2/tools/lazyconfig_train_net.py b/preprocess/detectron2/tools/lazyconfig_train_net.py deleted file mode 100755 index 27f0cc056b0cf05e7b907cb2931eaf0cfd315327..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/lazyconfig_train_net.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -""" -Training script using the new "LazyConfig" python config files. - -This scripts reads a given python config file and runs the training or evaluation. -It can be used to train any models or dataset as long as they can be -instantiated by the recursive construction defined in the given config file. - -Besides lazy construction of models, dataloader, etc., this scripts expects a -few common configuration parameters currently defined in "configs/common/train.py". -To add more complicated training logic, you can easily add other configs -in the config file and implement a new train_net.py to handle them. -""" -import logging - -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import instantiate, LazyConfig -from detectron2.engine import ( - AMPTrainer, - default_argument_parser, - default_setup, - default_writers, - hooks, - launch, - SimpleTrainer, -) -from detectron2.engine.defaults import create_ddp_model -from detectron2.evaluation import inference_on_dataset, print_csv_format -from detectron2.utils import comm - -logger = logging.getLogger("detectron2") - - -def do_test(cfg, model): - if "evaluator" in cfg.dataloader: - ret = inference_on_dataset( - model, - instantiate(cfg.dataloader.test), - instantiate(cfg.dataloader.evaluator), - ) - print_csv_format(ret) - return ret - - -def do_train(args, cfg): - """ - Args: - cfg: an object with the following attributes: - model: instantiate to a module - dataloader.{train,test}: instantiate to dataloaders - dataloader.evaluator: instantiate to evaluator for test set - optimizer: instantaite to an optimizer - lr_multiplier: instantiate to a fvcore scheduler - train: other misc config defined in `configs/common/train.py`, including: - output_dir (str) - init_checkpoint (str) - amp.enabled (bool) - max_iter (int) - eval_period, log_period (int) - device (str) - checkpointer (dict) - ddp (dict) - """ - model = instantiate(cfg.model) - logger = logging.getLogger("detectron2") - logger.info("Model:\n{}".format(model)) - model.to(cfg.train.device) - - cfg.optimizer.params.model = model - optim = instantiate(cfg.optimizer) - - train_loader = instantiate(cfg.dataloader.train) - - model = create_ddp_model(model, **cfg.train.ddp) - trainer = (AMPTrainer if cfg.train.amp.enabled else SimpleTrainer)( - model, train_loader, optim - ) - checkpointer = DetectionCheckpointer( - model, - cfg.train.output_dir, - trainer=trainer, - ) - trainer.register_hooks( - [ - hooks.IterationTimer(), - hooks.LRScheduler(scheduler=instantiate(cfg.lr_multiplier)), - hooks.PeriodicCheckpointer(checkpointer, **cfg.train.checkpointer) - if comm.is_main_process() - else None, - hooks.EvalHook(cfg.train.eval_period, lambda: do_test(cfg, model)), - hooks.PeriodicWriter( - default_writers(cfg.train.output_dir, cfg.train.max_iter), - period=cfg.train.log_period, - ) - if comm.is_main_process() - else None, - ] - ) - - checkpointer.resume_or_load(cfg.train.init_checkpoint, resume=args.resume) - if args.resume and checkpointer.has_checkpoint(): - # The checkpoint stores the training iteration that just finished, thus we start - # at the next iteration - start_iter = trainer.iter + 1 - else: - start_iter = 0 - trainer.train(start_iter, cfg.train.max_iter) - - -def main(args): - cfg = LazyConfig.load(args.config_file) - cfg = LazyConfig.apply_overrides(cfg, args.opts) - default_setup(cfg, args) - - if args.eval_only: - model = instantiate(cfg.model) - model.to(cfg.train.device) - model = create_ddp_model(model) - DetectionCheckpointer(model).load(cfg.train.init_checkpoint) - print(do_test(cfg, model)) - else: - do_train(args, cfg) - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/tools/lightning_train_net.py b/preprocess/detectron2/tools/lightning_train_net.py deleted file mode 100644 index c711a7173b0b87986322f3fc3c5c3b4cf0545efb..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/lightning_train_net.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. -# Lightning Trainer should be considered beta at this point -# We have confirmed that training and validation run correctly and produce correct results -# Depending on how you launch the trainer, there are issues with processes terminating correctly -# This module is still dependent on D2 logging, but could be transferred to use Lightning logging - -import logging -import os -import time -import weakref -from collections import OrderedDict -from typing import Any, Dict, List - -import detectron2.utils.comm as comm -import pytorch_lightning as pl # type: ignore -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import build_detection_test_loader, build_detection_train_loader -from detectron2.engine import ( - default_argument_parser, - default_setup, - default_writers, - DefaultTrainer, - hooks, - SimpleTrainer, -) -from detectron2.evaluation import print_csv_format -from detectron2.evaluation.testing import flatten_results_dict -from detectron2.modeling import build_model -from detectron2.solver import build_lr_scheduler, build_optimizer -from detectron2.utils.events import EventStorage -from detectron2.utils.logger import setup_logger -from pytorch_lightning import LightningDataModule, LightningModule - -from train_net import build_evaluator - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger("detectron2") - - -class TrainingModule(LightningModule): - def __init__(self, cfg): - super().__init__() - if not logger.isEnabledFor(logging.INFO): # setup_logger is not called for d2 - setup_logger() - self.cfg = DefaultTrainer.auto_scale_workers(cfg, comm.get_world_size()) - self.storage: EventStorage = None - self.model = build_model(self.cfg) - - self.start_iter = 0 - self.max_iter = cfg.SOLVER.MAX_ITER - - def on_save_checkpoint(self, checkpoint: Dict[str, Any]) -> None: - checkpoint["iteration"] = self.storage.iter - - def on_load_checkpoint(self, checkpointed_state: Dict[str, Any]) -> None: - self.start_iter = checkpointed_state["iteration"] - self.storage.iter = self.start_iter - - def setup(self, stage: str): - if self.cfg.MODEL.WEIGHTS: - self.checkpointer = DetectionCheckpointer( - # Assume you want to save checkpoints together with logs/statistics - self.model, - self.cfg.OUTPUT_DIR, - ) - logger.info( - f"Load model weights from checkpoint: {self.cfg.MODEL.WEIGHTS}." - ) - # Only load weights, use lightning checkpointing if you want to resume - self.checkpointer.load(self.cfg.MODEL.WEIGHTS) - - self.iteration_timer = hooks.IterationTimer() - self.iteration_timer.before_train() - self.data_start = time.perf_counter() - self.writers = None - - def training_step(self, batch, batch_idx): - data_time = time.perf_counter() - self.data_start - # Need to manually enter/exit since trainer may launch processes - # This ideally belongs in setup, but setup seems to run before processes are spawned - if self.storage is None: - self.storage = EventStorage(0) - self.storage.__enter__() - self.iteration_timer.trainer = weakref.proxy(self) - self.iteration_timer.before_step() - self.writers = ( - default_writers(self.cfg.OUTPUT_DIR, self.max_iter) - if comm.is_main_process() - else {} - ) - - loss_dict = self.model(batch) - SimpleTrainer.write_metrics(loss_dict, data_time) - - opt = self.optimizers() - self.storage.put_scalar( - "lr", - opt.param_groups[self._best_param_group_id]["lr"], - smoothing_hint=False, - ) - self.iteration_timer.after_step() - self.storage.step() - # A little odd to put before step here, but it's the best way to get a proper timing - self.iteration_timer.before_step() - - if self.storage.iter % 20 == 0: - for writer in self.writers: - writer.write() - return sum(loss_dict.values()) - - def training_step_end(self, training_step_outpus): - self.data_start = time.perf_counter() - return training_step_outpus - - def training_epoch_end(self, training_step_outputs): - self.iteration_timer.after_train() - if comm.is_main_process(): - self.checkpointer.save("model_final") - for writer in self.writers: - writer.write() - writer.close() - self.storage.__exit__(None, None, None) - - def _process_dataset_evaluation_results(self) -> OrderedDict: - results = OrderedDict() - for idx, dataset_name in enumerate(self.cfg.DATASETS.TEST): - results[dataset_name] = self._evaluators[idx].evaluate() - if comm.is_main_process(): - print_csv_format(results[dataset_name]) - - if len(results) == 1: - results = list(results.values())[0] - return results - - def _reset_dataset_evaluators(self): - self._evaluators = [] - for dataset_name in self.cfg.DATASETS.TEST: - evaluator = build_evaluator(self.cfg, dataset_name) - evaluator.reset() - self._evaluators.append(evaluator) - - def on_validation_epoch_start(self, _outputs): - self._reset_dataset_evaluators() - - def validation_epoch_end(self, _outputs): - results = self._process_dataset_evaluation_results(_outputs) - - flattened_results = flatten_results_dict(results) - for k, v in flattened_results.items(): - try: - v = float(v) - except Exception as e: - raise ValueError( - "[EvalHook] eval_function should return a nested dict of float. " - "Got '{}: {}' instead.".format(k, v) - ) from e - self.storage.put_scalars(**flattened_results, smoothing_hint=False) - - def validation_step(self, batch, batch_idx: int, dataloader_idx: int = 0) -> None: - if not isinstance(batch, List): - batch = [batch] - outputs = self.model(batch) - self._evaluators[dataloader_idx].process(batch, outputs) - - def configure_optimizers(self): - optimizer = build_optimizer(self.cfg, self.model) - self._best_param_group_id = hooks.LRScheduler.get_best_param_group_id(optimizer) - scheduler = build_lr_scheduler(self.cfg, optimizer) - return [optimizer], [{"scheduler": scheduler, "interval": "step"}] - - -class DataModule(LightningDataModule): - def __init__(self, cfg): - super().__init__() - self.cfg = DefaultTrainer.auto_scale_workers(cfg, comm.get_world_size()) - - def train_dataloader(self): - return build_detection_train_loader(self.cfg) - - def val_dataloader(self): - dataloaders = [] - for dataset_name in self.cfg.DATASETS.TEST: - dataloaders.append(build_detection_test_loader(self.cfg, dataset_name)) - return dataloaders - - -def main(args): - cfg = setup(args) - train(cfg, args) - - -def train(cfg, args): - trainer_params = { - # training loop is bounded by max steps, use a large max_epochs to make - # sure max_steps is met first - "max_epochs": 10**8, - "max_steps": cfg.SOLVER.MAX_ITER, - "val_check_interval": cfg.TEST.EVAL_PERIOD - if cfg.TEST.EVAL_PERIOD > 0 - else 10**8, - "num_nodes": args.num_machines, - "gpus": args.num_gpus, - "num_sanity_val_steps": 0, - } - if cfg.SOLVER.AMP.ENABLED: - trainer_params["precision"] = 16 - - last_checkpoint = os.path.join(cfg.OUTPUT_DIR, "last.ckpt") - if args.resume: - # resume training from checkpoint - trainer_params["resume_from_checkpoint"] = last_checkpoint - logger.info(f"Resuming training from checkpoint: {last_checkpoint}.") - - trainer = pl.Trainer(**trainer_params) - logger.info( - f"start to train with {args.num_machines} nodes and {args.num_gpus} GPUs" - ) - - module = TrainingModule(cfg) - data_module = DataModule(cfg) - if args.eval_only: - logger.info("Running inference") - trainer.validate(module, data_module) - else: - logger.info("Running training") - trainer.fit(module, data_module) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def invoke_main() -> None: - parser = default_argument_parser() - args = parser.parse_args() - logger.info("Command Line Args:", args) - main(args) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/tools/plain_train_net.py b/preprocess/detectron2/tools/plain_train_net.py deleted file mode 100755 index 89de94541d24f9ccd9155ddb027686c76f9c7e02..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/plain_train_net.py +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -""" -Detectron2 training script with a plain training loop. - -This script reads a given config file and runs the training or evaluation. -It is an entry point that is able to train standard models in detectron2. - -In order to let one script support training of many models, -this script contains logic that are specific to these built-in models and therefore -may not be suitable for your own project. -For example, your research project perhaps only needs a single "evaluator". - -Therefore, we recommend you to use detectron2 as a library and take -this file as an example of how to use the library. -You may want to write your own script with your datasets and other customizations. - -Compared to "train_net.py", this script supports fewer default features. -It also includes fewer abstraction, therefore is easier to add custom logic. -""" - -import logging -import os -from collections import OrderedDict - -import detectron2.utils.comm as comm -import torch -from detectron2.checkpoint import DetectionCheckpointer, PeriodicCheckpointer -from detectron2.config import get_cfg -from detectron2.data import ( - build_detection_test_loader, - build_detection_train_loader, - MetadataCatalog, -) -from detectron2.engine import ( - default_argument_parser, - default_setup, - default_writers, - launch, -) -from detectron2.evaluation import ( - CityscapesInstanceEvaluator, - CityscapesSemSegEvaluator, - COCOEvaluator, - COCOPanopticEvaluator, - DatasetEvaluators, - inference_on_dataset, - LVISEvaluator, - PascalVOCDetectionEvaluator, - print_csv_format, - SemSegEvaluator, -) -from detectron2.modeling import build_model -from detectron2.solver import build_lr_scheduler, build_optimizer -from detectron2.utils.events import EventStorage -from torch.nn.parallel import DistributedDataParallel - -logger = logging.getLogger("detectron2") - - -def get_evaluator(cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type in ["sem_seg", "coco_panoptic_seg"]: - evaluator_list.append( - SemSegEvaluator( - dataset_name, - distributed=True, - output_dir=output_folder, - ) - ) - if evaluator_type in ["coco", "coco_panoptic_seg"]: - evaluator_list.append(COCOEvaluator(dataset_name, output_dir=output_folder)) - if evaluator_type == "coco_panoptic_seg": - evaluator_list.append(COCOPanopticEvaluator(dataset_name, output_folder)) - if evaluator_type == "cityscapes_instance": - return CityscapesInstanceEvaluator(dataset_name) - if evaluator_type == "cityscapes_sem_seg": - return CityscapesSemSegEvaluator(dataset_name) - if evaluator_type == "pascal_voc": - return PascalVOCDetectionEvaluator(dataset_name) - if evaluator_type == "lvis": - return LVISEvaluator(dataset_name, cfg, True, output_folder) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - if len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - -def do_test(cfg, model): - results = OrderedDict() - for dataset_name in cfg.DATASETS.TEST: - data_loader = build_detection_test_loader(cfg, dataset_name) - evaluator = get_evaluator( - cfg, dataset_name, os.path.join(cfg.OUTPUT_DIR, "inference", dataset_name) - ) - results_i = inference_on_dataset(model, data_loader, evaluator) - results[dataset_name] = results_i - if comm.is_main_process(): - logger.info("Evaluation results for {} in csv format:".format(dataset_name)) - print_csv_format(results_i) - if len(results) == 1: - results = list(results.values())[0] - return results - - -def do_train(cfg, model, resume=False): - model.train() - optimizer = build_optimizer(cfg, model) - scheduler = build_lr_scheduler(cfg, optimizer) - - checkpointer = DetectionCheckpointer( - model, cfg.OUTPUT_DIR, optimizer=optimizer, scheduler=scheduler - ) - start_iter = ( - checkpointer.resume_or_load(cfg.MODEL.WEIGHTS, resume=resume).get( - "iteration", -1 - ) - + 1 - ) - max_iter = cfg.SOLVER.MAX_ITER - - periodic_checkpointer = PeriodicCheckpointer( - checkpointer, cfg.SOLVER.CHECKPOINT_PERIOD, max_iter=max_iter - ) - - writers = ( - default_writers(cfg.OUTPUT_DIR, max_iter) if comm.is_main_process() else [] - ) - - # compared to "train_net.py", we do not support accurate timing and - # precise BN here, because they are not trivial to implement in a small training loop - data_loader = build_detection_train_loader(cfg) - logger.info("Starting training from iteration {}".format(start_iter)) - with EventStorage(start_iter) as storage: - for data, iteration in zip(data_loader, range(start_iter, max_iter)): - storage.iter = iteration - - loss_dict = model(data) - losses = sum(loss_dict.values()) - assert torch.isfinite(losses).all(), loss_dict - - loss_dict_reduced = { - k: v.item() for k, v in comm.reduce_dict(loss_dict).items() - } - losses_reduced = sum(loss for loss in loss_dict_reduced.values()) - if comm.is_main_process(): - storage.put_scalars(total_loss=losses_reduced, **loss_dict_reduced) - - optimizer.zero_grad() - losses.backward() - optimizer.step() - storage.put_scalar( - "lr", optimizer.param_groups[0]["lr"], smoothing_hint=False - ) - scheduler.step() - - if ( - cfg.TEST.EVAL_PERIOD > 0 - and (iteration + 1) % cfg.TEST.EVAL_PERIOD == 0 - and iteration != max_iter - 1 - ): - do_test(cfg, model) - # Compared to "train_net.py", the test results are not dumped to EventStorage - comm.synchronize() - - if iteration - start_iter > 5 and ( - (iteration + 1) % 20 == 0 or iteration == max_iter - 1 - ): - for writer in writers: - writer.write() - periodic_checkpointer.step(iteration) - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup( - cfg, args - ) # if you don't like any of the default setup, write your own setup code - return cfg - - -def main(args): - cfg = setup(args) - - model = build_model(cfg) - logger.info("Model:\n{}".format(model)) - if args.eval_only: - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - return do_test(cfg, model) - - distributed = comm.get_world_size() > 1 - if distributed: - model = DistributedDataParallel( - model, device_ids=[comm.get_local_rank()], broadcast_buffers=False - ) - - do_train(cfg, model, resume=args.resume) - return do_test(cfg, model) - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/tools/train_net.py b/preprocess/detectron2/tools/train_net.py deleted file mode 100755 index 6f5aa669dc43f412cd487ae7d9ef95191620583a..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/train_net.py +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -""" -A main training script. - -This scripts reads a given config file and runs the training or evaluation. -It is an entry point that is made to train standard models in detectron2. - -In order to let one script support training of many models, -this script contains logic that are specific to these built-in models and therefore -may not be suitable for your own project. -For example, your research project perhaps only needs a single "evaluator". - -Therefore, we recommend you to use detectron2 as an library and take -this file as an example of how to use the library. -You may want to write your own script with your datasets and other customizations. -""" - -import logging -import os -from collections import OrderedDict - -import detectron2.utils.comm as comm -from detectron2.checkpoint import DetectionCheckpointer -from detectron2.config import get_cfg -from detectron2.data import MetadataCatalog -from detectron2.engine import ( - default_argument_parser, - default_setup, - DefaultTrainer, - hooks, - launch, -) -from detectron2.evaluation import ( - CityscapesInstanceEvaluator, - CityscapesSemSegEvaluator, - COCOEvaluator, - COCOPanopticEvaluator, - DatasetEvaluators, - LVISEvaluator, - PascalVOCDetectionEvaluator, - SemSegEvaluator, - verify_results, -) -from detectron2.modeling import GeneralizedRCNNWithTTA - - -def build_evaluator(cfg, dataset_name, output_folder=None): - """ - Create evaluator(s) for a given dataset. - This uses the special metadata "evaluator_type" associated with each builtin dataset. - For your own dataset, you can simply create an evaluator manually in your - script and do not have to worry about the hacky if-else logic here. - """ - if output_folder is None: - output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") - evaluator_list = [] - evaluator_type = MetadataCatalog.get(dataset_name).evaluator_type - if evaluator_type in ["sem_seg", "coco_panoptic_seg"]: - evaluator_list.append( - SemSegEvaluator( - dataset_name, - distributed=True, - output_dir=output_folder, - ) - ) - if evaluator_type in ["coco", "coco_panoptic_seg"]: - evaluator_list.append(COCOEvaluator(dataset_name, output_dir=output_folder)) - if evaluator_type == "coco_panoptic_seg": - evaluator_list.append(COCOPanopticEvaluator(dataset_name, output_folder)) - if evaluator_type == "cityscapes_instance": - return CityscapesInstanceEvaluator(dataset_name) - if evaluator_type == "cityscapes_sem_seg": - return CityscapesSemSegEvaluator(dataset_name) - elif evaluator_type == "pascal_voc": - return PascalVOCDetectionEvaluator(dataset_name) - elif evaluator_type == "lvis": - return LVISEvaluator(dataset_name, output_dir=output_folder) - if len(evaluator_list) == 0: - raise NotImplementedError( - "no Evaluator for the dataset {} with the type {}".format( - dataset_name, evaluator_type - ) - ) - elif len(evaluator_list) == 1: - return evaluator_list[0] - return DatasetEvaluators(evaluator_list) - - -class Trainer(DefaultTrainer): - """ - We use the "DefaultTrainer" which contains pre-defined default logic for - standard training workflow. They may not work for you, especially if you - are working on a new research project. In that case you can write your - own training loop. You can use "tools/plain_train_net.py" as an example. - """ - - @classmethod - def build_evaluator(cls, cfg, dataset_name, output_folder=None): - return build_evaluator(cfg, dataset_name, output_folder) - - @classmethod - def test_with_TTA(cls, cfg, model): - logger = logging.getLogger("detectron2.trainer") - # In the end of training, run an evaluation with TTA - # Only support some R-CNN models. - logger.info("Running inference with test-time augmentation ...") - model = GeneralizedRCNNWithTTA(cfg, model) - evaluators = [ - cls.build_evaluator( - cfg, name, output_folder=os.path.join(cfg.OUTPUT_DIR, "inference_TTA") - ) - for name in cfg.DATASETS.TEST - ] - res = cls.test(cfg, model, evaluators) - res = OrderedDict({k + "_TTA": v for k, v in res.items()}) - return res - - -def setup(args): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.freeze() - default_setup(cfg, args) - return cfg - - -def main(args): - cfg = setup(args) - - if args.eval_only: - model = Trainer.build_model(cfg) - DetectionCheckpointer(model, save_dir=cfg.OUTPUT_DIR).resume_or_load( - cfg.MODEL.WEIGHTS, resume=args.resume - ) - res = Trainer.test(cfg, model) - if cfg.TEST.AUG.ENABLED: - res.update(Trainer.test_with_TTA(cfg, model)) - if comm.is_main_process(): - verify_results(cfg, res) - return res - - """ - If you'd like to do anything fancier than the standard training logic, - consider writing your own training loop (see plain_train_net.py) or - subclassing the trainer. - """ - trainer = Trainer(cfg) - trainer.resume_or_load(resume=args.resume) - if cfg.TEST.AUG.ENABLED: - trainer.register_hooks( - [hooks.EvalHook(0, lambda: trainer.test_with_TTA(cfg, trainer.model))] - ) - return trainer.train() - - -def invoke_main() -> None: - args = default_argument_parser().parse_args() - print("Command Line Args:", args) - launch( - main, - args.num_gpus, - num_machines=args.num_machines, - machine_rank=args.machine_rank, - dist_url=args.dist_url, - args=(args,), - ) - - -if __name__ == "__main__": - invoke_main() # pragma: no cover diff --git a/preprocess/detectron2/tools/visualize_data.py b/preprocess/detectron2/tools/visualize_data.py deleted file mode 100755 index 7e585df081c468e0ad3441760c0c25301b329ca3..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/visualize_data.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. -import argparse -import os -from itertools import chain - -import cv2 -import tqdm - -from detectron2.config import get_cfg -from detectron2.data import ( - build_detection_train_loader, - DatasetCatalog, - detection_utils as utils, - MetadataCatalog, -) -from detectron2.data.build import filter_images_with_few_keypoints -from detectron2.utils.logger import setup_logger -from detectron2.utils.visualizer import Visualizer - - -def setup(args): - cfg = get_cfg() - if args.config_file: - cfg.merge_from_file(args.config_file) - cfg.merge_from_list(args.opts) - cfg.DATALOADER.NUM_WORKERS = 0 - cfg.freeze() - return cfg - - -def parse_args(in_args=None): - parser = argparse.ArgumentParser(description="Visualize ground-truth data") - parser.add_argument( - "--source", - choices=["annotation", "dataloader"], - required=True, - help="visualize the annotations or the data loader (with pre-processing)", - ) - parser.add_argument("--config-file", metavar="FILE", help="path to config file") - parser.add_argument("--output-dir", default="./", help="path to output directory") - parser.add_argument("--show", action="store_true", help="show output in a window") - parser.add_argument( - "opts", - help="Modify config options using the command-line", - default=None, - nargs=argparse.REMAINDER, - ) - return parser.parse_args(in_args) - - -def main() -> None: - global img - args = parse_args() - logger = setup_logger() - logger.info("Arguments: " + str(args)) - cfg = setup(args) - - dirname = args.output_dir - os.makedirs(dirname, exist_ok=True) - metadata = MetadataCatalog.get(cfg.DATASETS.TRAIN[0]) - - def output(vis, fname): - if args.show: - print(fname) - cv2.imshow("window", vis.get_image()[:, :, ::-1]) - cv2.waitKey() - else: - filepath = os.path.join(dirname, fname) - print("Saving to {} ...".format(filepath)) - vis.save(filepath) - - scale = 1.0 - if args.source == "dataloader": - train_data_loader = build_detection_train_loader(cfg) - for batch in train_data_loader: - for per_image in batch: - # Pytorch tensor is in (C, H, W) format - img = per_image["image"].permute(1, 2, 0).cpu().detach().numpy() - img = utils.convert_image_to_rgb(img, cfg.INPUT.FORMAT) - - visualizer = Visualizer(img, metadata=metadata, scale=scale) - target_fields = per_image["instances"].get_fields() - labels = [ - metadata.thing_classes[i] for i in target_fields["gt_classes"] - ] - vis = visualizer.overlay_instances( - labels=labels, - boxes=target_fields.get("gt_boxes", None), - masks=target_fields.get("gt_masks", None), - keypoints=target_fields.get("gt_keypoints", None), - ) - output(vis, str(per_image["image_id"]) + ".jpg") - else: - dicts = list( - chain.from_iterable([DatasetCatalog.get(k) for k in cfg.DATASETS.TRAIN]) - ) - if cfg.MODEL.KEYPOINT_ON: - dicts = filter_images_with_few_keypoints(dicts, 1) - for dic in tqdm.tqdm(dicts): - img = utils.read_image(dic["file_name"], "RGB") - visualizer = Visualizer(img, metadata=metadata, scale=scale) - vis = visualizer.draw_dataset_dict(dic) - output(vis, os.path.basename(dic["file_name"])) - - -if __name__ == "__main__": - main() # pragma: no cover diff --git a/preprocess/detectron2/tools/visualize_json_results.py b/preprocess/detectron2/tools/visualize_json_results.py deleted file mode 100755 index 9d374aa1e1cde838a2e600aac38cccd1b6b11d18..0000000000000000000000000000000000000000 --- a/preprocess/detectron2/tools/visualize_json_results.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Facebook, Inc. and its affiliates. - -import argparse -import json -import os -from collections import defaultdict - -import cv2 -import numpy as np -import tqdm - -from detectron2.data import DatasetCatalog, MetadataCatalog -from detectron2.structures import Boxes, BoxMode, Instances -from detectron2.utils.file_io import PathManager -from detectron2.utils.logger import setup_logger -from detectron2.utils.visualizer import Visualizer - - -def create_instances(predictions, image_size): - ret = Instances(image_size) - - score = np.asarray([x["score"] for x in predictions]) - chosen = (score > args.conf_threshold).nonzero()[0] - score = score[chosen] - bbox = np.asarray([predictions[i]["bbox"] for i in chosen]).reshape(-1, 4) - bbox = BoxMode.convert(bbox, BoxMode.XYWH_ABS, BoxMode.XYXY_ABS) - - labels = np.asarray([dataset_id_map(predictions[i]["category_id"]) for i in chosen]) - - ret.scores = score - ret.pred_boxes = Boxes(bbox) - ret.pred_classes = labels - - try: - ret.pred_masks = [predictions[i]["segmentation"] for i in chosen] - except KeyError: - pass - return ret - - -def main() -> None: - global args, dataset_id_map - parser = argparse.ArgumentParser( - description="A script that visualizes the json predictions from COCO or LVIS dataset." - ) - parser.add_argument( - "--input", required=True, help="JSON file produced by the model" - ) - parser.add_argument("--output", required=True, help="output directory") - parser.add_argument( - "--dataset", help="name of the dataset", default="coco_2017_val" - ) - parser.add_argument( - "--conf-threshold", default=0.5, type=float, help="confidence threshold" - ) - args = parser.parse_args() - - logger = setup_logger() - - with PathManager.open(args.input, "r") as f: - predictions = json.load(f) - - pred_by_image = defaultdict(list) - for p in predictions: - pred_by_image[p["image_id"]].append(p) - - dicts = list(DatasetCatalog.get(args.dataset)) - metadata = MetadataCatalog.get(args.dataset) - if hasattr(metadata, "thing_dataset_id_to_contiguous_id"): - - def dataset_id_map(ds_id): - return metadata.thing_dataset_id_to_contiguous_id[ds_id] - - elif "lvis" in args.dataset: - # LVIS results are in the same format as COCO results, but have a different - # mapping from dataset category id to contiguous category id in [0, #categories - 1] - def dataset_id_map(ds_id): - return ds_id - 1 - - else: - raise ValueError("Unsupported dataset: {}".format(args.dataset)) - - os.makedirs(args.output, exist_ok=True) - - for dic in tqdm.tqdm(dicts): - img = cv2.imread(dic["file_name"], cv2.IMREAD_COLOR)[:, :, ::-1] - basename = os.path.basename(dic["file_name"]) - - predictions = create_instances(pred_by_image[dic["image_id"]], img.shape[:2]) - vis = Visualizer(img, metadata) - vis_pred = vis.draw_instance_predictions(predictions).get_image() - - vis = Visualizer(img, metadata) - vis_gt = vis.draw_dataset_dict(dic).get_image() - - concat = np.concatenate((vis_pred, vis_gt), axis=1) - cv2.imwrite(os.path.join(args.output, basename), concat[:, :, ::-1]) - - -if __name__ == "__main__": - main() # pragma: no cover