numpyimage 1.3.0__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. numpyimage-2.0.0/PKG-INFO +52 -0
  2. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/core.py +146 -75
  3. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/operations.py +5 -5
  4. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/utils.py +10 -3
  5. numpyimage-2.0.0/numpyimage.egg-info/PKG-INFO +52 -0
  6. {numpyimage-1.3.0 → numpyimage-2.0.0}/numpyimage.egg-info/SOURCES.txt +1 -2
  7. {numpyimage-1.3.0 → numpyimage-2.0.0}/setup.py +1 -1
  8. numpyimage-1.3.0/PKG-INFO +0 -58
  9. numpyimage-1.3.0/numpyimage.egg-info/PKG-INFO +0 -58
  10. numpyimage-1.3.0/tests/tests.py +0 -39
  11. {numpyimage-1.3.0 → numpyimage-2.0.0}/LICENSE +0 -0
  12. {numpyimage-1.3.0 → numpyimage-2.0.0}/MANIFEST.in +0 -0
  13. {numpyimage-1.3.0 → numpyimage-2.0.0}/README.md +0 -0
  14. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/__init__.py +0 -0
  15. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/align.py +0 -0
  16. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/filetypes/__init__.py +0 -0
  17. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/filetypes/pbm.py +0 -0
  18. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/graphics.py +0 -0
  19. {numpyimage-1.3.0 → numpyimage-2.0.0}/npimage/nrrd_utils.py +0 -0
  20. {numpyimage-1.3.0 → numpyimage-2.0.0}/numpyimage.egg-info/dependency_links.txt +0 -0
  21. {numpyimage-1.3.0 → numpyimage-2.0.0}/numpyimage.egg-info/requires.txt +0 -0
  22. {numpyimage-1.3.0 → numpyimage-2.0.0}/numpyimage.egg-info/top_level.txt +0 -0
  23. {numpyimage-1.3.0 → numpyimage-2.0.0}/requirements.txt +0 -0
  24. {numpyimage-1.3.0 → numpyimage-2.0.0}/setup.cfg +0 -0
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.1
2
+ Name: numpyimage
3
+ Version: 2.0.0
4
+ Summary: Load, save, and manipulate image files as numpy arrays
5
+ Home-page: https://github.com/jasper-tms/npimage
6
+ Author: Jasper Phelps
7
+ Author-email: jasper.s.phelps@gmail.com
8
+ License: GNU GPL v3
9
+ Description: # npimage
10
+ Need to load pixel values from image files as numpy arrays, and hate having to remember whether you should use PIL, tifffile, matplotlib, or something else? Hate having to deal with the fact that those libraries all use different function names and syntaxes? Wish you could just provide a filename and get back a numpy array? This library's `core.py` does that, with `array = load(filename)`, `save(array, filename)`, and `show(array)` functions that let you easily handle a number of common image file formats without having to remember library-specific syntax. (Another choice of library to consider for accomplishing similar goals is [imageio](https://pypi.org/project/imageio/), which also supports loading videos through the FFmpeg wrapper library [pyav](https://pypi.org/project/av/).)
11
+
12
+ Want to draw simple shapes like lines, triangles, and circles into 3D numpy arrays? Frustrated that the python libraries you can find online like `opencv` and `skimage.draw` work on 2D arrays but not 3D? I wrote some functions in `graphics.py` that do the trick in 3D. (If you know of another library that can do this, please let me know!)
13
+
14
+
15
+ ### Documentation
16
+ - `core.py`: load, save, or show images.
17
+ - `graphics.py`: draw points, lines, triangles, circles, or spheres into 2D or 3D numpy arrays representing image volumes.
18
+ - `nrrd_utils.py`: compress or read metadata from `.nrrd` files.
19
+ - `operations.py`: perform operations on images.
20
+
21
+ For now, check each function's docstring for more. A jupyter notebook demonstrating this package's functions will come later.
22
+
23
+
24
+ ### Installation
25
+
26
+ As is always the case in python, consider making a virtual environment (using your preference of conda, virtualenv, or virtualenvwrapper) before installing.
27
+
28
+ **Option 1:** `pip install` from PyPI:
29
+
30
+ pip install numpyimage
31
+
32
+ (Unfortunately the name `npimage` was already taken on PyPI, so `pip install npimage` will get you a different package.)
33
+
34
+ **Option 2:** `pip install` directly from GitHub:
35
+
36
+ pip install git+https://github.com/jasper-tms/npimage.git
37
+
38
+ **Option 3:** First `git clone` this repo and then `pip install` it from your clone:
39
+
40
+ cd ~/repos # Or wherever on your computer you want to download this code to
41
+ git clone https://github.com/jasper-tms/npimage.git
42
+ cd npimage
43
+ pip install .
44
+
45
+ **After installing,** you can import this package in python using `import npimage` (not `import numpyimage`!)
46
+
47
+ Platform: UNKNOWN
48
+ Classifier: Programming Language :: Python :: 3
49
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
50
+ Classifier: Operating System :: OS Independent
51
+ Requires-Python: >=3.6
52
+ Description-Content-Type: text/markdown
@@ -15,7 +15,7 @@ from builtins import open as builtin_open
15
15
 
