Image#

class deeptrack.image.Image(value: ndarray | list | int | float | bool | Image, copy: bool = True)#

Bases: object

Wrapper for array-like values with property tracking.

This class encapsulates array-like values (e.g., NumPy arrays, lists, tensors) while providing a unified interface for array operations and property management.

It serves two primary purposes:

  1. Unified Interface

    Offers compatibility with NumPy and CuPy operations regardless of the underlying data type. This allows for seamless integration with NumPy functions and universal function calls (ufuncs).

  2. Property Tracking

    Stores and manages properties associated with features used in creating or modifying the image. This makes it possible to track metadata and ensure consistency across operations.

Attributes#

_valuenp.ndarray

The underlying data stored in the Image object as NumPy.

propertiesList[Dict[str, Property]]

A list of property dictionaries associated with the Image.

Parameters#

valuenp.ndarray or list or int or float or bool or Image

The array-like object to be converted to a NumPy array and stored in the Image object. If it is an Image, the value and properties of the image are copied or referenced depening on the value of the copy parameter.

copybool, optional

If True, the value is copied to ensure independence (default). If False, a reference to the original value is maintained.

Methods#

Property Management

append(property_dict: dict) -> ‘Image’

Add a dictionary of properties to the Image.

get_property(key: str, get_one: bool = True, default: Any = None) -> Union[Any, List[Any]]

Retrieve a property by key. If get_one is True, returns the first match; otherwise, returns a list of matches.

merge_properties_from(other: Union[‘Image’, List[‘Image’], np.ndarray]) -> ‘Image’

Merge properties from another Image, list of `Image`s, or a NumPy array.

Conversion Utilities

to_cupy() -> ‘Image’

Convert the Image to a CuPy array if the underlying value is a NumPy array.

to_numpy() -> ‘Image’

Convert the Image to a numpy array if the underlying value is a CuPy array.

__array__(*args: Tuple[Any, …], **kwargs: Dict[str, Any]) -> np.ndarray

Convert the Image to a numpy array. Used implicitly by numpy functions.

**NumPy Compatibility

__array_ufunc__(ufunc: Callable, method: str, *inputs: Tuple[Any], **kwargs: Dict[str, Any]) -> Union[‘Image’, Tuple[‘Image’, …], None]

Enable compatibility with numpy’s universal functions (ufuncs). Examples include np.add, np.multiply, and np.sin.

The following NumPy universal functions (ufuncs) are supported:

  • Arithmetic:

    np.add, np.subtract, np.multiply, np.divide, np.power, np.mod, etc.

  • Trigonometric:

    np.sin, np.cos, np.tan, np.arcsin, np.arccos, np.arctan, etc.

  • Exponential and logarithmic:

    np.exp, np.log, np.log10, etc.

  • Comparison:

    np.equal, np.not_equal, np.less, np.less_equal, np.greater, np.greater_equal, etc.

  • Bitwise:

    np.bitwise_and, np.bitwise_or, np.bitwise_xor, etc.

__array_function__(func: Callable[…, Any], types: Tuple[type, …], args: Tuple[Any, …], kwargs: Dict[str, Any]) -> Union[‘Image’, Tuple[‘Image’, …], Any]

Enable compatibility with numpy’s general functions, such as np.mean, np.dot, and np.concatenate.

The following numpy general functions are supported:

  • Array manipulation:

    np.reshape, np.transpose, np.concatenate, etc.

  • Statistical:

    np.mean, np.sum, np.std, etc.

  • Linear algebra:

    np.dot, np.cross, etc.

Indexing and Assignment

__getitem__(idx: Any) -> Union[‘Image’, Any]

Access array elements using standard indexing or slicing. If the result is scalar, returns it; otherwise, returns an Image.

__setitem__(key: Any, value: Any) -> None

Assign values to specific array elements. Updates the properties of the Image accordingly.

Special Methods

__repr__() -> str

Return a string representation of the Image object.

