使用Python图像库将一个图像中的黑色像素叠加到另一个图像上

使用Python图像库将一个图像中的黑色像素叠加到另一个图像上,python,Python,H正如我的名字所暗示的那样,我对代码是新手,我正在使用Python,并且非常感谢使用Python映像库来完成一项任务 我有2个位图图像。第一个图像是彩色绘画,第二个图像只包含黑白像素。。。 我想开发一个函数,它接受两个图像作为参数来创建一个新的图像,基本上是第一个图像(绘画),只有第二个图像的黑色像素被覆盖。第二个图像比第一个图像小,被覆盖的像素需要定位在新图像的中心 我已经安装了PIL,并且能够使用以下代码使用以下代码成功显示第一个图像: import PIL from PIL import

H正如我的名字所暗示的那样,我对代码是新手,我正在使用Python,并且非常感谢使用Python映像库来完成一项任务

我有2个位图图像。第一个图像是彩色绘画,第二个图像只包含黑白像素。。。 我想开发一个函数,它接受两个图像作为参数来创建一个新的图像,基本上是第一个图像(绘画),只有第二个图像的黑色像素被覆盖。第二个图像比第一个图像小,被覆盖的像素需要定位在新图像的中心

我已经安装了PIL,并且能够使用以下代码使用以下代码成功显示第一个图像:

import PIL
from PIL import Image

painting = Image.open("painting.bmp")
painting.show()
我已经排除了使用ImageChops模块中的.blend和.composite函数或.multiply函数,因为图像大小不同

我相信我需要使用.getpixel/.putpixel或.getdata/.putdata来查找由tuple(0,0,0)标识的黑色像素。 此外,我认为PIL的裁剪和粘贴功能应该有助于计算出绘画中的“区域”以覆盖黑色像素,并且可以帮助将黑色像素置于绘画的中心

所以我在看这样的东西也许

def overwrite_black(image1, image2): 

image_1 = Image.open('painting.bmp') 
image_2 = Image.open('black_white.bmp') 
pixels = list(image_2.getdata())

for y in xrange(image_2.size[1]):
    for x in xrange(image_2.size[0]):
        if pixels ==(o,o,o):
          image_2.putdata(pixels((x,y),(0,0,0)))

image_2.save('painted.bmp')
再说一次,我是新来的,所以请对我宽容一点,任何帮助都将不胜感激


干杯。

所以我假设你只想将两张图像相乘,问题是它们的大小不同?如果我误解了,请原谅,这里有一些代码可以将一个图像的黑色像素放到另一个图像上,即使黑白图像比另一个图像小

