5

编辑:代码现在工作,感谢马克和西风。 zephyr在下面还有两个备用工作解决方案。Python PIL - 分割混合两个图像的功能?

我想分割与PIL混合两个图像。我发现ImageChops.multiply(image1, image2)但我找不到类似的divide(image, image2)函数。

Divide Blend Mode Explained(我这里使用的前两个图像作为我的测试源。)

是否有一个内置的鸿沟混合函数,我错过了(PIL或其他)?

我的测试代码如下运行,并越来越接近我在找什么。生成的图像输出与此处的分割混合示例图像类似:Divide Blend Mode Explained

有没有一种更有效的方式来做这种分割混合操作(更少的步骤和更快)?起初,我尝试在Image.evalImageMath.eval中使用lambda函数检查黑色像素,并在除法过程中将它们翻转为白色,但是我无法获得正确的结果。

编辑:固定代码并缩短感谢马克和zephyr。最终的图像输出与来自zephyr的numpy和scipy解决方案的输出相匹配。

# PIL Divide Blend test 

import Image, os, ImageMath 

imgA = Image.open('01background.jpg') 
imgA.load() 
imgB = Image.open('02testgray.jpg') 
imgB.load() 

# split RGB images into 3 channels 
rA, gA, bA = imgA.split() 
rB, gB, bB = imgB.split() 

# divide each channel (image1/image2) 
rTmp = ImageMath.eval("int(a/((float(b)+1)/256))", a=rA, b=rB).convert('L') 
gTmp = ImageMath.eval("int(a/((float(b)+1)/256))", a=gA, b=gB).convert('L') 
bTmp = ImageMath.eval("int(a/((float(b)+1)/256))", a=bA, b=bB).convert('L') 

# merge channels into RGB image 
imgOut = Image.merge("RGB", (rTmp, gTmp, bTmp)) 

imgOut.save('PILdiv0.png', 'PNG') 

os.system('start PILdiv0.png') 

回答

3

没有为分频功能在这里的数学定义: http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node55_002.html

这里与SciPy的/ matplotlib的实现:

import numpy as np 
import scipy.misc as mpl 

a = mpl.imread('01background.jpg') 
b = mpl.imread('02testgray.jpg') 

c = a/((b.astype('float')+1)/256) 
d = c*(c < 255)+255*np.ones(np.shape(c))*(c > 255) 

e = d.astype('uint8') 

mpl.imshow(e) 
mpl.imsave('output.png', e) 

如果你不想使用matplotlib,你可以这样做(我假设你有numpy):

 
imgA = Image.open('01background.jpg') 
imgA.load() 
imgB = Image.open('02testgray.jpg') 
imgB.load() 

a = asarray(imgA) 
b = asarray(imgB) 
c = a/((b.astype('float')+1)/256) 
d = c*(c < 255)+255*ones(shape(c))*(c > 255) 
e = d.astype('uint8') 

imgOut = Image.fromarray(e) 
imgOut.save('PILdiv0.png', 'PNG') 

+0

感谢您的解决方案。这更直接。我会看看pylab和matplotlib。我想在PIL中没有那么简单?该链接对理解其他混合模式也很有帮助。 – moski 2011-04-09 15:24:55

+0

对不起,我对PIL不是很熟悉..我只用它来加载/保存文件。我想可能有办法做到这一点,但我发现在numpy中做数学的东西比较容易。 – so12311 2011-04-09 15:38:07

+0

再次感谢。我已经有了numpy和scipy,所以我也会尝试你的numpy方法。 (哦,我看到我也有matplotlib。)我试图将你以前的帖子转换回我的PIL函数,但它还没有工作。同时我看到你已经更新了一些东西,所以我会再次尝试这些更改。 – moski 2011-04-09 16:22:34

1

你遇到的问题是当你在图像B中有一个零时 - 它会导致零除。如果您将所有这些值转换为一个值,我认为您会得到期望的结果。这将消除检查零并在结果中修复它们的需要。

+0

感谢您的帮助。我会做出修复,看看它是如何工作的。 – moski 2011-04-09 15:19:37

1

你问:

有没有更有效的方式做到这道鸿沟的混合操作(更少的步骤和更快的)?

你也可以使用python包blend modes。它用矢量化的Numpy数学书写,速度一般很快。通过pip install blend_modes安装它。我已经以更详细的方式编写了这些命令以提高可读性,链接它们会更短。使用blend_modes这样来划分您的图像:

from PIL import Image 
import numpy 
import os 
from blend_modes import blend_modes 

# Load images 
imgA = Image.open('01background.jpg') 
imgA = numpy.array(imgA) 
# append alpha channel 
imgA = numpy.dstack((imgA, numpy.ones((imgA.shape[0], imgA.shape[1], 1))*255)) 
imgA = imgA.astype(float) 

imgB = Image.open('02testgray.jpg') 
imgB = numpy.array(imgB) 
# append alpha channel 
imgB = numpy.dstack((imgB, numpy.ones((imgB.shape[0], imgB.shape[1], 1))*255)) 
imgB = imgB.astype(float) 

# Divide images 
imgOut = blend_modes.divide(imgA, imgB, 1.0) 

# Save images 
imgOut = numpy.uint8(imgOut) 
imgOut = Image.fromarray(imgOut) 
imgOut.save('PILdiv0.png', 'PNG') 

os.system('start PILdiv0.png') 

要知道,这个工作,两个图像必须具有相同的尺寸,例如imgA.shape == (240,320,3)imgB.shape == (240,320,3)