Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
		
							parent
							
								
									00ad49a143
								
							
						
					
					
						commit
						45fb349a7d
					
				
					 5098 changed files with 952558 additions and 85 deletions
				
			
		
							
								
								
									
										31
									
								
								venv/Lib/site-packages/skimage/draw/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								venv/Lib/site-packages/skimage/draw/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| from .draw import (circle, ellipse, set_color, polygon_perimeter, | ||||
|                    line, line_aa, polygon, ellipse_perimeter, | ||||
|                    circle_perimeter, circle_perimeter_aa, | ||||
|                    disk, | ||||
|                    bezier_curve, rectangle, rectangle_perimeter) | ||||
| from .draw3d import ellipsoid, ellipsoid_stats | ||||
| from ._draw import _bezier_segment | ||||
| from ._random_shapes import random_shapes | ||||
| from ._polygon2mask import polygon2mask | ||||
| 
 | ||||
| from .draw_nd import line_nd | ||||
| 
 | ||||
| __all__ = ['line', | ||||
|            'line_aa', | ||||
|            'line_nd', | ||||
|            'bezier_curve', | ||||
|            'polygon', | ||||
|            'polygon_perimeter', | ||||
|            'ellipse', | ||||
|            'ellipse_perimeter', | ||||
|            'ellipsoid', | ||||
|            'ellipsoid_stats', | ||||
|            'circle', | ||||
|            'circle_perimeter', | ||||
|            'circle_perimeter_aa', | ||||
|            'disk', | ||||
|            'set_color', | ||||
|            'random_shapes', | ||||
|            'rectangle', | ||||
|            'rectangle_perimeter', | ||||
|            'polygon2mask'] | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								venv/Lib/site-packages/skimage/draw/_draw.cp36-win32.pyd
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								venv/Lib/site-packages/skimage/draw/_draw.cp36-win32.pyd
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										41
									
								
								venv/Lib/site-packages/skimage/draw/_polygon2mask.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								venv/Lib/site-packages/skimage/draw/_polygon2mask.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| import numpy as np | ||||
| 
 | ||||
| from . import draw | ||||
| 
 | ||||
| 
 | ||||
| def polygon2mask(image_shape, polygon): | ||||
|     """Compute a mask from polygon. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     image_shape : tuple of size 2. | ||||
|         The shape of the mask. | ||||
|     polygon : array_like. | ||||
|         The polygon coordinates of shape (N, 2) where N is | ||||
|         the number of points. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     mask : 2-D ndarray of type 'bool'. | ||||
|         The mask that corresponds to the input polygon. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     This function does not do any border checking, so that all | ||||
|     the vertices need to be within the given shape. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> image_shape = (128, 128) | ||||
|     >>> polygon = np.array([[60, 100], [100, 40], [40, 40]]) | ||||
|     >>> mask = polygon2mask(image_shape, polygon) | ||||
|     >>> mask.shape | ||||
|     (128, 128) | ||||
|     """ | ||||
|     polygon = np.asarray(polygon) | ||||
|     vertex_row_coords, vertex_col_coords = polygon.T | ||||
|     fill_row_coords, fill_col_coords = draw.polygon( | ||||
|         vertex_row_coords, vertex_col_coords, image_shape) | ||||
|     mask = np.zeros(image_shape, dtype=np.bool) | ||||
|     mask[fill_row_coords, fill_col_coords] = True | ||||
|     return mask | ||||
							
								
								
									
										434
									
								
								venv/Lib/site-packages/skimage/draw/_random_shapes.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								venv/Lib/site-packages/skimage/draw/_random_shapes.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,434 @@ | |||
| import math | ||||
| import numpy as np | ||||
| 
 | ||||
| from . import (polygon as draw_polygon, disk as draw_disk, | ||||
|     ellipse as draw_ellipse) | ||||
| from .._shared.utils import warn | ||||
| 
 | ||||
| 
 | ||||
| def _generate_rectangle_mask(point, image, shape, random): | ||||
|     """Generate a mask for a filled rectangle shape. | ||||
| 
 | ||||
|     The height and width of the rectangle are generated randomly. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     point : tuple | ||||
|         The row and column of the top left corner of the rectangle. | ||||
|     image : tuple | ||||
|         The height, width and depth of the image into which the shape is placed. | ||||
|     shape : tuple | ||||
|         The minimum and maximum size of the shape to fit. | ||||
|     random : np.random.RandomState | ||||
|         The random state to use for random sampling. | ||||
| 
 | ||||
|     Raises | ||||
|     ------ | ||||
|     ArithmeticError | ||||
|         When a shape cannot be fit into the image with the given starting | ||||
|         coordinates. This usually means the image dimensions are too small or | ||||
|         shape dimensions too large. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     label : tuple | ||||
|         A (category, ((r0, r1), (c0, c1))) tuple specifying the category and | ||||
|         bounding box coordinates of the shape. | ||||
|     indices : 2-D array | ||||
|         A mask of indices that the shape fills. | ||||
|     """ | ||||
|     available_width = min(image[1] - point[1], shape[1]) | ||||
|     if available_width < shape[0]: | ||||
|         raise ArithmeticError('cannot fit shape to image') | ||||
|     available_height = min(image[0] - point[0], shape[1]) | ||||
|     if available_height < shape[0]: | ||||
|         raise ArithmeticError('cannot fit shape to image') | ||||
|     # Pick random widths and heights. | ||||
|     r = random.randint(shape[0], available_height + 1) | ||||
|     c = random.randint(shape[0], available_width + 1) | ||||
|     rectangle = draw_polygon([ | ||||
|         point[0], | ||||
|         point[0] + r, | ||||
|         point[0] + r, | ||||
|         point[0], | ||||
|     ], [ | ||||
|         point[1], | ||||
|         point[1], | ||||
|         point[1] + c, | ||||
|         point[1] + c, | ||||
|     ]) | ||||
|     label = ('rectangle', ((point[0], point[0] + r), (point[1], point[1] + c))) | ||||
| 
 | ||||
|     return rectangle, label | ||||
| 
 | ||||
| 
 | ||||
| def _generate_circle_mask(point, image, shape, random): | ||||
|     """Generate a mask for a filled circle shape. | ||||
| 
 | ||||
|     The radius of the circle is generated randomly. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     point : tuple | ||||
|         The row and column of the top left corner of the rectangle. | ||||
|     image : tuple | ||||
|         The height, width and depth of the image into which the shape is placed. | ||||
|     shape : tuple | ||||
|         The minimum and maximum size and color of the shape to fit. | ||||
|     random : np.random.RandomState | ||||
|         The random state to use for random sampling. | ||||
| 
 | ||||
|     Raises | ||||
|     ------ | ||||
|     ArithmeticError | ||||
|         When a shape cannot be fit into the image with the given starting | ||||
|         coordinates. This usually means the image dimensions are too small or | ||||
|         shape dimensions too large. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     label : tuple | ||||
|         A (category, ((r0, r1), (c0, c1))) tuple specifying the category and | ||||
|         bounding box coordinates of the shape. | ||||
|     indices : 2-D array | ||||
|         A mask of indices that the shape fills. | ||||
|     """ | ||||
|     if shape[0] == 1 or shape[1] == 1: | ||||
|         raise ValueError('size must be > 1 for circles') | ||||
|     min_radius = shape[0] / 2.0 | ||||
|     max_radius = shape[1] / 2.0 | ||||
|     left = point[1] | ||||
|     right = image[1] - point[1] | ||||
|     top = point[0] | ||||
|     bottom = image[0] - point[0] | ||||
|     available_radius = min(left, right, top, bottom, max_radius) | ||||
|     if available_radius < min_radius: | ||||
|         raise ArithmeticError('cannot fit shape to image') | ||||
|     radius = random.randint(min_radius, available_radius + 1) | ||||
|     # TODO: think about how to deprecate this | ||||
|     # while draw_circle was deprecated in favor of draw_disk | ||||
|     # switching to a label of 'disk' here | ||||
|     # would be a breaking change for downstream libraries | ||||
|     # See discussion on naming convention here | ||||
|     # https://github.com/scikit-image/scikit-image/pull/4428 | ||||
|     disk = draw_disk((point[0], point[1]), radius) | ||||
|     # Until a deprecation path is decided, always return `'circle'` | ||||
|     label = ('circle', ((point[0] - radius + 1, point[0] + radius), | ||||
|                         (point[1] - radius + 1, point[1] + radius))) | ||||
| 
 | ||||
|     return disk, label | ||||
| 
 | ||||
| 
 | ||||
| def _generate_triangle_mask(point, image, shape, random): | ||||
|     """Generate a mask for a filled equilateral triangle shape. | ||||
| 
 | ||||
|     The length of the sides of the triangle is generated randomly. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     point : tuple | ||||
|         The row and column of the top left corner of a down-pointing triangle. | ||||
|     image : tuple | ||||
|         The height, width and depth of the image into which the shape is placed. | ||||
|     shape : tuple | ||||
|         The minimum and maximum size and color of the shape to fit. | ||||
|     random : np.random.RandomState | ||||
|         The random state to use for random sampling. | ||||
| 
 | ||||
|     Raises | ||||
|     ------ | ||||
|     ArithmeticError | ||||
|         When a shape cannot be fit into the image with the given starting | ||||
|         coordinates. This usually means the image dimensions are too small or | ||||
|         shape dimensions too large. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     label : tuple | ||||
|         A (category, ((r0, r1), (c0, c1))) tuple specifying the category and | ||||
|         bounding box coordinates of the shape. | ||||
|     indices : 2-D array | ||||
|         A mask of indices that the shape fills. | ||||
|     """ | ||||
|     if shape[0] == 1 or shape[1] == 1: | ||||
|         raise ValueError('dimension must be > 1 for triangles') | ||||
|     available_side = min(image[1] - point[1], point[0] + 1, shape[1]) | ||||
|     if available_side < shape[0]: | ||||
|         raise ArithmeticError('cannot fit shape to image') | ||||
|     side = random.randint(shape[0], available_side + 1) | ||||
|     triangle_height = int(np.ceil(np.sqrt(3 / 4.0) * side)) | ||||
|     triangle = draw_polygon([ | ||||
|         point[0], | ||||
|         point[0] - triangle_height, | ||||
|         point[0], | ||||
|     ], [ | ||||
|         point[1], | ||||
|         point[1] + side // 2, | ||||
|         point[1] + side, | ||||
|     ]) | ||||
|     label = ('triangle', ((point[0] - triangle_height, point[0]), | ||||
|                           (point[1], point[1] + side))) | ||||
| 
 | ||||
|     return triangle, label | ||||
| 
 | ||||
| 
 | ||||
| def _generate_ellipse_mask(point, image, shape, random): | ||||
|     """Generate a mask for a filled ellipse shape. | ||||
| 
 | ||||
|     The rotation, major and minor semi-axes of the ellipse are generated | ||||
|     randomly. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     point : tuple | ||||
|         The row and column of the top left corner of the rectangle. | ||||
|     image : tuple | ||||
|         The height, width and depth of the image into which the shape is | ||||
|         placed. | ||||
|     shape : tuple | ||||
|         The minimum and maximum size and color of the shape to fit. | ||||
|     random : np.random.RandomState | ||||
|         The random state to use for random sampling. | ||||
| 
 | ||||
|     Raises | ||||
|     ------ | ||||
|     ArithmeticError | ||||
|         When a shape cannot be fit into the image with the given starting | ||||
|         coordinates. This usually means the image dimensions are too small or | ||||
|         shape dimensions too large. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     label : tuple | ||||
|         A (category, ((r0, r1), (c0, c1))) tuple specifying the category and | ||||
|         bounding box coordinates of the shape. | ||||
|     indices : 2-D array | ||||
|         A mask of indices that the shape fills. | ||||
|     """ | ||||
|     if shape[0] == 1 or shape[1] == 1: | ||||
|         raise ValueError('size must be > 1 for ellipses') | ||||
|     min_radius = shape[0] / 2.0 | ||||
|     max_radius = shape[1] / 2.0 | ||||
|     left = point[1] | ||||
|     right = image[1] - point[1] | ||||
|     top = point[0] | ||||
|     bottom = image[0] - point[0] | ||||
|     available_radius = min(left, right, top, bottom, max_radius) | ||||
|     if available_radius < min_radius: | ||||
|         raise ArithmeticError('cannot fit shape to image') | ||||
|     # NOTE: very conservative because we could take into account the fact that | ||||
|     # we have 2 different radii, but this is a good first approximation. | ||||
|     # Also, we can afford to have a uniform sampling because the ellipse will | ||||
|     # be rotated. | ||||
|     r_radius = random.uniform(min_radius, available_radius + 1) | ||||
|     c_radius = random.uniform(min_radius, available_radius + 1) | ||||
|     rotation = random.uniform(-np.pi, np.pi) | ||||
|     ellipse = draw_ellipse( | ||||
|         point[0], | ||||
|         point[1], | ||||
|         r_radius, | ||||
|         c_radius, | ||||
|         shape=image[:2], | ||||
|         rotation=rotation, | ||||
|     ) | ||||
|     max_radius = math.ceil(max(r_radius, c_radius)) | ||||
|     min_x = np.min(ellipse[0]) | ||||
|     max_x = np.max(ellipse[0]) + 1 | ||||
|     min_y = np.min(ellipse[1]) | ||||
|     max_y = np.max(ellipse[1]) + 1 | ||||
|     label = ('ellipse', ((min_x, max_x), (min_y, max_y))) | ||||
| 
 | ||||
|     return ellipse, label | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # Allows lookup by key as well as random selection. | ||||
| SHAPE_GENERATORS = dict( | ||||
|     rectangle=_generate_rectangle_mask, | ||||
|     circle=_generate_circle_mask, | ||||
|     triangle=_generate_triangle_mask, | ||||
|     ellipse=_generate_ellipse_mask) | ||||
| SHAPE_CHOICES = list(SHAPE_GENERATORS.values()) | ||||
| 
 | ||||
| 
 | ||||
| def _generate_random_colors(num_colors, num_channels, intensity_range, random): | ||||
|     """Generate an array of random colors. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     num_colors : int | ||||
|         Number of colors to generate. | ||||
|     num_channels : int | ||||
|         Number of elements representing color. | ||||
|     intensity_range : {tuple of tuples of ints, tuple of ints}, optional | ||||
|         The range of values to sample pixel values from. For grayscale images | ||||
|         the format is (min, max). For multichannel - ((min, max),) if the | ||||
|         ranges are equal across the channels, and | ||||
|         ((min_0, max_0), ... (min_N, max_N)) if they differ. | ||||
|     random : np.random.RandomState | ||||
|         The random state to use for random sampling. | ||||
| 
 | ||||
|     Raises | ||||
|     ------ | ||||
|     ValueError | ||||
|         When the `intensity_range` is not in the interval (0, 255). | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     colors : array | ||||
|         An array of shape (num_colors, num_channels), where the values for | ||||
|         each channel are drawn from the corresponding `intensity_range`. | ||||
| 
 | ||||
|     """ | ||||
|     if num_channels == 1: | ||||
|         intensity_range = (intensity_range, ) | ||||
|     elif len(intensity_range) == 1: | ||||
|         intensity_range = intensity_range * num_channels | ||||
|     colors = [random.randint(r[0], r[1]+1, size=num_colors) | ||||
|               for r in intensity_range] | ||||
|     return np.transpose(colors) | ||||
| 
 | ||||
| 
 | ||||
| def random_shapes(image_shape, | ||||
|                   max_shapes, | ||||
|                   min_shapes=1, | ||||
|                   min_size=2, | ||||
|                   max_size=None, | ||||
|                   multichannel=True, | ||||
|                   num_channels=3, | ||||
|                   shape=None, | ||||
|                   intensity_range=None, | ||||
|                   allow_overlap=False, | ||||
|                   num_trials=100, | ||||
|                   random_seed=None): | ||||
|     """Generate an image with random shapes, labeled with bounding boxes. | ||||
| 
 | ||||
|     The image is populated with random shapes with random sizes, random | ||||
|     locations, and random colors, with or without overlap. | ||||
| 
 | ||||
|     Shapes have random (row, col) starting coordinates and random sizes bounded | ||||
|     by `min_size` and `max_size`. It can occur that a randomly generated shape | ||||
|     will not fit the image at all. In that case, the algorithm will try again | ||||
|     with new starting coordinates a certain number of times. However, it also | ||||
|     means that some shapes may be skipped altogether. In that case, this | ||||
|     function will generate fewer shapes than requested. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     image_shape : tuple | ||||
|         The number of rows and columns of the image to generate. | ||||
|     max_shapes : int | ||||
|         The maximum number of shapes to (attempt to) fit into the shape. | ||||
|     min_shapes : int, optional | ||||
|         The minimum number of shapes to (attempt to) fit into the shape. | ||||
|     min_size : int, optional | ||||
|         The minimum dimension of each shape to fit into the image. | ||||
|     max_size : int, optional | ||||
|         The maximum dimension of each shape to fit into the image. | ||||
|     multichannel : bool, optional | ||||
|         If True, the generated image has ``num_channels`` color channels, | ||||
|         otherwise generates grayscale image. | ||||
|     num_channels : int, optional | ||||
|         Number of channels in the generated image. If 1, generate monochrome | ||||
|         images, else color images with multiple channels. Ignored if | ||||
|         ``multichannel`` is set to False. | ||||
|     shape : {rectangle, circle, triangle, ellipse, None} str, optional | ||||
|         The name of the shape to generate or `None` to pick random ones. | ||||
|     intensity_range : {tuple of tuples of uint8, tuple of uint8}, optional | ||||
|         The range of values to sample pixel values from. For grayscale images | ||||
|         the format is (min, max). For multichannel - ((min, max),) if the | ||||
|         ranges are equal across the channels, and ((min_0, max_0), ... (min_N, max_N)) | ||||
|         if they differ. As the function supports generation of uint8 arrays only, | ||||
|         the maximum range is (0, 255). If None, set to (0, 254) for each | ||||
|         channel reserving color of intensity = 255 for background. | ||||
|     allow_overlap : bool, optional | ||||
|         If `True`, allow shapes to overlap. | ||||
|     num_trials : int, optional | ||||
|         How often to attempt to fit a shape into the image before skipping it. | ||||
|     random_seed : int, optional | ||||
|         Seed to initialize the random number generator. | ||||
|         If `None`, a random seed from the operating system is used. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     image : uint8 array | ||||
|         An image with the fitted shapes. | ||||
|     labels : list | ||||
|         A list of labels, one per shape in the image. Each label is a | ||||
|         (category, ((r0, r1), (c0, c1))) tuple specifying the category and | ||||
|         bounding box coordinates of the shape. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> import skimage.draw | ||||
|     >>> image, labels = skimage.draw.random_shapes((32, 32), max_shapes=3) | ||||
|     >>> image # doctest: +SKIP | ||||
|     array([ | ||||
|        [[255, 255, 255], | ||||
|         [255, 255, 255], | ||||
|         [255, 255, 255], | ||||
|         ..., | ||||
|         [255, 255, 255], | ||||
|         [255, 255, 255], | ||||
|         [255, 255, 255]]], dtype=uint8) | ||||
|     >>> labels # doctest: +SKIP | ||||
|     [('circle', ((22, 18), (25, 21))), | ||||
|      ('triangle', ((5, 6), (13, 13)))] | ||||
|     """ | ||||
|     if min_size > image_shape[0] or min_size > image_shape[1]: | ||||
|         raise ValueError('Minimum dimension must be less than ncols and nrows') | ||||
|     max_size = max_size or max(image_shape[0], image_shape[1]) | ||||
| 
 | ||||
|     if not multichannel: | ||||
|         num_channels = 1 | ||||
| 
 | ||||
