5

편집 : Mark and zephyr 덕분에 코드가 작동 중입니다. 제퍼는 아래에 두 가지 대체 해결책이 있습니다.파이썬 PIL - 두 이미지를 블렌드하는 기능?

두 이미지를 PIL로 블렌드하고 싶습니다. ImageChops.multiply(image1, image2)을 찾았지만 비슷한 divide(image, image2) 기능을 찾을 수 없습니다.

Divide Blend Mode Explained (나는 내 ​​테스트 소스로 여기 처음 두 이미지를 사용했습니다.)

이 거기에 내장 나누기 혼합 기능 내가 (그렇지 않으면 PIL 이상)를 놓친?

아래의 테스트 코드가 실행되고 찾고있는 항목에 가까워지고 있습니다. 결과 이미지 출력은 여기에서 나누기 블렌드 예제 이미지 (Divide Blend Mode Explained)와 유사합니다.

블렌드 작업을보다 효율적으로 나눌 수 있습니까? 처음에 나는 Image.evalImageMath.eval에있는 람다 함수를 사용하여 검정 픽셀을 확인하고 나눗셈 과정에서 흰색으로 뒤집어 보았습니다.하지만 올바른 결과를 얻지 못했습니다.

수정 : 수정 코드 및 마크 및 제퍼 덕분에 단축되었습니다. 결과 이미지 출력은 아래의 제피어의 numpy 및 scipy 솔루션의 출력과 일치합니다. 여기 http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node55_002.html

scipy /하기 matplotlib로 구현 것 :

# 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

여기에 분할 함수에 대한 수학적 정의가

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

+0

죄송합니다. PIL에 익숙하지 않습니다.나는 파일을로드/저장하는 데만 사용했습니다. 아마 그것을 할 수있는 방법이 있다고 생각하지만, 나는 numpy로 수학을하는 것이 더 쉽다고 생각합니다. – so12311

+0

다시 한번 감사드립니다. 나는 이미 멍청하고 scipy있다, 그래서 너의 numpy 방법을 시도 할게. (오, 나는 matplotlib도 가지고 있음을 압니다.) 이전 필자의 PIL 함수로 다시 변환하려고했는데 아직 제대로 작동하지 않았습니다. 그동안 업데이트 한 것을 보니 변경 사항을 다시 시도해 보겠습니다. – moski

1

이미지 B에 0이있을 때 문제가 발생합니다. 0으로 나누기가 발생합니다. 그 값을 모두 1로 변환하면 원하는 결과를 얻을 수 있다고 생각합니다. 그러면 0을 확인하고 결과를 수정하지 않아도됩니다.

+0

당신의 도움에 감사드립니다. 나는 그 수정을하고 그것이 어떻게 작동하는지 보게 될 것이다. – moski

1

당신은 묻고있다 :

이 분할 혼합 작업 (낮은 단계 빠르게)를 할 수있는보다 효율적인 방법이 있나요?

blend modes 파이썬 패키지를 사용할 수도 있습니다. 이것은 벡터화 된 넘 피 수학으로 작성되며 일반적으로 빠릅니다. 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).

관련 문제