## Thought this was cool: Fast Array Manipulation in Numpy

*You have a 500×500 numpy array of random integers between 0 and 5, ie only 0,1,2,3,4 (just consider you got it as a result of some calculations). These integers actually correspond to different colors like below:*

*0 —> Green, [0,255,0]*

*1 —> Blue, [255,0,0] // Note that according to OpenCV standards, it is BGR, not RGB*

*2 —> Red , [0,0,255]*

*3 —> White, [255,255,255]*

*4 —> Black, [0,0,0]*

*So you want to create another 500x500x3 array (or a color image) where integers in x is replaced by corresponding color value.*

First of all we deal with our normal method, which is direct indexing method.

What we normally do? Yes, a double loop.

**Method 1 : Direct element access**

for i in x.rows:

for j in x.cols:

check what value at x[i,j]

put corresponding color in y[i,j]

So that is given below:

First create necessary data, input array ‘x’, output array ‘y’, colors etc.

import numpy as np

import time

x = np.random.randint(0,5,(500,500))

green = [0,255,0]

blue = [255,0,0]

red = [0,0,255]

white = [255,255,255]

black = [0,0,0]

rows,cols = x.shape

y = np.zeros((rows,cols,3),np.uint8) # for output

Now enter the loop:

for i in xrange(rows):

for j in xrange(cols):

k = x[i,j]

if k==0:

y[i,j] = green

elif k==1:

y[i,j] = blue

elif k==2:

y[i,j] = red

elif k==3:

y[i,j] = white

else:

y[i,j] = black

**Method 2 : Using item() and itemsize()**

for i in xrange(rows):

for j in xrange(cols):

k = x.item(i,j)

if k==0:

y1.itemset((i,j,0),green[0])

y1.itemset((i,j,1),green[1])

y1.itemset((i,j,2),green[2])

elif k==1:

y1.itemset((i,j,0),blue[0])

y1.itemset((i,j,1),blue[1])

y1.itemset((i,j,2),blue[2])

elif k==2:

y1.itemset((i,j,0),red[0])

y1.itemset((i,j,1),red[1])

y1.itemset((i,j,2),red[2])

elif k==3:

y1.itemset((i,j,0),white[0])

y1.itemset((i,j,1),white[1])

y1.itemset((i,j,2),white[2])

else:

y1.itemset((i,j,0),black[0])

y1.itemset((i,j,1),black[1])

y1.itemset((i,j,2),black[2])

**9-10x faster than the previous method**. And that is good result, although length of code is a little problem.

**palette method**.

**Method 3 : Palette method**

Here, there is no loop. Just three lines of code:

color = [green,blue,red,white,black]

color = np.array(color,np.uint8)

y = color[x]

**Compared to first method, it is around 350x faster.Compared to second method, it is around 30-40x faster.**

Fist take an array of size 3×3 and elements includes only digits (0-9):

>>> a = np.random.randint(0,10,(3,3))

>>> a

array([[9, 8, 4],

[9, 0, 8],

[6, 6, 3]])

>>> b = np.random.randint(0,255,10)

>>> b

array([ 97, 177, 237, 29, 51, 230, 92, 198, 6, 7])

>>> c = b[a]

>>> c

array([[ 7, 6, 51],

[ 7, 97, 6],

[92, 92, 29]])

res = np.int0(np.around(res))

mini = res.min()

minie = 255.0/mini

maxi = res.max()

maxie = 255.0/maxi

drawing = np.zeros((maxi-mini+1,3),np.uint8)

res = res+abs(mini)

for h,i in enumerate(xrange(mini,maxi+1)):

if i<0:

drawing.itemset((h,0),255-int(minie*i))

elif i>0:

drawing.itemset((h,2),255-int(maxie*i))

else:

drawing[h]=[255,255,255]

Now finally apply the palette.

d = drawing[res]

Results in palette method. |

Result in normal method |

Hope, you enjoyed it. Let me have your feedback.

Regards,

ARK

from OpenCV-Python: http://opencvpython.blogspot.com/2012/06/fast-array-manipulation-in-numpy.html

## 发表评论