|     if intensity_range is None: | ||||
|         intensity_range = (0, 254) if num_channels == 1 else ((0, 254), ) | ||||
|     else: | ||||
|         tmp = (intensity_range, ) if num_channels == 1 else intensity_range | ||||
|         for intensity_pair in tmp: | ||||
|             for intensity in intensity_pair: | ||||
|                 if not (0 <= intensity <= 255): | ||||
|                     msg = 'Intensity range must lie within (0, 255) interval' | ||||
|                     raise ValueError(msg) | ||||
| 
 | ||||
|     random = np.random.RandomState(random_seed) | ||||
|     user_shape = shape | ||||
|     image_shape = (image_shape[0], image_shape[1], num_channels) | ||||
|     image = np.full(image_shape, 255, dtype=np.uint8) | ||||
|     filled = np.zeros(image_shape, dtype=bool) | ||||
|     labels = [] | ||||
| 
 | ||||
|     num_shapes = random.randint(min_shapes, max_shapes + 1) | ||||
|     colors = _generate_random_colors(num_shapes, num_channels, | ||||
|                                      intensity_range, random) | ||||
|     for shape_idx in range(num_shapes): | ||||
|         if user_shape is None: | ||||
|             shape_generator = random.choice(SHAPE_CHOICES) | ||||
|         else: | ||||
|             shape_generator = SHAPE_GENERATORS[user_shape] | ||||
|         shape = (min_size, max_size) | ||||
|         for _ in range(num_trials): | ||||
|             # Pick start coordinates. | ||||
|             column = random.randint(image_shape[1]) | ||||
|             row = random.randint(image_shape[0]) | ||||
|             point = (row, column) | ||||
|             try: | ||||
|                 indices, label = shape_generator(point, image_shape, shape, | ||||
|                                                  random) | ||||
|             except ArithmeticError: | ||||
|                 # Couldn't fit the shape, skip it. | ||||
|                 continue | ||||
|             # Check if there is an overlap where the mask is nonzero. | ||||
|             if allow_overlap or not filled[indices].any(): | ||||
|                 image[indices] = colors[shape_idx] | ||||
|                 filled[indices] = True | ||||
|                 labels.append(label) | ||||
|                 break | ||||
|         else: | ||||
|             warn('Could not fit any shapes to image, ' | ||||
|                  'consider reducing the minimum dimension') | ||||
| 
 | ||||
|     if not multichannel: | ||||
|         image = np.squeeze(image, axis=2) | ||||
|     return image, labels | ||||
							
								
								
									
										949
									
								
								venv/Lib/site-packages/skimage/draw/draw.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										949
									
								
								venv/Lib/site-packages/skimage/draw/draw.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,949 @@ | |||
| import warnings | ||||
| import numpy as np | ||||
| 
 | ||||
| from .._shared._geometry import polygon_clip | ||||
| from ._draw import (_coords_inside_image, _line, _line_aa, | ||||
|                     _polygon, _ellipse_perimeter, | ||||
|                     _circle_perimeter, _circle_perimeter_aa, | ||||
|                     _bezier_curve) | ||||
| 
 | ||||
| 
 | ||||
| def _ellipse_in_shape(shape, center, radii, rotation=0.): | ||||
|     """Generate coordinates of points within ellipse bounded by shape. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     shape :  iterable of ints | ||||
|         Shape of the input image.  Must be at least length 2. Only the first | ||||
|         two values are used to determine the extent of the input image. | ||||
|     center : iterable of floats | ||||
|         (row, column) position of center inside the given shape. | ||||
|     radii : iterable of floats | ||||
|         Size of two half axes (for row and column) | ||||
|     rotation : float, optional | ||||
|         Rotation of the ellipse defined by the above, in radians | ||||
|         in range (-PI, PI), in contra clockwise direction, | ||||
|         with respect to the column-axis. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rows : iterable of ints | ||||
|         Row coordinates representing values within the ellipse. | ||||
|     cols : iterable of ints | ||||
|         Corresponding column coordinates representing values within the ellipse. | ||||
|     """ | ||||
|     r_lim, c_lim = np.ogrid[0:float(shape[0]), 0:float(shape[1])] | ||||
|     r_org, c_org = center | ||||
|     r_rad, c_rad = radii | ||||
|     rotation %= np.pi | ||||
|     sin_alpha, cos_alpha = np.sin(rotation), np.cos(rotation) | ||||
|     r, c = (r_lim - r_org), (c_lim - c_org) | ||||
|     distances = ((r * cos_alpha + c * sin_alpha) / r_rad) ** 2 \ | ||||
|                 + ((r * sin_alpha - c * cos_alpha) / c_rad) ** 2 | ||||
|     return np.nonzero(distances < 1) | ||||
| 
 | ||||
| 
 | ||||
| def ellipse(r, c, r_radius, c_radius, shape=None, rotation=0.): | ||||
|     """Generate coordinates of pixels within ellipse. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r, c : double | ||||
|         Centre coordinate of ellipse. | ||||
|     r_radius, c_radius : double | ||||
|         Minor and major semi-axes. ``(r/r_radius)**2 + (c/c_radius)**2 = 1``. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output pixel | ||||
|         coordinates. This is useful for ellipses which exceed the image size. | ||||
|         By default the full extent of the ellipse are used. Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent. | ||||
|     rotation : float, optional (default 0.) | ||||
|         Set the ellipse rotation (rotation) in range (-PI, PI) | ||||
|         in contra clock wise direction, so PI/2 degree means swap ellipse axis | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : ndarray of int | ||||
|         Pixel coordinates of ellipse. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import ellipse | ||||
|     >>> img = np.zeros((10, 12), dtype=np.uint8) | ||||
|     >>> rr, cc = ellipse(5, 6, 3, 5, rotation=np.deg2rad(30)) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     The ellipse equation:: | ||||
| 
 | ||||
|         ((x * cos(alpha) + y * sin(alpha)) / x_radius) ** 2 + | ||||
|         ((x * sin(alpha) - y * cos(alpha)) / y_radius) ** 2 = 1 | ||||
| 
 | ||||
| 
 | ||||
|     Note that the positions of `ellipse` without specified `shape` can have | ||||
|     also, negative values, as this is correct on the plane. On the other hand | ||||
|     using these ellipse positions for an image afterwards may lead to appearing | ||||
|     on the other side of image, because ``image[-1, -1] = image[end-1, end-1]`` | ||||
| 
 | ||||
|     >>> rr, cc = ellipse(1, 2, 3, 6) | ||||
|     >>> img = np.zeros((6, 12), dtype=np.uint8) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1]], dtype=uint8) | ||||
|     """ | ||||
| 
 | ||||
|     center = np.array([r, c]) | ||||
|     radii = np.array([r_radius, c_radius]) | ||||
|     # allow just rotation with in range +/- 180 degree | ||||
|     rotation %= np.pi | ||||
| 
 | ||||
|     # compute rotated radii by given rotation | ||||
|     r_radius_rot = abs(r_radius * np.cos(rotation)) \ | ||||
|                    + c_radius * np.sin(rotation) | ||||
|     c_radius_rot = r_radius * np.sin(rotation) \ | ||||
|                    + abs(c_radius * np.cos(rotation)) | ||||
|     # The upper_left and lower_right corners of the smallest rectangle | ||||
|     # containing the ellipse. | ||||
|     radii_rot = np.array([r_radius_rot, c_radius_rot]) | ||||
|     upper_left = np.ceil(center - radii_rot).astype(int) | ||||
|     lower_right = np.floor(center + radii_rot).astype(int) | ||||
| 
 | ||||
|     if shape is not None: | ||||
|         # Constrain upper_left and lower_right by shape boundary. | ||||
|         upper_left = np.maximum(upper_left, np.array([0, 0])) | ||||
|         lower_right = np.minimum(lower_right, np.array(shape[:2]) - 1) | ||||
| 
 | ||||
|     shifted_center = center - upper_left | ||||
|     bounding_shape = lower_right - upper_left + 1 | ||||
| 
 | ||||
|     rr, cc = _ellipse_in_shape(bounding_shape, shifted_center, radii, rotation) | ||||
|     rr.flags.writeable = True | ||||
|     cc.flags.writeable = True | ||||
|     rr += upper_left[0] | ||||
|     cc += upper_left[1] | ||||
|     return rr, cc | ||||
| 
 | ||||
| 
 | ||||
| def circle(r, c, radius, shape=None): | ||||
|     """Generate coordinates of pixels within circle. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r, c : double | ||||
|         Center coordinate of disk. | ||||
|     radius : double | ||||
|         Radius of disk. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for disks that exceed the image | ||||
|         size. If None, the full extent of the disk is used.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : ndarray of int | ||||
|         Pixel coordinates of disk. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Warns | ||||
|     ----- | ||||
|     Deprecated: | ||||
|         .. versionadded:: 0.17 | ||||
| 
 | ||||
|             This function is deprecated and will be removed in scikit-image 0.19. | ||||
|             Please use the function named ``disk`` instead. | ||||
|     """ | ||||
|     warnings.warn("circle is deprecated in favor of " | ||||
|                   "disk." | ||||
|                   "circle will be removed in version 0.19", | ||||
|                   FutureWarning, stacklevel=2) | ||||
|     return disk((r, c), radius, shape=shape) | ||||
| 
 | ||||
| 
 | ||||
| def disk(center, radius, *, shape=None): | ||||
|     """Generate coordinates of pixels within circle. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     center : tuple | ||||
|         Center coordinate of disk. | ||||
|     radius : double | ||||
|         Radius of disk. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for disks that exceed the image | ||||
|         size. If None, the full extent of the disk is used.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : ndarray of int | ||||
|         Pixel coordinates of disk. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import disk | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = disk((4, 4), 5) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 1, 1, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
|     """ | ||||
|     r, c = center | ||||
|     return ellipse(r, c, radius, radius, shape) | ||||
| 
 | ||||
| 
 | ||||
| def polygon_perimeter(r, c, shape=None, clip=False): | ||||
|     """Generate polygon perimeter coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r : (N,) ndarray | ||||
|         Row coordinates of vertices of polygon. | ||||
|     c : (N,) ndarray | ||||
|         Column coordinates of vertices of polygon. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine maximum extents of output pixel | ||||
|         coordinates. This is useful for polygons that exceed the image size. | ||||
|         If None, the full extents of the polygon is used.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
|     clip : bool, optional | ||||
|         Whether to clip the polygon to the provided shape.  If this is set | ||||
|         to True, the drawn figure will always be a closed polygon with all | ||||
|         edges visible. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : ndarray of int | ||||
|         Pixel coordinates of polygon. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import polygon_perimeter | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = polygon_perimeter([5, -1, 5, 10], | ||||
|     ...                            [-1, 5, 11, 5], | ||||
|     ...                            shape=img.shape, clip=True) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 1, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [0, 1, 1, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [0, 0, 0, 1, 0, 0, 0, 1, 1, 0], | ||||
|            [0, 0, 0, 0, 1, 1, 1, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
|     """ | ||||
|     if clip: | ||||
|         if shape is None: | ||||
|             raise ValueError("Must specify clipping shape") | ||||
|         clip_box = np.array([0, 0, shape[0] - 1, shape[1] - 1]) | ||||
|     else: | ||||
|         clip_box = np.array([np.min(r), np.min(c), | ||||
|                              np.max(r), np.max(c)]) | ||||
| 
 | ||||
|     # Do the clipping irrespective of whether clip is set.  This | ||||
|     # ensures that the returned polygon is closed and is an array. | ||||
|     r, c = polygon_clip(r, c, *clip_box) | ||||
| 
 | ||||
|     r = np.round(r).astype(int) | ||||
|     c = np.round(c).astype(int) | ||||
| 
 | ||||
|     # Construct line segments | ||||
|     rr, cc = [], [] | ||||
|     for i in range(len(r) - 1): | ||||
|         line_r, line_c = line(r[i], c[i], r[i + 1], c[i + 1]) | ||||
|         rr.extend(line_r) | ||||
|         cc.extend(line_c) | ||||
| 
 | ||||
|     rr = np.asarray(rr) | ||||
|     cc = np.asarray(cc) | ||||
| 
 | ||||
|     if shape is None: | ||||
|         return rr, cc | ||||
|     else: | ||||
|         return _coords_inside_image(rr, cc, shape) | ||||
| 
 | ||||
| 
 | ||||
| def set_color(image, coords, color, alpha=1): | ||||
|     """Set pixel color in the image at the given coordinates. | ||||
| 
 | ||||
|     Note that this function modifies the color of the image in-place. | ||||
|     Coordinates that exceed the shape of the image will be ignored. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     image : (M, N, D) ndarray | ||||
|         Image | ||||
|     coords : tuple of ((P,) ndarray, (P,) ndarray) | ||||
|         Row and column coordinates of pixels to be colored. | ||||
|     color : (D,) ndarray | ||||
|         Color to be assigned to coordinates in the image. | ||||
|     alpha : scalar or (N,) ndarray | ||||
|         Alpha values used to blend color with image.  0 is transparent, | ||||
|         1 is opaque. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import line, set_color | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = line(1, 1, 20, 20) | ||||
|     >>> set_color(img, (rr, cc), 1) | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], dtype=uint8) | ||||
| 
 | ||||
|     """ | ||||
|     rr, cc = coords | ||||
| 
 | ||||
|     if image.ndim == 2: | ||||
|         image = image[..., np.newaxis] | ||||
| 
 | ||||
|     color = np.array(color, ndmin=1, copy=False) | ||||
| 
 | ||||
|     if image.shape[-1] != color.shape[-1]: | ||||
|         raise ValueError('Color shape ({}) must match last ' | ||||
|                          'image dimension ({}).'.format(color.shape[0], | ||||
|                                                         image.shape[-1])) | ||||
| 
 | ||||
|     if np.isscalar(alpha): | ||||
|         # Can be replaced by ``full_like`` when numpy 1.8 becomes | ||||
|         # minimum dependency | ||||
|         alpha = np.ones_like(rr) * alpha | ||||
| 
 | ||||
|     rr, cc, alpha = _coords_inside_image(rr, cc, image.shape, val=alpha) | ||||
| 
 | ||||
|     alpha = alpha[..., np.newaxis] | ||||
| 
 | ||||
|     color = color * alpha | ||||
|     vals = image[rr, cc] * (1 - alpha) | ||||
| 
 | ||||
|     image[rr, cc] = vals + color | ||||
| 
 | ||||
| 
 | ||||
| def line(r0, c0, r1, c1): | ||||
|     """Generate line pixel coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r0, c0 : int | ||||
|         Starting position (row, column). | ||||
|     r1, c1 : int | ||||
|         End position (row, column). | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : (N,) ndarray of int | ||||
|         Indices of pixels that belong to the line. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     Anti-aliased line generator is available with `line_aa`. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import line | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = line(1, 1, 8, 8) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
|     """ | ||||
|     return _line(r0, c0, r1, c1) | ||||
| 
 | ||||
| 
 | ||||
| def line_aa(r0, c0, r1, c1): | ||||
|     """Generate anti-aliased line pixel coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r0, c0 : int | ||||
|         Starting position (row, column). | ||||
|     r1, c1 : int | ||||
|         End position (row, column). | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc, val : (N,) ndarray (int, int, float) | ||||
|         Indices of pixels (`rr`, `cc`) and intensity values (`val`). | ||||
|         ``img[rr, cc] = val``. | ||||
| 
 | ||||
|     References | ||||
|     ---------- | ||||
|     .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 | ||||
|            http://members.chello.at/easyfilter/Bresenham.pdf | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import line_aa | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc, val = line_aa(1, 1, 8, 8) | ||||
|     >>> img[rr, cc] = val * 255 | ||||
|     >>> img | ||||
|     array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0], | ||||
|            [  0, 255,  74,   0,   0,   0,   0,   0,   0,   0], | ||||
|            [  0,  74, 255,  74,   0,   0,   0,   0,   0,   0], | ||||
|            [  0,   0,  74, 255,  74,   0,   0,   0,   0,   0], | ||||
|            [  0,   0,   0,  74, 255,  74,   0,   0,   0,   0], | ||||
|            [  0,   0,   0,   0,  74, 255,  74,   0,   0,   0], | ||||
|            [  0,   0,   0,   0,   0,  74, 255,  74,   0,   0], | ||||
|            [  0,   0,   0,   0,   0,   0,  74, 255,  74,   0], | ||||
|            [  0,   0,   0,   0,   0,   0,   0,  74, 255,   0], | ||||
|            [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8) | ||||
|     """ | ||||
|     return _line_aa(r0, c0, r1, c1) | ||||
| 
 | ||||
| 
 | ||||
| def polygon(r, c, shape=None): | ||||
|     """Generate coordinates of pixels within polygon. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r : (N,) ndarray | ||||
|         Row coordinates of vertices of polygon. | ||||
|     c : (N,) ndarray | ||||
|         Column coordinates of vertices of polygon. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for polygons that exceed the image | ||||
|         size. If None, the full extent of the polygon is used.  Must be at | ||||
|         least length 2. Only the first two values are used to determine the | ||||
|         extent of the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : ndarray of int | ||||
|         Pixel coordinates of polygon. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import polygon | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> r = np.array([1, 2, 8]) | ||||
|     >>> c = np.array([1, 7, 4]) | ||||
|     >>> rr, cc = polygon(r, c) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
|     """ | ||||
|     return _polygon(r, c, shape) | ||||
| 
 | ||||
| 
 | ||||
| def circle_perimeter(r, c, radius, method='bresenham', shape=None): | ||||
|     """Generate circle perimeter coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r, c : int | ||||
|         Centre coordinate of circle. | ||||
|     radius : int | ||||
|         Radius of circle. | ||||
|     method : {'bresenham', 'andres'}, optional | ||||
|         bresenham : Bresenham method (default) | ||||
|         andres : Andres method | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for circles that exceed the image | ||||
|         size. If None, the full extent of the circle is used.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : (N,) ndarray of int | ||||
|         Bresenham and Andres' method: | ||||
|         Indices of pixels that belong to the circle perimeter. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     Andres method presents the advantage that concentric | ||||
|     circles create a disc whereas Bresenham can make holes. There | ||||
|     is also less distortions when Andres circles are rotated. | ||||
|     Bresenham method is also known as midpoint circle algorithm. | ||||
|     Anti-aliased circle generator is available with `circle_perimeter_aa`. | ||||
| 
 | ||||
|     References | ||||
|     ---------- | ||||
|     .. [1] J.E. Bresenham, "Algorithm for computer control of a digital | ||||
|            plotter", IBM Systems journal, 4 (1965) 25-30. | ||||
|     .. [2] E. Andres, "Discrete circles, rings and spheres", Computers & | ||||
|            Graphics, 18 (1994) 695-706. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import circle_perimeter | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = circle_perimeter(4, 4, 3) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
|     """ | ||||
|     return _circle_perimeter(r, c, radius, method, shape) | ||||
| 
 | ||||
| 
 | ||||
