Indexing
Contents
Indexing into a dip.Image
object uses the same syntax as other array types in
Python:
img[0] img[0, 10] img[0:-1:2, 0:-1:2]
But the indexing follows DIPlib’s rules:
- Dimensions are ordered in reverse from how NumPy stores them (the first dimension is horizontal, or x).
- The end index is included in the range.
- You must provide one range (slice) per dimension, you cannot index only into a subset of dimensions.
The only exception to the 3rd point is that you can index a single pixel using linear indexing (i.e. a single
index), which will be interpreted as counting along rows. For example, for a 3D image, coordinates [x, y, z]
cooresponds to linear index (z * img.Size(1) + y) * img.Size(0) + x
.
It is possible to assign to a subset of the image pixels using indexing:
img[0] = 0 img[0, 10] = img[20, 30] img[0:-1:2, 0:-1:2] = 255
Unlike in DIPlib, the square brackets index into spatial dimensions. To index into tensor dimensions, use round brackets (parentheses):
img(0) img(0, 2) img(slice(0, 3))
When the indexing operation uses ranges, or indexes into the tensor dimension, then the output is
a new dip.Image
object that shares data with the original image object. This means that writing
to that output also changes the original image:
img2 = img(0) # this copy shares data with img img2.Fill(100) # same as img(0).Fill(100) img(1).Copy(img(0)) img(2)[:,:] = img(0) # note that img(2) = img(0) is not allowed by Python img2 = img(0).Copy() # this copy does not share data with img img2.Fill(100) # does not affect img
Indexing operations that use only single indices along each dimension return a pixel. This is represented as a list with the pixel values (even for scalar images). This list does not share data with the image.
Irregular indexing
There are also indexing operations that select an arbitrary (irregular) subset of pixels. These indexing
operations return a new dip.Image
object, which is always 1D.
This new object does not share data with the original image, the pixel values are copied over.
But of course there is also an assignment version of these indexing operations.
There are two irregular indexing methods: a mask image and a list of coordinates.
# Mask image indexing mask = img > 100 img2 = img[mask] # this copy does not share data with img img2.Fill(0) # does not affect img img[mask] = 0 # sets pixels selected by mask to 0 # Coordinate list indexing list = [ (0, 0), (0, 1), (0, 5), (10, 3), ] img3 = img[list] # also does not share data with img img[list] = 0 # sets selected pixels to 0
For the mask indexing, the order of the pixels in the 1D output image depends on the internal linear pixel
storage order, which is not consistent with any specific (row-major or column-major) order due to operations
such as Rotation90()
and Mirror()
. For the coordinate list indexing, the output order always matches
the coordinate list order.