2
votes

I'm using Python, OpenCV and Numpy to read a black and white image. I then iterate over each pixel using numpy.nditer and either change the pixel to 255 (if it is greater than 128), or change it to 0. Through some testing, I think I have that part right. What I cannot figure out is how to use cv2.imshow to 'show' the altered image. Currently, it only seems to show the original image.

    import cv2
    import numpy as np
    image = cv2.imread('someimage', cv2.IMREAD_GRAYSCALE)

    it = np.nditer(image)
    for (x) in it:
        if x > 128:
            x = 255
        else:
            x = 0

    cv2.imshow('image',image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Thank you for any advice.

3

3 Answers

3
votes

The best way is probably to use the threshold function from opencv. Opencv functions are often faster than numpy functions.

import cv2

image = cv2.imread('someimage', cv2.IMREAD_GRAYSCALE)

ret, image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)

cv2.imshow("Threshold image", image)
cv2.waitKey(-1)
cv2.destroyAllWindows()
4
votes

You may want to look into the np.where function:

image[:] = np.where(image > 128, 255, 0)

You really shouldn't be looping through arrays unless absolutely necessary:

In [16]: %%timeit
   ....: a = np.random.randint(0, 255, (800,600))
   ....: a[:] = np.where(a > 128, 255, 0)
   ....:
10 loops, best of 3: 27.6 ms per loop

In [17]: %%timeit
   ....: image = np.random.randint(0, 255, (800,600))
   ....: it = np.nditer(image, op_flags=['readwrite'])
   ....: for (x) in it:
   ....:     if x > 128:
   ....:         x[...] = 255
   ....:     else:
   ....:         x[...] = 0
   ....:
1 loops, best of 3: 1.26 s per loop
1
votes

Try:

it = np.nditer(image, op_flags=['readwrite'])
for (x) in it:
    if x > 128:
        x[...] = 255
    else:
        x[...] = 0

From http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html - by default assigning to elements in the iterator will just change their reference, rather than modify the original array. We have to specify the readwrite flag, and include the ellipsis.