Question

I have an image ( gotten using img = ImageGrab.grab( box ) ) and I wish to replace all pixels of a certain RGB value (precisely rgb(74,38,63)) with white and the rest with black.

The problem is that the image is in RGB, if it was in a single band (as i had earlier in the program) I could just use : img2 = img.point (lambda i: i>254 and 255); but this does not work with the rgb image, the i in the img.point doesn't seem to be a tuple of 3 ints (as I'd hoped it'd be) it's just the numbers 0 to 255 (if i didn't mess up somewhere).



Note, I don't want to use the .getpixel() method as it's too slow for what I want to do.

One alternative for my problem is using img.load() then working through the matrix of pixels myself, but I don't know how efficient this is.

Was it helpful?

Solution

Numpy works very well for generalized fast and specific pixel manipulation. Here's an example:

enter image description here

import Image
import numpy as np
import matplotlib.pyplot as plt

im = Image.open("python.jpg")
a = np.asarray(im)

b = np.where(np.all(((a>[240, 40, 20]) * (a<=[255, 255, 150])), axis=2, keepdims=True), [80,0,0], [0,0,90])

plt.figure()
plt.subplot(1,2,1)
plt.imshow(a)
plt.subplot(1,2,2)
plt.imshow(b)
plt.show()

Here I converted a range of pixel values rather than a single value. To do a single value, remove the use == rather than >, and only use one condition. Also, I used matplotlib for an easy way to show the output and input together, but you could also convert back to an image using Image.fromarray(b.astype(np.uint8)).

Staying in pure PIL will work fine if you want to apply some simple standard filters, or use local getpixel operations, but for most numerical work with images, numpy or an image processing package is the way to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top