【问题标题】:NumPy, PIL adding an imageNumPy,PIL 添加图像
【发布时间】:2010-10-06 05:05:51
【问题描述】:

我正在尝试使用 NumPy 和 PIL 将两个图像添加在一起。我在MATLAB 中执行此操作的方式类似于:

>> M1 = imread('_1.jpg');
>> M2 = imread('_2.jpg');
>> resM = M1 + M2;
>> imwrite(resM, 'res.jpg');

我得到这样的东西:

alt text http://www.deadlink.cc/matlab.jpg

使用合成程序并添加图像,MATLAB 结果似乎是正确的。

在 Python 中,我正在尝试做同样的事情:

from PIL import Image
from numpy import *

im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
im2 = Image.open('/Users/rem7/Desktop/_2.jpg')

im1arr = asarray(im1)
im2arr = asarray(im2)

addition = im1arr + im2arr

resultImage = Image.fromarray(addition)
resultImage.save('/Users/rem7/Desktop/a.jpg')

我得到这样的结果:

alt text http://www.deadlink.cc/python.jpg

为什么我会得到所有这些时髦的颜色?我也尝试过使用ImageMath.eval("a+b", a=im1, b=im2),但我收到一个关于 RGB 不受支持的错误。

我还看到有一个Image.blend(),但这需要一个 alpha。

实现我的目标的最佳方法是什么?

源图片(图片已被删除):

alt text http://www.deadlink.cc/_1.jpg alt text http://www.deadlink.cc/_2.jpg

嗯,好的,我使用添加图像图标添加了源图像,它们会在我编辑帖子时出现,但由于某种原因,这些图像没有出现在帖子中。

(图片已被删除)2013 05 09

【问题讨论】:

    标签: python image-processing numpy python-imaging-library


    【解决方案1】:

    您发布的代码似乎只是总结了值,大于 256 的值溢出了。你想要“(a + b)/ 2”或“min(a + b,256)”之类的东西。后者似乎是您的 Matlab 示例的方式。

    【讨论】:

    • 是的,matlab 在对 uint8 值进行算术运算时会限制值(例如,它隐式地等效于 max(double(a)+double(b),256))"
    • 当我尝试执行 max(im1arr+im2arr,256) 时出现错误:“ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或a.all()" 我做了 (im1arr+im2arr)/2 我得到了时髦的颜色,只有更暗,最大值 127 所以我做了:addition=(im1arr/2)+(im2arr/2) 这似乎有效。
    • 你真的不想要min(a + b, 256),因为如果你得到一个超过 256 的值,你想把这个值限制在 256(你不想取一个超过 256 的值)。无论如何,要修复@rem7 指出的错误,您可以执行additionF = np.minimum(im1arrF + im2arrF, 256)
    【解决方案2】:

    正如大家已经建议的那样,您观察到的奇怪颜色已经溢出。正如您在comment of schnaader's answer 中指出的那样,如果您像这样添加图像,仍然会溢出

    addition=(im1arr+im2arr)/2
    

    这种溢出的原因是您的 NumPy 数组 (im1arr im2arr) 属于 uint8 类型(即 8 位)。这意味着数组的每个元素最多只能保存 255 的值,因此当总和超过 255 时,它会在 0 附近循环:

    >>>array([255,10,100],dtype='uint8') +  array([1,10,160],dtype='uint8')
    array([ 0, 20,  4], dtype=uint8)
    

    为避免溢出,您的数组应该能够包含超过 255 的值。例如,您需要将它们转换为浮点数,执行混合操作并将结果转换回 uint8:

    im1arrF = im1arr.astype('float')
    im2arrF = im2arr.astype('float')
    additionF = (im1arrF+im2arrF)/2
    addition = additionF.astype('uint8')
    

    不应该这样做:

    addition = im1arr/2 + im2arr/2
    

    当您丢失信息时,通过在执行混合信息之前压缩图像的动态(您实际上使图像为 7 位)。

    MATLAB 注释:您在 MATLAB 中看不到此问题的原因可能是因为 MATLAB 在其函数之一中隐式处理了溢出。

    【讨论】:

    • 为什么是“浮动”? 'uint16' 就足够了。
    • 选择float没有合理的理由,uint16确实足够了。
    【解决方案3】:

    要钳制 numpy 数组值:

    >>> c = a + b
    >>> c[c > 256] = 256
    

    【讨论】:

    • 它假设元素的类型大于uint8。
    【解决方案4】:

    使用 alpha 值为 0.5 的 PIL 的 blend() 将等效于 (im1arr + im2arr)/2。 Blend 不要求图像具有 Alpha 层。

    试试这个:

    from PIL import Image
    im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
    im2 = Image.open('/Users/rem7/Desktop/_2.jpg')
    Image.blend(im1,im2,0.5).save('/Users/rem7/Desktop/a.jpg')
    

    【讨论】:

    • 这对于在不拖入 numpy 的情况下完成工作特别好。
    【解决方案5】:

    你的示例图片没有显示在我的表格中,所以我会做一些猜测。

    我不记得从 numpy 到 pil 的转换是如何工作的,但有两种可能的情况。我 95% 确定它是 1,但我给出 2 以防万一我错了。 1) 1 im1Arr 是一个 MxN 整数数组 (ARGB),当您将 im1arr 和 im2arr 加在一起时,如果组件 b1+b2>255,您将从一个通道溢出到下一个通道。我猜 matlab 将他们的图像表示为 MxNx3 数组,因此每个颜色通道都是独立的。您可以通过拆分 PIL 图像通道然后制作 numpy 数组来解决此问题

    2) 1 im1Arr 是一个 MxNx3 字节数组,当您将 im1arr 和 im2arr 相加时,您正在包装组件。

    在显示之前,您还必须将范围重新调整到 0-255 之间。您的选择是除以 2、缩放 255/array.max() 或进行剪辑。我不知道matlab是做什么的

    【讨论】:

    • 图片还没有显示吗?我编辑了这个问题,然后,它在这里工作。
    • 现在为我工作。它绝对看起来像一个包装/饱和问题。如果你发布你的源图像也很好。
    • 我认为 pil 转换确实使它成为 MxNx3,因为 im1arr.shape 打印了这个:(2477, 3700, 3)。选项二似乎是正确的。
    • 看来我必须先分割两个图像才能添加它们,即使我在结果上做了一个剪辑(min=0, max=255),溢出已经发生了,所以很时髦颜色仍然存在。
    • 首先除法的替代方法是从字节数组转换为 int(或短)数组,然后进行数学运算。
    猜你喜欢
    • 2021-09-04
    • 2018-11-22
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 2017-06-25
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多