3

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

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

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

import PIL
from PIL import Image

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

我已排除使用 ImageChops 模块中的 .blend 和 .composite 函数或 .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')

再说一次,我是新手,所以对我放轻松,任何帮助将不胜感激。

干杯。

4

2 回答 2

3

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

源图像(painting.bmpmask.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_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 值元组,用于定义区域左上角右下角(x1, y1, x2, y2)的 x 和 y,如下所示:不是 x, y 和 width, height,这会更方便。无论如何,要定义区域以使图像居中,该代码就是我们得到的。

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

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

好吧,我希望这有足够的意义,祝你的项目好运!

于 2013-10-11T08:33:09.077 回答
1

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

调整大小:

1:绘画2:原始面具3:调整大小

  1. 参考图像
  2. 输入掩码
  3. 调整大小的蒙版

这可以通过这个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

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

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

输出:

输出

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

于 2013-10-13T04:41:41.953 回答