1

I have an image that I want to perform some calculations on. The image pixels will be represented as f(x, y) where x is the column number and y is the row number of each pixel. I want to perform a calculation using the following formula:

enter image description here

Here is the code that does the calculation:

import matplotlib.pyplot as plt
import numpy as np
import os.path
from PIL import Image

global image_width, image_height


# A. Blur Measurement
def  measure_blur(f):

    D_sub_h = [[0 for y in range(image_height)] for x in range(image_width)]

    for x in range(image_width):
        for y in range(image_height):
            if(y == 0):                
                f_x_yp1 = f[x][y+1]
                f_x_ym1 = 0 
            elif(y == (image_height -1)):

                f_x_yp1 = 0
                f_x_ym1 = f[x][y -1]
            else:                
                f_x_yp1 = f[x][y+1]
                f_x_ym1 = f[x][y -1]

            D_sub_h[x][y] = abs(f_x_yp1 - f_x_ym1)

    return D_sub_h

if __name__ == '__main__':

    image_counter = 1

    while True:

        if not os.path.isfile(str (image_counter) + '.jpg'):
            break

        image_path = str(image_counter) + '.jpg'
        image = Image.open(image_path )
        image_height, image_width = image.size

        print("Image Width : " + str(image_width))
        print("Image Height : " + str(image_height))

        f = np.array(image)
        D_sub_h = measure_blur(f)
        image_counter = image_counter + 1

The problem with this code is when the image size becomes large, such as (5000, 5000), it takes a very long time to complete. Is there any way or function I can use to make the execution time faster by not doing one by one or manual computation?

6
  • Have a look at numba - it uses your graphics card to do the computations. Commented Mar 26, 2020 at 18:01
  • 1
    f[2:, :] - f[:-2, :] should do it Commented Mar 26, 2020 at 18:03
  • @cup - I dont have a graphics card :( Commented Mar 26, 2020 at 18:05
  • 1
    You might need some zero padding, so using np.subtract with an out buffer might help, or you can just concatenate with the pad Commented Mar 26, 2020 at 18:06
  • 1
    I missed the one by one or manual computation Commented Mar 26, 2020 at 18:13

1 Answer 1

1

Since you specifically convert the input f to a numpy array, I am assuming you want to use numpy. In that case, the allocation of D_sub_h needs to change from a list to an array:

D_sub_h = np.empty_like(f)

If we assume that everything outside your array is zeros, then the first row and last row can be computed as the second and negative second-to-last rows, respectively:

D_sub_h[0, :] = f[1, :]
D_sub_h[-1, :] = -f[-2, :]

The remainder of the data is just the difference between the next and previous index at each location, which is idiomatically computed by shifting views: f[2:, :] - f[:-2, :]. This formulation creates a temporary array. You can avoid doing that by using np.subtract explicitly:

np.subtract(f[2:, :], f[:-2, :], out=D_sub_h[1:-1, :])

The entire thing takes four lines in this formulation, and is fully vectorized, which means that loops run quickly under the hood, without most of Python's overhead:

def measure_blur(f):
    D_sub_h = np.empty_like(f)
    D_sub_h[0, :] = f[1, :]
    D_sub_h[-1, :] = -f[-2, :]
    np.subtract(f[2:, :], f[:-2, :], out=D_sub_h[1:-1, :])
    return D_sub_h

Notice that I return the value instead of printing it. When you write functions, get in the habit of returning a value. Printing can be done later, and effectively discards the computation if it replaces a proper return.

The way shown above is fairly efficient with regards to time and space. If you want to write a one liner that uses a lot of temporary arrays, you can also do:

D_sub_h = np.concatenate((f[1, None], f[2:, :] - f[:-2, :], -f[-2, None]), axis=0)
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.