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?

Stephen Rauch
4,31412 gold badges24 silver badges36 bronze badges
asked Apr 23, 2018 at 12:18
\$\endgroup\$
3
  • \$\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\$ Commented Apr 23, 2018 at 12:21
  • 1
    \$\begingroup\$ Do you really need counter and counter2? \$\endgroup\$ Commented Apr 23, 2018 at 12:23
  • \$\begingroup\$ Actually not, I could use np.count_nonzero on image_new at the end...Good point! \$\endgroup\$ Commented Apr 23, 2018 at 12:31

1 Answer 1

8
\$\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
answered Apr 23, 2018 at 12:42
\$\endgroup\$
4
  • \$\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\$ Commented Apr 23, 2018 at 13:02
  • \$\begingroup\$ The rest of the image1 contain pixel with values of 255 but they should be excluded in the count. \$\endgroup\$ Commented Apr 23, 2018 at 13:04
  • 2
    \$\begingroup\$ Added counter2, this isn't the cleanest way of doing this but it works pretty efficiently \$\endgroup\$ Commented Apr 23, 2018 at 13:06
  • 2
    \$\begingroup\$ ~ 300x speed up, nice! \$\endgroup\$ Commented Apr 23, 2018 at 14:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.