Examples#

Create an Image instance from a NumPy array:

>>> import numpy as np
>>> from deeptrack.image import Image
>>> img = Image(np.array([[1, 2], [3, 4]]))
>>> print(img)
Image(array([[1, 2],
             [3, 4]]))

Access NumPy attributes and methods:

>>> print(img.shape)
(2, 2)
>>> print(img.sum())
10

Manage properties:

>>> img.append({"property_name": "example"})
>>> print(img.properties)
[{'property_name': 'example'}]

Compatibility with NumPy ufuncs:

>>> print(img + 10)
Image(array([[11, 12],
             [13, 14]]))

Conversion between NumPy and CuPy arrays:

>>> import cupy
>>> gpu_img = img.to_cupy()
>>> print(type(gpu_img._value))
<class 'cupy.ndarray'>
>>> converted_back = gpu_img.to_numpy()
>>> print(type(converted_back._value))
<class 'numpy.ndarray'>

Methods Summary

append(property_dict)

Append a dictionary to the properties list.

get_property(key[, get_one, default])

Retrieve the value of a property of the Image.

merge_properties_from(other)

Merge properties with those from another Image.

to_cupy()

Convert the image's underlying value to a CuPy array.

to_numpy()

Convert the image's underlying value to a NumPy array.

Methods Documentation

append(property_dict: Dict[str, Property]) Image#

Append a dictionary to the properties list.

This method adds a dictionary of property values to the properties list of the Image instance.

This method does not ensure uniqueness of properties within the properties list. Duplicate entries may be added if the same dictionary is appended multiple times.

Parameters#

property_dictDict[str, Property]

A dictionary to append to the property list.

Returns#

Image

Returns itself.

Example#

>>> import numpy as np
>>> from deeptrack import Feature, Image

Define the feature and enable property storage:

>>> class SimpleParticle(Feature):
...     def get(self, image, position=None, **kwargs):
...         return image
>>> particle = SimpleParticle(position=(128, 128))
>>> particle.store_properties()  # Return Image instead of NumPy array.

Create an input image and resolve the feature:

>>> input_image = Image(np.zeros((256, 256)))
>>> output_image = particle.resolve(input_image)
>>> print(output_image.properties)
[{'position': (128, 128), 'name': 'SimpleParticle'}]

Append new properties to the image:

>>> output_image.append({"key1": 1, "key2": 2})
>>> print(output_image.properties)
[{'position': (128, 128), 'name': 'SimpleParticle'},
{'key1': 1, 'key2': 2}]
get_property(key: str, get_one: bool = True, default: Any | None = None) Any | List[Any]#

Retrieve the value of a property of the Image.

If the feature has the property defined by key, the method returns its current_value. Otherwise, it returns the default value.

If get_one is True, the first instance is returned; otherwise, all instances are returned as a list.

Parameters#

keystr

The name of the property.

get_one: bool, optional

Whether to return only the first instance of the property (default behavior for True) or all instances of the property (False).

defaultAny, optional

The value to be returned as default, which is by default None.

Returns#

Any or List[Any]

The value of the property (if get_one is True) or all instances as a list (if get_one is True). If the property is not found, it returns default.

Example#

>>> import numpy as np
>>> from deeptrack import Feature, Image

Define the feature and enable property storage:

>>> class SimpleParticle(Feature):
...     def get(self, image, position=None, **kwargs):
...         return image
>>> particle = SimpleParticle(position=(128, 128))
>>> particle.store_properties()  # Return Image instead of NumPy array.

Create an input image and resolve the feature:

>>> input_image = Image(np.zeros((256, 256)))
>>> output_image = particle.resolve(input_image)

Retrieve the properties:

>>> print(output_image.get_property("position"))
>>> print(output_image.get_property("name"))
merge_properties_from(other: ndarray | Image | Iterable) Image#

Merge properties with those from another Image.

Appends properties from another images without duplicating properties. The uniqueness of a dictionary of properties is determined from the property hash_key.

Most functions involving two images should automatically output an image with merged properties. However, since each property is guaranteed to be unique, it is safe to manually call this function if there is any uncertainty.

Parameters#

otherImage or np.ndarray or Iterable

The data to retrieve properties from. It can be an Image, a NumPy array (which has no properties), or an iterable object.

Returns#

Image

Returns itself.

Example#

>>> import numpy as np
>>> from deeptrack import Feature, Image

Define the feature and enable property storage:

>>> class SimpleParticle(Feature):
...     def get(self, image, position=None, **kwargs):
...         return image
>>> particle = SimpleParticle(position=(128, 128))
>>> particle.store_properties()  # To return an Image and not an array.

Create an input image:

>>> input_image = Image(np.zeros((256, 256)))

Resolve the feature twice without update and verify that only one set of properties is stored:

>>> output_image1 = particle.resolve(input_image)
>>> output_image2 = particle.resolve(input_image)
>>> output_image1.merge_properties_from(output_image2)
>>> print(output_image1.properties)
[{'position': (128, 128), 'name': 'SimpleParticle'}]

Update the feature, resolve it, and verify that now two sets of properties are stored:

>>> particle.update()
>>> output_image3 = particle.resolve(input_image)
>>> output_image1.merge_properties_from(output_image3)
>>> print(output_image1.properties)
[{'position': (128, 128), 'name': 'SimpleParticle'},
{'position': (128, 128), 'name': 'SimpleParticle'}]

Now, call the method with a list including a previously merged feature and a NumPy array that are not merged:

>>> particle.update()
>>> output_image4 = particle.resolve(input_image)
>>> output_image1.merge_properties_from(
...     [output_image3, output_image4, np.zeros((10, 10))]
... )
>>> print(output_image1.properties)
[{'position': (128, 128), 'name': 'SimpleParticle'},
{'position': (128, 128), 'name': 'SimpleParticle'},
{'position': (128, 128), 'name': 'SimpleParticle'}]
to_cupy() Image#

Convert the image’s underlying value to a CuPy array.

This method converts the _value of the Image object to a CuPy array if it is currently a NumPy array. If the conversion is performed, the method returns a new Image object with the converted value while preserving the properties of the original Image.

If the _value is already a CuPy array or an unsupported type, the method returns the Image object unchanged.

Returns#

Image

A new Image object with the _value as a CuPy array, or the unchanged Image object if conversion is not applicable.

Examples#

Convert a NumPy array to CuPy:

>>> import numpy as np
>>> from deeptrack.image import Image
>>> img = Image(np.array([1, 2, 3]))
>>> cupy_img = img.to_cupy()
>>> print(cupy_img)
Image(array([1, 2, 3]))

If the _value is already a CuPy array, no conversion occurs:

>>> import cupy
>>> cupy_img = Image(cupy.array([1, 2, 3]))
>>> print(cupy_img.to_cupy() is cupy_img)
True
to_numpy() Image#

Convert the image’s underlying value to a NumPy array.

This method converts the _value of the Image object to a NumPy array if it is currently a CuPy array. If the conversion is performed, the method returns a new Image object with the converted value while preserving the properties of the original Image.

If the _value is already a NumPy array or an unsupported type, the method returns the Image object unchanged.

Returns#

Image

A new Image object with the _value as a NumPy array, or the unchanged Image object if conversion is not applicable.

Examples#

Convert a CuPy array to NumPy:

>>> import cupy
>>> from deeptrack.image import Image
>>> img = Image(cupy.array([1, 2, 3]))
>>> numpy_img = img.to_numpy()
>>> print(numpy_img)
Image(array([1, 2, 3]))

If the _value is already a NumPy array, no conversion occurs:

>>> import numpy as np
>>> numpy_img = Image(np.array([1, 2, 3]))
>>> print(numpy_img.to_numpy() is numpy_img)
True