1

I'm developing a small software for a college project and I'm having a problem: The code has a way too low performance.

It's an image editing software, and the image is a larg 3d list (the main list is the whole image, each list inside it is an horizontal line and each list inside that one is a pixel, containing three elements).

I need to make pixel-by-pixel adjustments, like multiplying all of them by a constant, so it would go like

for y in range(0,len(image)): 
    for x in range (0,len(image[0])):
        for c in range (0,3):
            im[y][x][c] = (im[y][x][c])*a

Where image is the 3d list
len(image) is the amount of horizontal lines in the image (vertical size)
len(image[0]) is the amount of pixels in a horizontal line (horizontal size)
and c is the component of the pixel (going from 0 to 2).

This loop takes several minutes to go through a single 12 MP image and the amount of images I have to process is in the order of the hundreds, so this is just impossible.

What can I do to get a greater performance? Even editing softwares take some seconds because it can be a pretty large operation, but this code is just too slow.

Thank you!

Torxed
  • 22,866
  • 14
  • 82
  • 131
user2934303
  • 111
  • 3
  • 1
    This question most likely belongs on https://codereview.stackexchange.com/ – Torxed Nov 01 '18 at 06:19
  • Why not use specilaized libraries like `OpenCV` or `PIL`? If it is prohibited, consider using `NumPy` arrays - they are significantly faster than lists – MBo Nov 01 '18 at 06:24
  • The problem here is that you need to iterate over each pixel. And this is a classical example of where you most likely want to use a library specifically designed for this kind of task. [python-pillow (PIL)](https://pillow.readthedocs.io/en/5.3.x/) is a good start, others are [python-numpy](http://www.numpy.org/) for data structures or [pandas](https://stackoverflow.com/questions/49649215/pandas-image-to-dataframe). – Torxed Nov 01 '18 at 06:25
  • Well, my pixel manipulation functions are custom, I don't know if i'm going to find them anywhere else, but, there is in fact one case that is simple which is this one I used in this post, just multiplying by a constant. But I didn't create the list, it's the tifffile module that does that in this way. – user2934303 Nov 01 '18 at 06:37

1 Answers1

0

I also (as in the comments) suggest using Numpy. Sample code would be something like this:

import numpy as np

im = np.array(image,dtype="float16")

# Define your custom function
def myFunc(x,a):
    x = x * a
    return x

# Vectorise function
vfunc = np.vectorize(myFunc)

# Apply function to the array with the parameter a = 5
im = vfunc(im,5)

I compared timings for a vectorized numpy function and nested loops for an array of the size roughly eqivalent to a 12MP image: 4242 x 2828 x 3.

Nested loops took 99 second, while numpy took about 6.5 secs.

For your reference here is a question about numpy functions efficiency: Most efficient way to map function over numpy array

For simple functions like multiplication using numpy native functions is the fastest.

# Multiply each element by 5
im = im * 5

This code took only 0.5 sec on my machine.

Peter
  • 11
  • 3