Skip to content

Commit f1a7764

Browse files
committed
Merge pull request #418 from rapidsai/branch-22.10
2 parents 61500c2 + 5cad8d3 commit f1a7764

File tree

27 files changed

+470
-417
lines changed

27 files changed

+470
-417
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
# cuCIM 22.10.00 (12 Oct 2022)
2+
3+
## 🐛 Bug Fixes
4+
5+
- Correctly use dtype when computing shared memory requirements of separable convolution ([#409](https://github.com/rapidsai/cucim/pull/409)) [@grlee77](https://github.com/grlee77)
6+
- Forward-merge branch-22.08 to branch-22.10 ([#403](https://github.com/rapidsai/cucim/pull/403)) [@jakirkham](https://github.com/jakirkham)
7+
- Add missing imports of euler_number and perimeter_crofton ([#386](https://github.com/rapidsai/cucim/pull/386)) [@grlee77](https://github.com/grlee77)
8+
9+
## 📖 Documentation
10+
11+
- update pypi CHANGELOG.md for releases 22.08.00 and 22.08.01 ([#404](https://github.com/rapidsai/cucim/pull/404)) [@grlee77](https://github.com/grlee77)
12+
- Update README.md ([#396](https://github.com/rapidsai/cucim/pull/396)) [@HesAnEasyCoder](https://github.com/HesAnEasyCoder)
13+
14+
## 🚀 New Features
15+
16+
- Allow cupy 11 ([#399](https://github.com/rapidsai/cucim/pull/399)) [@galipremsagar](https://github.com/galipremsagar)
17+
- Add cucim.skimage.feature.match_descriptors ([#338](https://github.com/rapidsai/cucim/pull/338)) [@grlee77](https://github.com/grlee77)
18+
19+
## 🛠️ Improvements
20+
21+
- Merge docs and add links ([#415](https://github.com/rapidsai/cucim/pull/415)) [@jakirkham](https://github.com/jakirkham)
22+
- Add benchmarks for scikit-image functions introduced in 22.08 ([#378](https://github.com/rapidsai/cucim/pull/378)) [@grlee77](https://github.com/grlee77)
23+
124
# cuCIM 22.08.00 (17 Aug 2022)
225

326
## 🚨 Breaking Changes

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ cuCIM supports the following formats:
2828
- [GTC 2021 cuCIM: A GPU Image I/O and Processing Toolkit [S32194]](https://www.nvidia.com/en-us/on-demand/search/?facet.mimetype[]=event%20session&layout=list&page=1&q=cucim&sort=date)
2929
- [video](https://www.nvidia.com/en-us/on-demand/session/gtcspring21-s32194/)
3030

31+
**[Developer Page](https://developer.nvidia.com/multidimensional-image-processing)**
32+
3133
**Blogs**
3234
- [Enhanced Image Analysis with Multidimensional Image Processing](https://developer.nvidia.com/blog/enhanced-image-analysis-with-multidimensional-image-processing/)
3335
- [Accelerating Scikit-Image API with cuCIM: n-Dimensional Image Processing and IO on GPUs](https://developer.nvidia.com/blog/cucim-rapid-n-dimensional-image-processing-and-i-o-on-gpus/)
@@ -68,7 +70,7 @@ pip install scipy scikit-image cupy-cuda110
6870

6971
### Notebooks
7072

71-
Please check out our [Welcome](notebooks/Welcome.ipynb) notebook ([NBViewer](https://nbviewer.jupyter.org/github/rapidsai/cucim/blob/branch-22.08/notebooks/Welcome.ipynb))
73+
Please check out our [Welcome](notebooks/Welcome.ipynb) notebook ([NBViewer](https://nbviewer.jupyter.org/github/rapidsai/cucim/blob/branch-22.10/notebooks/Welcome.ipynb))
7274

7375
#### Downloading sample images
7476

@@ -108,4 +110,4 @@ is used in this project.
108110

109111
Apache-2.0 License (see [LICENSE](LICENSE) file).
110112

111-
Copyright (c) 2020-2021, NVIDIA CORPORATION.
113+
Copyright (c) 2020-2022, NVIDIA CORPORATION.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
22.08.01
1+
22.10.00

benchmarks/skimage/cucim_morphology_bench.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ def main(args):
138138
("white_tophat", dict(), dict(), False, True),
139139
("black_tophat", dict(), dict(), False, True),
140140
# _skeletonize.py
141+
("medial_axis", dict(random_state=123), dict(return_distance=[False, True]), False, False),
141142
("thin", dict(), dict(), False, True),
142143
# grayreconstruct.py
143144
("reconstruction", dict(), dict(), False, True),
@@ -149,7 +150,7 @@ def main(args):
149150
continue
150151

151152
ndim = len(shape)
152-
if function_name == 'thin':
153+
if function_name in ['thin', 'medial_axis']:
153154
if ndim != 2:
154155
raise ValueError("only 2d benchmark data has been implemented")
155156

@@ -263,7 +264,7 @@ def main(args):
263264

264265
if __name__ == '__main__':
265266
parser = argparse.ArgumentParser(description='Benchmarking cuCIM morphology functions')
266-
func_name_choices = ['binary_erosion', 'binary_dilation', 'binary_opening', 'binary_closing', 'remove_small_objects', 'remove_small_holes', 'erosion', 'dilation', 'opening', 'closing', 'white_tophat', 'black_tophat', 'thin', 'reconstruction']
267+
func_name_choices = ['binary_erosion', 'binary_dilation', 'binary_opening', 'binary_closing', 'remove_small_objects', 'remove_small_holes', 'erosion', 'dilation', 'opening', 'closing', 'white_tophat', 'black_tophat', 'thin', 'medial_axis', 'reconstruction']
267268
dtype_choices = ['float16', 'float32', 'float64', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64']
268269
parser.add_argument('-i','--img_size', type=str, help='Size of input image (omit color channel, it will be appended as needed)', required=True)
269270
parser.add_argument('-d','--dtype', type=str, help='Dtype of input image', choices = dtype_choices, required=True)

benchmarks/skimage/cucim_segmentation_bench.py

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
import pickle
55

66
import cucim.skimage
7-
import cucim.skimage.data
8-
import cucim.skimage.exposure
9-
import cucim.skimage.segmentation
7+
from cucim.skimage import data, exposure, measure, segmentation
108
import cupy as cp
119
import numpy as np
1210
import pandas as pd
@@ -21,7 +19,6 @@ def __init__(
2119
self,
2220
function_name,
2321
shape,
24-
contiguous_labels=True,
2522
dtypes=np.float32,
2623
fixed_kwargs={},
2724
var_kwargs={},
@@ -31,8 +28,6 @@ def __init__(
3128
run_cpu=True,
3229
):
3330

34-
self.contiguous_labels = contiguous_labels
35-
3631
super().__init__(
3732
function_name=function_name,
3833
shape=shape,
@@ -45,44 +40,33 @@ def __init__(
4540
run_cpu=run_cpu,
4641
)
4742

48-
def set_args(self, dtype):
49-
a = np.array(
50-
[
51-
[0, 0, 1, 1, 0, 0, 0, 0],
52-
[0, 0, 0, 1, 0, 0, 4, 0],
53-
[2, 2, 0, 0, 3, 0, 4, 4],
54-
[0, 0, 0, 0, 0, 5, 0, 0],
55-
],
56-
dtype=dtype,
43+
def _generate_labels(self, dtype):
44+
ndim = len(self.shape)
45+
blobs_kwargs = dict(blob_size_fraction=0.05,
46+
volume_fraction=0.35,
47+
seed=5)
48+
# binary blobs only creates square outputs
49+
labels = measure.label(
50+
data.binary_blobs(max(self.shape), n_dim=ndim, **blobs_kwargs)
5751
)
58-
tiling = tuple(s // a_s for s, a_s in zip(self.shape, a.shape))
59-
if self.contiguous_labels:
60-
labels = np.kron(a, np.ones(tiling, dtype=a.dtype))
61-
else:
62-
labels = np.tile(a, tiling)
63-
labels_d = cp.asarray(labels)
52+
print(f"# labels generated = {labels.max()}")
53+
54+
# crop to rectangular
55+
labels = labels[tuple(slice(s) for s in self.shape)]
56+
return labels.astype(dtype, copy=False)
57+
58+
def set_args(self, dtype):
59+
labels_d = self._genereate_labels(dtype)
60+
labels = cp.asnumpy(labels_d)
6461
self.args_cpu = (labels,)
6562
self.args_gpu = (labels_d,)
6663

6764

6865
class LabelAndImageBench(LabelBench):
6966

7067
def set_args(self, dtype):
71-
a = np.array(
72-
[
73-
[0, 0, 1, 1, 0, 0, 0, 0],
74-
[0, 0, 0, 1, 0, 0, 4, 0],
75-
[2, 2, 0, 0, 3, 0, 4, 4],
76-
[0, 0, 0, 0, 0, 5, 0, 0],
77-
],
78-
dtype=dtype,
79-
)
80-
tiling = tuple(s // a_s for s, a_s in zip(self.shape, a.shape))
81-
if self.contiguous_labels:
82-
labels = np.kron(a, np.ones(tiling, dtype=a.dtype))
83-
else:
84-
labels = np.tile(a, tiling)
85-
labels_d = cp.asarray(labels)
68+
labels_d = self._genereate_labels(dtype)
69+
labels = cp.asnumpy(labels_d)
8670
image_d = cp.random.standard_normal(labels.shape).astype(np.float32)
8771
image = cp.asnumpy(image_d)
8872
self.args_cpu = (image, labels)
@@ -150,7 +134,6 @@ def set_args(self, dtype):
150134
self.args_gpu = (data, markers)
151135

152136

153-
154137
def main(args):
155138

156139
pfile = "cucim_segmentation_results.pickle"
@@ -175,6 +158,14 @@ def main(args):
175158
False,
176159
True,
177160
),
161+
# _expand_labels.py
162+
(
163+
"expand_labels",
164+
dict(distance=1),
165+
dict(),
166+
False,
167+
True,
168+
),
178169
# _join.py
179170
(
180171
"relabel_sequential",
@@ -221,6 +212,16 @@ def main(args):
221212
False,
222213
False,
223214
),
215+
(
216+
"chan_vese",
217+
dict(),
218+
# Reduced number of iterations so scikit-image comparison will not
219+
# take minutes to complete. Empirically, approximately the same
220+
# acceleration was measured for 10 or 100 iterations.
221+
dict(max_num_iter=[10], init_level_set=["checkerboard", "disk"]),
222+
False,
223+
False,
224+
),
224225
# omit: disk_level_set (simple array generation function)
225226
# omit: checkerboard_level_set (simple array generation function)
226227
]:
@@ -239,7 +240,7 @@ def main(args):
239240
if shape[-1] == 3 and not allow_color:
240241
continue
241242

242-
if function_name in ["clear_border", "relabel_sequential", "find_boundaries", "mark_boundaries", "random_walker"]:
243+
if function_name in ["clear_border", "expand_labels", "relabel_sequential", "find_boundaries", "mark_boundaries", "random_walker"]:
243244
if function_name == 'random_walker':
244245
fixed_kwargs['channel_axis'] = -1 if shape[-1] == 3 else None
245246

@@ -263,7 +264,7 @@ def main(args):
263264
all_results = pd.concat([all_results, results["full"]])
264265

265266

266-
elif function_name in ["inverse_gaussian_gradient", "morphological_geodesic_active_contour", "morphological_chan_vese"]:
267+
elif function_name in ["inverse_gaussian_gradient", "morphological_geodesic_active_contour", "morphological_chan_vese", "chan_vese"]:
267268

268269
if function_name == "morphological_geodesic_active_contour":
269270
bench_class = MorphGeodesicBench
@@ -296,7 +297,7 @@ def main(args):
296297

297298
if __name__ == '__main__':
298299
parser = argparse.ArgumentParser(description='Benchmarking cuCIM segmentation functions')
299-
func_name_choices = ["clear_border", "relabel_sequential", "find_boundaries", "mark_boundaries", "random_walker", "inverse_gaussian_gradient", "morphological_geodesic_active_contour", "morphological_chan_vese"]
300+
func_name_choices = ["clear_border", "expand_labels", "relabel_sequential", "find_boundaries", "mark_boundaries", "random_walker", "inverse_gaussian_gradient", "morphological_geodesic_active_contour", "morphological_chan_vese", "chan_vese"]
300301
label_dtype_choices = ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64']
301302
dtype_choices = ['float16', 'float32', 'float64', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64']
302303
parser.add_argument('-i','--img_size', type=str, help='Size of input image (omit color channel, it will be appended as needed)', required=True)

benchmarks/skimage/run-nv-bench-morphology.sh

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#!/bin/bash
22
param_shape=(512,512 3840,2160 3840,2160,3 192,192,192)
3-
param_filt=(binary_erosion binary_dilation binary_opening binary_closing remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat thin reconstruction)
4-
# Note: user-specified dtype ignored for binary_* functions and thin (these only accept binary input)
5-
param_dt=(float32 uint8)
3+
param_filt=(binary_erosion binary_dilation binary_opening binary_closing remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat medial_axis thin reconstruction)
4+
5+
param_dt=(uint8)
6+
for shape in "${param_shape[@]}"; do
7+
for filt in "${param_filt[@]}"; do
8+
for dt in "${param_dt[@]}"; do
9+
python cucim_morphology_bench.py -f $filt -i $shape -d $dt -t 10
10+
done
11+
done
12+
done
13+
14+
# Note: Omit binary_*, medial_axis and thin from floating point benchmarks.
15+
# (these functions only take binary input).
16+
param_filt_float=(remove_small_objects remove_small_holes erosion dilation opening closing white_tophat black_tophat reconstruction)
17+
param_dt=(float32)
618
for shape in "${param_shape[@]}"; do
719
for filt in "${param_filt[@]}"; do
820
for dt in "${param_dt[@]}"; do

benchmarks/skimage/run-nv-bench-segmentation.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
param_shape=(512,512 3840,2160 3840,2160,3 192,192,192)
33

44
# these require an integer-valued label image
5-
param_filt=(clear_border relabel_sequential find_boundaries mark_boundaries random_walker)
5+
param_filt=(clear_border expand_labels relabel_sequential find_boundaries mark_boundaries random_walker)
66
param_dt=(float32)
77
param_dt_label=(uint8 uint32)
88
for shape in "${param_shape[@]}"; do
@@ -16,7 +16,7 @@ for shape in "${param_shape[@]}"; do
1616
done
1717

1818
# these do not require an integer-valued input image
19-
param_filt=(inverse_gaussian_gradient morphological_geodesic_active_contour morphological_chan_vese)
19+
param_filt=(inverse_gaussian_gradient morphological_geodesic_active_contour morphological_chan_vese chan_vese)
2020
param_dt=(float32)
2121
for shape in "${param_shape[@]}"; do
2222
for filt in "${param_filt[@]}"; do

conda/recipes/cucim/meta.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ requirements:
2929
- python {{ python_version }}.*
3030
- libcucim {{ version }}.*
3131
- click
32-
- cupy >=9,<11.0.0a0
32+
- cupy >=9,<12.0.0a0
3333
- numpy 1.19
3434
- scipy
3535
- scikit-image >=0.19.0,<0.20.0a0
@@ -38,7 +38,7 @@ requirements:
3838
- python {{ python_version }}.*
3939
- libcucim {{ version }}.*
4040
- click
41-
- cupy >=9,<11.0.0a0
41+
- cupy >=9,<12.0.0a0
4242
- {{ pin_compatible('numpy') }}
4343
- scipy
4444
- scikit-image >=0.19.0,<0.20.0a0
@@ -51,8 +51,10 @@ tests: # [linux64]
5151
- cucim # [linux64]
5252

5353
about:
54-
home: http://rapids.ai/
54+
home: https://developer.nvidia.com/multidimensional-image-processing
55+
summary: cucim Python package
5556
license: Apache-2.0
5657
license_family: Apache
5758
license_file: LICENSE
58-
summary: cucim Python package
59+
doc_url: https://docs.rapids.ai/api/cucim/stable/
60+
dev_url: https://github.com/rapidsai/cucim

conda/recipes/libcucim/meta.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ requirements:
4444
- libwebp-base # [linux or osx]
4545

4646
about:
47-
home: http://rapids.ai/
47+
home: https://developer.nvidia.com/multidimensional-image-processing
48+
summary: libcucim C++ library
4849
license: Apache-2.0
4950
license_family: Apache
5051
license_file: LICENSE
51-
summary: libcucim C++ library
52+
doc_url: https://docs.rapids.ai/api/cucim/stable/
53+
dev_url: https://github.com/rapidsai/cucim
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
22.08.01
1+
22.10.00

0 commit comments

Comments
 (0)