cellprofiler-library-nightly 5.0.0.dev466__tar.gz → 5.0.0.dev478__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/PKG-INFO +1 -1
  2. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/_version.py +3 -3
  3. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/image_processing.py +192 -20
  4. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_enhanceedges.py +22 -20
  5. cellprofiler_library_nightly-5.0.0.dev478/cellprofiler_library/modules/_flipandrotate.py +89 -0
  6. cellprofiler_library_nightly-5.0.0.dev478/cellprofiler_library/modules/_smooth.py +44 -0
  7. cellprofiler_library_nightly-5.0.0.dev478/cellprofiler_library/opts/enhanceedges.py +14 -0
  8. cellprofiler_library_nightly-5.0.0.dev478/cellprofiler_library/opts/flipandrotate.py +29 -0
  9. cellprofiler_library_nightly-5.0.0.dev478/cellprofiler_library/opts/smooth.py +9 -0
  10. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library_nightly.egg-info/PKG-INFO +1 -1
  11. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library_nightly.egg-info/SOURCES.txt +5 -0
  12. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/LICENSE +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/README.md +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/__init__.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/__init__.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/file_processing.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/measurement.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/object_processing.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/functions/segmentation.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/__init__.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_closing.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_colortogray.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_combineobjects.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_crop.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_dilateimage.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_dilateobjects.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_erodeimage.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_erodeobjects.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_fillobjects.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_graytocolor.py +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_imagemath.py +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  42. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
  43. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_medialaxis.py +0 -0
  44. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_medianfilter.py +0 -0
  45. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_morph.py +0 -0
  46. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  47. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_opening.py +0 -0
  48. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  49. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
  50. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_reducenoise.py +0 -0
  51. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_removeholes.py +0 -0
  52. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_resize.py +0 -0
  53. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  54. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
  55. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_threshold.py +0 -0
  56. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/modules/_watershed.py +0 -0
  57. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/__init__.py +0 -0
  58. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/colortogray.py +0 -0
  59. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
  60. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
  61. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
  62. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/crop.py +0 -0
  63. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/dilateimage.py +0 -0
  64. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/dilateobjects.py +0 -0
  65. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
  66. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/erodeimage.py +0 -0
  67. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/erodeobjects.py +0 -0
  68. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/graytocolor.py +0 -0
  69. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
  70. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
  71. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
  72. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/imagemath.py +0 -0
  73. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  74. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/morph.py +0 -0
  75. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
  76. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/overlayoutlines.py +0 -0
  77. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/removeholes.py +0 -0
  78. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/resize.py +0 -0
  79. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
  80. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/structuring_elements.py +0 -0
  81. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/opts/threshold.py +0 -0
  82. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/py.typed +0 -0
  83. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library/types.py +0 -0
  84. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  85. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  86. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  87. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/environment.yml +0 -0
  88. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/pyproject.toml +0 -0
  89. {cellprofiler_library_nightly-5.0.0.dev466 → cellprofiler_library_nightly-5.0.0.dev478}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev466
3
+ Version: 5.0.0.dev478
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '5.0.0.dev466'
32
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev466')
31
+ __version__ = version = '5.0.0.dev478'
32
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev478')
33
33
 
34
- __commit_id__ = commit_id = 'ge958a4dc2'
34
+ __commit_id__ = commit_id = 'g030288a08'
@@ -17,7 +17,8 @@ import matplotlib
17
17
  import math
18
18
  from typing import Any, Optional, Tuple, Callable, Union, List, cast, Dict, TypeVar
19
19
  from numpy.typing import NDArray
20
- from cellprofiler_library.types import ImageGrayscale, ImageGrayscaleMask, Image2DColor, Image2DGrayscale, ImageAny, ImageAnyMask, ObjectSegmentation, Image2D, Image2DMask, StructuringElement, ObjectLabelSet, ImageColor, ImageBinaryMask
20
+ from skimage.restoration import denoise_bilateral
21
+ from cellprofiler_library.types import ImageGrayscale, ImageGrayscaleMask, Image2DColor, Image2DGrayscale, Image2DGrayscaleMask, ImageAny, ImageAnyMask, ObjectSegmentation, Image2D, Image2DMask, StructuringElement, ObjectLabelSet, ImageColor, ImageBinaryMask
21
22
  from cellprofiler_library.opts import threshold as Threshold
22
23
  from cellprofiler_library.opts.enhanceorsuppressfeatures import SpeckleAccuracy, NeuriteMethod
