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)