我一直在经历一个奇怪的困难时期。我有两个图像,我们称它们为基准
和光
(实际图像的分辨率要高得多,但是无论如何,问题都应相同)。我的目标是产生一个新图像,我们将其称为alpha
,当它覆盖在base
上时会产生light
。我已经尝试过进行各种差异/相减,缩放,亮度调整等操作,但是我似乎并没有实际产生结果(通常看起来很接近,但是从不精确)。
例如,这段代码与我所使用的代码差不多,而无需使用图像编辑软件来对其进行猜测和检查。
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])
结果看起来像这样
。
有什么建议吗?
编辑:在Paint.net上四处乱逛,如果您执行以下操作,您可能会很接近:
这是大量的转换,但是结果比我以编程方式得出的结果要近得多。无论“死神”在做什么,都比我在做的更接近纠正。结果如下:
不幸的是,这不能解决问题,因为我需要反复进行此操作,但是它使我希望它可以以某种方式解决。
编辑2:请参见这篇文章,以了解我要完成的工作:https://community.home-assistant.io/t/floorplan-with-many-lights-in-one-area-say-hello-to-transparent-png-files/90006/8
编辑3:我现在需要继续解决这个问题,但是我认为与其努力工作以制作出合适的图像,我还想出了CSS方面的一种解决方法,可以使混合更接近什么合适。现在,我只使用像这样的图像之间的差异:
import numpy as np
from PIL import Image
import sys
def create_mask(foreground_filename, background_filename, output_filename):
foreground = cv2.imread(foreground_filename)
background = cv2.imread(background_filename)
diff = foreground - background
diff = cv2.cvtColor(diff, cv2.COLOR_BGR2RGB)
out_pil_image = Image.fromarray(diff)
out_pil_image.save(output_filename)
if __name__ == "__main__":
create_mask(sys.argv[1], sys.argv[2], sys.argv[3])
结果如下:https://codepen.io/anon/pen/agBqXr
目前对我来说哪个足够好。如果有人知道,我很想知道这个问题的正确答案!
答案 0 :(得分:1)
我不太了解Opecv,但是在ImageMagick中,我将执行以下操作:
基础:
灯光:
convert base.png light.png -compose minus -composite minus.png
convert base.png minus.png -compose plus -composite result.png
添加:
这是在原件上构成彩色透明图像的另一种方法。但是您将不得不稍微调整颜色。我在基础图像中测了一个亮黄点。
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
以下是步骤的结果:
灰色:
彩色灰色:
透明:
结果:
ADDITION2:
convert light.png -alpha copy -channel a -evaluate multiply 2 +channel alpha.png
convert base.png alpha.png -compose over -composite result3.png
阿尔法:
结果:
答案 1 :(得分:0)
一种获取两个图像之间差异的方法是使用在scikit-image库中实现的结构相似性索引(SSIM),以进行图像处理。 scikit-image
可以与pip install scikit-image
一起安装。
具体来说,compare_ssim()
函数返回一个score
,用于测量两个图像之间的相似度指数,以及一个包含实际图像差异的diff
图像。
结果
from skimage.measure import compare_ssim
import cv2
before = cv2.imread('base.png')
after = cv2.imread('light.png')
# Convert images to grayscale
before_gray = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
after_gray = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)
# Compute SSIM between two images
(score, diff) = compare_ssim(before_gray, after_gray, full=True)
print("Image similarity", score)
# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type in the range [0,1]
# so we must convert the array to 8-bit unsigned integers in the range
# [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")
cv2.imshow('result', diff)
cv2.imwrite('result.png', diff)
cv2.waitKey(0)
答案 2 :(得分:0)
这是您问题的纯PIL答案。
要获取两个图像之间的差异:-
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()
接受两个Image对象作为参数,并返回两个像素之间的逐像素差的绝对值。简而言之,它计算两个图像之间的差异。
diff.show()
的输出:-
现在,由于我们现在已经获得了两个图像的差异点,因此我们现在可以从 diff 图像和原始 base 图像中创建一个合成图像< / p>
将这行代码添加到先前的代码中:-
overlaid_img1 = Image.blend(img1, diff, 0.5)
Image.blend()
将两个图像对象和一个阈值作为参数,并使用恒定的alpha(阈值参数)通过在两个输入图像之间进行插值来创建新图像。输出由以下公式指导:-
image1 *(1.0-alpha)+ image2 * alpha
其中image1和image2是图像对象,而alpha是阈值。由于我们使用0.5
作为阈值,因此公式更改为:-
(图像1 * 0.5)+(图像2 * 0.5)
这意味着我们获取的是image1(基础)的一半颜色值和image2(diff)的一半。由于差异图像(diff)主要包含黑色像素,因此,我们的基础图像的彩色像素亮度值减半(或者比以前更暗)。
overlaid_img1.show()
的输出:-
现在,为了使基本图像的像素获得原始亮度值,我们需要将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()
的输出:-
附言:-原始代码是通过在答案中添加所有提供的代码而产生的。我对原始代码进行了细分,以便可以解释每个函数的工作原理及其背后的原因。因此,为使整个工作正常进行,只需附加答案中提供的每个代码。
编辑:-
刚刚看到您对@ 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通道):-
两个代码段的输出仍然相同。
P.S。:-:我建议您更改问题的标题/说明,并在此处明确说明问题。