0

I'm analyzing image color, but am getting rid of any RGB color pixel that is 0,0,0 (black). (Using this top answer as reference)

I have an array of pixels

pixels = np.float32(img.reshape(-1, 3))

[[ 126.   94.   51.]
 [ 171.  115.   65.]
 [ 188.  119.   64.]
 ..., 
 [   0.    0.    0.]
 [   0.    0.    0.]
 [   0.    0.    0.]]

I then try to go through and delete any sub arrays that are black.

pixelstoignore = np.delete(pixels, np.where(pixels == [0,0,0]), axis=0)

This appears to works: enter image description here

However the difference between the average color and dominant color tell you otherwise. The Average color is working correctly. Here is my picture:

enter image description here

What appears to be happening, is my code is deleting any subarray containing a 0. For example the red above has an RGB value as 255,0,0. My code is deleting this. But I only want to delete it if all 3 values are 0!

I got the average to work using np.all, but I can't get this to work with the delete function. Help!

EDIT: Solution seems to be this:

pixelstoignore = np.delete(pixels, np.where((pixels == [0,0,0]).all(axis=1)), axis=0)
Chris Norris
  • 197
  • 1
  • 2
  • 13
  • This looks like a bug in `delete` to me - it should not be accepting a tuple argument. – Eric Jan 27 '19 at 06:26
  • One question though, I understood how to remove the whole row having just zeroes and I've got it, though what I don't get it is, won't that have an issue on your actual image which have to have specific shape? – Amit Amola Jan 27 '19 at 06:30

1 Answers1

2

Do you want to remove pixels where any value is 0, or just ones where all are?

In [212]: arr = np.array([[ 126.,   94.,   51.],
     ...:  [ 171.,  0.,   65.],
     ...:  [ 188.,  119.,   64.],
     ...:  [   1. ,   0.,    0.],
     ...:  [   0. ,   0.,    0.],
     ...:  [   0. ,   1.,    0.]])
     ...:  
     ...:  
In [213]: arr
Out[213]: 
array([[126.,  94.,  51.],
       [171.,   0.,  65.],
       [188., 119.,  64.],
       [  1.,   0.,   0.],
       [  0.,   0.,   0.],
       [  0.,   1.,   0.]])
In [214]: arr == [0,0,0]
Out[214]: 
array([[False, False, False],
       [False,  True, False],
       [False, False, False],
       [False,  True,  True],
       [ True,  True,  True],
       [ True, False,  True]])
In [215]: np.where(arr == [0,0,0])
Out[215]: (array([1, 3, 3, 4, 4, 4, 5, 5]), array([1, 1, 2, 0, 1, 2, 0, 2]))

To test for all in a 'row':

In [216]: (arr == [0,0,0]).all(axis=1)
Out[216]: array([False, False, False, False,  True, False])
In [217]: np.where((arr == [0,0,0]).all(axis=1))
Out[217]: (array([4]),)

In [218]: np.where((arr == [0,0,0]).any(axis=1))
Out[218]: (array([1, 3, 4, 5]),)

Your delete and where is only as good as the conditional inside the where.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • _"our delete and where is only as good as the conditional inside the where"_ it's worse than that - combining `delete` and `where` just always does the wrong thing. `delete` reinterprets the `i, j` tuple returned by `where` as a 2d array of `i` values - the result is just garbage - `np.delete(a, ([1, 2], [3, 4]), 0)` is the same as `np.delete(a, [1, 2, 3, 4], 0)` – Eric Jan 27 '19 at 06:33
  • Thanks man. `pixelstoignore = np.delete(pixels, np.where((pixels == [0,0,0]).all(axis=1)), axis=0)` Seems to do it. – Chris Norris Jan 27 '19 at 21:17
  • I think the above works as the following - `np.where((pixels == [0,0,0]).all(axis=1)) `locates the position in the array where all 3 columns equal 0. `np.delete(, axis=0)` then goes through and deletes the rows that are true. – Chris Norris Jan 27 '19 at 21:25