10
\$\begingroup\$

I have the following code which iterates over all pixels of an image and does some manipulations on two images of the same size. I would like to speed it up and to avoid iterating over the positions in a for loop:

import numpy as np
import cv2

# Two images of same size 
image_in = cv2.imread('my_image.png')
image_in2 = cv2.imread('my_image2.png')
image_new = np.ones(image_in.shape[:2], dtype="uint8") * 255

counter = 0
counter2 = 0

for i in range(image_in.shape[0]):
    for j in range(image_in.shape[1]):
        if image_in[i, j] < 255:
            counter += 1
            if image_in2[i, j] == 0:
                image_new[i, j] = 0
            else:
                image_new[i, j] = 255
                counter2 += 1

How can I improve my code?

\$\endgroup\$
  • \$\begingroup\$ I simply threshold my image. If the pixel values are greater of smaller then a threshold, the pixel value of a new image should be set to 0 or 1. \$\endgroup\$ – snowflake Apr 23 '18 at 12:21
  • 1
    \$\begingroup\$ Do you really need counter and counter2? \$\endgroup\$ – Peilonrayz Apr 23 '18 at 12:23
  • \$\begingroup\$ Actually not, I could use np.count_nonzero on image_new at the end...Good point! \$\endgroup\$ – snowflake Apr 23 '18 at 12:31
9
\$\begingroup\$

I think the trick is trying to vectorise this as much as possible:

By the look of it, the code is trying to threshold at 0 and count pixels under 255.

We can change the first part of the loop to:

counter = np.sum(image_in < 255) # Sums work on binary values
counter2 = np.sum(np.bitwise_and(image_in < 255, image_in2 != 0)) 

And the second to:

# This is 0 or 1 depending on whether it is == 0
image_new[:,:] = (image_in2 != 0) # image_new[i,j] = (image_in2[i,j] != 0)

# So scale the values up with a simple multiplcation
image_new = image_new*255 # image_new[i,j] = image_new[i,j]*255
\$\endgroup\$
  • \$\begingroup\$ But how do I get the value of the second counter, it should count only pixels with values of 255 where the same position of image2 has the value 0. \$\endgroup\$ – snowflake Apr 23 '18 at 13:02
  • \$\begingroup\$ The rest of the image1 contain pixel with values of 255 but they should be excluded in the count. \$\endgroup\$ – snowflake Apr 23 '18 at 13:04
  • 2
    \$\begingroup\$ Added counter2, this isn't the cleanest way of doing this but it works pretty efficiently \$\endgroup\$ – gbartonowen Apr 23 '18 at 13:06
  • 2
    \$\begingroup\$ ~ 300x speed up, nice! \$\endgroup\$ – snowflake Apr 23 '18 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.