从两个图像的差异创建Alpha覆盖图像

2024-09-27 21:29:43 发布

您现在位置:Python中文网/ 问答频道 /正文

在这个问题上我一直有一个奇怪的困难时期。我有两个图像,我们称之为基地

和光

(实际图像的分辨率要高得多,但不管怎样,问题应该是一样的)。我的目标是生成一个新的图像,我们将其称为alpha,当它叠加在base上时,会产生{}。我尝试过做各种差/减、缩放、亮度调整等,但我做的似乎都没有真正产生结果(通常看起来很接近,但从不精确)。在

例如,这段代码几乎和我没有使用图像编辑软件来猜测和检查它一样接近。在

from PIL import Image, ImageEnhance
import numpy
import blend_modes
import sys
import scipy


background_img_raw = Image.open(sys.argv[1])
background_img_raw.putalpha(255)
background_img = numpy.array(background_img_raw)
background_img_float = background_img.astype(float)
foreground_img_raw = Image.open(sys.argv[2])
foreground_img_raw.putalpha(255)
foreground_img = numpy.array(foreground_img_raw)
foreground_img_float = foreground_img.astype(float)
opacity = 1.0
blended_img_float = blend_modes.difference(background_img_float, foreground_img_float, opacity)
r, g, b, a = np.transpose(blended_img_float)
alpha = np.clip((r+g+b)*2, 0, 255)
r = np.clip(r + 100, 0, 255)
g = np.clip(g + 100, 0, 255)
b = np.clip(b + 100, 0, 255)
blended_img_float = np.transpose([r, g, b, alpha])
blended_img = numpy.uint8(blended_img_float)
blended_img_raw = Image.fromarray(blended_img)
blended_img_raw.save(sys.argv[3])

结果是这样的

。在

有什么建议吗?在

编辑:摆弄油漆.net,如果执行以下操作,则可以非常接近:

  1. 混合->区分图层
  2. 在黑色上使用Grim Color Reaper
  3. 最大亮度和最小对比度
  4. 色调偏移一点,使饱和度最大化,并增加亮度

这是大量的转换,但是结果比我用编程方式得到的结果要接近得多。不管死神在做什么,似乎比我做的更接近正确。结果如下:

不幸的是,这并不能解决这个问题,因为我需要反复这样做,但它给了我希望,它是可以解决的。在

编辑2:请看这篇文章以获取我正在尝试完成的一个例子:https://community.home-assistant.io/t/floorplan-with-many-lights-in-one-area-say-hello-to-transparent-png-files/90006/8

编辑3:我现在需要继续解决这个问题,但我认为与其花那么多力气来制作合适的图像,我在CSS方面想出了一个解决办法,让混合更接近于合适的效果。现在我只需要利用这些图像之间的差异:

^{pr2}$

结果如下:https://codepen.io/anon/pen/agBqXr

这对我来说已经足够好了。我很想知道这个问题的正确答案,如果有人想出来的话!在


Tags: 图像imageimportalphanumpyimgrawclip
2条回答

我不太了解Opecv,但在ImageMagick中,我会做以下工作:

底座:

enter image description here

灯光:

enter image description here

convert base.png light.png -compose minus -composite minus.png


enter image description here

^{pr2}$


enter image description here

附加:

这是一种替代方法,在原始图像上合成彩色透明图像。但你得稍微调整一下颜色。我在底图上测量了一个亮黄色的点。在

1) turn the minus image into gray by desaturating it. The stretch the dynamic range, then apply a gamma adjustment.

2) create a look-up table between black and that yellow color and apply it to the gray image with -clut

3) put the gray image into the alpha channel of the colorized image

4) composite the previous image over the base image


convert minus.png -modulate 100,0,100 -auto-level -gamma 1.5 minus_gray.png
convert minus_gray.png \( xc:black xc:"rgb(251,220,120)" +append \) -clut minus_color.png
convert minus_color.png minus_gray.png -alpha off -compose copy_opacity -composite alpha.png
convert base.png alpha.png -compose over -composite result3.png

