bluemellophone commited on
Commit
c43979a
·
unverified ·
1 Parent(s): 58cc9e4

Added wheel testing

Browse files
.github/workflows/python-publish.yml CHANGED
@@ -61,11 +61,35 @@ jobs:
61
  with:
62
  path: ./dist/*.tar.gz
63
 
64
- upload_pypi:
65
  needs: [build_wheels, build_sdist]
66
  runs-on: ubuntu-latest
67
  # upload to PyPI on every tag starting with 'v'
68
  if: github.event_name == 'push' # && startsWith(github.event.ref, 'refs/tags/v')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  steps:
70
  - uses: actions/download-artifact@v2
71
  with:
 
61
  with:
62
  path: ./dist/*.tar.gz
63
 
64
+ test_wheel:
65
  needs: [build_wheels, build_sdist]
66
  runs-on: ubuntu-latest
67
  # upload to PyPI on every tag starting with 'v'
68
  if: github.event_name == 'push' # && startsWith(github.event.ref, 'refs/tags/v')
69
+ steps:
70
+ - uses: actions/setup-python@v2
71
+ name: Install Python
72
+ with:
73
+ python-version: '3.8'
74
+
75
+ - uses: actions/download-artifact@v2
76
+ with:
77
+ name: artifact
78
+ path: dist
79
+
80
+ - name: Install wheel
81
+ run: |
82
+ pip install --upgrade pip
83
+ pip install wheel
84
+ pip install dist/*.whl
85
+ ls -al dist/
86
+ python -c "import scoutbot; scoutbot.fetch();"
87
+
88
+ upload_pypi:
89
+ needs: [test_wheel]
90
+ runs-on: ubuntu-latest
91
+ # upload to PyPI on every tag starting with 'v'
92
+ if: github.event_name == 'push' # && startsWith(github.event.ref, 'refs/tags/v')
93
  steps:
94
  - uses: actions/download-artifact@v2
95
  with:
MANIFEST.in CHANGED
@@ -9,3 +9,8 @@ include LICENSE
9
  # Include ONNX files (disabled, too large for PyPI)
10
  # include scoutbot/loc/models/onnx/scout.loc.5fbfff26.0.onnx
11
  # include scoutbot/wic/models/onnx/scout.wic.5fbfff26.3.0.onnx
 
 
 
 
 
 
9
  # Include ONNX files (disabled, too large for PyPI)
10
  # include scoutbot/loc/models/onnx/scout.loc.5fbfff26.0.onnx
11
  # include scoutbot/wic/models/onnx/scout.wic.5fbfff26.3.0.onnx
12
+
13
+ # Include examples files for testing
14
+ include examples/1be4d40a-6fd0-42ce-da6c-294e45781f41.jpg
15
+ include examples/0d01a14e-311d-e153-356f-8431b6996b84.true.jpg
16
+ include examples/1e8372e4-357d-26e6-d7fd-0e0ae402463a.true.jpg
scoutbot/__init__.py CHANGED
@@ -44,7 +44,12 @@ how the entire pipeline can be run on tiles or images, respectively.
44
  nms_thresh=agg_nms_thresh,
45
  )
46
  '''
47
- from scoutbot import agg, loc, tile, wic
 
 
 
 
 
48
 
49
  VERSION = '0.1.6'
50
  version = VERSION
 
44
  nms_thresh=agg_nms_thresh,
45
  )
46
  '''
47
+ from scoutbot import utils
48
+
49
+ log = utils.init_logging()
50
+
51
+
52
+ from scoutbot import agg, loc, tile, wic # NOQA
53
 
54
  VERSION = '0.1.6'
55
  version = VERSION
scoutbot/agg/__init__.py CHANGED
@@ -9,6 +9,8 @@ on the combined results.
9
  import numpy as np
10
  import utool as ut
11
 
 
 
12
  MARGIN = 32.0
13
  AGG_THRESH = 0.4
14
  NMS_THRESH = 0.2
@@ -141,6 +143,8 @@ def compute(
141
  """
142
  from scoutbot.agg.py_cpu_nms import py_cpu_nms
143
 
 
 
144
  # Demosaic tile detection results and aggregate across the image
145
  detects = demosaic(img_shape, tile_grids, loc_outputs)
146
 
@@ -165,4 +169,6 @@ def compute(
165
  final = ut.take(detects, keeps)
166
  final.sort(key=lambda val: val['c'], reverse=True)
167
 
 
 
168
  return final
 
9
  import numpy as np
10
  import utool as ut
11
 
12
+ from scoutbot import log
13
+
14
  MARGIN = 32.0
15
  AGG_THRESH = 0.4
16
  NMS_THRESH = 0.2
 
143
  """
144
  from scoutbot.agg.py_cpu_nms import py_cpu_nms
145
 
146
+ log.info(f'Aggregating {len(tile_grids)} tiles onto {img_shape} canvas')
147
+
148
  # Demosaic tile detection results and aggregate across the image
149
  detects = demosaic(img_shape, tile_grids, loc_outputs)
150
 
 
169
  final = ut.take(detects, keeps)
170
  final.sort(key=lambda val: val['c'], reverse=True)
171
 
172
+ log.info(f'Found {len(final)} detections')
173
+
174
  return final
scoutbot/loc/__init__.py CHANGED
@@ -18,6 +18,7 @@ import torch
18
  import torchvision
19
  import utool as ut
20
 
 
21
  from scoutbot.loc.transforms import (
22
  Compose,
23
  GetBoundingBoxes,
@@ -77,6 +78,7 @@ def fetch(pull=False):
77
  progressbar=True,
78
  )
79
  assert exists(onnx_model)
 
80
 
81
  return onnx_model
82
 
@@ -130,6 +132,8 @@ def predict(data, fill=True):
130
  """
131
  onnx_model = fetch()
132
 
 
 
133
  ort_session = ort.InferenceSession(
134
  onnx_model, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
135
  )
 
18
  import torchvision
19
  import utool as ut
20
 
21
+ from scoutbot import log
22
  from scoutbot.loc.transforms import (
23
  Compose,
24
  GetBoundingBoxes,
 
78
  progressbar=True,
79
  )
80
  assert exists(onnx_model)
81
+ log.info(f'LOC Model: {onnx_model}')
82
 
83
  return onnx_model
84
 
 
132
  """
133
  onnx_model = fetch()
134
 
135
+ log.info(f'Running WIC inference on {len(data)} tiles')
136
+
137
  ort_session = ort.InferenceSession(
138
  onnx_model, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
139
  )
scoutbot/loc/transforms/__init__.py CHANGED
@@ -15,3 +15,4 @@ from scoutbot.loc.transforms._postprocess import ( # NOQA
15
  TensorToBrambox,
16
  )
17
  from scoutbot.loc.transforms._preprocess import Letterbox # NOQA
 
 
15
  TensorToBrambox,
16
  )
17
  from scoutbot.loc.transforms._preprocess import Letterbox # NOQA
18
+ from scoutbot.loc.transforms.util import Compose # NOQA
scoutbot/scoutbot.py CHANGED
@@ -1,32 +1,116 @@
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
  """
4
- Coming Soon
5
  """
 
 
 
6
  import click
 
 
 
 
7
 
8
- from scoutbot import utils
9
 
10
- log = utils.init_logging()
 
 
 
 
11
 
12
 
13
  @click.command()
14
  @click.option(
15
- '--config', help='Path to config file', default='configs/mnist_resnet18.yaml'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  )
17
- def wic(config):
18
- """ """
19
- pass
20
-
21
-
22
- @click.command()
23
  @click.option(
24
- '--config', help='Path to config file', default='configs/mnist_resnet18.yaml'
 
 
 
25
  )
26
- def main(config):
27
- """ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  pass
29
 
30
 
 
 
 
 
31
  if __name__ == '__main__':
32
- main()
 
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
  """
4
+ CLI for ScoutBot
5
  """
6
+ import json
7
+ from os.path import exists
8
+
9
  import click
10
+ import utool as ut
11
+
12
+ import scoutbot
13
+ from scoutbot import agg, loc, log, wic
14
 
 
15
 
16
+ def pipeline_filepath_validator(ctx, param, value):
17
+ if not exists(value):
18
+ log.error(f'Input filepath does not exist: {value}')
19
+ ctx.exit()
20
+ return value
21
 
22
 
23
  @click.command()
24
  @click.option(
25
+ '--filepath',
26
+ help='Path to image',
27
+ required=True,
28
+ type=str,
29
+ callback=pipeline_filepath_validator,
30
+ )
31
+ @click.option(
32
+ '--output',
33
+ help='Path to output JSON (if unspecified, results are printed to screen)',
34
+ default=None,
35
+ type=click.IntRange(0, 100, clamp=True),
36
+ )
37
+ @click.option(
38
+ '--wic_thresh',
39
+ help='Whole Image Classifier (WIC) confidence threshold',
40
+ default=wic.WIC_THRESH,
41
+ type=click.IntRange(0, 100, clamp=True),
42
+ )
43
+ @click.option(
44
+ '--loc_thresh',
45
+ help='Localizer (LOC) confidence threshold',
46
+ default=loc.LOC_THRESH,
47
+ type=click.IntRange(0, 100, clamp=True),
48
  )
 
 
 
 
 
 
49
  @click.option(
50
+ '--loc_nms_thresh',
51
+ help='Localizer (LOC) non-maximum suppression (NMS) threshold',
52
+ default=loc.NMS_THRESH,
53
+ type=click.IntRange(0, 100, clamp=True),
54
  )
55
+ @click.option(
56
+ '--agg_thresh',
57
+ help='Aggregation (AGG) confidence threshold',
58
+ default=agg.AGG_THRESH,
59
+ type=click.IntRange(0, 100, clamp=True),
60
+ )
61
+ @click.option(
62
+ '--agg_nms_thresh',
63
+ help='Aggregation (AGG) non-maximum suppression (NMS) threshold',
64
+ default=agg.NMS_THRESH,
65
+ type=click.IntRange(0, 100, clamp=True),
66
+ )
67
+ def pipeline(
68
+ filepath, output, wic_thresh, loc_thresh, loc_nms_thresh, agg_thresh, agg_nms_thresh
69
+ ):
70
+ """
71
+ Run the ScoutBot pipeline on an input image filepath
72
+ """
73
+ wic_thresh /= 100.0
74
+ loc_thresh /= 100.0
75
+ loc_nms_thresh /= 100.0
76
+ agg_thresh /= 100.0
77
+ agg_nms_thresh /= 100.0
78
+
79
+ detects = scoutbot.pipeline(
80
+ filepath,
81
+ wic_thresh=wic_thresh,
82
+ loc_thresh=loc_thresh,
83
+ loc_nms_thresh=loc_nms_thresh,
84
+ agg_thresh=agg_thresh,
85
+ agg_nms_thresh=agg_nms_thresh,
86
+ )
87
+
88
+ if output:
89
+ with open(output, 'w') as outfile:
90
+ json.dump(detects, outfile)
91
+ else:
92
+ log.info(ut.repr3(detects))
93
+
94
+
95
+ @click.command('fetch')
96
+ def fetch():
97
+ """
98
+ Fetch the required machine learning ONNX models for the WIC and LOC
99
+ """
100
+ scoutbot.fetch()
101
+
102
+
103
+ @click.group()
104
+ def cli():
105
+ """
106
+ ScoutBot CLI
107
+ """
108
  pass
109
 
110
 
111
+ cli.add_command(fetch)
112
+ cli.add_command(pipeline)
113
+
114
+
115
  if __name__ == '__main__':
116
+ cli()
scoutbot/tile/__init__.py CHANGED
@@ -7,6 +7,8 @@ from os.path import abspath, exists, join, split, splitext
7
  import cv2
8
  import numpy as np
9
 
 
 
10
  TILE_WIDTH = 256
11
  TILE_HEIGHT = 256
12
  TILE_SIZE = (TILE_WIDTH, TILE_HEIGHT)
@@ -42,6 +44,8 @@ def compute(img_filepath, grid1=True, grid2=True, ext=None, **kwargs):
42
  img = cv2.imread(img_filepath)
43
  shape = img.shape
44
 
 
 
45
  grids = []
46
  if grid1:
47
  grids += tile_grid(shape, **kwargs)
@@ -52,6 +56,8 @@ def compute(img_filepath, grid1=True, grid2=True, ext=None, **kwargs):
52
  for grid, filepath in zip(grids, filepaths):
53
  assert tile_write(img, grid, filepath)
54
 
 
 
55
  return shape, grids, filepaths
56
 
57
 
 
7
  import cv2
8
  import numpy as np
9
 
10
+ from scoutbot import log
11
+
12
  TILE_WIDTH = 256
13
  TILE_HEIGHT = 256
14
  TILE_SIZE = (TILE_WIDTH, TILE_HEIGHT)
 
44
  img = cv2.imread(img_filepath)
45
  shape = img.shape
46
 
47
+ log.info(f'Computing tiles (grid1={grid1}, grid2={grid2}) on {img_filepath}')
48
+
49
  grids = []
50
  if grid1:
51
  grids += tile_grid(shape, **kwargs)
 
56
  for grid, filepath in zip(grids, filepaths):
57
  assert tile_write(img, grid, filepath)
58
 
59
+ log.info(f'Rendered {len(filepaths)} tiles')
60
+
61
  return shape, grids, filepaths
62
 
63
 
scoutbot/wic/__init__.py CHANGED
@@ -15,6 +15,7 @@ import pooch
15
  import torch
16
  import utool as ut
17
 
 
18
  from scoutbot.wic.dataloader import (
19
  BATCH_SIZE,
20
  INPUT_SIZE,
@@ -59,6 +60,8 @@ def fetch(pull=False):
59
  )
60
  assert exists(onnx_model)
61
 
 
 
62
  return onnx_model
63
 
64
 
@@ -104,6 +107,8 @@ def predict(data, fill=False):
104
  """
105
  onnx_model = fetch()
106
 
 
 
107
  ort_session = ort.InferenceSession(
108
  onnx_model, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
109
  )
 
15
  import torch
16
  import utool as ut
17
 
18
+ from scoutbot import log
19
  from scoutbot.wic.dataloader import (
20
  BATCH_SIZE,
21
  INPUT_SIZE,
 
60
  )
61
  assert exists(onnx_model)
62
 
63
+ log.info(f'WIC Model: {onnx_model}')
64
+
65
  return onnx_model
66
 
67
 
 
107
  """
108
  onnx_model = fetch()
109
 
110
+ log.info(f'Running WIC inference on {len(data)} tiles')
111
+
112
  ort_session = ort.InferenceSession(
113
  onnx_model, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
114
  )