THERE IS ONE MORE "hidden-DIMENSION" OF THE PROBLEM :
Numpy has a few performance-motivated tricks, that may confuse you, if not taking due care of:
There are tricks that np.view()
creates, as a view into a "foreign"-owned data, which actually means there has appeared a form of hidden sharing, which may pretty ugly surprise you if some operations on already "return()
-ed" image
store any modification into a just-.view()
-created view. In such cases your code will silently damage the "foreign"-data, because you did not realise or notice that while the image
reports correctly both the image.{shape|ndim}
, yet it does not "have" its own data, but provides just a view through a "periscope-alike-window" into the original data, still "owned" somewhere else by someone else ( here, a write into image
, like in an exemplary assignment of image[0,0] = -1
will actually "write-through" the -1
to get it stored into the "throat" of A
-s A.data
, being actually a <read-write buffer for 0x7efe9ff73800, size 7372800, offset 0 at 0x7efe9ff6cbf0>
implementor-zone of the actual write-storage operation resulting in modification taking place in A
's data
)
This side-effect of .view()
-s is both very powerful (if used knowingly, where intended, for performance or other reasons) yet also very awful to detect/debug (if not detected in the code design phase and just hunting the devils tail once the "source"-data get damaged without knowing who does turned the so far clear and sound design wreck havoc "foreign&safely-owned"-data from behind a curtain ... that may take and indeed takes pretty long to detect such hidden sharing write-throughs ... if they take place without your prior intent )
>>> A = np.arange( 3*640*480 ).reshape( 3, 640, 480 )
>>> A.shape
(3, 640, 480)
>>> A.ndim
3
>>> B = A.view() # ENFORCE B BECOME A VIEW() ON AN ARRAY
>>> B.shape # B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
(3, 640, 480)
>>> B.ndim # B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
3
>>> B.flags # B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False <------------------- a view() on array, not the array itself
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
>>> image = B[0,:,:] # slice B into an IMAGE, which will still look as if it is an array
>>> image.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False <----------------- a view() onto an array, not the array itself
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
>>> image.ndim
2
>>> image.shape
(640, 480)
Hope you will enjoy the .view()
-s, where used for performance or other reasons and hope you will never have to back-track the hidden-sharing side-effects in production.