Python PIL函数分割混合两个图像?

2024-05-16 21:13:55 发布

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

编辑:由于Mark和zephyr的帮助,代码现在可以工作了。zephyr还有两种替代的工作解决方案。

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

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

有没有一个内置的除法混合函数,我错过了(PIL或其他)?

我下面的测试代码正在运行,并且正在接近我想要的。生成的图像输出类似于这里的divide-blend示例图像:Divide Blend Mode Explained

有没有一种更有效的方法来进行这种分割混合操作(步骤更少,速度更快)?起初,我尝试使用lambda函数在Image.evalImageMath.eval中检查黑色像素,并在除法过程中将其翻转为白色,但两种方法都无法产生正确的结果。

编辑:固定代码并由于Mark和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')

Tags: 函数图像imagepilevalrgbsplitzephyr
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 &lt 255)+255*ones(shape(c))*(c &gt 255)
e = d.astype('uint8')

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

你遇到的问题是当你在图像B中有一个0时,它会导致除以0。如果你把这些值都转换成一个,我想你会得到想要的结果。这将消除检查零并在结果中修正它们的需要。

你在问:

Is there a more efficient way to do this divide blend operation (less steps and faster)?

您还可以使用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)

相关问题 更多 >