I want to apply Arnold cat map on an image. I manage this code from Wikipedia but it was getting slow when I increase the iteration number like for 600 by 600 image with 83 iteration it took time=567.8921346664429 second. Can any improvement possible for this code. I guess the looping things make this code very slow, O(n^2) for every iteration.
from PIL.Image import open as load_pic, new as new_pic
def main(path, iterations, keep_all=False, name="arnold_cat-{name}-{index}.png"):
"""
Params
path:str
path to photograph
iterations:int
number of iterations to compute
name:str
formattable string to use as template for file names
"""
title = os.path.splitext(os.path.split(path)[1])[0]
counter = 0
while counter < iterations:
with load_pic(path) as image:
dim = width, height = image.size
with new_pic(image.mode, dim) as canvas:
for x in range(width):
for y in range(height):
nx = (2 * x + y) % width
ny = (x + y) % height
canvas.putpixel((nx, height-ny-1), image.getpixel((x, height-y-1)))
if counter > 0 and not keep_all:
os.remove(path)
counter += 1
print(counter, end="\r")
path = name.format(name=title, index=counter)
canvas.save(path)
return canvas
I modify the code for my use case like this:
def cat_map(image_matrix,MAX):
dim = width, height = image_matrix.shape
transformed_matrix = np.zeros((width,height))
# Apply Arnold cat map on image_matrix
index = []
counter = 0
iterations = MAX
# collect initial index of the image_matrix
for i in range(len(image_matrix)):
for j in range(len(image_matrix[0])):
index.append([i,j])
forward_index = []
while counter < iterations:
for coordinate in index:
x = coordinate[0]
y = coordinate[1]
new_x = (2 * x + y) % width
new_y = (x + y) % height
transformed_matrix[new_x][new_y] = image_matrix[x][y]
forward_index.append([new_x,new_y])
index = forward_index
# apply recursive transformation on image_matrix
image_matrix = transformed_matrix
# only store the last index matrix
if counter != iterations - 1:
forward_index = []
# re-initialize transformation matrix
transformed_matrix = np.zeros((width,height))
counter += 1
return transformed_matrix,forward_index
I need the index_array of the last iteration also. I appreciated the vectorized idea of @dankal444 but then how to store the index array?