以下是步骤的结果:

灰色:

enter image description here

彩色灰色:

enter image description here

透明:

enter image description here

结果:

enter image description here

附加2:

convert light.png -alpha copy -channel a -evaluate multiply 2 +channel alpha.png
convert base.png alpha.png -compose over -composite result3.png


阿尔法:

enter image description here

结果:

enter image description here

这是对你问题的纯粹的回答。在

为了找出两者的区别图像:-在

from PIL import Image, ImageChops, ImageEnhance

img1 = Image.open(r"base.png")
img2 = Image.open(r"light.png")

diff = ImageChops.difference(img2, img1)

ImageChops.difference()接受两个图像对象作为参数,并返回两个对象之间逐像素差的绝对值。简而言之,它计算两个图像之间的差异。在

输出diff.show():-

enter image description here

现在,由于我们已经获得了这两幅图像的差分点,我们现在可以从diff图像和原始基础图像中创建一个合成图像

将这行代码添加到上一行代码:-在

^{pr2}$

Image.blend()将两个图像对象和一个阈值作为参数,并使用常量alpha(threshold参数)在两个输入图像之间插值来创建一个新图像。输出由公式:-在

image1 * (1.0 - alpha) + image2 * alpha

其中image1和image2是图像对象,alpha是阈值。由于我们使用0.5作为阈值,因此公式更改为:-

(image1 * 0.5) + (image2 * 0.5)

这意味着我们要取image1的一半颜色值(base)和image2的一半(diff)。因为,差分图像(diff)主要包含黑色像素,因此我们的基础图像的颜色像素亮度值减半(或变得比以前更暗)。在

输出overlaid_img1.show():-

enter image description here

现在,为了使基础图像的像素获得原始亮度值,我们需要将Image.blend()获得的输出图像的亮度加倍。在

将此行添加到原始行代码:-在

bright_overlay_img1 = ImageEnhance.Brightness(overlaid_img1).enhance(2.0)

ImageEnhance.Brightness()是一个用来调整图像亮度的类。ImageEnhance.Brightness.enhance()是用于执行此操作的函数。在

enhance(2.0)所做的是,它使overlaid_img1图像对象中每个像素的亮度值加倍。在

输出bright_overlay_img1.show():-

enter image description here

p.S.:-原始代码是通过在答案中添加所有提供的代码生成的。我对原始代码进行了分段,以便能够解释每个函数的工作原理及其背后的推理。因此,对于完整的工作,只需附加答案中提供的每个代码。在

编辑:-

刚刚看到你对@fmw42答案的评论,原来你的要求和你问的问题不一样。在

根据我的理解,您希望diff(存储两个图像的差异的图像)的格式支持alpha(透明度),而不是一个完全黑色的图像。在

为了这个用这个代码:-在

# This is the full code

from PIL import Image, ImageChops, ImageEnhance

img1 = Image.open(r"base.png")
img2 = Image.open(r"light.png")

diff = ImageChops.difference(img2, img1).convert("RGBA")

pixels = diff.load()

for x in range(diff.size[0]):
    for y in range(diff.size[1]):
        if pixels[x, y] == (0, 0, 0, 255):
            pixels[x, y] = (0, 0, 0, 0)

diff.save("alpha_difference.png")   # saving the difference image (having alpha channel)

overlaid_img1 = Image.blend(img1.convert("RGBA"), diff, 0.5)

bright_overlay_img1 = ImageEnhance.Brightness(overlaid_img1).enhance(2.0).convert("RGB")

上面的代码与我之前提到的不同之处在于,它将差异图像diff转换为alpha通道图像,如果它的颜色是完全黑色的(与原始图像没有区别),那么它将使像素透明。在

差分图像(有alpha通道):-

enter image description here

两段代码的输出仍然是相同的。在

p.S.:-我建议您更改问题的标题/描述,并在那里明确说明您的问题。在

相关问题 更多 >

    热门问题