【问题标题】:Image Processing: Merging images with PIL.paste图像处理:使用 PIL.paste 合并图像
【发布时间】:2018-10-22 00:34:49
【问题描述】:

我有 2 个 png 图像列表,列表 _c 和列表 _v。我想使用以下代码将 _v 粘贴到 _c 上:

from PIL import Image

background = [Image.open(path, 'r') for path in glob.glob(list_c_path)]
foreground = [Image.open(path, 'r') for path in glob.glob(list_v_path)]

for im in range(len(background)):
    pasted = background[im].paste(foreground[im], (0, 0), foreground[im])

此代码不起作用,但它会让您了解我想要什么。我还需要在粘贴之前以灰度格式读取图像。

这是背景图片的示例:

这是前景图像的示例:

这是想要的结果:

我用这段代码粘贴了这张图片:

background = Image.open('1000_c.png')
foreground = Image.open('1000_v.png')


background.paste(foreground, (0, 0), foreground)
background.save('example.png')

我怎样才能做到这一点??

提前致谢

【问题讨论】:

  • 图片粘贴后如何读取灰度?您必须在粘贴之前阅读它们。前景、背景和结果图像的外观如何 - 请提供示例。
  • 你说得对,我要编辑我的问题。请稍等
  • @MarkSetchell 问题已编辑
  • 我不在电脑前查看,但您的结果看起来与您粘贴在背景顶部的图像相同?
  • 嗯...您的结果图像与您的前景图像相同,因为尽管前景图像具有 Alpha/透明层,但它们完全不透明并且完全隐藏了您的背景。你需要重新考虑一下!

标签: python-3.x image-processing python-imaging-library


【解决方案1】:

嗯...您的结果图像与您的前景图像相同,因为尽管前景图像具有 Alpha/透明层,但它们完全不透明并且完全隐藏了您的背景。你需要重新考虑一下!

您可以在终端中使用 ImageMagick 来检查您的图像。那么,让我们看看你的前景图像:

identify -verbose fg.png

样本输出

Image: fg.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 118x128+0+0
  Units: Undefined
  Colorspace: sRGB
  Type: PaletteAlpha             <--- Image does have alpha/transparency layer
  Base type: Undefined
  Endianess: Undefined
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
    Alpha: 1-bit
  Channel statistics:
    Pixels: 15104
    Red:
      min: 30  (0.117647)
      ...
      ...
    Alpha:
      min: 255  (1)              <--- ... but alpha layer is fully opaque
      max: 255 (1)
      mean: 255 (1)
      standard deviation: 0 (0)
      kurtosis: 8.192e+51
      skewness: 1e+36
      entropy: 0

因此,将完全不透明的图像粘贴到背景上是没有意义的,因为它会完全隐藏它。

如果我们使用 ImageMagick 在您的前景图像上打一个透明孔:

convert fg.png -region 100x100+9+14 -alpha transparent fg.png

现在看起来像这样:

如果我们随后运行您的代码:

#!/usr/local/bin/python3

from PIL import Image
background = Image.open('bg.png')
foreground = Image.open('fg.png')

background.paste(foreground, (0, 0), foreground)
background.save('result.png')

有效:

所以这个故事的寓意是,您的前景图像要么需要一些透明度以允许背景显示出来,要么您需要使用某种混合模式来选择每个位置的前景和背景图像中的一个或另一个,或选择一些组合 - 例如两者的平均值,或两者中较亮的那个。


如果您想平均两个图像,或者实际上,执行任何其他混合模式,您可以考虑使用 Pillow 的 ImageChops 模块 - 文档 here。因此,平均值如下所示:

#!/usr/local/bin/python3

from PIL import Image, ImageChops
bg = Image.open('bg.png')
fg = Image.open('fg.png')

# Average the two images, i.e. add and divide by 2
result = ImageChops.add(bg, fg, scale=2.0)
result.save('result.png')

【讨论】:

  • 嗨,马克,非常感谢您的回答。你认为使用它们的平均值组合图像可能是可行的方法吗?事实上,我正在使用 CNN 构建一个分类模型来对这些图像进行分类,我想组合它们的原因是因为我每次观察都有 2 张图像,但如果我让图像保持原样,我只能使用 2 种图像类型 _c 或 _v,这意味着 2 个模型独立工作。但我正在考虑将 2 种图像组合起来构建一个与其中 2 种图像一起使用的模型,并提高准确性。我试过np.vstack
  • 但这只会沿垂直轴连接图像,我认为这对我不起作用,我想的是以某种方式逐层堆叠图像,构建组合2,也许你建议的平均方法在这里可以工作。我在this 帖子上发现了类似的东西。如果我错了,请纠正我,将这两种图像合二为一只是我的一个想法,我没有任何证据表明它可以满足我的目的。
  • 如果您有更好的建议来实现这一目标,或者您认为另一种方法可能更有效,请告诉我,我愿意接受任何建议:) 再次感谢
  • 我真的不知道 - 有数百种组合图像的方法。您可以将它们并排、从上到下放置,您可以选择每个位置的两个像素中较亮或较暗的位置。您可以平均每个位置的两个像素,或者使用不同的权重来拍摄一张图像而不是另一张图像。您可以将每个位置的像素相乘。或者区分它们。您可以对它们进行异或。您可以采用其中一种的色调和另一种的饱和度。您可以采用一种的亮度和另一种的色调。或任何组合...我知道如何做,但不知道哪一种最适合您。
  • 我在答案末尾添加了一个平均示例。还有一个指向 Pillow 的 “通道操作” 模块的链接,它允许您实现我提到的其他混合模式。
猜你喜欢
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
相关资源
最近更新 更多