| def circle_perimeter_aa(r, c, radius, shape=None): | ||||
|     """Generate anti-aliased circle perimeter coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r, c : int | ||||
|         Centre coordinate of circle. | ||||
|     radius : int | ||||
|         Radius of circle. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for circles that exceed the image | ||||
|         size. If None, the full extent of the circle is used.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc, val : (N,) ndarray (int, int, float) | ||||
|         Indices of pixels (`rr`, `cc`) and intensity values (`val`). | ||||
|         ``img[rr, cc] = val``. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     Wu's method draws anti-aliased circle. This implementation doesn't use | ||||
|     lookup table optimization. | ||||
| 
 | ||||
|     Use the function ``draw.set_color`` to apply ``circle_perimeter_aa`` | ||||
|     results to color images. | ||||
| 
 | ||||
|     References | ||||
|     ---------- | ||||
|     .. [1] X. Wu, "An efficient antialiasing technique", In ACM SIGGRAPH | ||||
|            Computer Graphics, 25 (1991) 143-152. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import circle_perimeter_aa | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc, val = circle_perimeter_aa(4, 4, 3) | ||||
|     >>> img[rr, cc] = val * 255 | ||||
|     >>> img | ||||
|     array([[  0,   0,   0,   0,   0,   0,   0,   0,   0,   0], | ||||
|            [  0,   0,  60, 211, 255, 211,  60,   0,   0,   0], | ||||
|            [  0,  60, 194,  43,   0,  43, 194,  60,   0,   0], | ||||
|            [  0, 211,  43,   0,   0,   0,  43, 211,   0,   0], | ||||
|            [  0, 255,   0,   0,   0,   0,   0, 255,   0,   0], | ||||
|            [  0, 211,  43,   0,   0,   0,  43, 211,   0,   0], | ||||
|            [  0,  60, 194,  43,   0,  43, 194,  60,   0,   0], | ||||
|            [  0,   0,  60, 211, 255, 211,  60,   0,   0,   0], | ||||
|            [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0], | ||||
|            [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8) | ||||
| 
 | ||||
|     >>> from skimage import data, draw | ||||
|     >>> image = data.chelsea() | ||||
|     >>> rr, cc, val = draw.circle_perimeter_aa(r=100, c=100, radius=75) | ||||
|     >>> draw.set_color(image, (rr, cc), [1, 0, 0], alpha=val) | ||||
|     """ | ||||
|     return _circle_perimeter_aa(r, c, radius, shape) | ||||
| 
 | ||||
| 
 | ||||
| def ellipse_perimeter(r, c, r_radius, c_radius, orientation=0, shape=None): | ||||
|     """Generate ellipse perimeter coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r, c : int | ||||
|         Centre coordinate of ellipse. | ||||
|     r_radius, c_radius : int | ||||
|         Minor and major semi-axes. ``(r/r_radius)**2 + (c/c_radius)**2 = 1``. | ||||
|     orientation : double, optional | ||||
|         Major axis orientation in clockwise direction as radians. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for ellipses that exceed the image | ||||
|         size. If None, the full extent of the ellipse is used.  Must be at | ||||
|         least length 2. Only the first two values are used to determine the | ||||
|         extent of the input image. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : (N,) ndarray of int | ||||
|         Indices of pixels that belong to the ellipse perimeter. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     References | ||||
|     ---------- | ||||
|     .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 | ||||
|            http://members.chello.at/easyfilter/Bresenham.pdf | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> from skimage.draw import ellipse_perimeter | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = ellipse_perimeter(5, 5, 3, 4) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 1, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 1], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 1, 0], | ||||
|            [0, 0, 0, 1, 1, 1, 1, 1, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
| 
 | ||||
|     Note that the positions of `ellipse` without specified `shape` can have | ||||
|     also, negative values, as this is correct on the plane. On the other hand | ||||
|     using these ellipse positions for an image afterwards may lead to appearing | ||||
|     on the other side of image, because ``image[-1, -1] = image[end-1, end-1]`` | ||||
| 
 | ||||
|     >>> rr, cc = ellipse_perimeter(2, 3, 4, 5) | ||||
|     >>> img = np.zeros((9, 12), dtype=np.uint8) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], | ||||
|            [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | ||||
|            [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
|     """ | ||||
|     return _ellipse_perimeter(r, c, r_radius, c_radius, orientation, shape) | ||||
| 
 | ||||
| 
 | ||||
| def bezier_curve(r0, c0, r1, c1, r2, c2, weight, shape=None): | ||||
|     """Generate Bezier curve coordinates. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     r0, c0 : int | ||||
|         Coordinates of the first control point. | ||||
|     r1, c1 : int | ||||
|         Coordinates of the middle control point. | ||||
|     r2, c2 : int | ||||
|         Coordinates of the last control point. | ||||
|     weight : double | ||||
|         Middle control point weight, it describes the line tension. | ||||
|     shape : tuple, optional | ||||
|         Image shape which is used to determine the maximum extent of output | ||||
|         pixel coordinates. This is useful for curves that exceed the image | ||||
|         size. If None, the full extent of the curve is used. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rr, cc : (N,) ndarray of int | ||||
|         Indices of pixels that belong to the Bezier curve. | ||||
|         May be used to directly index into an array, e.g. | ||||
|         ``img[rr, cc] = 1``. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     The algorithm is the rational quadratic algorithm presented in | ||||
|     reference [1]_. | ||||
| 
 | ||||
|     References | ||||
|     ---------- | ||||
|     .. [1] A Rasterizing Algorithm for Drawing Curves, A. Zingl, 2012 | ||||
|            http://members.chello.at/easyfilter/Bresenham.pdf | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> import numpy as np | ||||
|     >>> from skimage.draw import bezier_curve | ||||
|     >>> img = np.zeros((10, 10), dtype=np.uint8) | ||||
|     >>> rr, cc = bezier_curve(1, 5, 5, -2, 8, 8, 2) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 1, 1, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 1, 0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 1, 1, 1, 0, 0, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 1, 1, 0], | ||||
|            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) | ||||
|     """ | ||||
|     return _bezier_curve(r0, c0, r1, c1, r2, c2, weight, shape) | ||||
| 
 | ||||
| 
 | ||||
| def rectangle(start, end=None, extent=None, shape=None): | ||||
|     """Generate coordinates of pixels within a rectangle. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     start : tuple | ||||
|         Origin point of the rectangle, e.g., ``([plane,] row, column)``. | ||||
|     end : tuple | ||||
|         End point of the rectangle ``([plane,] row, column)``. | ||||
|         For a 2D matrix, the slice defined by the rectangle is | ||||
|         ``[start:(end+1)]``. | ||||
|         Either `end` or `extent` must be specified. | ||||
|     extent : tuple | ||||
|         The extent (size) of the drawn rectangle.  E.g., | ||||
|         ``([num_planes,] num_rows, num_cols)``. | ||||
|         Either `end` or `extent` must be specified. | ||||
|         A negative extent is valid, and will result in a rectangle | ||||
|         going along the oposite direction. If extent is negative, the | ||||
|         `start` point is not included. | ||||
|     shape : tuple, optional | ||||
|         Image shape used to determine the maximum bounds of the output | ||||
|         coordinates. This is useful for clipping rectangles that exceed | ||||
|         the image size. By default, no clipping is done. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     coords : array of int, shape (Ndim, Npoints) | ||||
|         The coordinates of all pixels in the rectangle. | ||||
| 
 | ||||
|     Notes | ||||
|     ----- | ||||
|     This function can be applied to N-dimensional images, by passing `start` and | ||||
|     `end` or `extent` as tuples of length N. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> import numpy as np | ||||
|     >>> from skimage.draw import rectangle | ||||
|     >>> img = np.zeros((5, 5), dtype=np.uint8) | ||||
|     >>> start = (1, 1) | ||||
|     >>> extent = (3, 3) | ||||
|     >>> rr, cc = rectangle(start, extent=extent, shape=img.shape) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 0, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
| 
 | ||||
|     >>> img = np.zeros((5, 5), dtype=np.uint8) | ||||
|     >>> start = (0, 1) | ||||
|     >>> end = (3, 3) | ||||
|     >>> rr, cc = rectangle(start, end=end, shape=img.shape) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 1, 1, 1, 0], | ||||
|            [0, 0, 0, 0, 0]], dtype=uint8) | ||||
| 
 | ||||
|     >>> import numpy as np | ||||
|     >>> from skimage.draw import rectangle | ||||
|     >>> img = np.zeros((6, 6), dtype=np.uint8) | ||||
|     >>> start = (3, 3) | ||||
|     >>> | ||||
|     >>> rr, cc = rectangle(start, extent=(2, 2)) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> rr, cc = rectangle(start, extent=(-2, 2)) | ||||
|     >>> img[rr, cc] = 2 | ||||
|     >>> rr, cc = rectangle(start, extent=(-2, -2)) | ||||
|     >>> img[rr, cc] = 3 | ||||
|     >>> rr, cc = rectangle(start, extent=(2, -2)) | ||||
|     >>> img[rr, cc] = 4 | ||||
|     >>> print(img) | ||||
|     [[0 0 0 0 0 0] | ||||
|      [0 3 3 2 2 0] | ||||
|      [0 3 3 2 2 0] | ||||
|      [0 4 4 1 1 0] | ||||
|      [0 4 4 1 1 0] | ||||
|      [0 0 0 0 0 0]] | ||||
| 
 | ||||
|     """ | ||||
|     tl, br = _rectangle_slice(start=start, end=end, extent=extent) | ||||
| 
 | ||||
|     if shape is not None: | ||||
|         n_dim = len(start) | ||||
|         br = np.minimum(shape[0:n_dim], br) | ||||
|         tl = np.maximum(np.zeros_like(shape[0:n_dim]), tl) | ||||
|     coords = np.meshgrid(*[np.arange(st, en) for st, en in zip(tuple(tl), | ||||
|                                                                tuple(br))]) | ||||
|     return coords | ||||
| 
 | ||||
| 
 | ||||