16
16
  import numpy as np
17
17
 
18
- from . import utils
18
+ from . import operations, utils
19
19
 
20
20
  supported_extensions = [
21
21
  'tif', 'tiff', 'jpg', 'jpeg', 'png', 'pbm',
@@ -30,9 +30,7 @@ def load(filename, dim_order='zyx', **kwargs):
30
30
  As is typical for Python, the returned array will by default have
31
31
  dimensions ordered as zyx for 3D image volumes, yx for 1-channel 2D
32
32
  images, or yxc for multi-channel (RGB/RGBA) 2D images.
33
- Set dim_order='xy' if you instead want dimensions ordered as
34
- xyz for 3D image volumes, xy for 1-channel 2D images, or
35
- xyc for multi-channel 2D images.
33
+ Set dim_order='xy' if you want to reverse the order of the axes.
36
34
  """
37
35
  filename = str(filename)
38
36
  while filename.endswith('/'):
@@ -109,13 +107,7 @@ def load(filename, dim_order='zyx', **kwargs):
109
107
  data = zarr.open(TODO) #TODO check zyx/xyz order
110
108
 
111
109
  if 'xy' in dim_order:
112
- if is_rgb_or_rgba(data):
113
- # Can't just transpose because if data is a multi-channel 2D
114
- # image, need the channel axis to stay as the last axis.
115
- data = data.swapaxes(0, 1)
116
- else:
117
- data = data.T
118
-
110
+ data = data.T
119
111
  if extension == 'nrrd': # TODO check if other formats need this
120
112
  utils.transpose_metadata(metadata, inplace=True)
121
113
 
@@ -142,6 +134,7 @@ def save(data,
142
134
  pixel_size=None,
143
135
  units=None,
144
136
  compress=None,
137
+ compression_level=3,
145
138
  metadata=None):
146
139
  """
147
140
  Save a numpy array to file with a file type specified by the
@@ -170,13 +163,15 @@ def save(data,
170
163
  '.nrrd. Whether or not compression occurs now will depend on '
171
164
  'the format you are saving to.')
172
165
 
166
+ channel_axis = find_channel_axis(data)
173
167
  if 'xy' in dim_order:
174
- if is_rgb_or_rgba(data):
175
- # Can't just transpose because if data is a multi-channel 2D
176
- # image, need the channel axis to stay as the last axis.
177
- data = data.swapaxes(0, 1)
178
- else:
179
- data = data.T
168
+ data = data.T
169
+ if hasattr(pixel_size, '__iter__') and not isinstance(pixel_size, str):
170
+ pixel_size = pixel_size[::-1]
171
+ if hasattr(units, '__iter__') and not isinstance(units, str):
172
+ units = units[::-1]
173
+ utils.transpose_metadata(metadata, inplace=True)
174
+ # The spatial axes and associated metadata are now in zyx order.
180
175
 
181
176
  if extension in ['tif', 'tiff']:
182
177
  import tifffile
@@ -199,30 +194,60 @@ def save(data,
199
194
  metadata = {}
200
195
  else:
201
196
  metadata = metadata.copy()
197
+ custom_field_map = {}
198
+
202
199
  if compress is True:
203
200
  metadata.update({'encoding': 'gzip'})
204
201
  if compress is False or 'encoding' not in metadata:
205
202
  metadata.update({'encoding': 'raw'})
203
+
204
+ if isinstance(metadata.get('space directions', None), str):
205
+ custom_field_map['space directions'] = 'string'
206
206
  if pixel_size is not None:
207
+ if 'space directions' in metadata:
208
+ raise ValueError('Cannot specify both "space directions" in'
209
+ ' metadata and "pixel_size" as an argument.')
210
+
207
211
  try:
208
212
  iter(pixel_size)
213
+ if len(pixel_size) == data.ndim - 1 and channel_axis is not None:
214
+ pixel_size.insert(channel_axis, np.nan)
209
215
  except TypeError:
210
- pixel_size = [pixel_size] * data.ndim
216
+ if channel_axis is not None:
217
+ pixel_size = [pixel_size] * (data.ndim - 1)
218
+ pixel_size.insert(channel_axis, np.nan)
219
+ else:
220
+ pixel_size = [pixel_size] * data.ndim
221
+ if len(pixel_size) != data.ndim:
222
+ raise ValueError(f'pixel_size has length {len(pixel_size)},'
223
+ ' but data has {data.ndim} dimensions.')
224
+
225
+ pixel_size_not_none = [size for size in pixel_size
226
+ if size is not None and size != np.nan]
227
+ space_directions = np.diag(pixel_size_not_none).astype(float)
228
+ # nrrd.format_optional_matrix() expects an entire row of
229
+ # np.nan for non-spatial dimensions, so insert row(s) for that.
230
+ none_indices = [i for i, size in enumerate(pixel_size)
231
+ if size is None or size == np.nan]
232
+ space_directions = np.insert(space_directions, none_indices, np.nan, axis=0)
233
+ metadata.update({'space directions': space_directions})
211
234
 
212
- if 'xy' in dim_order:
213
- pixel_size = np.flip(pixel_size)
214
- metadata.update({'space directions': np.flip(np.diag(pixel_size),
215
- axis=-1)})
216
235
  if 'space dimension' not in metadata and 'space' not in metadata:
217
236
  # If the number of spatial dimensions is not specified, assume
218
- # it's the number of dimensions in the data array, minus the
219
- # channel axis if it's present.
220
- if is_rgb_or_rgba(data):
237
+ # it's the number of dimensions in the data array, minus 1 if
238
+ # a channel axis is present.
239
+ if find_channel_axis(data) is not None:
221
240
  metadata.update({'space dimension': data.ndim - 1})
222
241
  else:
223
242
  metadata.update({'space dimension': data.ndim})
224
243
  if units is not None:
225
- metadata.update({'space units': [units] * data.ndim})
244
+ if hasattr(units, '__iter__') and not isinstance(units, str):
245
+ units = list(units)
246
+ elif 'space dimension' in metadata:
247
+ units = [units] * metadata['space dimension']
248
+ else:
249
+ units = [units] * data.ndim
250
+ metadata.update({'space units': units})
226
251
 
227
252
  # From https://pynrrd.readthedocs.io/en/stable/background/index-ordering.html
228
253
  # "C-order is the index order used in Python and many Python libraries
@@ -241,7 +266,12 @@ def save(data,
241
266
  # index_order='C' to the nrrd.write command below, we also need to flip
242
267
  # the order of any per-axis metadata fields.
243
268
  utils.transpose_metadata(metadata, inplace=True)
244
- nrrd.write(filename, data, header=metadata, index_order='C')
269
+ nrrd.write(filename,
270
+ data,
271
+ header=metadata,
272
+ custom_field_map=custom_field_map,
273
+ compression_level=compression_level,
274
+ index_order='C')
245
275
 
246
276
  if extension in ['raw', 'vol']:
247
277
  raise NotImplementedError
@@ -251,12 +281,10 @@ def save(data,
251
281
 
252
282
  if extension == 'ng':
253
283
  from cloudvolume import CloudVolume
284
+ from cloudvolume.exceptions import InfoUnavailableError
254
285
 
255
286
  # CloudVolume expects data in Fortran order
256
- if is_rgb_or_rgba(data):
257
- data = data.swapaxes(0, 1)
258
- else:
259
- data = data.T
287
+ data = data.T
260
288
 
261
289
  resolution = 1
262
290
  if pixel_size is not None:
@@ -265,35 +293,46 @@ def save(data,
265
293
  iter(resolution)
266
294
  except TypeError:
267
295
  resolution = [resolution] * data.ndim
268
- if compress is True or compress == 'lossy':
296
+ if compress is True or compress in ['lossy', 'jpeg', 'jpg']:
269
297
  encoding = 'jpeg'
298
+ gzip = False
299
+ elif compress is None or compress in ['lossless', 'gzip']:
300
+ if compress is None:
301
+ print('Using gzip compression by default for .ng format.')
302
+ encoding = 'raw'
270
303
  gzip = True
271
- elif compress == 'lossless':
272
- encoding = 'raw',
273
- gzip = True
274
- elif compress is False or compress is None:
304
+ elif compress is False:
275
305
  encoding = 'raw'
276
306
  gzip = False
277
307
  else:
278
- raise ValueError('For .ng format, compress must be True, False,'
279
- f' "lossy", or "lossless" but was {compress}')
280
-
281
- info = CloudVolume.create_new_info(
282
- num_channels=1,
283
- layer_type='image',
284
- data_type=data.dtype,
285
- encoding=encoding,
286
- resolution=resolution,
287
- voxel_offset=[0, 0, 0],
288
- chunk_size=[64, 64, 64],
289
- volume_size=data.shape
290
- )
308
+ raise ValueError('For .ng format, compress must be '
309
+ 'True/"lossy"/"jpeg"/"jpg", "lossless"/"gzip",'
310
+ f' or False, but was "{compress}"')
291
311
 
292
312
  if not any(filename.startswith(prefix)
293
313
  for prefix in ['file://', 'gs://', 's3://']):
294
314
  filename = 'file://' + filename
295
- vol = CloudVolume(filename, info=info, compress=gzip)
296
- vol.commit_info()
315
+
316
+ try:
317
+ vol = CloudVolume(filename, compress=gzip)
318
+ if (vol.shape[:data.ndim] != data.shape
319
+ or any(s != 1 for s in vol.shape[data.ndim:])):
320
+ raise ValueError('Dataset already exists at the specified path,'
321
+ ' but its shape does not match the given data.')
322
+ except InfoUnavailableError:
323
+ info = CloudVolume.create_new_info(
324
+ num_channels=1,
325
+ layer_type='image',
326
+ data_type=data.dtype,
327
+ encoding=encoding,
328
+ resolution=resolution,
329
+ voxel_offset=[0, 0, 0],
330
+ chunk_size=[64, 64, 64],
331
+ volume_size=data.shape
332
+ )
333
+
334
+ vol = CloudVolume(filename, info=info, compress=gzip)
335
+ vol.commit_info()
297
336
 
298
337
  vol[:] = data
299
338
 
@@ -309,11 +348,6 @@ def save_video(data, filename, overwrite=False, dim_order='yx', time_axis=0,
309
348
 
310
349
  Follows the PyAV cookbook section on generating video from numpy arrays:
311
350
  https://pyav.basswood-io.com/docs/develop/cookbook/numpy.html#generating-video
312
-
313
- Parameters
314
- ----------
315
- data : numpy.ndarray or list of filenames
316
- A 3D numpy array of pixel values, with the time axis as the first axis.
317
351
  """
318
352
  if not data.ndim == 3:
319
353
  raise ValueError('Input data must be a 3D numpy array.')
@@ -351,7 +385,11 @@ def save_video(data, filename, overwrite=False, dim_order='yx', time_axis=0,
351
385
  container.close()
352
386
 
353
387
 
354
- def show(data, dim_order='yx', mode='PIL', **kwargs):
388
+ def show(data,
389
+ dim_order='yx',
390
+ mode='PIL',
391
+ convert_to_8bit=True,
392
+ **kwargs):
355
393
  """
356
394
  Display a numpy array of pixel values as an image. Supported types:
357
395
  1-channel (grayscale) : data.shape must be (y, x)
@@ -359,7 +397,7 @@ def show(data, dim_order='yx', mode='PIL', **kwargs):
359
397
  4-channel (RGBA) : data.shape must be (y, x, 4)
360
398
 
361
399
  If `dim_order` is set to 'xy' (instead of the default 'yx'), then
362
- swap the y and x above. The channel axis must come last regardless.
400
+ swap the y and x above.
363
401
 
364
402
  Images will be shown using either `PIL.Image.fromarray(data).show()`
365
403
  or `matplotlib.pyplot.imshow(data)` depending on 'mode'. Uses PIL by
@@ -374,18 +412,22 @@ def show(data, dim_order='yx', mode='PIL', **kwargs):
374
412
  if os.path.exists(data):
375
413
  data = load(data)
376
414
 
377
- if not is_rgb_or_rgba(data) and data.ndim != 2:
378
- m = ('Input array must have shape (y, x) for grayscale, '
379
- '(y, x, 3) for RGB, or (y, x, 4) for RGBA but had '
380
- f'shape {data.shape}')
415
+ if (not data.ndim == 2) and not (data.ndim == 3 and find_channel_axis(data) is not None):
416
+ m = ('Data must have shape (y, x) for grayscale, '
417
+ '(y, x, 3) for RGB, or (y, x, 4) for RGBA but had '
418
+ f'shape {data.shape}')
381
419
  if 'xy' in dim_order:
382
420
  m = m.replace('y, x', 'x, y')
383
421
  raise ValueError(m)
384
422
 
385
423
  if 'xy' in dim_order:
386
- # Can't just transpose because if data is a multi-channel 2D
387
- # image, need the channel axis to stay as the last axis.
388
- data = data.swapaxes(0, 1)
424
+ data = data.T
425
+ channel_axis = find_channel_axis(data, expected_channel_axis=-1)
426
+ if channel_axis is not None and channel_axis != -1:
427
+ data = np.moveaxis(data, find_channel_axis(data), -1)
428
+
429
+ if convert_to_8bit and data.dtype != np.uint8:
430
+ data = operations.to_8bit(data)
389
431
 
390
432
  colorbar = False
391
433
  if 'colorbar' in kwargs:
@@ -407,16 +449,45 @@ def show(data, dim_order='yx', mode='PIL', **kwargs):
407
449
  imshow = show # Function name alias
408
450
 
409
451
 
410
- def is_rgb_or_rgba(data):
452
+ def find_channel_axis(data, expected_channel_axis=[0, -1]):
411
453
  """
412
- Return True if the given numpy array has a shape indicating
413
- that it's either an RGB or RGBA image.
414
-
415
- data.shape == (i, j, 3) -> it's RGB, return True
416
- data.shape == (i, j, 4) -> it's RGBA, return True
417
- data.shape == anything else -> return False
454
+ If the given numpy array has a shape suggesting that it has a
455
+ channel (color) axis (that is, any axis with length 2 (2-color),
456
+ 3 (RGB), or 4 (RGBA)), return the index of that axis.
418
457
 
458
+ Parameters
459
+ ----------
460
+ data : numpy.ndarray
461
+ The numpy array to check for a channel axis.
462
+
463
+ expected_channel_axis : int or list of int, default [0, -1]
464
+ If None, any axis having length 2, 3, or 4 will be considered
465
+ a channel axis.
466
+ If an int, only that axis index will be checked.
467
+ If a list of ints, all axes with those indices will be checked.
468
+ The default value of [0, -1] checks the first and last axes, which is
469
+ almost always where a channel axis will be found.
470
+
471
+ Returns
472
+ -------
473
+ int or None
474
+ The index of the channel axis, or None if no channel axis was found.
475
+
476
+ If expected_channel_axis is given, the returned value will be one of
477
+ the expected_channel_axis values, or None if no channel axis was found.
478
+
479
+ If expected_channel_axis is None, the returned value will be between
480
+ 0 and data.ndim - 1, inclusive, or None if no channel axis was found.
481
+
482
+ Note that returning 0 means the channel axis was found and is the first
483
+ axis, so be careful not to do a test like `if find_channel_axis(data):`
484
+ because 0 will evaluate to False even though the data has a channel axis.
419
485
  """
420
- if data.ndim == 3 and data.shape[2] in [3, 4]:
421
- return True
422
- return False
486
+ if isinstance(expected_channel_axis, int):
487
+ expected_channel_axis = [expected_channel_axis]
488
+ if expected_channel_axis is None:
489
+ expected_channel_axis = range(data.ndim)
490
+ for axis in expected_channel_axis:
491
+ if data.shape[axis] in [2, 3, 4]:
492
+ return axis
493
+ return None
@@ -11,7 +11,7 @@ Function list:
11
11
  - overlay_two_images: Overlay two images with the second one offset.
12
12
  """
13
13
 
14
- from typing import Iterable, Literal, Union, Optional
14
+ from typing import Iterable, Literal, Union, Optional, Tuple, List
15
15
  import gc
16
16
 
17
17
  import numpy as np
@@ -136,8 +136,8 @@ def cast(image: np.ndarray,
136
136
 
137
137
 
138
138
  def adjust_brightness(image: np.ndarray,
139
- starting_range: tuple[float, float],
140
- target_range: tuple[float, float],
139
+ starting_range: Tuple[float, float],
140
+ target_range: Tuple[float, float],
141
141
  output_dtype: Optional[Union[str, np.dtype]] = None,
142
142
  clip: bool = False) -> np.ndarray:
143
143
  """
@@ -436,8 +436,8 @@ def paste(image: np.ndarray,
436
436
  target[tuple(target_range)] = image[tuple(source_range)]
437
437
 
438
438
 
439
- def overlay(ims: list[np.ndarray],
440
- offsets: list[tuple[float]],
439
+ def overlay(ims: List[np.ndarray],
440
+ offsets: List[Tuple[float]],
441
441
  later_images_on_top=True,
442
442
  expand_bounds=False,
443
443
  fill_value=0):
@@ -68,10 +68,17 @@ def transpose_metadata(metadata: dict or OrderedDict,
68
68
  Designed to work with OrderedDicts that contain nrrd files'
69
69
  metadata, but may be useful for metadata from other formats.
70
70
  """
71
+ if metadata is None:
72
+ return None
71
73
  if not inplace:
72
74
  metadata = metadata.copy()
73
- for key in metadata:
74
- if hasattr(metadata[key], '__iter__') and not isinstance(metadata[key], str):
75
- metadata[key] = metadata[key][::-1]
75
+ for key, value in metadata.items():
76
+ if isinstance(value, str) or not hasattr(value, '__iter__'):
77
+ continue
78
+ if isinstance(value, np.ndarray):
79
+ value = np.flip(value)
80
+ else:
81
+ value = value[::-1]
82
+ metadata[key] = value
76
83
  if not inplace:
77
84
  return metadata
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.1
2
+ Name: numpyimage
3
+ Version: 2.0.0
4
+ Summary: Load, save, and manipulate image files as numpy arrays
5
+ Home-page: https://github.com/jasper-tms/npimage
6
+ Author: Jasper Phelps
7
+ Author-email: jasper.s.phelps@gmail.com
8
+ License: GNU GPL v3
9
+ Description: # npimage
10
+ Need to load pixel values from image files as numpy arrays, and hate having to remember whether you should use PIL, tifffile, matplotlib, or something else? Hate having to deal with the fact that those libraries all use different function names and syntaxes? Wish you could just provide a filename and get back a numpy array? This library's `core.py` does that, with `array = load(filename)`, `save(array, filename)`, and `show(array)` functions that let you easily handle a number of common image file formats without having to remember library-specific syntax. (Another choice of library to consider for accomplishing similar goals is [imageio](https://pypi.org/project/imageio/), which also supports loading videos through the FFmpeg wrapper library [pyav](https://pypi.org/project/av/).)
11
+
12
+ Want to draw simple shapes like lines, triangles, and circles into 3D numpy arrays? Frustrated that the python libraries you can find online like `opencv` and `skimage.draw` work on 2D arrays but not 3D? I wrote some functions in `graphics.py` that do the trick in 3D. (If you know of another library that can do this, please let me know!)
13
+
14
+
15
+ ### Documentation
16
+ - `core.py`: load, save, or show images.
17
+ - `graphics.py`: draw points, lines, triangles, circles, or spheres into 2D or 3D numpy arrays representing image volumes.
18
+ - `nrrd_utils.py`: compress or read metadata from `.nrrd` files.
19
+ - `operations.py`: perform operations on images.
20
+
21
+ For now, check each function's docstring for more. A jupyter notebook demonstrating this package's functions will come later.
22
+
23
+
24
+ ### Installation
25
+
26
+ As is always the case in python, consider making a virtual environment (using your preference of conda, virtualenv, or virtualenvwrapper) before installing.
27
+
28
+ **Option 1:** `pip install` from PyPI:
29
+
30
+ pip install numpyimage
31
+
32
+ (Unfortunately the name `npimage` was already taken on PyPI, so `pip install npimage` will get you a different package.)
33
+
34
+ **Option 2:** `pip install` directly from GitHub:
35
+
36
+ pip install git+https://github.com/jasper-tms/npimage.git
37
+
38
+ **Option 3:** First `git clone` this repo and then `pip install` it from your clone:
39
+
40
+ cd ~/repos # Or wherever on your computer you want to download this code to
41
+ git clone https://github.com/jasper-tms/npimage.git
42
+ cd npimage
43
+ pip install .
44
+
45
+ **After installing,** you can import this package in python using `import npimage` (not `import numpyimage`!)
46
+
47
+ Platform: UNKNOWN
48
+ Classifier: Programming Language :: Python :: 3
49
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
50
+ Classifier: Operating System :: OS Independent
51
+ Requires-Python: >=3.6
52
+ Description-Content-Type: text/markdown
@@ -16,5 +16,4 @@ numpyimage.egg-info/PKG-INFO
16
16
  numpyimage.egg-info/SOURCES.txt
17
17
  numpyimage.egg-info/dependency_links.txt
18
18
  numpyimage.egg-info/requires.txt
19
- numpyimage.egg-info/top_level.txt
20
- tests/tests.py
19
+ numpyimage.egg-info/top_level.txt
@@ -9,7 +9,7 @@ with open("requirements.txt", "r") as f:
9
9
 
10
10
  setuptools.setup(
11
11
  name="numpyimage",
12
- version="1.3.0",
12
+ version="2.0.0",
13
13
  author="Jasper Phelps",
14
14
  author_email="jasper.s.phelps@gmail.com",
15
15
  description="Load, save, and manipulate image files as numpy arrays",
numpyimage-1.3.0/PKG-INFO DELETED
@@ -1,58 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: numpyimage
3
- Version: 1.3.0
4
- Summary: Load, save, and manipulate image files as numpy arrays
5
- Home-page: https://github.com/jasper-tms/npimage
6
- Author: Jasper Phelps
7
- Author-email: jasper.s.phelps@gmail.com
8
- License: GNU GPL v3
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
- Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.6
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: numpy
16
- Requires-Dist: pillow
17
- Requires-Dist: tifffile
18
- Requires-Dist: pynrrd
19
- Requires-Dist: matplotlib
20
- Requires-Dist: opencv-python-headless
21
-
22
- # npimage
23
- Need to load pixel values from image files as numpy arrays, and hate having to remember whether you should use PIL, tifffile, matplotlib, or something else? Hate having to deal with the fact that those libraries all use different function names and syntaxes? Wish you could just provide a filename and get back a numpy array? This library's `core.py` does that, with `array = load(filename)`, `save(array, filename)`, and `show(array)` functions that let you easily handle a number of common image file formats without having to remember library-specific syntax. (Another choice of library to consider for accomplishing similar goals is [imageio](https://pypi.org/project/imageio/), which also supports loading videos through the FFmpeg wrapper library [pyav](https://pypi.org/project/av/).)
24
-
25
- Want to draw simple shapes like lines, triangles, and circles into 3D numpy arrays? Frustrated that the python libraries you can find online like `opencv` and `skimage.draw` work on 2D arrays but not 3D? I wrote some functions in `graphics.py` that do the trick in 3D. (If you know of another library that can do this, please let me know!)
26
-
27
-
28
- ### Documentation
29
- - `core.py`: load, save, or show images.
30
- - `graphics.py`: draw points, lines, triangles, circles, or spheres into 2D or 3D numpy arrays representing image volumes.
31
- - `nrrd_utils.py`: compress or read metadata from `.nrrd` files.
32
- - `operations.py`: perform operations on images.
33
-
34
- For now, check each function's docstring for more. A jupyter notebook demonstrating this package's functions will come later.
35
-
36
-
37
- ### Installation
38
-
39
- As is always the case in python, consider making a virtual environment (using your preference of conda, virtualenv, or virtualenvwrapper) before installing.
40
-
41
- **Option 1:** `pip install` from PyPI:
42
-
43
- pip install numpyimage
44
-
45
- (Unfortunately the name `npimage` was already taken on PyPI, so `pip install npimage` will get you a different package.)
46
-
47
- **Option 2:** `pip install` directly from GitHub:
48
-
49
- pip install git+https://github.com/jasper-tms/npimage.git
50
-
51
- **Option 3:** First `git clone` this repo and then `pip install` it from your clone:
52
-
53
- cd ~/repos # Or wherever on your computer you want to download this code to
54
- git clone https://github.com/jasper-tms/npimage.git
55
- cd npimage
56
- pip install .
57
-
58
- **After installing,** you can import this package in python using `import npimage` (not `import numpyimage`!)
@@ -1,58 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: numpyimage
3
- Version: 1.3.0
4
- Summary: Load, save, and manipulate image files as numpy arrays
5
- Home-page: https://github.com/jasper-tms/npimage
6
- Author: Jasper Phelps
7
- Author-email: jasper.s.phelps@gmail.com
8
- License: GNU GPL v3
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
- Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.6
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: numpy
16
- Requires-Dist: pillow
17
- Requires-Dist: tifffile
18
- Requires-Dist: pynrrd
19
- Requires-Dist: matplotlib
20
- Requires-Dist: opencv-python-headless
21
-
22
- # npimage
23
- Need to load pixel values from image files as numpy arrays, and hate having to remember whether you should use PIL, tifffile, matplotlib, or something else? Hate having to deal with the fact that those libraries all use different function names and syntaxes? Wish you could just provide a filename and get back a numpy array? This library's `core.py` does that, with `array = load(filename)`, `save(array, filename)`, and `show(array)` functions that let you easily handle a number of common image file formats without having to remember library-specific syntax. (Another choice of library to consider for accomplishing similar goals is [imageio](https://pypi.org/project/imageio/), which also supports loading videos through the FFmpeg wrapper library [pyav](https://pypi.org/project/av/).)
24
-
25
- Want to draw simple shapes like lines, triangles, and circles into 3D numpy arrays? Frustrated that the python libraries you can find online like `opencv` and `skimage.draw` work on 2D arrays but not 3D? I wrote some functions in `graphics.py` that do the trick in 3D. (If you know of another library that can do this, please let me know!)
26
-
27
-
28
- ### Documentation
29
- - `core.py`: load, save, or show images.
30
- - `graphics.py`: draw points, lines, triangles, circles, or spheres into 2D or 3D numpy arrays representing image volumes.
31
- - `nrrd_utils.py`: compress or read metadata from `.nrrd` files.
32
- - `operations.py`: perform operations on images.
33
-
34
- For now, check each function's docstring for more. A jupyter notebook demonstrating this package's functions will come later.
35
-
36
-
37
- ### Installation
38
-
39
- As is always the case in python, consider making a virtual environment (using your preference of conda, virtualenv, or virtualenvwrapper) before installing.
40
-
41
- **Option 1:** `pip install` from PyPI:
42
-
43
- pip install numpyimage
44
-
45
- (Unfortunately the name `npimage` was already taken on PyPI, so `pip install npimage` will get you a different package.)
46
-
47
- **Option 2:** `pip install` directly from GitHub:
48
-
49
- pip install git+https://github.com/jasper-tms/npimage.git
50
-
51
- **Option 3:** First `git clone` this repo and then `pip install` it from your clone:
52
-
53
- cd ~/repos # Or wherever on your computer you want to download this code to
54
- git clone https://github.com/jasper-tms/npimage.git
55
- cd npimage
56
- pip install .
57
-
58
- **After installing,** you can import this package in python using `import npimage` (not `import numpyimage`!)
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import numpy as np
4
- import fire
5
-
6
- import npimage
7
- import npimage.operations
8
-
9
- test_im = np.zeros((8, 8), dtype=np.uint8)
10
- test_im[0:1, 0:2] = 255
11
- test_im[1:3, 2:4] = 255
12
- test_im[3:7, 3:7] = 255
13
-
14
-
15
- def mplshow(*args):
16
- npimage.show(*args, mode='matplotlib')
17
-
18
-
19
- def test_offset():
20
- mplshow(test_im)
21
- mplshow(npimage.operations.offset(test_im, (0.5, 0)))
22
- mplshow(npimage.operations.offset(test_im, (0, 0.5)))
23
- mplshow(npimage.operations.offset(test_im, (0.5, 0.5)))
24
- mplshow(npimage.operations.offset(test_im, (1, 1)))
25
-
26
-
27
- def test_paste():
28
- offsets = [('++', [100, 50]),
29
- ('+-', [100, -50]),
30
- ('-+', [-100, 50]),
31
- ('--', [-100, -50])]
32
- for offset in offsets:
33
- im = npimage.load('firefox-logo.png', dim_order='xy')
34
- npimage.operations.paste(im, im, offset[1])
35
- npimage.save(im, 'firefox-logo_paste' + offset[0] + '.png', dim_order='xy')
36
-
37
-
38
- if __name__ == '__main__':
39
- fire.Fire()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes