Turbolay
Turbolay

Reputation: 88

Unexpected behaviour in numpy np.where with np.logical_and

I want to find an RGB pixel in a numpy tri-dimensional array (X/Y/RGB) created with Pillow

conditions = np.logical_and(np.logical_and(array[:,:,0]==rgb[0],array[:,:,1]==rgb[1]),array[:,:,2]==rgb[2])
res = np.flip(np.transpose(np.where(conditions))).tolist()

It works like a charm.

However, I'd like to add a tolerance, so I just changed the conditions by:

abs(array[:,:,i]-rgb[i]) <= tolerance

But this does not work as expected, it returns zeros instead of pixels in the tolerated range. How can I add tolerance to my upper snippet?

Upvotes: 1

Views: 76

Answers (2)

Turbolay
Turbolay

Reputation: 88

Problem was calling np.array() on a PIL Image automatically create a dtype=uint8. During my logical tests value can go higher than 255, thus the unexpected behaviour

Logic can be changed to make it work, but array = np.array(im,dtype=np.int16) also does the trick (even if it's less optimized)

Upvotes: 0

constantstranger
constantstranger

Reputation: 9379

Your code seems as though it correctly identifies values within the given tolerance.

Here's my test code:

import numpy as np
array = np.reshape(np.array([i%3 + (i//3) / 10 for i in range(27)]), (3,3,3))
print('array:', array, '', sep='\n')
rgb = [0,1,2]
for x in range(3):
    for y in range(3):
        print(f'x={x} y={y} rgb={array[x,y,:]}')

conditions = np.logical_and(np.logical_and(array[:,:,0]==rgb[0],array[:,:,1]==rgb[1]),array[:,:,2]==rgb[2])
print('', 'conditions:', conditions, sep='\n')
res = np.flip(np.transpose(np.where(conditions))).tolist()
print(res)
print('', 'res:', res, sep='\n')

tolerance = 0.35
conditions = np.logical_and(np.logical_and(abs(array[:,:,0]-rgb[0]) <= tolerance,abs(array[:,:,1]-rgb[1]) <= tolerance),abs(array[:,:,2]-rgb[2]) <= tolerance)
print('', f'conditions @ tolerance={tolerance}:', conditions, sep='\n')
res = np.flip(np.transpose(np.where(conditions))).tolist()
print(res)
print('', 'res:', res, sep='\n')

Output:

array:
[[[0.  1.  2. ]
  [0.1 1.1 2.1]
  [0.2 1.2 2.2]]

 [[0.3 1.3 2.3]
  [0.4 1.4 2.4]
  [0.5 1.5 2.5]]

 [[0.6 1.6 2.6]
  [0.7 1.7 2.7]
  [0.8 1.8 2.8]]]

x=0 y=0 rgb=[0. 1. 2.]
x=0 y=1 rgb=[0.1 1.1 2.1]
x=0 y=2 rgb=[0.2 1.2 2.2]
x=1 y=0 rgb=[0.3 1.3 2.3]
x=1 y=1 rgb=[0.4 1.4 2.4]
x=1 y=2 rgb=[0.5 1.5 2.5]
x=2 y=0 rgb=[0.6 1.6 2.6]
x=2 y=1 rgb=[0.7 1.7 2.7]
x=2 y=2 rgb=[0.8 1.8 2.8]

conditions:
[[ True False False]
 [False False False]
 [False False False]]
[[0, 0]]

res:
[[0, 0]]

conditions @ tolerance=0.35:
[[ True  True  True]
 [ True False False]
 [False False False]]
[[0, 1], [2, 0], [1, 0], [0, 0]]

res:
[[0, 1], [2, 0], [1, 0], [0, 0]]

Upvotes: 2

Related Questions