0

I have an numpy array I which stores N images of size P (number of pixels). Every image is of size P = q*q.

N = 1000 # number of images
q = 10 # length and width of image
P = q*q # pixels of image
I = np.ones((N,P)) # array with N images of size P

Now I want to delete patches of size ps around a selected index IDX (set all values to zero).

ps = 2 # patch size (ps x ps)
IDX = np.random.randint(0,P,(N,1))

My approach was to reshape every single image using reshape(q,q) and delete the pixels around IDX. Here I have the problem, that I do not know how to compute the position inside the image given IDX. Additionally I have to check if the index is not outside the image.

How to tackle this problem and is there any way to vectorize this procedure?

EDIT:

With the help of @Brenlla I did the following to remove patches. The problem with my approach is, that it needs three for-loops, and I have to reshape every image twice. Is there any way to increase the performance? This part slows down my code significantly.

import numpy as np
import matplotlib.pyplot as plt

def myplot(I):
    imgs = 10
    for i in range(imgs**2):
        plt.subplot(imgs,imgs,(i+1))
        plt.imshow(I[i].reshape(q,q), interpolation="none")
        plt.axis("off")
    plt.show()

N = 10000
q = 28
P = q*q
I = np.random.rand(N,P)

ps = 3
IDX = np.random.randint(0,P,(N,1))

for i in range(N):
    img = I[i].reshape(q,q)
    y0, x0 = np.unravel_index(IDX[i,0],(q,q))
    for x in range(ps):
        for y in range(ps):
            if (x0+x < q) and (y0+y < q):
                img[x0+x,y0+y] = 2.0
    I[i] = img.reshape(1,q*q)

myplot(I)
4
  • Before jumping to find a vectorized method, work on a loopy solution? Commented Jun 6, 2018 at 15:35
  • I tried that already but got stuck at the point where I have to find the coordinate (x,y) in the image given an index from IDX. I also omitted this problem and found, that it takes ages to do it this way. Commented Jun 6, 2018 at 15:40
  • To find the coordinate (x,y), you can just np.unravel_index(IDX, (q,q)) Commented Jun 6, 2018 at 15:48
  • @Brenlla Great! I did not know that. I will try that and update my question. Commented Jun 6, 2018 at 21:36

1 Answer 1

2

Yes, that can be done, but it involves heavy use of np.broadcasting.

Generate data plus a hard copy of I:

import time

N = 10000
q = 28
P = q*q
ps = 3 
I = np.random.rand(N,P)
IDX = np.random.randint(0,P,(N,1))
I_copy = I.copy()

And now run the loop solution. I switched x0 and y0:

t0=time.clock()
for i in range(N):
    img = I[i].reshape(q,q)
    x0, y0 = np.unravel_index(IDX[i,0],(q,q))
    for x in range(ps):
        for y in range(ps):
            if (x0+x < q) and (y0+y < q):
                img[x0+x,y0+y] = 2.0
    I[i] = img.reshape(1,q*q)
print('With loop: {:.2f} ms'.format(time.clock()*1e3-t0*1e3))

Approx. 276 ms on my machine. Now the broadcasting:

t0 = time.clock()
x_shift, y_shift = np.meshgrid(range(ps), range(ps))
x, y = np.unravel_index(IDX, (q,q))
#roi for region of interest
roix = x[:,:,None]+x_shift; 
roiy = y[:,:,None]+y_shift;
roix[roix>q-1] = q-1; roiy[roiy>q-1] = q-1;
I_copy.reshape(N,q,q)[np.arange(N)[:, None, None], roix, roiy] = 2.0

print('No loop: {:.2f} ms'.format(time.clock()*1e3-t0*1e3))

print(np.array_equal(I, I_copy))

Roughly 80x faster

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.