23
24
  from cellprofiler_library.opts.overlayoutlines import BrightnessMode
@@ -25,8 +26,9 @@ from cellprofiler_library.opts.crop import RemovalMethod
25
26
  from cellprofiler_library.opts.structuring_elements import StructuringElementShape2D, StructuringElementShape3D
26
27
  from cellprofiler_library.opts.resize import ResizingMethod, DimensionMethod, InterpolationMethod
27
28
  from cellprofiler_library.opts.imagemath import Operator
29
+ from cellprofiler_library.opts.flipandrotate import RotationCoordinateAlignmnet
30
+ from cellprofiler_library.opts.enhanceedges import EdgeDirection
28
31
 
29
- # TODO: python_latest - remove this if later skimage versions update types
30
32
  invert = cast(Callable[[ImageAny], ImageAny], _invert)
31
33
  isscalar = cast(Callable[[Optional[ImageAny]], bool], _isscalar)
32
34
 
@@ -49,30 +51,46 @@ def medial_axis(image):
49
51
  return skimage.morphology.medial_axis(image)
50
52
 
51
53
 
52
- def enhance_edges_sobel(image, mask=None, direction="all"):
53
- if direction.casefold() == "all":
54
+ ###############################################################################
55
+ # EnhanceEdges
56
+ ###############################################################################
57
+
58
+ def enhance_edges_sobel(
59
+ image: Image2DGrayscale,
60
+ mask: Optional[Image2DGrayscaleMask]=None,
61
+ direction: EdgeDirection=EdgeDirection.ALL
62
+ ):
63
+ if direction == EdgeDirection.ALL:
54
64
  output_pixels = centrosome.filter.sobel(image, mask)
55
- elif direction.casefold() == "horizontal":
65
+ elif direction == EdgeDirection.HORIZONTAL:
56
66
  output_pixels = centrosome.filter.hsobel(image, mask)
57
- elif direction.casefold() == "vertical":
67
+ elif direction == EdgeDirection.VERTICAL:
58
68
  output_pixels = centrosome.filter.vsobel(image, mask)
59
69
  else:
60
70
  raise NotImplementedError(f"Unimplemented direction for Sobel: {direction}")
61
71
  return output_pixels
62
72
 
63
73
 
64
- def enhance_edges_log(image, mask=None, sigma=2.0):
74
+ def enhance_edges_log(
75
+ image: Image2DGrayscale,
76
+ mask: Optional[Image2DGrayscaleMask]=None,
77
+ sigma: float=2.0
78
+ ) -> Image2DGrayscale:
65
79
  size = int(sigma * 4) + 1
66
80
  output_pixels = centrosome.filter.laplacian_of_gaussian(image, mask, size, sigma)
67
81
  return output_pixels
68
82
 
69
83
 
70
- def enhance_edges_prewitt(image, mask=None, direction="all"):
71
- if direction.casefold() == "all":
84
+ def enhance_edges_prewitt(
85
+ image: Image2DGrayscale,
86
+ mask: Optional[Image2DGrayscaleMask]=None,
87
+ direction: EdgeDirection=EdgeDirection.ALL
88
+ ) -> Image2DGrayscale:
89
+ if direction == EdgeDirection.ALL:
72
90
  output_pixels = centrosome.filter.prewitt(image, mask)
73
- elif direction.casefold() == "horizontal":
91
+ elif direction == EdgeDirection.HORIZONTAL:
74
92
  output_pixels = centrosome.filter.hprewitt(image, mask)
75
- elif direction.casefold() == "vertical":
93
+ elif direction == EdgeDirection.VERTICAL:
76
94
  output_pixels = centrosome.filter.vprewitt(image, mask)
77
95
  else:
78
96
  raise NotImplementedError(f"Unimplemented direction for Prewitt: {direction}")
@@ -80,15 +98,15 @@ def enhance_edges_prewitt(image, mask=None, direction="all"):
80
98
 
81
99
 
82
100
  def enhance_edges_canny(
83
- image,
84
- mask=None,
85
- auto_threshold=True,
86
- auto_low_threshold=True,
87
- sigma=1.0,
88
- low_threshold=0.1,
89
- manual_threshold=0.2,
90
- threshold_adjustment_factor=1.0,
91
- ):
101
+ image: Image2DGrayscale,
102
+ mask: Optional[Image2DGrayscaleMask] = None,
103
+ auto_threshold: bool = True,
104
+ auto_low_threshold: bool = True,
105
+ sigma: float = 1.0,
106
+ low_threshold: float = 0.1,
107
+ manual_threshold: float = 0.2,
108
+ threshold_adjustment_factor: float = 1.0,
109
+ ) -> Image2DGrayscale:
92
110
 
