Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
286 views
in Technique[技术] by (71.8m points)

python imaging library - How to Access and Change Color Channels using PIL?

I'm trying to access the RGB color channels of an image using PIL, and then change the color intensity of the color channel of the entire image at once.

When I say RGB color channels, here is an online example.

I don't understand if this has to be done on a pixel by pixel basis or not.

I image the logic of the code would look like this:

import PIL
from PIL import Image
image=Image.open("my_pic.gif")
image=image.convert('RGB')
# made up function
channel_values = image.get_channel_values()
#channel_values = i.e. (50, 100, 50)
# do some math function to transform channel_values
channel_values = (95,125,75)
image.update_channel_value('R',channel_values)
display(image.getchannel('R'))

This answer is the only one that comes close, but it is way too complicated for what I'm trying to do.

I've searched the PIL docs, etc. for a couple of hours but can't seem to get anywhere.

Here's how far I've gotten:

import PIL
from PIL import Image
image=Image.open("my_pic.gif")
image=image.convert('RGB')
display(image.getchannel('R'))

The problem is the image.getchannel() only returns a grey/black & white image.

I not only want to access the color channel value, I want to change it too.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If, for example, you want to multiply all pixels in the red channel by 1.2, and all the green pixels by 0.9, you have several options....


Split the image into Red, Green and Blue channels, upscale the Red channel and recombine:

from PIL import Image
im = Image.open('image.jpg').convert('RGB')

# Split into 3 channels
r, g, b = im.split()

# Increase Reds
r = r.point(lambda i: i * 1.2)

# Decrease Greens
g = g.point(lambda i: i * 0.9)

# Recombine back to RGB image
result = Image.merge('RGB', (r, g, b))

result.save('result.png')

See "Processing Individual Bands" here.


Or, use a matrix to transform the channels:

from PIL import Image 

# Open image 
im = Image.open('image.jpg') 

# Make transform matrix, to multiply R by 1.1, G by 0.9 and leave B unchanged
# newRed   = 1.1*oldRed  +  0*oldGreen    +  0*oldBlue  + constant
# newGreen = 0*oldRed    +  0.9*OldGreen  +  0*OldBlue  + constant
# newBlue  = 0*oldRed    +  0*OldGreen    +  1*OldBlue  + constant
Matrix = ( 1.1,   0,  0, 0, 
           0,   0.9,  0, 0, 
           0,     0,  1, 0) 

# Apply transform and save 
im = im.convert("RGB", Matrix) 
im.save('result.png') 

Or, convert to Numpy array, do some processing and convert back to PIL Image:

from PIL import Image 

# Open image 
im = Image.open('image.jpg') 

# Make into Numpy array of floats
na = np.array(im).astype(np.float)

# Multiply all red values by 1.1
na[...,0] *= 1.1

# Reduce green values
na[...,1] *= 0.9

# You may want to use "np.clip()" here to ensure you don't exceed 255

# Convert Numpy array back to PIL Image and save
pi = Image.fromarray(na.astype(np.uint8))
pi.save('result.png') 

This option has the added benefit that the Numpy arrays can be intermixed and processed with OpenCV, scikit-image, vips, wand and other libraries to get MUCH more sophisticated processing done - morphology, granulometry, video processing, SIFT, object tracking...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...