简体   繁体   中英

Applying tuple operations element-wise to a numpy array of tuples

I'm working with a 2d array of "pixels" (rgb int tuples), and I need an efficient way to apply some numpy operations to each element. Specifically, I'm trying to find pixels within a few color shades of a goal colour to later isolate them with numpy.nonzero

Using For loops is for this case takes tens of seconds, so I'm looking to apply the numpy operations element-wise to achieve the same result.

I'm looking to apply

Tuple subtraction :

pixel_diff = numpy.subtract( pixel_a, pixel_b) 

Tuple absolute value:

pixel_abs = numpy.abs( pixel_diff )

Tuple comparison:

pixel_bool = pixel_abs < int_tolerance

Tuple all ():

is_similar = numpy.all(pixel_bool)

Trying to apply any of these operations blindly to my array results in invalid promotion errors, so I figure there must be a proper way to do it, instead.

   import numpy as np
   #create a RGB array of 1000x1000x3 and separate into colors
   R, G, B = np.random.randint(0, 255, size = (1000, 1000, 3))
   #find all pixels less than 100, 100, 100
   np.logical_and((R<100), (G<100), (B<100))

You may modify the last line to suit your color needs. As is, the last line takes about 1.5 ms on a single core.

You can convert into an equivalent non-structured view (without incurring any additional cost of making a copy of the underlying data):

my_3dview_of_ints = my_2d_of_3tuples.view(dtype=int)

where my_2d_of_3tuples is your current structured array (array of tuples)

You can then perform your usual numpy array operations on this view without running into any type errors.

For example, if your array looks like this:

 [[(207,  27, 185) ( 90, 197,  52) ( 58, 153, 145) (239,  42,  39)]
 [(218,  23, 195) (226,  92, 170) ( 21, 114, 190) (192, 145,  48)]]

then the view, as created above, would look like this:

[[[207  27 185]
  [ 90 197  52]
  [ 58 153 145]
  [239  42  39]]

 [[218  23 195]
  [226  92 170]
  [ 21 114 190]
  [192 145  48]]]

For example:

pixel_a = my_3dview_of_ints[0,0] # pixel [207,27,185] at [0,0]
pixel_b = my_3dview_of_ints[1,1] # pixel [226,92,170] at [1,1]

pixel_diff = numpy.subtract( pixel_a, pixel_b) # Gives [-12,-65,5]

You can even change specific elements in the view, and the changes would automatically reflect at the corresponding location in your original structured array:

my_3dview_of_ints[3,3] = pixel_a # Assign [207, 27,185] to location [3,3]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM