Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does numpy.astype(np.uint8) convert a float array? -1.2997805 became 255

this is an execution in ipython3

In [81]: r2
Out[81]: 
array([-1.2997805, -1.4251276, -1.3047135, ..., -2.0358603, -1.9741256,
       -1.6412157], dtype=float32)

In [82]: r2.astype(np.uint8)
Out[82]: array([255, 255, 255, ..., 254, 255, 255], dtype=uint8)

how is -1.2997805 converted to 255?

ADD : from the comments below(thanks), I tested like this. looks like the float is converted to int, and the modulo 255 (to read it as unsigned int8) is done.

is first convereted to int. and the it is cut using modulo(%).  
In [98]: b
Out[98]: array([-1.,  0.,  1.])

In [99]: b.astype(np.uint8)
Out[99]: array([255,   0,   1], dtype=uint8)
like image 343
Chan Kim Avatar asked Mar 02 '23 00:03

Chan Kim


2 Answers

You converted to unsigned int 8, where -1 correspond to 255, -2 to 254 etc. If you want to get -1, -2 you have to convert it to signed int8 using np.int8:

>>> np.float32(-2.0358603).astype(np.uint8)
254                                        
>>> np.float32(-2.0358603).astype(np.int8) 
-2                                         
like image 177
pygri Avatar answered Apr 19 '23 23:04

pygri


This is an "unsafe cast" according to numpy docs on astype, meaning "any data conversions may be done". They didn't say how exactly the casting is done and I did not find it in a quick search of the docs, so it may be implementation dependent.

My guess is the following: first the 32 bit float is cast to 8 bit signed integer, which defaults to truncating towards zero, ex. -1.3 becomes -1. Then a cast from unsigned 8 bit integer to 8 bit unsigned integer, giving a value of 255. Something like

float x = -1.2997805;  # Assume float is 32-bit
(uint8_t)(int8_t)x;

This is not the same as directly converting to 8-bit unsigned int with (uint8_t)x, which gives 0 at least on the platform I tested on (godbolt's x86-64 gcc).

This kind of thing is very confusing and may even be platform dependent (possibly depending on what OS, numpy version, what the FP hardware decides to do or if the processor even uses 2s complement, etc) so do not ever rely on this behavior without knowing exactly what platform you will be running the code on, and it is poor coding practice anyway. Surprisingly, I couldn't find a reference on exactly how numpy's casting rules work.

like image 22
qwr Avatar answered Apr 19 '23 23:04

qwr