numpy.all strange behaviour
Question:
In the following code, I try to generate a mask on an image. The mask should only be true where the image (originalFormat, ndarry with shape [720, 1280, 3]) has a specific value (segmentId, nd array with shape [3,]).
Here’s a small part of the code as minimal example:
originalFormat = np.array(Image.open(path_to_image))[..., :3]
segment_ids = np.unique(originalFormat.reshape(-1, originalFormat.shape[2]), axis=0)
segment_ids.sort(axis=0)
segmentId = segment_ids[0]
mask = originalFormat == segmentId
test = [True, True, True] in mask
mask = mask.all(axis=2)
test = True in mask
In the second line of the second block, I create the mask and get an output of shape [720, 1280, 3].
In the third line, I test if the image contains the segmentId.
In the fourth line, I apply np.all on the second axis of the mask to get a mask of shape [720, 1280].
In the fifth line, I test again, but now there are no true values in the mask.
So np.all returns false for all values, but should be true for at least one value.
Answers:
Ok, I found the mistake.
It seems like the sort function also sorts the values in every single segmentId, so the resulting segment_ids do not occur in the image.
But this does not explain why
test = segmentId in originalFormat
is True, although segmentId is not in the image.
The test [True, True, True] in mask
does not do what you think it does. Here [True, True, True]
is a plain Python list, and in
is a plain Python operator, nothing NumPy-specific, whereas mask
is a NumPy array.
Thus, it is actually not quite clear what the test checks. See the linked question. In any case, there do not need to be three True
values in the same row for this test to evaluate as True
. Here`s a small example reproducing the behavior you observed:
originalFormat = np.arange(12).reshape((2, 2, 3))
segmentId = np.array([6, 4, 5])
In the following code, I try to generate a mask on an image. The mask should only be true where the image (originalFormat, ndarry with shape [720, 1280, 3]) has a specific value (segmentId, nd array with shape [3,]).
Here’s a small part of the code as minimal example:
originalFormat = np.array(Image.open(path_to_image))[..., :3]
segment_ids = np.unique(originalFormat.reshape(-1, originalFormat.shape[2]), axis=0)
segment_ids.sort(axis=0)
segmentId = segment_ids[0]
mask = originalFormat == segmentId
test = [True, True, True] in mask
mask = mask.all(axis=2)
test = True in mask
In the second line of the second block, I create the mask and get an output of shape [720, 1280, 3].
In the third line, I test if the image contains the segmentId.
In the fourth line, I apply np.all on the second axis of the mask to get a mask of shape [720, 1280].
In the fifth line, I test again, but now there are no true values in the mask.
So np.all returns false for all values, but should be true for at least one value.
Ok, I found the mistake.
It seems like the sort function also sorts the values in every single segmentId, so the resulting segment_ids do not occur in the image.
But this does not explain why
test = segmentId in originalFormat
is True, although segmentId is not in the image.
The test [True, True, True] in mask
does not do what you think it does. Here [True, True, True]
is a plain Python list, and in
is a plain Python operator, nothing NumPy-specific, whereas mask
is a NumPy array.
Thus, it is actually not quite clear what the test checks. See the linked question. In any case, there do not need to be three True
values in the same row for this test to evaluate as True
. Here`s a small example reproducing the behavior you observed:
originalFormat = np.arange(12).reshape((2, 2, 3))
segmentId = np.array([6, 4, 5])