93
111
  if auto_threshold or auto_low_threshold:
94
112
  sobel_image = centrosome.filter.sobel(image)
@@ -104,6 +122,26 @@ def enhance_edges_canny(
104
122
  output_pixels = centrosome.filter.canny(image, mask, sigma, low_th, high_th)
105
123
  return output_pixels
106
124
 
125
+ def stretched_rgb_from_components(
126
+ r: Image2DGrayscale,
127
+ g: Optional[Image2DGrayscale]=None,
128
+ b: Optional[Image2DGrayscale]=None
129
+ ):
130
+ if g:
131
+ assert r.shape == g.shape
132
+ if b:
133
+ assert r.shape == b.shape
134
+
135
+ color_image = numpy.zeros((r.shape[0], r.shape[1], 3))
136
+ color_image[:, :, 0] = centrosome.filter.stretch(r)
137
+
138
+ if g:
139
+ color_image[:, :, 1] = centrosome.filter.stretch(g)
140
+ if b:
141
+ color_image[:, :, 2] = centrosome.filter.stretch(b)
142
+
143
+ return color_image
144
+
107
145
 
108
146
  def morphology_closing(image, structuring_element=skimage.morphology.disk(1)):
109
147
  if structuring_element.ndim == 3 and image.ndim == 2:
@@ -1939,3 +1977,137 @@ def gray_to_stacked_color(
1939
1977
  source_channels = pixel_data_arr
1940
1978
  rgb_pixel_data = numpy.dstack(source_channels)
1941
1979
  return rgb_pixel_data
1980
+
1981
+
1982
+ ################################################################################
1983
+ # FlipAndRotate
1984
+ ################################################################################
1985
+
1986
+ def flip_image_left_to_right(pixel_data: Image2D) -> NDArray[numpy.int_]:
1987
+ i, j = numpy.mgrid[
1988
+ 0 : pixel_data.shape[0], pixel_data.shape[1] - 1 : -1 : -1
1989
+ ]
1990
+ return i, j
1991
+
1992
+ def flip_image_top_to_bottom(pixel_data: Image2D) -> NDArray[numpy.int_]:
1993
+ i, j = numpy.mgrid[
1994
+ pixel_data.shape[0] - 1 : -1 : -1, 0 : pixel_data.shape[1]
1995
+ ]
1996
+ return i, j
1997
+
1998
+ def flip_image_both(pixel_data: Image2D) -> NDArray[numpy.int_]:
1999
+ i, j = numpy.mgrid[
2000
+ pixel_data.shape[0] - 1 : -1 : -1, pixel_data.shape[1] - 1 : -1 : -1
2001
+ ]
2002
+ return i, j
2003
+
2004
+
2005
+ def rotate_image_angle(pixel_data: Image2D, mask: Image2DMask, rotate_angle: float, wants_crop: bool) -> Tuple[Image2D, Image2DMask, Optional[Image2DMask]]:
2006
+ angle = rotate_angle
2007
+ mask = scipy.ndimage.rotate(mask.astype(float), angle, reshape=True) > 0.50
2008
+ crop = (
2009
+ scipy.ndimage.rotate(
2010
+ numpy.ones(pixel_data.shape[:2]), angle, reshape=True
2011
+ )
2012
+ > 0.50
2013
+ )
2014
+ mask = mask & crop
2015
+ pixel_data = scipy.ndimage.rotate(pixel_data, angle, reshape=True)
2016
+ if wants_crop:
2017
+ #
2018
+ # We want to find the largest rectangle that fits inside
2019
+ # the crop. The cumulative sum in the i and j direction gives
2020
+ # the length of the rectangle in each direction and
2021
+ # multiplying them gives you the area.
2022
+ #
2023
+ # The left and right halves are symmetric, so we compute
2024
+ # on just two of the quadrants.
2025
+ #
2026
+ half = (numpy.array(crop.shape) / 2).astype(int)
2027
+ #
2028
+ # Operate on the lower right
2029
+ #
2030
+ quartercrop = crop[half[0] :, half[1] :]
2031
+ ci = numpy.cumsum(quartercrop, 0)
2032
+ cj = numpy.cumsum(quartercrop, 1)
2033
+ carea_d = ci * cj
2034
+ carea_d[quartercrop == 0] = 0
2035
+ #
2036
+ # Operate on the upper right by flipping I
2037
+ #
2038
+ quartercrop = crop[crop.shape[0] - half[0] - 1 :: -1, half[1] :]
2039
+ ci = numpy.cumsum(quartercrop, 0)
2040
+ cj = numpy.cumsum(quartercrop, 1)
2041
+ carea_u = ci * cj
2042
+ carea_u[quartercrop == 0] = 0
2043
+ carea = carea_d + carea_u
2044
+ max_carea = numpy.max(carea)
2045
+ max_area = numpy.argwhere(carea == max_carea)[0] + half
2046
+ min_i = max(crop.shape[0] - max_area[0] - 1, 0)
2047
+ max_i = max_area[0] + 1
2048
+ min_j = max(crop.shape[1] - max_area[1] - 1, 0)
2049
+ max_j = max_area[1] + 1
2050
+ ii = numpy.index_exp[min_i:max_i, min_j:max_j]
2051
+ crop = numpy.zeros(pixel_data.shape, bool)
2052
+ crop[ii] = True
2053
+ mask = mask[ii]
2054
+ pixel_data = pixel_data[ii]
2055
+ else:
2056
+ crop = None
2057
+ return pixel_data, mask, crop
2058
+
2059
+
2060
+ def rotate_image_coordinates(pixel_data: Image2D, mask: Image2DMask, rotate_point_1: Tuple[float, float], rotate_point_2: Tuple[float, float], rotate_coordinate_alignment: RotationCoordinateAlignmnet) -> float:
2061
+ xdiff = rotate_point_2[0] - rotate_point_1[0]
2062
+ ydiff = rotate_point_2[1] - rotate_point_1[1]
2063
+
2064
+ if rotate_coordinate_alignment == RotationCoordinateAlignmnet.VERTICALLY:
2065
+ angle = -numpy.arctan2(ydiff, xdiff) * 180.0 / numpy.pi
2066
+ elif rotate_coordinate_alignment == RotationCoordinateAlignmnet.HORIZONTALLY:
2067
+ angle = numpy.arctan2(xdiff, ydiff) * 180.0 / numpy.pi
2068
+ else:
2069
+ raise NotImplementedError(
2070
+ "Unknown axis: %s" % rotate_coordinate_alignment.value
2071
+ )
2072
+ return angle
2073
+
2074
+
2075
+ ###############################################################################
2076
+ # Smoothing
2077
+ ###############################################################################
2078
+
2079
+ def smoothing_gaussian(pixel_data: Image2D, mask: Optional[Image2DMask], sigma: float) -> Image2D:
2080
+ def fn(image: Image2D) -> Image2D:
2081
+ return scipy.ndimage.gaussian_filter(
2082
+ image, sigma, mode="constant", cval=0
2083
+ )
2084
+ return centrosome.smooth.smooth_with_function_and_mask(pixel_data, fn, mask)
2085
+
2086
+
2087
+ def smoothing_median(pixel_data: Image2D, mask: Optional[Image2DMask], obj_size: float) -> Image2D:
2088
+ return centrosome.filter.median_filter(pixel_data, mask, obj_size / 2 + 1)
2089
+
2090
+
2091
+ def smoothing_keeping_edges(pixel_data: Image2D, multichannel: bool, sigma_range: float, sigma: float) -> Image2D:
2092
+ assert sigma_range is not None, "sigma_range must be provided for smooth_keeping_edges"
2093
+ return denoise_bilateral(
2094
+ image=pixel_data.astype(float),
2095
+ channel_axis=2 if multichannel else None,
2096
+ sigma_color=sigma_range,
2097
+ sigma_spatial=sigma,
2098
+ )
2099
+
2100
+
2101
+ def smoothing_fit_polynomial(pixel_data: Image2D, mask: Optional[Image2DMask], clip: bool) -> Image2D:
2102
+ return centrosome.smooth.fit_polynomial(pixel_data, mask, clip)
2103
+
2104
+
2105
+ def smoothing_circular_average(pixel_data: Image2D, mask: Optional[Image2DMask], obj_size: float) -> Image2D:
2106
+ return centrosome.filter.circular_average_filter(pixel_data, obj_size / 2 + 1, mask)
2107
+
2108
+ def smoothing_smooth_to_average(pixel_data: Image2D, mask: Optional[Image2DMask]) -> Image2D:
2109
+ if mask is not None:
2110
+ mean = numpy.mean(pixel_data[mask])
2111
+ else:
2112
+ mean = numpy.mean(pixel_data)
2113
+ return numpy.ones(pixel_data.shape, pixel_data.dtype) * mean
@@ -2,28 +2,30 @@ import warnings
2
2
 
3
3
  import numpy
4
4
  import centrosome
5
-
5
+ from pydantic import Field, validate_call, ConfigDict
6
+ from typing import Annotated, Optional
6
7
  from ..functions.image_processing import (
7
8
  enhance_edges_sobel,
8
9
  enhance_edges_log,
9
10
  enhance_edges_prewitt,
10
11
  enhance_edges_canny,
11
12
  )
13
+ from ..opts.enhanceedges import EdgeFindingMethod, EdgeDirection
14
+ from ..types import Image2DGrayscale, Image2DGrayscaleMask
12
15
 
13
-
16
+ @validate_call(config=ConfigDict(arbitrary_types_allowed=True))
14
17
  def enhanceedges(
15
- image,
16
- mask=None,
17
- method="sobel",
18
- automatic_threshold=True,
19
- direction="all",
20
- automatic_gaussian=True,
21
- sigma=10,
22
- manual_threshold=0.2,
23
- threshold_adjustment_factor=1.0,
24
- automatic_low_threshold=True,
25
- low_threshold=0.1,
26
- ):
18
+ image: Annotated[Image2DGrayscale, Field(description="Input image")],
19
+ mask: Annotated[Optional[Image2DGrayscaleMask], Field(description="Mask of the input image")] = None,
20
+ method: Annotated[EdgeFindingMethod, Field(description="Edge finding method")] = EdgeFindingMethod.SOBEL,
21
+ automatic_threshold: Annotated[bool, Field(description="Automatically calculate the threshold?")] = True,
22
+ direction: Annotated[EdgeDirection, Field(description="Select edge direction to enhance")] = EdgeDirection.ALL,
23
+ sigma: Annotated[int, Field(description="Gaussian's sigma value")] = 10,
24
+ manual_threshold: Annotated[float, Field(description="Absolute threshold")] = 0.2,
25
+ threshold_adjustment_factor: Annotated[float, Field(description="Threshold adjustment factor")] = 1.0,
26
+ automatic_low_threshold: Annotated[bool, Field(description="Automatically calculate the low / soft threshold cutoff for the Canny method?")] = True,
27
+ low_threshold: Annotated[float, Field(description="Low threshold value")] = 0.1,
28
+ ) -> Image2DGrayscale:
27
29
  """EnhanceEdges module
28
30
 
29
31
  Parameters
@@ -64,13 +66,13 @@ def enhanceedges(
64
66
  if mask is None:
65
67
  mask = numpy.ones(image.shape, bool)
66
68
 
67
- if method.casefold() == "sobel":
69
+ if method == EdgeFindingMethod.SOBEL:
68
70
  output_pixels = enhance_edges_sobel(image, mask, direction)
69
- elif method.casefold() == "log":
71
+ elif method == EdgeFindingMethod.LOG:
70
72
  output_pixels = enhance_edges_log(image, mask, sigma)
71
- elif method.casefold() == "prewitt":
73
+ elif method == EdgeFindingMethod.PREWITT:
72
74
  output_pixels = enhance_edges_prewitt(image, mask, direction)
73
- elif method.casefold() == "canny":
75
+ elif method == EdgeFindingMethod.CANNY:
74
76
  output_pixels = enhance_edges_canny(
75
77
  image,
76
78
  mask,
@@ -81,9 +83,9 @@ def enhanceedges(
81
83
  manual_threshold=manual_threshold,
82
84
  threshold_adjustment_factor=threshold_adjustment_factor,
83
85
  )
84
- elif method.casefold() == "roberts":
86
+ elif method == EdgeFindingMethod.ROBERTS:
85
87
  output_pixels = centrosome.filter.roberts(image, mask)
86
- elif method.casefold() == "kirsch":
88
+ elif method == EdgeFindingMethod.KIRSCH:
87
89
  output_pixels = centrosome.kirsch.kirsch(image)
88
90
  else:
89
91
  raise NotImplementedError(f"{method} edge detection method is not implemented.")
@@ -0,0 +1,89 @@
1
+ import numpy
2
+ from pydantic import Field, validate_call, ConfigDict
3
+ from typing import Annotated, Optional, Tuple, Dict, Callable
4
+ from numpy.typing import NDArray
5
+ from cellprofiler_library.functions.image_processing import flip_image_both, flip_image_left_to_right, flip_image_top_to_bottom, rotate_image_angle, rotate_image_coordinates
6
+ from cellprofiler_library.types import Image2D, Image2DMask
7
+ from cellprofiler_library.opts.flipandrotate import FlipDirection, RotateMethod, RotationCoordinateAlignmnet
8
+
9
+ @validate_call(config=ConfigDict(arbitrary_types_allowed=True))
10
+ def flip_and_rotate(
11
+ pixel_data: Annotated[Image2D, Field(description="Pixel data of image to be flipped and/or rotated")],
12
+ mask: Annotated[Image2DMask, Field(description="Mask of the image to be flipped and/or rotated")],
13
+ flip_choice: Annotated[FlipDirection, Field(description="Direction to flip the image")],
14
+ rotate_choice: Annotated[RotateMethod, Field(description="Rotation method")],
15
+ rotate_angle: Annotated[Optional[float], Field(description="Angle to rotate the image")],
16
+ rotate_point_1: Annotated[Optional[Tuple[float, float]], Field(description="Point to rotate the image around")],
17
+ rotate_point_2: Annotated[Optional[Tuple[float, float]], Field(description="Second point to rotate the image around")],
18
+ rotate_coordinate_alignment: Annotated[Optional[RotationCoordinateAlignmnet], Field(description="Alignment of the rotated points. The points you select will be aligned horizontally or vertically after the rotation is complete.")],
19
+ wants_crop: Annotated[bool, Field(description="Whether to crop the image")],
20
+ ) -> Tuple[Image2D, Image2DMask, Optional[Image2DMask], float]:
21
+ #
22
+ # Perform flip
23
+ #
24
+ pixel_data, mask = flip_image(pixel_data, mask, flip_choice)
25
+
26
+ #
27
+ # Perform rotation
28
+ #
29
+ pixel_data, mask, crop, angle = rotate_image(pixel_data, mask, rotate_choice, rotate_angle, rotate_point_1, rotate_point_2, rotate_coordinate_alignment, wants_crop)
30
+
31
+ return pixel_data, mask, crop, angle
32
+
33
+
34
+ def flip_image(
35
+ pixel_data: Image2D,
36
+ mask: Image2DMask,
37
+ flip_choice: FlipDirection
38
+ ) -> Tuple[Image2D, Image2DMask]:
39
+ flip_dispatch: Dict[FlipDirection, Callable[[Image2D], NDArray[numpy.int_]]] = {
40
+ FlipDirection.LEFT_TO_RIGHT: flip_image_left_to_right,
41
+ FlipDirection.TOP_TO_BOTTOM: flip_image_top_to_bottom,
42
+ FlipDirection.BOTH: flip_image_both,
43
+ }
44
+ if flip_choice != FlipDirection.NONE:
45
+ if flip_choice in flip_dispatch.keys():
46
+ i, j = flip_dispatch[flip_choice](pixel_data)
47
+ else:
48
+ raise NotImplementedError(
49
+ "Unknown flipping operation: %s" % flip_choice.value
50
+ )
51
+ mask = mask[i, j]
52
+ if pixel_data.ndim == 2:
53
+ pixel_data = pixel_data[i, j]
54
+ else:
55
+ pixel_data = pixel_data[i, j, :]
56
+ return pixel_data, mask
57
+
58
+
59
+ def rotate_image(
60
+ pixel_data: Image2D,
61
+ mask: Image2DMask,
62
+ rotate_choice: RotateMethod,
63
+ rotate_angle: Optional[float],
64
+ rotate_point_1: Optional[Tuple[float, float]],
65
+ rotate_point_2: Optional[Tuple[float, float]],
66
+ rotate_coordinate_alignment: Optional[RotationCoordinateAlignmnet],
67
+ wants_crop: bool,
68
+ ) -> Tuple[Image2D, Image2DMask, Optional[Image2DMask], float]:
69
+ if rotate_choice != RotateMethod.NONE:
70
+ if rotate_choice == RotateMethod.ANGLE:
71
+ assert rotate_angle is not None, "rotate_angle must be provided for rotate_choice == RotateMethod.ANGLE"
72
+ angle = rotate_angle
73
+ elif rotate_choice == RotateMethod.COORDINATES:
74
+ assert rotate_point_1 is not None, "rotate_point_1 must be provided for rotate_choice == RotateMethod.COORDINATES"
75
+ assert rotate_point_2 is not None, "rotate_point_2 must be provided for rotate_choice == RotateMethod.COORDINATES"
76
+ assert rotate_coordinate_alignment is not None, "rotate_coordinate_alignment must be provided for rotate_choice == RotateMethod.COORDINATES"
77
+ angle = rotate_image_coordinates(pixel_data, mask, rotate_point_1, rotate_point_2, rotate_coordinate_alignment)
78
+
79
+ else:
80
+ raise NotImplementedError(
81
+ "Unknown rotation method: %s" % rotate_choice.value
82
+ )
83
+ # rangle = angle * numpy.pi / 180.0
84
+ pixel_data, mask, crop = rotate_image_angle(pixel_data, mask, angle, wants_crop)
85
+
86
+ else:
87
+ crop = None
88
+ angle = 0.0
89
+ return pixel_data, mask, crop, angle
@@ -0,0 +1,44 @@
1
+ import numpy
2
+ from typing import Annotated, Optional
3
+ from pydantic import Field, validate_call, ConfigDict
4
+
5
+ from cellprofiler_library.functions.image_processing import smoothing_gaussian, smoothing_median, smoothing_keeping_edges, smoothing_fit_polynomial, smoothing_circular_average, smoothing_smooth_to_average
6
+ from cellprofiler_library.opts.smooth import SmoothingMethod
7
+ from cellprofiler_library.types import Image2D, Image2DMask
8
+
9
+
10
+ @validate_call(config=ConfigDict(arbitrary_types_allowed=True))
11
+ def smooth(
12
+ pixel_data: Annotated[Image2D, Field(description="Pixel data of image to be smoothed")],
13
+ mask: Annotated[Optional[Image2DMask], Field(description="Mask of the pixel data")],
14
+ multichannel: Annotated[bool, Field(description="Set to true if image is multichannel")],
15
+ object_size: Annotated[Optional[float], Field(description="Object size")],
16
+ smoothing_method: Annotated[SmoothingMethod, Field(description="Smoothing method")],
17
+ sigma_range: Annotated[Optional[float], Field(description="Sigma range")],
18
+ clip: Annotated[Optional[bool], Field(description="Clip intensities to 0 and 1")] = True,
19
+ ) -> Image2D:
20
+ if object_size is not None:
21
+ obj_size = float(object_size)
22
+ else:
23
+ obj_size = float(min(30, max(1, numpy.mean(pixel_data.shape) / 40)))
24
+ sigma = obj_size / 2.35
25
+
26
+ if smoothing_method == SmoothingMethod.GAUSSIAN_FILTER:
27
+ output_pixels = smoothing_gaussian(pixel_data, mask, sigma)
28
+ elif smoothing_method == SmoothingMethod.MEDIAN_FILTER:
29
+ output_pixels = smoothing_median(pixel_data, mask, obj_size)
30
+ elif smoothing_method == SmoothingMethod.SMOOTH_KEEPING_EDGES:
31
+ assert sigma_range is not None, "sigma_range must be provided for smooth_keeping_edges"
32
+ output_pixels = smoothing_keeping_edges(pixel_data, multichannel, sigma_range, sigma)
33
+ elif smoothing_method == SmoothingMethod.FIT_POLYNOMIAL:
34
+ assert clip is not None, "clip must be provided for fit_polynomial"
35
+ output_pixels = smoothing_fit_polynomial(pixel_data, mask, clip)
36
+ elif smoothing_method == SmoothingMethod.CIRCULAR_AVERAGE_FILTER:
37
+ output_pixels = smoothing_circular_average(pixel_data, mask, obj_size)
38
+ elif smoothing_method == SmoothingMethod.SM_TO_AVERAGE:
39
+ output_pixels = smoothing_smooth_to_average(pixel_data, mask)
40
+ else:
41
+ raise ValueError(
42
+ "Unsupported smoothing method: %s" % smoothing_method
43
+ )
44
+ return output_pixels
@@ -0,0 +1,14 @@
1
+ from enum import Enum
2
+
3
+ class EdgeFindingMethod(str, Enum):
4
+ SOBEL = "Sobel"
5
+ PREWITT = "Prewitt"
6
+ ROBERTS = "Roberts"
7
+ LOG = "Log"
8
+ CANNY = "Canny"
9
+ KIRSCH = "Kirsch"
10
+
11
+ class EdgeDirection(str, Enum):
12
+ ALL = "All"
13
+ HORIZONTAL = "Horizontal"
14
+ VERTICAL = "Vertical"
@@ -0,0 +1,29 @@
1
+ from enum import Enum
2
+
3
+ class FlipDirection(str, Enum):
4
+ NONE = "Do not flip"
5
+ LEFT_TO_RIGHT = "Left to right"
6
+ TOP_TO_BOTTOM = "Top to bottom"
7
+ BOTH = "Left to right and top to bottom"
8
+
9
+ class RotateMethod(str, Enum):
10
+ NONE = "Do not rotate"
11
+ ANGLE = "Enter angle"
12
+ COORDINATES = "Enter coordinates"
13
+
14
+ class RotationCoordinateAlignmnet(str, Enum):
15
+ HORIZONTALLY = "Horizontally"
16
+ VERTICALLY = "Vertically"
17
+
18
+ D_ANGLE = "angle"
19
+
20
+ """Rotation measurement category"""
21
+ M_ROTATION_CATEGORY = "Rotation"
22
+ """Rotation measurement format (+ image name)"""
23
+ M_ROTATION_F = "%s_%%s" % M_ROTATION_CATEGORY
24
+
25
+ FLIP_ALL = [FlipDirection.NONE, FlipDirection.LEFT_TO_RIGHT, FlipDirection.TOP_TO_BOTTOM, FlipDirection.BOTH]
26
+
27
+ ROTATE_ALL = [RotateMethod.NONE, RotateMethod.ANGLE, RotateMethod.COORDINATES]
28
+
29
+ C_ALL = [RotationCoordinateAlignmnet.HORIZONTALLY, RotationCoordinateAlignmnet.VERTICALLY]
@@ -0,0 +1,9 @@
1
+ from enum import Enum
2
+
3
+ class SmoothingMethod(str, Enum):
4
+ FIT_POLYNOMIAL = "Fit Polynomial"
5
+ MEDIAN_FILTER = "Median Filter"
6
+ GAUSSIAN_FILTER = "Gaussian Filter"
7
+ SMOOTH_KEEPING_EDGES = "Smooth Keeping Edges"
8
+ CIRCULAR_AVERAGE_FILTER = "Circular Average Filter"
9
+ SM_TO_AVERAGE = "Smooth to Average"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev466
3
+ Version: 5.0.0.dev478
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -28,6 +28,7 @@ cellprofiler_library/modules/_erodeimage.py
28
28
  cellprofiler_library/modules/_erodeobjects.py
29
29
  cellprofiler_library/modules/_expandorshrinkobjects.py
30
30
  cellprofiler_library/modules/_fillobjects.py
31
+ cellprofiler_library/modules/_flipandrotate.py
31
32
  cellprofiler_library/modules/_gaussianfilter.py
32
33
  cellprofiler_library/modules/_graytocolor.py
33
34
  cellprofiler_library/modules/_identifyprimaryobjects.py
@@ -48,6 +49,7 @@ cellprofiler_library/modules/_removeholes.py
48
49
  cellprofiler_library/modules/_resize.py
49
50
  cellprofiler_library/modules/_savecroppedobjects.py
50
51
  cellprofiler_library/modules/_shrinktoobjectcenters.py
52
+ cellprofiler_library/modules/_smooth.py
51
53
  cellprofiler_library/modules/_threshold.py
52
54
  cellprofiler_library/modules/_watershed.py
53
55
  cellprofiler_library/opts/__init__.py
@@ -58,9 +60,11 @@ cellprofiler_library/opts/correctilluminationapply.py
58
60
  cellprofiler_library/opts/crop.py
59
61
  cellprofiler_library/opts/dilateimage.py
60
62
  cellprofiler_library/opts/dilateobjects.py
63
+ cellprofiler_library/opts/enhanceedges.py
61
64
  cellprofiler_library/opts/enhanceorsuppressfeatures.py
62
65
  cellprofiler_library/opts/erodeimage.py
63
66
  cellprofiler_library/opts/erodeobjects.py
67
+ cellprofiler_library/opts/flipandrotate.py
64
68
  cellprofiler_library/opts/graytocolor.py
65
69
  cellprofiler_library/opts/identifyprimaryobjects.py
66
70
  cellprofiler_library/opts/identifysecondaryobjects.py
@@ -73,6 +77,7 @@ cellprofiler_library/opts/overlayoutlines.py
73
77
  cellprofiler_library/opts/removeholes.py
74
78
  cellprofiler_library/opts/resize.py
75
79
  cellprofiler_library/opts/shrinktoobjectcenters.py
80
+ cellprofiler_library/opts/smooth.py
76
81
  cellprofiler_library/opts/structuring_elements.py
77
82
  cellprofiler_library/opts/threshold.py
78
83
  cellprofiler_library_nightly.egg-info/PKG-INFO