简体   繁体   English

用颜色填充图像,但保留Alpha(PIL中的颜色叠加)

[英]Fill an image with color but keep the alpha (Color overlay in PIL)

Basically, I'm trying to make a function that will take a given image and a color. 基本上,我正在尝试制作一个将采用给定图像和颜色的函数。 for each pixel in the image, it will keep the original alpha value but will change the color to the given one. 对于图像中的每个像素,它将保留原始的Alpha值,但会将颜色更改为给定的颜色。

for example, if the function gets the arrow image below and the color red, 例如,如果函数获取下面的箭头图像和红色,

原始图像-所有颜色

It will output the following image: 它将输出以下图像:

结果图像-红色

In Photoshop and other image editors, this effect called "color overlay". 在Photoshop和其他图像编辑器中,此效果称为“颜色叠加”。 Is there any quick and easy way of achieving the same result in PIL? 在PIL中是否有任何快速简便的方法来达到相同的结果? Thanks in advance! 提前致谢! (; (;

One way of doing it is to create a solid red image the same size as the original and then copy the alpha channel from the original image across to it: 一种方法是创建与原始尺寸相同的纯红色图像,然后将原始图像的alpha通道复制到该图像上:

from PIL import Image

# Open original image and extract the alpha channel
im = Image.open('arrow.png')
alpha = im.getchannel('A')

# Create red image the same size and copy alpha channel across
red = Image.new('RGBA', im.size, color='red')
red.putalpha(alpha) 

在此处输入图片说明


Here is a second method using Numpy: 这是使用Numpy的第二种方法:

from PIL import Image
import numpy as np

# Open image
im = Image.open('arrow.png')

# Make into Numpy array
n = np.array(im) 

# Set first three channels to red
n[...,0:3]=[255,0,0] 

# Convert back to PIL Image and save
Image.fromarray(n).save('result.png')

A third way is to composite with a similarly-sized red copy and use the original alpha mask: 第三种方法是使用相似大小的红色副本进行合成,并使用原始的Alpha蒙版:

from PIL import Image

# Open image
im = Image.open('arrow.png')                                                                                                       

# Make solid red image same size
red = Image.new('RGBA', im.size, color='red')                                                                                      

# Composite the two together, honouring the original mask
im = Image.composite(red,im,im)  

Keywords : Image, image processing, Python, Pillow, PIL, Numpy, extract alpha, alpha channel, transparency, replace transparency, copy transparency, copy alpha, transplant alpha, transplant transparency. 关键字 :图像,图像处理,Python,Pillow,PIL,Numpy,提取Alpha,Alpha通道,透明度,替换透明度,复制透明度,复制Alpha,移植Alpha,移植透明度。

Let us consider the following image - http://www.libpng.org/pub/png/img_png/globe-scene-fish-bowl-pngcrush.png 让我们考虑以下图像-http: //www.libpng.org/pub/png/img_png/globe-scene-fish-bowl-pngcrush.png

image = cv2.imread("/home/thalish/bleed_test/globe-scene-fish-bowl-pngcrush.png",cv2.IMREAD_UNCHANGED)

image[:,:,0],image[:,:,1],image[:,:,2] = (255,0,0) #to replace all pixels with Red but keep alpha channel unchanged

最终影像

Try: 尝试:

from PIL import Image

# Takes the input image
img = Image.open(r"Arrow.png")

# Getting the dimensions of the image
x, y = img.size

# Obtaining values of Red, Green, Blue for each opaque pixel
red = int(input("Enter the red value you want in each pixel = "))
green = int(input("Enter the green value you want in each pixel = "))
blue = int(input("Enter the blue value you want in each pixel = "))

i = j = 0

# This loop makes sure that alpha only has two discrete values (0 , 255)
# This is to ensure that constant color is obtained, at pixels where transparence may not be 255
# (prevents color escapes at pixels where total transparency is not achieved)
while i < x:
    while j < y:
        r, g, b, a = img.getpixel((i,j))
        if a > 200 and a < 256:
            a = 255
        else:
            a = 0
        img.putpixel((i,j),(r,g,b,a))
        j += 1
    j = 0
    i += 1

i = j = 0

# Two nested loops
# Outer one goes through rows of image
# Inner one (nested one) goes through columns of image
while i < x:
    while j < y:

        # This condition checks, if the value of alpha for that individual pixel is 255 (~opaque), 
        # if true then change its RGB values to user defined values
        if img.getpixel((i,j))[-1] == 255:
            img.putpixel((i,j), (red, green, blue, 255))
        j += 1
    j = 0
    i += 1

img.save("Arrow.png")

INPUT:- 输入: -

Enter the red value you want in each pixel = 0
Enter the green value you want in each pixel = 0
Enter the blue value you want in each pixel = 255

OUTPUT:- 输出: -

EXPLANATION FOR THE FIRST LOOP:- 解释第一圈:-

If the first loop doesn't flat out, the alpha values by a threshold, then a lot of error gets produced in the output image. 如果第一个循环的alpha值没有达到阈值,那么在输出图像中会产生很多错误。 ie Pixel values near the edge of a object tends to have alpha pixel values a little lesser than 255 (total opacity) to enable smooth anti-aliasing . 即,靠近对象边缘的像素值倾向于具有比255 (总不透明度)小一点的alpha像素值,以实现平滑的抗锯齿效果 If these pixels are discarded then output image may look something like this:- 如果这些像素被丢弃,则输出图像可能看起来像这样:

注意箭头边缘的不需要的颜色

PS:- Even though OpenCV would be the preferred choice for most Image Analysts/Experts, I would definitely advice you to stick with PIL/Pillow at the beginning, as it allows you to get the grasp the fundamentals of imaging in a really friendly way. PS:-尽管OpenCV是大多数图像分析师/专家的首选,但我绝对会建议您一开始就坚持使用PIL / Pillow,因为它可以使您以一种非常友好的方式掌握成像的基础知识。 There is no denying that OpenCV far outweighs PIL in almost every aspect, but still if you learn PIL in the beginning, transitioning from PIL to OpenCV would be alot easier for you to do later on. 不可否认,OpenCV在几乎所有方面都远远超过了PIL,但是,即使您一开始就学习PIL,从PIL过渡到OpenCV也会很容易在以后进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM