1

I've imported an image as RGB using scipy and imread(). Say I want to separate out the "R" component and copy it to a new object in memory. The code below works:

import scipy as sp
import scipy.misc as misc
import matplotlib.pyplot as plt
%matplotlib inline 
pic = misc.imread("ARBITRARY IMAGE.png");

r = pic[:,:,0].copy()
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])

Outputs the expected:

0
255

However I got there by the following path, and I don't know why they don't work:

r = pic[:,:,0]
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])

outputs:

0
0

Fair enough, I took the syntax cue from here and it involves using a slice like b = a[:] instead of a single layer. How about:

r = pic[:]
r[0,0,0] = 0
print(r[0,0,0])
print(pic[0,0,0])

or to add an extra step:

r = pic[:]
r= r[:,:,0]
r[0,0] = 0
print(r[0,0])
print(pic[0,0,0])

Still outputs:

0
0

It is an array not a list, but this answer for arrays implies that this syntax should be okay. Basically, how come a new object isn't created in memory when I use the slice notation in my examples? I assume I am missing something else, and my googling just seems to tell me the syntax should work. Thanks for any help!

martineau
  • 119,623
  • 25
  • 170
  • 301
Mudbeard
  • 13
  • 2
  • Variable `pic` probably isn't an ordinary array, but some object with an overloaded slice operator that doesn't create a copy, but rather a view referencing the same data. E.g. numpy doesn't like creating copies as well, if I remember correctly. – Jacques de Hooge Oct 24 '17 at 20:13

1 Answers1

3

The other question you linked uses incorrect terminology; it's asking about Python lists, whereas you're using a Numpy array. Slicing a list does give you a copy of the chosen range, but slicing an array gives you a view instead. Changes you make to the view are reflected in the original.

With Numpy arrays, you need to use copy() to get a separate copy that you can change without affecting the original. This is a design choice, because Numpy arrays can often be very large and you wouldn't want to copy them inadvertently.

David Z
  • 128,184
  • 27
  • 255
  • 279
  • be forwarned if you are using 32 bit python np.array.copy can be an expensive operation wrt memory (numpy requires contiguous memory) – Joran Beasley Oct 24 '17 at 20:19
  • @David Duh I didn't even think to take a guess that they were using the wrong terms. Joran, Not that it's necessary for me here, but do you have an alternative? Or should I just try to avoid making copies with such an array – Mudbeard Oct 24 '17 at 21:12