I'm having some troubles with the skimage.color.rgb2gray method. I'm using it to turn an image (some simple black lines drawn on a white canvas with Paint) with a Python3 program, which is this:
import matplotlib.image as mpimg
from skimage import color
img = mpimg.imread('Image (1).png')
gray = color.rgb2gray(img)
and I've found out that it returns different arrays on two different devices.
The first one is a Raspberry Pi 3 Model B (OS: Raspbian GNU/Linux 8 (jessie)), and it returns this,
[[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]
[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]
[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]
...
[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]
[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]
[0.99999994 0.99999994 0.99999994 ... 0.99999994 0.99999994 0.99999994]]
which is wrong, since the numbers should be 1.0, that's white.
The second one is a Windows 10 Home (1803 version), where everything runs smoothly:
[[1. 1. 1. ... 1. 1. 1.]
[1. 1. 1. ... 1. 1. 1.]
[1. 1. 1. ... 1. 1. 1.]
...
[1. 1. 1. ... 1. 1. 1.]
[1. 1. 1. ... 1. 1. 1.]
[1. 1. 1. ... 1. 1. 1.]]
Could someone explain me the reason for this? Thanks in advance! If some other details are needed, tell me.
As mentioned in the comments to your question, floating point (ie non-integer) calculations in computers are not exact. The standard way to demonstrate this is to verify that 0.1 + 0.2 == 0.3
returns False
. How things are approximated differs between processors, and between numerical libraries (which might perform operations in different orders). You can read more about this here: http://0.30000000000000004.com
I don't think there is any easy way around this, other than minimising the number of operations being done. In your case, your image is a png, which can be grayscale directly, so you could save your image as a grayscale image from the beginning, removing the need for conversion. Alternatively, if you know that your image is just black-and-white or grayscale (ie has no colour information, other than being saved as an RGB image), then the content is the same in every channel, and you can write:
from skimage.util import img_as_float
from skimage.io import imread
image = imread('Image (1).png') # typically uint8 values in [0, 255]
gray = image[..., 0] # 0th channel, red
gray_float = img_as_float(gray) # optional, get floats in [0, 1]
For more information about that last conversion, see this page in the scikit-image documentation: http://scikit-image.org/docs/dev/user_guide/data_types.html