Tyler Silva
Tyler Silva

Reputation: 421

selecting rgb image pixels satisfying multiple conditions in numpy

I'm attempting to do video processing, and I want to be able to efficiently get all of the pixels with red above 100, green below 100, and blue below 100. I managed to do it with a for loop and doing 3 evaluations on each pixel, but that was too slow and took 13 seconds per frame. I currently am using cv2 to get the image, and have the processing code of

retval = np.delete(frame, (0, 1), 2) #extracts just red of the pixels
retval = np.argwhere(retval>100) #extracts where red is above 100
retval = np.delete(retval, 2, 1) #removes the actual color value, leaving it as coordinates

This leaves me with a partial solution to anything that has a red value of above 100, but it also includes things like brown, and white, which is not ideal. This loop needs to happen extremely fast, which is why I want to use numpy, but I'm not sure what commands to use. Any help would be greatly appreciated. the "frame" array is structured like this and is formatted BGR, not RGB. the first index is the x coordinate, the second index is the y coordinate, and the third index is 0, 1, or 2, corresponding to blue, green, and red.

[[[255,   0,   0],
  [255,   0,   0],
  [255,   0,   0],
  ...,
  [  8,  20,   8],
  [ 12,  15,  20],
  [ 16,  14,  26]],

  [[255,   0,   0],
  [ 37,  27,  20],
  [ 45,  36,  32],
  ...,
  [177, 187, 157],
  [180, 192, 164],
  [182, 193, 167]]]

Upvotes: 2

Views: 2814

Answers (1)

kevinkayaks
kevinkayaks

Reputation: 2726

Try it by making three boolean masks, one for each condition, and then merging them with np.logical_and

im = #define the image suitably 
mask = np.logical_and.reduce((im[:,:,0]<100,im[:,:,1]<100,im[:,:,2]>100))
im[mask] # returns all pixels satisfying these conditions

This is fast. It is based upon two numpy capabilities: broadcasting and masking. You can and should read about these in the numpy documentation. You only need for loops for relatively complex tasks.

edit:

if you want the indices of the pixels, do

i,j = np.where(mask)

Then the pixel values are

im[i,j] 

Upvotes: 1

Related Questions