源图像(
painting.bmp
mask.bmp

输出:

“…基本上是第一幅图像(绘画)的新图像,只有第二幅图像的黑色像素被覆盖。”-这是你想要的吗


本质上,代码只是通过将较小的图像放在与第一个图像大小相同的空白图像中心,使其与第一个图像一样大

import PIL
from PIL import Image
from PIL import ImageChops # used for multiplying images

# open images
painting = Image.open("painting.bmp")
mask     = Image.open("mask.bmp")


def black_onto(img1, img2):  
    # create blank white canvas to put img2 onto
    resized = Image.new("RGB", img1.size, "white")

    # define where to paste mask onto canvas
    img1_w, img1_h = img1.size
    img2_w, img2_h = img2.size
    box = (img1_w/2-img2_w/2, img1_h/2-img2_h/2, img1_w/2-img2_w/2+img2_w, img1_h/2-img2_h/2+img2_h)

    # multiply new mask onto image
    resized.paste(img2, box)
    return ImageChops.multiply(img1, resized)


out = black_onto(painting, mask)
out.show() # this gives the output image shown above
解释:
(img1\u w/2-img2\u w/2、img1\u h/2-img2\u h/2、img1\u w/2-img2\u w/2+img2\u w、img1\u h/2-img2\u h/2+img2\u h)

好的,这是难看的一点,但其实很简单:
box
定义画布上我们要放置遮罩的区域,即中心<代码>框是一个4值元组,定义区域左上角和右下角的x和y,如下所示:
(x1,y1,x2,y2)
。而不是x、y和宽度、高度,这样更方便。无论如何,要定义区域以便图像居中,代码就是我们得到的

它是这样的:左上角的x值等于大图像宽度的一半减去遮罩图像宽度的一半。(我发现笔和纸在这里很有用。)左上角的y值也是如此。这是前两个值

现在,如果元组接受
(x,y,width,height)
,那么后两个值将只是掩码图像的尺寸。但它们不是,它们更多的是x和y位置。因此,我们必须手动计算它们,方法是将相同的代码作为前两个值(左上位置),并将图像的宽度和高度添加到其中,这是我们从一些变量(
img2\u w
img2\u h
)中知道的。因此,元组的后两个值与第一个和第二个值相同,但增加了掩码的宽度或高度(
img2


好吧,我希望这有足够的道理,祝你的项目好运

好的,这里有一个更通用、更可扩展的替代解决方案。它有两个部分;首先是将较小的图像调整大小(但不是缩放)到较大图像的尺寸,然后将该图像拍摄成仅由黑色或透明像素组成的图像,可以简单地粘贴到较大的图像上,然后给我们留下您想要的

调整大小:

1:2:3:

  • 参考图像
  • 输入掩码
  • 调整大小的掩码
  • 这可以通过此
    中心调整大小()功能完成:

    def center_resize(smaller, (width, height)):
        resized = Image.new("RGB", (width, height), "white")
        smaller_w, smaller_h = smaller.size
        box = (width/2-smaller_w/2,
               height/2-smaller_h/2,
               width/2-smaller_w/2+smaller_w,
               height/2-smaller_h/2+smaller_h)
        resized.paste(smaller, box)
        return resized
    

    筛选:

    此函数用于迭代图像中的所有像素,并将它们设置为指定颜色(如果它们是指定颜色)。(否则会设置为第三种指定颜色。)在这种情况下,我们希望将所有黑色像素保留为黑色,但将所有其他像素设置为完全透明的黑色。为此,您需要输入以下内容:

    pixel_filter(image, condition=(0, 0, 0), true_colour=(0, 0, 0, 255), false_colour=(0, 0, 0, 0))
    
    。。。它将返回一个经过过滤的图像

    def pixel_filter(image, condition, true_colour, false_colour):
        filtered = Image.new("RGBA", image.size)
        pixels = list(image.getdata())
        for index, colour in enumerate(pixels):
            if colour == condition:
                filtered.putpixel((index%image.size[1],index/image.size[1]), true_colour)
            else:
                filtered.putpixel((index%image.size[1],index/image.size[1]), false_colour)
        return filtered
    

    现在,在您的情况下,我们可以将这些应用于黑白图像,并简单地将其粘贴到主图像上

    mask = center_resize(mask, painting.size)
    mask = pixel_filter(mask, (0, 0, 0), (0, 0, 0, 255), (0, 0, 0, 0))
    
    painting.paste(mask, (0, 0), mask)
    painting.show()
    
    输出:


    看看这段代码是否有用,把它拆开并使用你想要的

    那真是太酷了约瑟夫…工作得很好!我尝试了.multiply函数,但没有考虑调整第二幅图像的大小,这样它就不会裁剪最终的图像。我真的不明白你在创建box变量时做了什么…这是一个4个数字的元组,是吗?但是这里发生了什么:(img1_w/2-img2_w/2,等等)。。。为什么要除以2等等?谢谢!很高兴能在一起共事!因此,4值元组基本上定义了“区域”左上角和右下角的x和y值。(不是X、Y和宽度、高度)< <代码>框>代码>是空白图像中要粘贴掩码图像的区域。我会在我的回答中做一个适当的解释…再次感谢约瑟夫,这个详细的解释为我澄清了这一点…你是对的,这真的很简单。我现在可以看到,它被二分之一,因为剩下的宽度和高度差