-1

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.

enter image description here

Marco
  • 33
  • 7
  • `mask = originalFormat == segmentId` This will make `mask` a true/false value. But then the next line does `... in mask`, which should be an error, because a single true/false value is not iterable. As shown, this code cannot run. Please show the real code. – John Gordon Feb 16 '23 at 19:22
  • can you simplify this example? would `mask = np.array([[[True, True, True]]])` work in the same way? – njzk2 Feb 16 '23 at 19:22
  • Well, this is the real code. mask is a numpy array with shape (720, 1280, 3) and segmentId is also a numpy array with shape (3,). And the resulting mask has also shape (720, 1280, 3) – Marco Feb 16 '23 at 19:25
  • 2
    @JohnGordon presumably those are np arrays, for which the return value of the `==` operator is not a single boolean value, but another np array – njzk2 Feb 16 '23 at 19:25
  • 1
    @Marco but can you simplify? take a (2,2,3) and and (3,), write down the actual values, and allow us to see exactly what happens? (https://stackoverflow.com/help/minimal-reproducible-example) – njzk2 Feb 16 '23 at 19:26
  • When I only use ```mask = np.array([[[True, True, True]]])``` it works – Marco Feb 16 '23 at 19:27
  • indeed. now you need to find what happens that it stops working – njzk2 Feb 16 '23 at 19:27
  • With `originalFormat = np.arange(12).reshape((2, 2, 3))` and `segmentId = np.array([6, 7, 8])` the code works fine, exactly as expected. – Arne Feb 16 '23 at 19:27
  • notice: `[True, True, True] in np.array([[[False, True, True]]])` is actually `True` – njzk2 Feb 16 '23 at 19:28
  • @njzk2 Yes, that is the strange behaviour I meant ^^ It should work, but for some reason it doesn't. When i test for a specific value like ```[1, 111, 127] in originalFormat``` i get True, and there is also [True, True, True] in the mask. But applying np.all on it removes this true value for some reason – Marco Feb 16 '23 at 19:35
  • 1
    How sure are you that `segmentId` is contained in the image? Maybe it`s a format or datatype or numerical issue. Are the values integer or float? – Arne Feb 16 '23 at 19:38
  • Please read [ask] and [mre] and show code that someone else can **copy and paste, without adding or changing anything**, to see the **exact problem, directly**. This means: include the relevant `import`s; include small, hard-coded examples of what `originalFormat` and `segmentId` might be beforehand in order to show the problem; and explain step by step what should happen with those values and what the result should be. – Karl Knechtel Feb 16 '23 at 19:40
  • @Arne Pretty sure. When i execute ```test = segmentId in originalFormat``` I get True as result – Marco Feb 16 '23 at 19:40
  • 2
    If you don't know specifically what data needs to be in your inputs to cause the problem, then start with your existing data, and try taking slices of it, until you find small pieces that show the problem. This is a fundamental [debugging](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) skill which you are [expected](https://meta.stackoverflow.com/questions/261592) to try applying before asking a question. – Karl Knechtel Feb 16 '23 at 19:41
  • @Marco If you can't post an example of an array which triggers this problem, can you at least post an example of an image which triggers this problem? Preferably with code to load the image as an array. – Nick ODell Feb 16 '23 at 19:41
  • @NickODell Im using a self generated image, so I don't have a link to it. Where can I upload it? :) – Marco Feb 16 '23 at 19:43
  • Users with at least 10 rep can post images in their questions. – Nick ODell Feb 16 '23 at 19:45
  • Your [mre] doesn't have any example data. – wwii Feb 16 '23 at 19:50
  • Okay, I added the minimal example :) – Marco Feb 16 '23 at 19:54
  • Does this answer your question? [testing whether a Numpy array contains a given row](https://stackoverflow.com/questions/14766194/testing-whether-a-numpy-array-contains-a-given-row) – Pranav Hosangadi Feb 16 '23 at 20:34

2 Answers2

0

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.

Marco
  • 33
  • 7
  • 1
    `segmentId in originalFormat` is `True` because that is equivalent to `(originalFormat == segmentId).any()`. Since `originalFormat == segmentId` is bound to contain one `True`, the expression evaluates to `True` – Pranav Hosangadi Feb 16 '23 at 20:26
  • 1
    Instead, you need to do `(originalFormat == segmentId).all(axis=-1).any()` to check if any of the pixels in `originalFormat` have the value given by `segmentId` – Pranav Hosangadi Feb 16 '23 at 20:27
  • PS. Your second snippet: `mask = mask.all(axis=2); test = True in mask` does basically what I said in "instead you need to do..." – Pranav Hosangadi Feb 16 '23 at 20:34
0

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])
Arne
  • 9,990
  • 2
  • 18
  • 28