Reputation: 763
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.
Upvotes: 2
Views: 1520
Reputation: 153
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()
Upvotes: 3
Reputation: 46530
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
Upvotes: 4
Reputation: 1172
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.
Upvotes: 1