| def rectangle_perimeter(start, end=None, extent=None, shape=None, clip=False): | ||||
|     """Generate coordinates of pixels that are exactly around a rectangle. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     start : tuple | ||||
|         Origin point of the inner rectangle, e.g., ``(row, column)``. | ||||
|     end : tuple | ||||
|         End point of the inner rectangle ``(row, column)``. | ||||
|         For a 2D matrix, the slice defined by inner the rectangle is | ||||
|         ``[start:(end+1)]``. | ||||
|         Either `end` or `extent` must be specified. | ||||
|     extent : tuple | ||||
|         The extent (size) of the inner rectangle.  E.g., | ||||
|         ``(num_rows, num_cols)``. | ||||
|         Either `end` or `extent` must be specified. | ||||
|         Negative extents are permitted. See `rectangle` to better | ||||
|         understand how they behave. | ||||
|     shape : tuple, optional | ||||
|         Image shape used to determine the maximum bounds of the output | ||||
|         coordinates. This is useful for clipping perimeters that exceed | ||||
|         the image size. By default, no clipping is done.  Must be at least | ||||
|         length 2. Only the first two values are used to determine the extent of | ||||
|         the input image. | ||||
|     clip : bool, optional | ||||
|         Whether to clip the perimeter to the provided shape. If this is set | ||||
|         to True, the drawn figure will always be a closed polygon with all | ||||
|         edges visible. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     coords : array of int, shape (2, Npoints) | ||||
|         The coordinates of all pixels in the rectangle. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> import numpy as np | ||||
|     >>> from skimage.draw import rectangle_perimeter | ||||
|     >>> img = np.zeros((5, 6), dtype=np.uint8) | ||||
|     >>> start = (2, 3) | ||||
|     >>> end = (3, 4) | ||||
|     >>> rr, cc = rectangle_perimeter(start, end=end, shape=img.shape) | ||||
|     >>> img[rr, cc] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 1, 1, 1], | ||||
|            [0, 0, 1, 0, 0, 1], | ||||
|            [0, 0, 1, 0, 0, 1], | ||||
|            [0, 0, 1, 1, 1, 1]], dtype=uint8) | ||||
| 
 | ||||
|     >>> img = np.zeros((5, 5), dtype=np.uint8) | ||||
|     >>> r, c = rectangle_perimeter(start, (10, 10), shape=img.shape, clip=True) | ||||
|     >>> img[r, c] = 1 | ||||
|     >>> img | ||||
|     array([[0, 0, 0, 0, 0], | ||||
|            [0, 0, 1, 1, 1], | ||||
|            [0, 0, 1, 0, 1], | ||||
|            [0, 0, 1, 0, 1], | ||||
|            [0, 0, 1, 1, 1]], dtype=uint8) | ||||
| 
 | ||||
|     """ | ||||
|     top_left, bottom_right = _rectangle_slice(start=start, | ||||
|                                               end=end, | ||||
|                                               extent=extent) | ||||
| 
 | ||||
|     top_left -= 1 | ||||
|     r = [top_left[0], top_left[0], bottom_right[0], bottom_right[0], | ||||
|          top_left[0]] | ||||
|     c = [top_left[1], bottom_right[1], bottom_right[1], top_left[1], | ||||
|          top_left[1]] | ||||
|     return polygon_perimeter(r, c, shape=shape, clip=clip) | ||||
| 
 | ||||
| 
 | ||||
| def _rectangle_slice(start, end=None, extent=None): | ||||
|     """Return the slice ``(top_left, bottom_right)`` of the rectangle. | ||||
| 
 | ||||
|     Returns | ||||
|     ======= | ||||
|     (top_left, bottomm_right) | ||||
|         The slice you would need to select the region in the rectangle defined | ||||
|         by the parameters. | ||||
|         Select it like: | ||||
| 
 | ||||
|         ``rect[top_left[0]:bottom_right[0], top_left[1]:bottom_right[1]]`` | ||||
|     """ | ||||
|     if end is None and extent is None: | ||||
|         raise ValueError("Either `end` or `extent` must be given.") | ||||
|     if end is not None and extent is not None: | ||||
|         raise ValueError("Cannot provide both `end` and `extent`.") | ||||
| 
 | ||||
|     if extent is not None: | ||||
|         end = np.asarray(start) + np.asarray(extent) | ||||
|     top_left = np.minimum(start, end) | ||||
|     bottom_right = np.maximum(start, end) | ||||
| 
 | ||||
|     if extent is None: | ||||
|         bottom_right += 1 | ||||
| 
 | ||||
|     return (top_left, bottom_right) | ||||
							
								
								
									
										114
									
								
								venv/Lib/site-packages/skimage/draw/draw3d.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								venv/Lib/site-packages/skimage/draw/draw3d.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | |||
| import numpy as np | ||||
| from scipy.special import (ellipkinc as ellip_F, ellipeinc as ellip_E) | ||||
| 
 | ||||
| 
 | ||||
| def ellipsoid(a, b, c, spacing=(1., 1., 1.), levelset=False): | ||||
|     """ | ||||
|     Generates ellipsoid with semimajor axes aligned with grid dimensions | ||||
|     on grid with specified `spacing`. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     a : float | ||||
|         Length of semimajor axis aligned with x-axis. | ||||
|     b : float | ||||
|         Length of semimajor axis aligned with y-axis. | ||||
|     c : float | ||||
|         Length of semimajor axis aligned with z-axis. | ||||
|     spacing : tuple of floats, length 3 | ||||
|         Spacing in (x, y, z) spatial dimensions. | ||||
|     levelset : bool | ||||
|         If True, returns the level set for this ellipsoid (signed level | ||||
|         set about zero, with positive denoting interior) as np.float64. | ||||
|         False returns a binarized version of said level set. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     ellip : (N, M, P) array | ||||
|         Ellipsoid centered in a correctly sized array for given `spacing`. | ||||
|         Boolean dtype unless `levelset=True`, in which case a float array is | ||||
|         returned with the level set above 0.0 representing the ellipsoid. | ||||
| 
 | ||||
|     """ | ||||
|     if (a <= 0) or (b <= 0) or (c <= 0): | ||||
|         raise ValueError('Parameters a, b, and c must all be > 0') | ||||
| 
 | ||||
|     offset = np.r_[1, 1, 1] * np.r_[spacing] | ||||
| 
 | ||||
|     # Calculate limits, and ensure output volume is odd & symmetric | ||||
|     low = np.ceil((- np.r_[a, b, c] - offset)) | ||||
|     high = np.floor((np.r_[a, b, c] + offset + 1)) | ||||
| 
 | ||||
|     for dim in range(3): | ||||
|         if (high[dim] - low[dim]) % 2 == 0: | ||||
|             low[dim] -= 1 | ||||
|         num = np.arange(low[dim], high[dim], spacing[dim]) | ||||
|         if 0 not in num: | ||||
|             low[dim] -= np.max(num[num < 0]) | ||||
| 
 | ||||
|     # Generate (anisotropic) spatial grid | ||||
|     x, y, z = np.mgrid[low[0]:high[0]:spacing[0], | ||||
|                        low[1]:high[1]:spacing[1], | ||||
|                        low[2]:high[2]:spacing[2]] | ||||
| 
 | ||||
|     if not levelset: | ||||
|         arr = ((x / float(a)) ** 2 + | ||||
|                (y / float(b)) ** 2 + | ||||
|                (z / float(c)) ** 2) <= 1 | ||||
|     else: | ||||
|         arr = ((x / float(a)) ** 2 + | ||||
|                (y / float(b)) ** 2 + | ||||
|                (z / float(c)) ** 2) - 1 | ||||
| 
 | ||||
|     return arr | ||||
| 
 | ||||
| 
 | ||||
| def ellipsoid_stats(a, b, c): | ||||
|     """ | ||||
|     Calculates analytical surface area and volume for ellipsoid with | ||||
|     semimajor axes aligned with grid dimensions of specified `spacing`. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     a : float | ||||
|         Length of semimajor axis aligned with x-axis. | ||||
|     b : float | ||||
|         Length of semimajor axis aligned with y-axis. | ||||
|     c : float | ||||
|         Length of semimajor axis aligned with z-axis. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     vol : float | ||||
|         Calculated volume of ellipsoid. | ||||
|     surf : float | ||||
|         Calculated surface area of ellipsoid. | ||||
| 
 | ||||
|     """ | ||||
|     if (a <= 0) or (b <= 0) or (c <= 0): | ||||
|         raise ValueError('Parameters a, b, and c must all be > 0') | ||||
| 
 | ||||
|     # Calculate volume & surface area | ||||
|     # Surface calculation requires a >= b >= c and a != c. | ||||
|     abc = [a, b, c] | ||||
|     abc.sort(reverse=True) | ||||
|     a = abc[0] | ||||
|     b = abc[1] | ||||
|     c = abc[2] | ||||
| 
 | ||||
|     # Volume | ||||
|     vol = 4 / 3. * np.pi * a * b * c | ||||
| 
 | ||||
|     # Analytical ellipsoid surface area | ||||
|     phi = np.arcsin((1. - (c ** 2 / (a ** 2.))) ** 0.5) | ||||
|     d = float((a ** 2 - c ** 2) ** 0.5) | ||||
|     m = (a ** 2 * (b ** 2 - c ** 2) / | ||||
|          float(b ** 2 * (a ** 2 - c ** 2))) | ||||
|     F = ellip_F(phi, m) | ||||
|     E = ellip_E(phi, m) | ||||
| 
 | ||||
|     surf = 2 * np.pi * (c ** 2 + | ||||
|                         b * c ** 2 / d * F + | ||||
|                         b * d * E) | ||||
| 
 | ||||
|     return vol, surf | ||||
							
								
								
									
										108
									
								
								venv/Lib/site-packages/skimage/draw/draw_nd.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								venv/Lib/site-packages/skimage/draw/draw_nd.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,108 @@ | |||
| import numpy as np | ||||
| 
 | ||||
| 
 | ||||
| def _round_safe(coords): | ||||
|     """Round coords while ensuring successive values are less than 1 apart. | ||||
| 
 | ||||
|     When rounding coordinates for `line_nd`, we want coordinates that are less | ||||
|     than 1 apart (always the case, by design) to remain less than one apart. | ||||
|     However, NumPy rounds values to the nearest *even* integer, so: | ||||
| 
 | ||||
|     >>> np.round([0.5, 1.5, 2.5, 3.5, 4.5]) | ||||
|     array([0., 2., 2., 4., 4.]) | ||||
| 
 | ||||
|     So, for our application, we detect whether the above case occurs, and use | ||||
|     ``np.floor`` if so. It is sufficient to detect that the first coordinate | ||||
|     falls on 0.5 and that the second coordinate is 1.0 apart, since we assume | ||||
|     by construction that the inter-point distance is less than or equal to 1 | ||||
|     and that all successive points are equidistant. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     coords : 1D array of float | ||||
|         The coordinates array. We assume that all successive values are | ||||
|         equidistant (``np.all(np.diff(coords) = coords[1] - coords[0])``) | ||||
|         and that this distance is no more than 1 | ||||
|         (``np.abs(coords[1] - coords[0]) <= 1``). | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     rounded : 1D array of int | ||||
|         The array correctly rounded for an indexing operation, such that no | ||||
|         successive indices will be more than 1 apart. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> coords0 = np.array([0.5, 1.25, 2., 2.75, 3.5]) | ||||
|     >>> _round_safe(coords0) | ||||
|     array([0, 1, 2, 3, 4]) | ||||
|     >>> coords1 = np.arange(0.5, 8, 1) | ||||
|     >>> coords1 | ||||
|     array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]) | ||||
|     >>> _round_safe(coords1) | ||||
|     array([0, 1, 2, 3, 4, 5, 6, 7]) | ||||
|     """ | ||||
|     if (len(coords) > 1 | ||||
|             and coords[0] % 1 == 0.5 | ||||
|             and coords[1] - coords[0] == 1): | ||||
|         _round_function = np.floor | ||||
|     else: | ||||
|         _round_function = np.round | ||||
|     return _round_function(coords).astype(int) | ||||
| 
 | ||||
