hysts HF staff commited on
Commit
7dcb60d
1 Parent(s): 28feecc
Files changed (8) hide show
  1. .gitmodules +3 -0
  2. .pre-commit-config.yaml +35 -0
  3. .style.yapf +5 -0
  4. CutLER +1 -0
  5. Dockerfile +60 -0
  6. app.py +89 -0
  7. model.py +145 -0
  8. style.css +3 -0
.gitmodules ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ [submodule "CutLER"]
2
+ path = CutLER
3
+ url = https://github.com/facebookresearch/CutLER
.pre-commit-config.yaml ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.2.0
4
+ hooks:
5
+ - id: check-executables-have-shebangs
6
+ - id: check-json
7
+ - id: check-merge-conflict
8
+ - id: check-shebang-scripts-are-executable
9
+ - id: check-toml
10
+ - id: check-yaml
11
+ - id: double-quote-string-fixer
12
+ - id: end-of-file-fixer
13
+ - id: mixed-line-ending
14
+ args: ['--fix=lf']
15
+ - id: requirements-txt-fixer
16
+ - id: trailing-whitespace
17
+ - repo: https://github.com/myint/docformatter
18
+ rev: v1.4
19
+ hooks:
20
+ - id: docformatter
21
+ args: ['--in-place']
22
+ - repo: https://github.com/pycqa/isort
23
+ rev: 5.10.1
24
+ hooks:
25
+ - id: isort
26
+ - repo: https://github.com/pre-commit/mirrors-mypy
27
+ rev: v0.991
28
+ hooks:
29
+ - id: mypy
30
+ args: ['--ignore-missing-imports']
31
+ - repo: https://github.com/google/yapf
32
+ rev: v0.32.0
33
+ hooks:
34
+ - id: yapf
35
+ args: ['--parallel', '--in-place']
.style.yapf ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ [style]
2
+ based_on_style = pep8
3
+ blank_line_before_nested_class_or_def = false
4
+ spaces_before_comment = 2
5
+ split_before_logical_operator = true
CutLER ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit 077938c626341723050a1971107af552a6ca6697
Dockerfile ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM nvidia/cuda:11.7.1-cudnn8-devel-ubuntu22.04
2
+ ENV DEBIAN_FRONTEND=noninteractive
3
+ RUN apt-get update && \
4
+ apt-get upgrade -y && \
5
+ apt-get install -y --no-install-recommends \
6
+ git \
7
+ wget \
8
+ curl \
9
+ # python build dependencies \
10
+ build-essential \
11
+ libssl-dev \
12
+ zlib1g-dev \
13
+ libbz2-dev \
14
+ libreadline-dev \
15
+ libsqlite3-dev \
16
+ libncursesw5-dev \
17
+ xz-utils \
18
+ tk-dev \
19
+ libxml2-dev \
20
+ libxmlsec1-dev \
21
+ libffi-dev \
22
+ liblzma-dev && \
23
+ apt-get clean && \
24
+ rm -rf /var/lib/apt/lists/*
25
+
26
+ RUN useradd -m -u 1000 user
27
+ USER user
28
+ ENV HOME=/home/user \
29
+ PATH=/home/user/.local/bin:${PATH}
30
+ WORKDIR ${HOME}/app
31
+
32
+ RUN curl https://pyenv.run | bash
33
+ ENV PATH=${HOME}/.pyenv/shims:${HOME}/.pyenv/bin:${PATH}
34
+ ARG PYTHON_VERSION=3.10.9
35
+ RUN pyenv install ${PYTHON_VERSION} && \
36
+ pyenv global ${PYTHON_VERSION} && \
37
+ pyenv rehash && \
38
+ pip install --no-cache-dir -U pip setuptools wheel
39
+
40
+ RUN pip install --no-cache-dir -U torch==1.13.1 torchvision==0.14.1
41
+ RUN pip install --no-cache-dir \
42
+ git+https://github.com/facebookresearch/detectron2.git@58e472e \
43
+ git+https://github.com/cocodataset/panopticapi.git@7bb4655 \
44
+ git+https://github.com/mcordts/cityscapesScripts.git@8da5dd0
45
+ RUN pip install --no-cache-dir -U \
46
+ numpy==1.23.5 \
47
+ scikit-image==0.19.2 \
48
+ opencv-python-headless==4.6.0.66 \
49
+ colored==1.4.4
50
+ RUN pip install --no-cache-dir -U gradio==3.16.2
51
+
52
+ COPY --chown=1000 . ${HOME}/app
53
+ ENV PYTHONPATH=${HOME}/app \
54
+ PYTHONUNBUFFERED=1 \
55
+ GRADIO_ALLOW_FLAGGING=never \
56
+ GRADIO_NUM_PORTS=1 \
57
+ GRADIO_SERVER_NAME=0.0.0.0 \
58
+ GRADIO_THEME=huggingface \
59
+ SYSTEM=spaces
60
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env
2
+
3
+ import pathlib
4
+
5
+ import gradio as gr
6
+
7
+ from model import FULLY_SUPERVISED_MODELS, SEMI_SUPERVISED_MODELS, Model
8
+
9
+ DESCRIPTION = '''# CutLER
10
+
11
+ This is an unofficial demo for [https://github.com/facebookresearch/CutLER](https://github.com/facebookresearch/CutLER).
12
+ '''
13
+
14
+ model = Model()
15
+ paths = sorted(pathlib.Path('CutLER/cutler/demo/imgs').glob('*.jpg'))
16
+
17
+
18
+ def create_unsupervised_demo():
19
+ with gr.Blocks() as demo:
20
+ with gr.Row():
21
+ with gr.Column():
22
+ image = gr.Image(label='Input image', type='filepath')
23
+ model_name = gr.Text(label='Model',
24
+ value='Unsupervised',
25
+ visible=False)
26
+ score_threshold = gr.Slider(label='Score threshold',
27
+ minimum=0,
28
+ maximum=1,
29
+ value=0.5,
30
+ step=0.05)
31
+ run_button = gr.Button('Run')
32
+ with gr.Column():
33
+ result = gr.Image(label='Result', type='numpy')
34
+ with gr.Row():
35
+ gr.Examples(examples=[[path.as_posix()] for path in paths],
36
+ inputs=[image])
37
+
38
+ run_button.click(fn=model,
39
+ inputs=[
40
+ image,
41
+ model_name,
42
+ score_threshold,
43
+ ],
44
+ outputs=result)
45
+
46
+ return demo
47
+
48
+
49
+ def create_supervised_demo():
50
+ model_names = list(SEMI_SUPERVISED_MODELS.keys()) + list(
51
+ FULLY_SUPERVISED_MODELS.keys())
52
+ with gr.Blocks() as demo:
53
+ with gr.Row():
54
+ with gr.Column():
55
+ image = gr.Image(label='Input image', type='filepath')
56
+ model_name = gr.Dropdown(label='Model',
57
+ choices=model_names,
58
+ value=model_names[-1])
59
+ score_threshold = gr.Slider(label='Score threshold',
60
+ minimum=0,
61
+ maximum=1,
62
+ value=0.5,
63
+ step=0.05)
64
+ run_button = gr.Button('Run')
65
+ with gr.Column():
66
+ result = gr.Image(label='Result', type='numpy')
67
+ with gr.Row():
68
+ gr.Examples(examples=[[path.as_posix()] for path in paths],
69
+ inputs=[image])
70
+
71
+ run_button.click(fn=model,
72
+ inputs=[
73
+ image,
74
+ model_name,
75
+ score_threshold,
76
+ ],
77
+ outputs=result)
78
+
79
+ return demo
80
+
81
+
82
+ with gr.Blocks(css='style.css') as demo:
83
+ gr.Markdown(DESCRIPTION)
84
+ with gr.Tabs():
85
+ with gr.TabItem('Zero-shot unsupervised'):
86
+ create_unsupervised_demo()
87
+ with gr.TabItem('Semi/Fully-supervised'):
88
+ create_supervised_demo()
89
+ demo.queue().launch()
model.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is adapted from https://github.com/facebookresearch/CutLER/blob/077938c626341723050a1971107af552a6ca6697/cutler/demo/demo.py
2
+ # The original license file is the file named LICENSE.CutLER in this repo.
3
+
4
+ import argparse
5
+ import multiprocessing as mp
6
+ import pathlib
7
+ import shlex
8
+ import subprocess
9
+ import sys
10
+
11
+ import numpy as np
12
+ import torch
13
+ from detectron2.config import get_cfg
14
+ from detectron2.data.detection_utils import read_image
15
+
16
+ sys.path.append('CutLER/cutler/')
17
+ sys.path.append('CutLER/cutler/demo')
18
+
19
+ from config import add_cutler_config
20
+ from predictor import VisualizationDemo
21
+
22
+ mp.set_start_method('spawn', force=True)
23
+
24
+ UNSUPERVISED_MODELS = {
25
+ 'Unsupervised': {
26
+ 'config_path':
27
+ 'CutLER/cutler/model_zoo/configs/CutLER-ImageNet/cascade_mask_rcnn_R_50_FPN.yaml',
28
+ 'weight_url':
29
+ 'http://dl.fbaipublicfiles.com/cutler/checkpoints/cutler_cascade_final.pth',
30
+ }
31
+ }
32
+ SEMI_SUPERVISED_MODELS = {
33
+ f'Semi-supervised with COCO ({perc}%)': {
34
+ 'config_path':
35
+ f'CutLER/cutler/model_zoo/configs/COCO-Semisupervised/cascade_mask_rcnn_R_50_FPN_{perc}perc.yaml',
36
+ 'weight_url':
37
+ f'http://dl.fbaipublicfiles.com/cutler/checkpoints/cutler_semi_{perc}perc.pth',
38
+ }
39
+ for perc in [1, 2, 5, 10, 20, 30, 40, 50, 60, 80]
40
+ }
41
+ FULLY_SUPERVISED_MODELS = {
42
+ 'Fully-supervised with COCO': {
43
+ 'config_path':
44
+ f'CutLER/cutler/model_zoo/configs/COCO-Semisupervised/cascade_mask_rcnn_R_50_FPN_100perc.yaml',
45
+ 'weight_url':
46
+ f'http://dl.fbaipublicfiles.com/cutler/checkpoints/cutler_fully_100perc.pth',
47
+ }
48
+ }
49
+
50
+
51
+ def setup_cfg(args):
52
+ # load config from file and command-line arguments
53
+ cfg = get_cfg()
54
+ add_cutler_config(cfg)
55
+ cfg.merge_from_file(args.config_file)
56
+ cfg.merge_from_list(args.opts)
57
+ # Disable the use of SyncBN normalization when running on a CPU
58
+ # SyncBN is not supported on CPU and can cause errors, so we switch to BN instead
59
+ if cfg.MODEL.DEVICE == 'cpu' and cfg.MODEL.RESNETS.NORM == 'SyncBN':
60
+ cfg.MODEL.RESNETS.NORM = 'BN'
61
+ cfg.MODEL.FPN.NORM = 'BN'
62
+ # Set score_threshold for builtin models
63
+ cfg.MODEL.RETINANET.SCORE_THRESH_TEST = args.confidence_threshold
64
+ cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = args.confidence_threshold
65
+ cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = args.confidence_threshold
66
+ cfg.freeze()
67
+ return cfg
68
+
69
+
70
+ def get_parser():
71
+ parser = argparse.ArgumentParser(
72
+ description='Detectron2 demo for builtin configs')
73
+ parser.add_argument(
74
+ '--config-file',
75
+ default=
76
+ 'model_zoo/configs/CutLER-ImageNet/cascade_mask_rcnn_R_50_FPN.yaml',
77
+ metavar='FILE',
78
+ help='path to config file',
79
+ )
80
+ parser.add_argument('--webcam',
81
+ action='store_true',
82
+ help='Take inputs from webcam.')
83
+ parser.add_argument('--video-input', help='Path to video file.')
84
+ parser.add_argument(
85
+ '--input',
86
+ nargs='+',
87
+ help='A list of space separated input images; '
88
+ "or a single glob pattern such as 'directory/*.jpg'",
89
+ )
90
+ parser.add_argument(
91
+ '--output',
92
+ help='A file or directory to save output visualizations. '
93
+ 'If not given, will show output in an OpenCV window.',
94
+ )
95
+
96
+ parser.add_argument(
97
+ '--confidence-threshold',
98
+ type=float,
99
+ default=0.35,
100
+ help='Minimum score for instance predictions to be shown',
101
+ )
102
+ parser.add_argument(
103
+ '--opts',
104
+ help="Modify config options using the command-line 'KEY VALUE' pairs",
105
+ default=[],
106
+ nargs=argparse.REMAINDER,
107
+ )
108
+ return parser
109
+
110
+
111
+ class Model:
112
+ MODEL_DICT = UNSUPERVISED_MODELS | SEMI_SUPERVISED_MODELS | FULLY_SUPERVISED_MODELS
113
+
114
+ def __init__(self):
115
+ self.model_dir = pathlib.Path('checkpoints')
116
+ self.model_dir.mkdir(exist_ok=True)
117
+
118
+ def load_model(self, model_name: str,
119
+ score_threshold: float) -> VisualizationDemo:
120
+ model_info = self.MODEL_DICT[model_name]
121
+ weight_url = model_info['weight_url']
122
+ weight_path = self.model_dir / weight_url.split('/')[-1]
123
+ if not weight_path.exists():
124
+ weight_path.parent.mkdir(exist_ok=True)
125
+ subprocess.run(shlex.split(f'wget {weight_url} -O {weight_path}'))
126
+
127
+ arg_list = [
128
+ '--config-file', model_info['config_path'],
129
+ '--confidence-threshold',
130
+ str(score_threshold), '--opts', 'MODEL.WEIGHTS',
131
+ weight_path.as_posix(), 'MODEL.DEVICE',
132
+ 'cuda:0' if torch.cuda.is_available() else 'cpu'
133
+ ]
134
+ args = get_parser().parse_args(arg_list)
135
+ cfg = setup_cfg(args)
136
+ return VisualizationDemo(cfg)
137
+
138
+ def __call__(self,
139
+ image_path: str,
140
+ model_name: str,
141
+ score_threshold: float = 0.5) -> np.ndarray:
142
+ model = self.load_model(model_name, score_threshold)
143
+ image = read_image(image_path, format='BGR')
144
+ _, res = model.run_on_image(image)
145
+ return res.get_image()
style.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ h1 {
2
+ text-align: center;
3
+ }