pulse2percept.stimuli.ImageStimulus

class pulse2percept.stimuli.ImageStimulus[source]

A stimulus made from an image, where each pixel gets assigned to an electrode, and grayscale values in the range [0, 255] get converted to activation values in the range [0, 1].

See also

  • Basic Concepts > Electrical Stimuli <topics-stimuli>

  • VideoStimulus

Added in version 0.7.

Parameters:
  • source (str, os.PathLike, ImageStimulus, or np.ndarray) –

    Path to an image file (str or pathlib.Path). File types are inferred from the file ending (support types include JPG, PNG, and TIF).

    Note

    For GIFs, use VideoStimulus.

    Changed in version 0.11.0: A pathlib.Path is accepted wherever a filename is. metadata['source'] is always a string.

  • resize ((height, width) or None, optional) – Shape of the resized image. If one of the dimensions is set to -1, its value will be inferred by keeping a constant aspect ratio.

  • as_gray (bool, optional) – Flag whether to convert the image to grayscale. A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.

  • electrodes (int, string or list thereof; optional) –

    Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).

    Note

    The number of electrode names provided must match the number of pixels in the (resized) image.

  • metadata (dict, optional) – Additional stimulus metadata can be stored in a dictionary.

  • compress (bool, optional) – If True, will remove pixels with 0 grayscale value.

__init__(source, resize=None, as_gray=False, electrodes=None, metadata=None, compress=False)[source]

Methods

__init__(source[, resize, as_gray, ...])

append(other)

Append another stimulus

apply(func, *args[, electrodes])

Apply a function to the image

center([loc])

Center the image foreground

compress()

Compress the source data in place

crop([idx_rect, left, right, top, bottom, ...])

Crop the image

crop_square()

Crop the image to the largest centered square

encode([amp_range, freq, implant])

Encode the image using amplitude modulation

filter(filt, **kwargs)

Filter the image

invert()

Invert the gray levels of the image

pad(duration)

Pad the stimulus with zeros up to a given time.

plot([ax])

Plot the stimulus

remove(electrodes)

Remove electrode(s)

resize(shape[, electrodes])

Resize the image

rgb2gray([electrodes])

Convert the image to grayscale

rotate(angle[, mode, electrodes])

Rotate the image

save(fname[, vmin, vmax])

Save the stimulus as an image

scale(scaling_factor)

Scale the image foreground

shift(shift_cols, shift_rows)

Shift the image foreground

threshold(thresh, **kwargs)

Threshold the image

times([unit])

The stimulus time axis, expressed in unit

trim([tol, electrodes])

Remove any black border around the image

values([unit])

The stimulus data, expressed in unit

Attributes

img_shape

data

Stimulus data container

dt

Sampling time step (duration of signal edge transitions)

duration

Stimulus duration (ms)

electrodes

Electrode names A list of electrode names, corresponding to the rows in the data container.

is_charge_balanced

Flag indicating whether the stimulus is charge-balanced

is_compressed

Flag indicating whether the stimulus has been compressed

metadata

quantity

The stimulus data, with its unit attached

shape

Data container shape

time

A list of time steps (i.e., the columns in the data container)

time_quantity

The stimulus time axis with its unit attached, or None

time_unit

The unit time is expressed in

unit

The unit data is expressed in

apply(func, *args, electrodes=None, **kwargs)[source]

Apply a function to the image

Changed in version 0.10.0: func may now change the shape of the image, and electrodes can name the result.

Parameters:
  • func (function) – The function to apply to the image. Must accept a 2D or 3D image and return a 2D or 3D image. The returned image need not have the same shape as the original; see electrodes.

  • args (*) – Additional positional arguments passed to the function

  • electrodes (int, string or list thereof; optional) –

    Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever func leaves the shape of the image alone, and the result is named after its place in the new image otherwise (e.g. for skimage.transform.resize).

    Note

    The number of electrode names provided must match the number of pixels in the returned image.

  • **kwargs – Additional keyword arguments passed to the function

Returns:

stim – A copy of the stimulus object with the new image

Return type:

ImageStimulus

invert()[source]

Invert the gray levels of the image

Returns:

stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].

Return type:

ImageStimulus

rgb2gray(electrodes=None)[source]

Convert the image to grayscale

Parameters:

electrodes (int, string or list thereof; optional) –

Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).

Note

The number of electrode names provided must match the number of pixels in the grayscale image.

Returns:

stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].

Return type:

ImageStimulus

Notes

  • A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.

resize(shape, electrodes=None, **kwargs)[source]

Resize the image

Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.

Parameters:
  • shape ((rows, cols)) – Shape of the resized image

  • electrodes (int, string or list thereof; optional) –

    Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).

    Note

    The number of electrode names provided must match the number of pixels in the grayscale image.

  • **kwargs – Additional keyword arguments passed to skimage.transform.resize, such as order=0 for nearest-neighbor interpolation (which keeps a binary image binary).

Returns:

stim – A copy of the stimulus object containing the resized image

Return type:

ImageStimulus

crop(idx_rect=None, left=0, right=0, top=0, bottom=0, electrodes=None)[source]

Crop the image

This method maps a rectangle (defined by two corners) from the image to a rectangle of the given size. Alternatively, this method can be used to crop a number of columns either from the left or the right of the image, or a number of rows either from the top or the bottom.

Added in version 0.8.

Parameters:
  • idx_rect (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner [y0, x0] and bottom-right corner [y1, x1] (exclusive) of the rectangle to crop.

  • left (int) – Number of columns to crop from the left

  • right (int) – Number of columns to crop from the right

  • top (int) – Number of rows to crop from the top

  • bottom (int) – Number of rows to crop from the bottom

  • electrodes (int, string or list thereof; optional) –

    Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).

    Note

    The number of electrode names provided must match the number of pixels in the cropped image.

Returns:

stim – A copy of the stimulus object containing the cropped image

Return type:

ImageStimulus

crop_square()[source]

Crop the image to the largest centered square

The image is cropped without resizing. If its dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.

Added in version 0.11.0.

Returns:

stim – A copy of the stimulus containing the centered square crop.

Return type:

ImageStimulus

trim(tol=0, electrodes=None)[source]

Remove any black border around the image

Added in version 0.7.

Parameters:
  • tol (float) – Any pixels with gray levels > tol will be trimmed.

  • electrodes (int, string or list thereof; optional) –

    Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).

    Note

    The number of electrode names provided must match the number of pixels in the trimmed image.

Returns:

stim – A copy of the stimulus object with trimmed borders.

Return type:

ImageStimulus

threshold(thresh, **kwargs)[source]

Threshold the image

Parameters:

thresh (str or float) –

If a float in [0,1] is provided, pixels whose grayscale value is above said threshold will be white, others black.

A number of additional methods are supported:

  • ’mean’: Threshold image based on the mean of grayscale values.

  • ’minimum’: Threshold image based on the minimum method, where

    the histogram of the input image is computed and smoothed until there are only two maxima.

  • ’local’: Threshold image based on local pixel neighborhood. Requires block_size: odd number of pixels in the neighborhood.

  • ’otsu’: Otsu’s method

  • ’isodata’: ISODATA method, also known as the Ridler-Calvard method or intermeans.

Returns:

stim – A copy of the stimulus object with two gray levels 0.0 and 1.0

Return type:

ImageStimulus

rotate(angle, mode='constant', electrodes=None, **kwargs)[source]

Rotate the image

Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.

Parameters:
  • angle (float or Quantity) – Angle by which to rotate the image (degrees). Positive: counter-clockwise, negative: clockwise

  • mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.

  • electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless resize=True grew the canvas, in which case the enlarged image is named after its own pixel grid.

  • **kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as order, cval, or resize=True to grow the image so that it contains every rotated pixel.

Returns:

stim – A copy of the stimulus object containing the rotated image

Return type:

ImageStimulus

shift(shift_cols, shift_rows)[source]

Shift the image foreground

This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.

Parameters:
  • shift_cols (float) – Number of columns by which to shift the CoM. Positive: to the right, negative: to the left

  • shift_rows (float) – Number of rows by which to shift the CoM. Positive: downward, negative: upward

Returns:

stim – A copy of the stimulus object containing the shifted image

Return type:

ImageStimulus

center(loc=None)[source]

Center the image foreground

This function shifts the center of mass (CoM) to the image center.

Parameters:

loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.

Returns:

stim – A copy of the stimulus object containing the centered image

Return type:

ImageStimulus

scale(scaling_factor)[source]

Scale the image foreground

This function scales the image foreground (excluding black pixels) by a factor.

Parameters:

scaling_factor (float) – Factory by which to scale the image

Returns:

stim – A copy of the stimulus object containing the scaled image

Return type:

ImageStimulus

filter(filt, **kwargs)[source]

Filter the image

Parameters:
  • filt (str) –

    Image filter. Additional parameters can be passed as keyword arguments. The following filters are supported:

    • ’sobel’: Edge filter the image using the Sobel filter.

    • ’scharr’: Edge filter the image using the Scharr filter.

    • ’canny’: Edge filter the image using the Canny algorithm. You can also specify sigma, low_threshold, high_threshold, mask, and use_quantiles.

    • ’median’: Return local median of the image.

  • **kwargs – Additional parameters passed to the filter

Returns:

stim – A copy of the stimulus object with the filtered image

Return type:

ImageStimulus

encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]

Encode the image using amplitude modulation

Encodes the image as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses.

This is a shorthand for AmplitudeEncoder; use that directly for the full set of options.

Changed in version 0.10.0: Gray levels now map onto amp_range absolutely rather than being stretched to fill it (pass stretch=True for the old behavior), the image receives a pulse train rather than a single pulse, and implant encodes at electrode rather than pixel resolution.

Parameters:
  • amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto min_amp, a gray level of 1 onto max_amp.

  • freq (float, optional) – Pulse train frequency (Hz). The image is treated as a single frame lasting 500 ms unless frame_dur says otherwise.

  • implant (Implant, optional) – If given, the image is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution.

  • **kwargs – Additional arguments passed to AmplitudeEncoder.

Returns:

stim – Encoded stimulus

Return type:

Stimulus

plot(ax=None, **kwargs)[source]

Plot the stimulus

Parameters:

ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object or a list thereof (one per electrode to plot). If None, a new Axes object will be created.

Returns:

ax – Returns the axes with the plot on it

Return type:

matplotlib.axes.Axes

save(fname, vmin=0, vmax=None)[source]

Save the stimulus as an image

Parameters:

fname (str or os.PathLike) –

The name of the image file to be created. Image type will be inferred from the file extension.

Changed in version 0.11.0: A pathlib.Path is accepted.

append(other)[source]

Append another stimulus

This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.

Added in version 0.7.

Parameters:

other (Stimulus) – Another stimulus with matching electrodes.

Returns:

comb – A combined stimulus with the same number of electrodes and new stimulus duration equal to the sum of the two individual stimuli.

Return type:

Stimulus

compress()[source]

Compress the source data in place

property data

Stimulus data container

A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.

property dt

Sampling time step (duration of signal edge transitions)

Added in version 0.7.

property duration

Stimulus duration (ms)

property electrodes

Electrode names A list of electrode names, corresponding to the rows in the data container.

property is_charge_balanced

Flag indicating whether the stimulus is charge-balanced

A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.

Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.

property is_compressed

Flag indicating whether the stimulus has been compressed

pad(duration)[source]

Pad the stimulus with zeros up to a given time.

Adds zero-valued endpoints at t=0 and t=duration as needed. duration specifies the final time, not the amount of padding to add.

Added in version 0.10.0.

Parameters:

duration (float or Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.

Returns:

padded – Padded copy of the stimulus.

Return type:

Stimulus

Notes

Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.

property quantity

The stimulus data, with its unit attached

Added in version 0.10.0.

Examples

>>> from pulse2percept.stimuli import Stimulus
>>> from pulse2percept.units import uA
>>> Stimulus([500, 1000] * uA).quantity
[[ 500.]
 [1000.]] uA
remove(electrodes)[source]

Remove electrode(s)

Removes the stimulus of a certain electrode or list of electrodes.

Added in version 0.8.

Parameters:

electrodes (int, string, or list of int/str) – The item(s) to remove from the stimulus. Can either be an electrode index, electrode name, or a list thereof.

property shape

Data container shape

property time

A list of time steps (i.e., the columns in the data container)

property time_quantity

The stimulus time axis with its unit attached, or None

Added in version 0.10.0.

property time_unit

The unit time is expressed in

Added in version 0.10.0.

times(unit=None)[source]

The stimulus time axis, expressed in unit

Added in version 0.10.0.

Parameters:

unit (Unit, optional) – The unit to express the time axis in. If None, time is returned as it is stored (milliseconds).

Returns:

times – An ordinary NumPy array, or None if the stimulus has no time component.

Return type:

np.ndarray or None

property unit

The unit data is expressed in

Added in version 0.10.0.

values(unit=None)[source]

The stimulus data, expressed in unit

Added in version 0.10.0.

Parameters:

unit (Unit, optional) – The unit to express the data in. Must be compatible with unit. If None, the stimulus’ own unit is used and data is returned as it is stored.

Returns:

values – An ordinary NumPy array, never a Quantity.

Return type:

np.ndarray

Examples

>>> from pulse2percept.stimuli import Stimulus
>>> from pulse2percept.units import uA, mA
>>> Stimulus([500, 1000] * uA).values(mA)
array([[0.5],
       [1. ]], dtype=float32)