| 
 | ||||
| def line_nd(start, stop, *, endpoint=False, integer=True): | ||||
|     """Draw a single-pixel thick line in n dimensions. | ||||
| 
 | ||||
|     The line produced will be ndim-connected. That is, two subsequent | ||||
|     pixels in the line will be either direct or diagonal neighbours in | ||||
|     n dimensions. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     start : array-like, shape (N,) | ||||
|         The start coordinates of the line. | ||||
|     stop : array-like, shape (N,) | ||||
|         The end coordinates of the line. | ||||
|     endpoint : bool, optional | ||||
|         Whether to include the endpoint in the returned line. Defaults | ||||
|         to False, which allows for easy drawing of multi-point paths. | ||||
|     integer : bool, optional | ||||
|         Whether to round the coordinates to integer. If True (default), | ||||
|         the returned coordinates can be used to directly index into an | ||||
|         array. `False` could be used for e.g. vector drawing. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     coords : tuple of arrays | ||||
|         The coordinates of points on the line. | ||||
| 
 | ||||
|     Examples | ||||
|     -------- | ||||
|     >>> lin = line_nd((1, 1), (5, 2.5), endpoint=False) | ||||
|     >>> lin | ||||
|     (array([1, 2, 3, 4]), array([1, 1, 2, 2])) | ||||
|     >>> im = np.zeros((6, 5), dtype=int) | ||||
|     >>> im[lin] = 1 | ||||
|     >>> im | ||||
|     array([[0, 0, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0], | ||||
|            [0, 1, 0, 0, 0], | ||||
|            [0, 0, 1, 0, 0], | ||||
|            [0, 0, 1, 0, 0], | ||||
|            [0, 0, 0, 0, 0]]) | ||||
|     >>> line_nd([2, 1, 1], [5, 5, 2.5], endpoint=True) | ||||
|     (array([2, 3, 4, 4, 5]), array([1, 2, 3, 4, 5]), array([1, 1, 2, 2, 2])) | ||||
|     """ | ||||
|     start = np.asarray(start) | ||||
|     stop = np.asarray(stop) | ||||
|     npoints = int(np.ceil(np.max(np.abs(stop - start)))) | ||||
|     if endpoint: | ||||
|         npoints += 1 | ||||
|     coords = [] | ||||
|     for dim in range(len(start)): | ||||
|         dimcoords = np.linspace(start[dim], stop[dim], npoints, endpoint) | ||||
|         if integer: | ||||
|             dimcoords = _round_safe(dimcoords).astype(int) | ||||
|         coords.append(dimcoords) | ||||
|     return tuple(coords) | ||||
							
								
								
									
										31
									
								
								venv/Lib/site-packages/skimage/draw/setup.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								venv/Lib/site-packages/skimage/draw/setup.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| import os | ||||
| from skimage._build import cython | ||||
| 
 | ||||
| base_path = os.path.abspath(os.path.dirname(__file__)) | ||||
| 
 | ||||
| 
 | ||||
| def configuration(parent_package='', top_path=None): | ||||
|     from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs | ||||
| 
 | ||||
|     config = Configuration('draw', parent_package, top_path) | ||||
| 
 | ||||
|     cython(['_draw.pyx'], working_path=base_path) | ||||
| 
 | ||||
|     config.add_extension('_draw', sources=['_draw.c'], | ||||
|                          include_dirs=[get_numpy_include_dirs(), '../_shared']) | ||||
| 
 | ||||
|     return config | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     from numpy.distutils.core import setup | ||||
|     setup(maintainer='scikit-image developers', | ||||
|           author='scikit-image developers', | ||||
|           maintainer_email='scikit-image@python.org', | ||||
|           description='Drawing', | ||||
|           url='https://github.com/scikit-image/scikit-image', | ||||
|           license='SciPy License (BSD Style)', | ||||
|           **(configuration(top_path='').todict()) | ||||
|           ) | ||||
							
								
								
									
										9
									
								
								venv/Lib/site-packages/skimage/draw/tests/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								venv/Lib/site-packages/skimage/draw/tests/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| from ..._shared.testing import setup_test, teardown_test | ||||
| 
 | ||||
| 
 | ||||
| def setup(): | ||||
|     setup_test() | ||||
| 
 | ||||
| 
 | ||||
| def teardown(): | ||||
|     teardown_test() | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1111
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1111
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										174
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw3d.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw3d.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,174 @@ | |||
| import numpy as np | ||||
| from skimage._shared.testing import assert_array_equal, assert_allclose | ||||
| 
 | ||||
| from skimage.draw import ellipsoid, ellipsoid_stats, rectangle | ||||
| from skimage._shared import testing | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_sign_parameters1(): | ||||
|     with testing.raises(ValueError): | ||||
|         ellipsoid(-1, 2, 2) | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_sign_parameters2(): | ||||
|     with testing.raises(ValueError): | ||||
|         ellipsoid(0, 2, 2) | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_sign_parameters3(): | ||||
|     with testing.raises(ValueError): | ||||
|         ellipsoid(-3, -2, 2) | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_bool(): | ||||
|     test = ellipsoid(2, 2, 2)[1:-1, 1:-1, 1:-1] | ||||
|     test_anisotropic = ellipsoid(2, 2, 4, spacing=(1., 1., 2.)) | ||||
|     test_anisotropic = test_anisotropic[1:-1, 1:-1, 1:-1] | ||||
| 
 | ||||
|     expected = np.array([[[0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 1, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
| 
 | ||||
|                          [[0, 0, 0, 0, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
| 
 | ||||
|                          [[0, 0, 1, 0, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [1, 1, 1, 1, 1], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 0, 1, 0, 0]], | ||||
| 
 | ||||
|                          [[0, 0, 0, 0, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 1, 1, 1, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
| 
 | ||||
|                          [[0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 1, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]]]) | ||||
| 
 | ||||
|     assert_array_equal(test, expected.astype(bool)) | ||||
|     assert_array_equal(test_anisotropic, expected.astype(bool)) | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_levelset(): | ||||
|     test = ellipsoid(2, 2, 2, levelset=True)[1:-1, 1:-1, 1:-1] | ||||
|     test_anisotropic = ellipsoid(2, 2, 4, spacing=(1., 1., 2.), | ||||
|                                  levelset=True) | ||||
|     test_anisotropic = test_anisotropic[1:-1, 1:-1, 1:-1] | ||||
| 
 | ||||
|     expected = np.array([[[ 2.  ,  1.25,  1.  ,  1.25,  2.  ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 1.  ,  0.25,  0.  ,  0.25,  1.  ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 2.  ,  1.25,  1.  ,  1.25,  2.  ]], | ||||
| 
 | ||||
|                          [[ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 0.5 , -0.25, -0.5 , -0.25,  0.5 ], | ||||
|                           [ 0.25, -0.5 , -0.75, -0.5 ,  0.25], | ||||
|                           [ 0.5 , -0.25, -0.5 , -0.25,  0.5 ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25]], | ||||
| 
 | ||||
|                          [[ 1.  ,  0.25,  0.  ,  0.25,  1.  ], | ||||
|                           [ 0.25, -0.5 , -0.75, -0.5 ,  0.25], | ||||
|                           [ 0.  , -0.75, -1.  , -0.75,  0.  ], | ||||
|                           [ 0.25, -0.5 , -0.75, -0.5 ,  0.25], | ||||
|                           [ 1.  ,  0.25,  0.  ,  0.25,  1.  ]], | ||||
| 
 | ||||
|                          [[ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 0.5 , -0.25, -0.5 , -0.25,  0.5 ], | ||||
|                           [ 0.25, -0.5 , -0.75, -0.5 ,  0.25], | ||||
|                           [ 0.5 , -0.25, -0.5 , -0.25,  0.5 ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25]], | ||||
| 
 | ||||
|                          [[ 2.  ,  1.25,  1.  ,  1.25,  2.  ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 1.  ,  0.25,  0.  ,  0.25,  1.  ], | ||||
|                           [ 1.25,  0.5 ,  0.25,  0.5 ,  1.25], | ||||
|                           [ 2.  ,  1.25,  1.  ,  1.25,  2.  ]]]) | ||||
| 
 | ||||
|     assert_allclose(test, expected) | ||||
|     assert_allclose(test_anisotropic, expected) | ||||
| 
 | ||||
| 
 | ||||
| def test_ellipsoid_stats(): | ||||
|     # Test comparison values generated by Wolfram Alpha | ||||
|     vol, surf = ellipsoid_stats(6, 10, 16) | ||||
|     assert_allclose(1280 * np.pi, vol, atol=1e-4) | ||||
|     assert_allclose(1383.28, surf, atol=1e-2) | ||||
| 
 | ||||
|     # Test when a <= b <= c does not hold | ||||
|     vol, surf = ellipsoid_stats(16, 6, 10) | ||||
|     assert_allclose(1280 * np.pi, vol, atol=1e-4) | ||||
|     assert_allclose(1383.28, surf, atol=1e-2) | ||||
| 
 | ||||
|     # Larger test to ensure reliability over broad range | ||||
|     vol, surf = ellipsoid_stats(17, 27, 169) | ||||
|     assert_allclose(103428 * np.pi, vol, atol=1e-4) | ||||
|     assert_allclose(37426.3, surf, atol=1e-1) | ||||
| 
 | ||||
| 
 | ||||
| def test_rect_3d_extent(): | ||||
|     expected = np.array([[[0, 0, 1, 1, 1], | ||||
|                           [0, 0, 1, 1, 1], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 1], | ||||
|                           [0, 0, 1, 1, 1], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 1], | ||||
|                           [0, 0, 1, 1, 1], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 1], | ||||
|                           [0, 0, 1, 1, 1], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]]], dtype=np.uint8) | ||||
|     img = np.zeros((4, 5, 5), dtype=np.uint8) | ||||
|     start = (0, 0, 2) | ||||
|     extent = (5, 2, 3) | ||||
|     pp, rr, cc = rectangle(start, extent=extent, shape=img.shape) | ||||
|     img[pp, rr, cc] = 1 | ||||
|     assert_array_equal(img, expected) | ||||
| 
 | ||||
| 
 | ||||
| def test_rect_3d_end(): | ||||
|     expected = np.array([[[0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]], | ||||
|                          [[0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 1, 1, 0], | ||||
|                           [0, 0, 0, 0, 0], | ||||
|                           [0, 0, 0, 0, 0]]], dtype=np.uint8) | ||||
|     img = np.zeros((4, 5, 5), dtype=np.uint8) | ||||
|     start = (1, 0, 2) | ||||
|     end = (3, 2, 3) | ||||
|     pp, rr, cc = rectangle(start, end=end, shape=img.shape) | ||||
|     img[pp, rr, cc] = 1 | ||||
|     assert_array_equal(img, expected) | ||||
							
								
								
									
										18
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw_nd.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_draw_nd.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| from skimage.draw import line_nd | ||||
| from skimage._shared.testing import assert_equal | ||||
| 
 | ||||
| 
 | ||||
| def test_empty_line(): | ||||
|     coords = line_nd((1, 1, 1), (1, 1, 1)) | ||||
|     assert len(coords) == 3 | ||||
|     assert all(len(c) == 0 for c in coords) | ||||
| 
 | ||||
| 
 | ||||
| def test_zero_line(): | ||||
|     coords = line_nd((-1, -1), (2, 2)) | ||||
|     assert_equal(coords, [[-1, 0, 1], [-1, 0, 1]]) | ||||
| 
 | ||||
| 
 | ||||
| def test_no_round(): | ||||
|     coords = line_nd((0.5, 0), (2.5, 0), integer=False, endpoint=True) | ||||
|     assert_equal(coords, [[0.5, 1.5, 2.5], [0, 0, 0]]) | ||||
|  | @ -0,0 +1,14 @@ | |||
| import numpy as np | ||||
| 
 | ||||
| from skimage import draw | ||||
| 
 | ||||
| 
 | ||||
| image_shape = (512, 512) | ||||
| polygon = np.array([[80, 111, 146, 234, 407, 300, 187, 45], | ||||
|                     [465, 438, 499, 380, 450, 287, 210, 167]]).T | ||||
| 
 | ||||
| 
 | ||||
| def test_polygon2mask(): | ||||
|     mask = draw.polygon2mask(image_shape, polygon) | ||||
|     assert mask.shape == image_shape | ||||
|     assert mask.sum() == 57647 | ||||
							
								
								
									
										171
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_random_shapes.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								venv/Lib/site-packages/skimage/draw/tests/test_random_shapes.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,171 @@ | |||
| import numpy as np | ||||
| 
 | ||||
| from skimage.draw import random_shapes | ||||
| 
 | ||||
| from skimage._shared import testing | ||||
| from skimage._shared._warnings import expected_warnings | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_color_images_with_correct_shape(): | ||||
|     image, _ = random_shapes((128, 128), max_shapes=10) | ||||
|     assert image.shape == (128, 128, 3) | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_gray_images_with_correct_shape(): | ||||
|     image, _ = random_shapes( | ||||
|         (4567, 123), min_shapes=3, max_shapes=20, multichannel=False) | ||||
|     assert image.shape == (4567, 123) | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_correct_bounding_boxes_for_rectangles(): | ||||
|     image, labels = random_shapes( | ||||
|         (128, 128), | ||||
|         max_shapes=1, | ||||
|         shape='rectangle', | ||||
|         random_seed=42) | ||||
|     assert len(labels) == 1 | ||||
|     label, bbox = labels[0] | ||||
|     assert label == 'rectangle', label | ||||
| 
 | ||||
|     crop = image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] | ||||
| 
 | ||||
|     # The crop is filled. | ||||
|     assert (crop >= 0).all() and (crop < 255).all() | ||||
| 
 | ||||
|     # The crop is complete. | ||||
|     image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] = 255 | ||||
|     assert (image == 255).all() | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_correct_bounding_boxes_for_triangles(): | ||||
|     image, labels = random_shapes( | ||||
|         (128, 128), | ||||
|         max_shapes=1, | ||||
|         shape='triangle', | ||||
|         random_seed=42) | ||||
|     assert len(labels) == 1 | ||||
|     label, bbox = labels[0] | ||||
|     assert label == 'triangle', label | ||||
| 
 | ||||
|     crop = image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] | ||||
| 
 | ||||
|     # The crop is filled. | ||||
|     assert (crop >= 0).any() and (crop < 255).any() | ||||
| 
 | ||||
|     # The crop is complete. | ||||
|     image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] = 255 | ||||
|     assert (image == 255).all() | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_correct_bounding_boxes_for_circles(): | ||||
|     image, labels = random_shapes( | ||||
|         (43, 44), | ||||
|         max_shapes=1, | ||||
|         min_size=20, | ||||
|         max_size=20, | ||||
|         shape='circle', | ||||
|         random_seed=42) | ||||
|     assert len(labels) == 1 | ||||
|     label, bbox = labels[0] | ||||
|     assert label == 'circle', label | ||||
| 
 | ||||
|     crop = image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] | ||||
| 
 | ||||
|     # The crop is filled. | ||||
|     assert (crop >= 0).any() and (crop < 255).any() | ||||
| 
 | ||||
|     # The crop is complete. | ||||
|     image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] = 255 | ||||
|     assert (image == 255).all() | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_correct_bounding_boxes_for_ellipses(): | ||||
|     image, labels = random_shapes( | ||||
|         (43, 44), | ||||
|         max_shapes=1, | ||||
|         min_size=20, | ||||
|         max_size=20, | ||||
|         shape='ellipse', | ||||
|         random_seed=42) | ||||
|     assert len(labels) == 1 | ||||
|     label, bbox = labels[0] | ||||
|     assert label == 'ellipse', label | ||||
| 
 | ||||
|     crop = image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] | ||||
| 
 | ||||
|     # The crop is filled. | ||||
|     assert (crop >= 0).any() and (crop < 255).any() | ||||
| 
 | ||||
|     # The crop is complete. | ||||
|     image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] = 255 | ||||
|     assert (image == 255).all() | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_circle_throws_when_size_too_small(): | ||||
|     with testing.raises(ValueError): | ||||
|         random_shapes( | ||||
|             (64, 128), max_shapes=1, min_size=1, max_size=1, shape='circle') | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_ellipse_throws_when_size_too_small(): | ||||
|     with testing.raises(ValueError): | ||||
|         random_shapes( | ||||
|             (64, 128), max_shapes=1, min_size=1, max_size=1, shape='ellipse') | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_triangle_throws_when_size_too_small(): | ||||
|     with testing.raises(ValueError): | ||||
|         random_shapes( | ||||
|             (128, 64), max_shapes=1, min_size=1, max_size=1, shape='triangle') | ||||
| 
 | ||||
| 
 | ||||
| def test_can_generate_one_by_one_rectangle(): | ||||
|     image, labels = random_shapes( | ||||
|         (50, 128), | ||||
|         max_shapes=1, | ||||
|         min_size=1, | ||||
|         max_size=1, | ||||
|         shape='rectangle') | ||||
|     assert len(labels) == 1 | ||||
|     _, bbox = labels[0] | ||||
|     crop = image[bbox[0][0]:bbox[0][1], bbox[1][0]:bbox[1][1]] | ||||
| 
 | ||||
|     # rgb | ||||
|     assert (np.shape(crop) == (1, 1, 3) and np.any(crop >= 1) | ||||
|             and np.any(crop < 255)) | ||||
| 
 | ||||
| 
 | ||||
| def test_throws_when_intensity_range_out_of_range(): | ||||
|     with testing.raises(ValueError): | ||||
|         random_shapes((1000, 1234), max_shapes=1, multichannel=False, | ||||
|                       intensity_range=(0, 256)) | ||||
|     with testing.raises(ValueError): | ||||
|         random_shapes((2, 2), max_shapes=1, | ||||
|                       intensity_range=((-1, 255),)) | ||||
| 
 | ||||
| 
 | ||||
| def test_returns_empty_labels_and_white_image_when_cannot_fit_shape(): | ||||
|     # The circle will never fit this. | ||||
|     with expected_warnings(['Could not fit']): | ||||
|         image, labels = random_shapes( | ||||
|             (10000, 10000), max_shapes=1, min_size=10000, shape='circle') | ||||
|     assert len(labels) == 0 | ||||
|     assert (image == 255).all() | ||||
| 
 | ||||
| 
 | ||||
| def test_random_shapes_is_reproducible_with_seed(): | ||||
|     random_seed = 42 | ||||
|     labels = [] | ||||
|     for _ in range(5): | ||||
|         _, label = random_shapes((128, 128), max_shapes=5, | ||||
|                                  random_seed=random_seed) | ||||
|         labels.append(label) | ||||
|     assert all(other == labels[0] for other in labels[1:]) | ||||
| 
 | ||||
| 
 | ||||
| def test_generates_white_image_when_intensity_range_255(): | ||||
|     image, labels = random_shapes((128, 128), max_shapes=3, | ||||
|                                   intensity_range=((255, 255),), | ||||
|                                   random_seed=42) | ||||
|     assert len(labels) > 0 | ||||
|     assert (image == 255).all() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue