I start with a 2D array and want to broadcast it to a 3D array (eg. from greyscale image to rgb image). This is the code I use.
>>> img_grey = np.random.randn(4, 4)
>>> img_rgb = np.broadcast_to(np.expand_dims(img_grey, axis=-1), (4, 4, 3))
This creates an array img_rgb
that works as expected: 3 colored channels (last dimension), each slice being equal to the original greyscale image. However, if I do
>>> img_rgb[0, 0, 0] = 0.
ValueError: assignment destination is read-only
I can't change the rgb image!
The reason is that broadcast_to
does not create a new array in memory. Instead, you just get a view of the original data. This can be seen by inspecting the flags.
>>> img_rg.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : False
ALIGNED : True
UPDATEIFCOPY : False
In particular, the OWNDATA flag is set to False (which means the array borrows the memory from another object), as well as the WRITEABLE flag being False (this is why you can't change the object). See the numpy flags documentation.
The workaround is to create a copy of the array.
>>> img_rgb = np.broadcast_to(np.expand_dims(img_grey, axis=-1), (4, 4, 3)).copy()
>>> img_rgb[0, 0, 0] = 0. # works!
This gives the rgb image its own memory space, which can be changed without altering the greyscale image. The OWNDATA and WRITEABLE flags are thus also set to True.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With