使用Python Imaging Library将图像中的黑色像素覆盖在另一个图像上

时间:2013-10-11 06:41:57

标签: python

H我的名字暗示我是代码新手,正在使用Python,非常感谢使用Python Imaging Library完成任务的一些帮助。

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

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

import PIL
from PIL import Image

painting = Image.open("painting.bmp")
painting.show()

我已经排除了使用.blend和.composite函数或ImageChops模块中的.multiply函数,因为图像的大小不同。

我相信我需要使用.getpixel / .putpixel或.getdata / .putdata来查找由元组(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')

再一次,我是新人,所以对我很轻松,任何帮助都将非常感激。

干杯。

2 个答案:

答案 0 :(得分:3)

所以我假设你只想将两张图像相互叠加,那就是它们的尺寸不同?如果我误解了,请原谅我,但是这里有一些代码可以将一个图像的黑色像素放到另一个图像上,即使黑白图像比另一个图像小。

Sourse Images(painting.bmpmask.bmp

painting mask

输出:

result

“...新图像基本上是第一张图片(绘画),第二张图片中只有黑色像素,覆盖在它上面。” - 这就是你想要的吗?


基本上,代码只是将较小的图像与第一个图像一样大,方法是将其放在与第一个图像大小相同的空白图像的中心。

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_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)

好的,所以这很丑陋,但它真的很简单:box定义画布上我们想要将蒙版放在哪个区域,即中心。 box是一个4值元组,用于定义区域的左上角右下角角的x和y,如下所示:{{ 1}}。不是x,y和宽度,高度,这将更方便。无论如何,要定义区域以使图像居中,那么代码就是我们得到的。

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

现在,如果元组接受(x1, y1, x2, y2),则后两个值将只是蒙版图像的尺寸。但他们不是,他们更多的是x和y职位。所以我们必须手动计算它们,通过使用相同的代码作为前两个值(左上角位置)和添加图像的宽度和高度,我们从一些变量({{ 1}}和(x, y, width, height))。因此,元组的后两个值与第一个和第二个相同,但添加了掩码(img2_w)的 width height

嗯,我希望这对你的项目有充分的理解和好运!

答案 1 :(得分:1)

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

<强>调整大小:

1:painting 2:original mask 3:resized

  1. 参考图片
  2. 输入掩码
  3. 调整大小的面具
  4. 可以使用此center_resize()函数完成:

    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
    

    现在,在您的情况下,我们可以将这些应用于B&amp; W图像,只需将其粘贴到主图像上即可。

    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()
    

    输出:

    output

    查看此代码是否有用 - 将其拉开并使用您想要的内容!