Reputation: 37
In the following piece of code, the 2 for loops take about .05s to complete on average. data
is a numpy array. Each i, j cell contains a tuple that holds the RGB values as defined by those functions. I am later building up an image using those RGB values and i, j
are x, y
pixel coordinates.
Is there any way to reduce the time of this operation? Or is there any other faster way that I build up an image by specifying the RGB values of each pixels as some sort of mathematical functions?
start = time.time()
for i in range (0, 150):
for j in range(0, 150):
data[i,j] = [int(math.sin(math.pi*i/300.0)*127.5 + 127.5),
int(math.cos(peak)*127.5 + 127.5),
int(math.sin(math.pi*j/300.0)*127.5 + 127.5)]
print ('Time: ', time.time() - start)```
Upvotes: 1
Views: 59
Reputation: 51185
You can remove all the loops here using ogrid
and instead just use three calculations, one for r
, g
, and b
.
x, y, z = data.shape
i, j = np.ogrid[:x, :y]
data[..., 0] = (np.sin(np.pi*i/300)*127.5 + 127.5).astype(int)
data[..., 1] = (np.cos(peak)*127.5 + 127.5).astype(int)
data[..., 2] = (np.sin(np.pi*j/300)*127.5 + 127.5).astype(int)
Performance
def rgb_vectorized(x, y, peak=1):
data = np.empty((x, y, 3), dtype=int)
i, j = np.ogrid[:x, :y]
data[..., 0] = (np.sin(np.pi*i/300)*127.5 + 127.5).astype(int)
data[..., 1] = (np.cos(peak)*127.5 + 127.5).astype(int)
data[..., 2] = (np.sin(np.pi*j/300)*127.5 + 127.5).astype(int)
return data
def rgb_original(x, y, peak=1):
data = np.empty((x, y, 3), dtype=int)
for i in range (x):
for j in range(y):
data[i,j] = [int(math.sin(math.pi*i/300.0)*127.5 + 127.5),
int(math.cos(peak)*127.5 + 127.5),
int(math.sin(math.pi*j/300.0)*127.5 + 127.5)]
return data
%timeit rgb_vectorized(1000, 1000)
9.85 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit rgb_original(1000, 1000)
3.4 s ± 27.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Validation
>>> np.array_equal(rgb_vectorized(1000, 1000), rgb_original(1000, 1000))
True
Upvotes: 3