python - 为什么 ImageStat 返回有符号整数图像 (`mode=' I'`) 的错误统计信息?

标签 python numpy python-imaging-library

我的深度图像具有非常大的值范围,大约为 [0, 10,000],保存为 png。这些默认加载为 PIL 图像 mode='I' ,32 位有符号整数像素,但有一些意外的行为。

例如,Image.show()显示空白屏幕。这在某种程度上是预料之中的,因为我猜测该函数需要输入 [0, 1] 或 [0, 255],并且会截断图像中超出该范围的像素值。

更令人担忧的是,ImageStat对于大多数统计数据返回不正确的值。我已经通过从 numpy 和 Matlab 独立获得的结果确认了这两个值。对于更传统的 RGB 图像 mode='RGB' ,不会发生这种情况。

问题

这是怎么回事?这也是一个截断问题吗?

MCVE

使用以下图像作为test.png

Depth camera capture with smoothing

from PIL import Image
im = Image.open("test.png")
im.show() # shows white blank screen 
print(im.mode) # prints 'I'

from PIL.ImageStat import Stat
stat = Stat(im)
print(stat.mean)    # [85.10539415869734]
print(stat.extrema) # [(0, 255)]
print(stat.sum)     # [32927277.0]

import numpy as np
print(np.mean(im)) # 28051.3720754717
print(np.min(im))  # 9992
print(np.max(im))  # 63816
print(np.sum(im))  # 10853075856

Matlab的结果与numpy类似

最佳答案

Image.show() displays a blank white screen

这是因为Image.show()使用临时缓冲区来存储图像对象。然后在显示之前将 Image 对象转换为 .bmp (位图)。位图格式不支持 32 位单 channel 图像(灰度),因此通过 show() 获得的结果是不理想的。

ImageStat is returning an incorrect values for most statistics

在对 ImageStat 模块进行源代码分析时,我发现该模块是专门为处理 0 ≤ 样本空间> 256 的图像而构建的,或像素值在(0 ≤ value ≤ 255)范围内的图像。

例如,如果我们分析 Stat.extreme:-

def _getextrema(self):
    """Get min/max values for each band in the image"""

    def minmax(histogram):
        n = 255
        x = 0
        for i in range(256):
            if histogram[i]:
                n = min(n, i)
                x = max(x, i)
        return n, x  # returns (255, 0) if there's no data in the histogram

    v = []
    for i in range(0, len(self.h), 256):
        v.append(minmax(self.h[i:]))
    return v

我们可以清楚地看到,用于计算图像像素值上下界的函数不能返回小于0的值,也不能返回大于255的值.即(值 ∈ {0 - 255})

Stat 函数的制作方式是这样的,只有当图像的像素值范围低于 256 时,它才能正常工作。

Is this also a truncation issue

没有。在计算 Stat 中的值期间,不会发生截断。 Stat 模块的制作方式不应使其能够展平/截断超出正常范围的像素值。相反,发生的情况是,当图像对象传递给 Stat 时,它只是对其进行正常计算(假设像素值的范围在 0 到 255 之间)。那么输出仅取决于输入参数是否导致值计算中断/异常,即如果一切顺利,输出将是不合需要的。但这并不总是正确的。

例如:-

img = Image.new("I", (300, 300), (3000))

stat = Stat(img)
print(stat.mean)
print(stat.extrema)
print(stat.sum)     

执行时的代码:-

Traceback (most recent call last):
  File "C:/Users/Vasu/AppData/Local/Programs/Python/Python37-32/Lib/site-packages/PIL/testing.py", line 10, in <module>
    print(stat.mean)
  File "C:\Users\Vasu\AppData\Local\Programs\Python\Python37-32\lib\site-packages\PIL\ImageStat.py", line 48, in __getattr__
    v = getattr(self, "_get" + id)()
  File "C:\Users\Vasu\AppData\Local\Programs\Python\Python37-32\lib\site-packages\PIL\ImageStat.py", line 104, in _getmean
    v.append(self.sum[i] / self.count[i])
ZeroDivisionError: float division by zero

因此,输出要么是不需要的,要么最终会导致错误/异常。

Does that mean PIL doesn't support I color mode

没有。 PIL 完全支持 32 位有符号整数。

例如,如果我们尝试获取您图像的像素值:-

im = Image.open(r"Input_img")
im = list(im.getdata())

print(im)

我们得到实际的像素值:-

40384, 40384, 40384, 40384, 40384, 40600, 40600, 40600, 40808, 41016, 41232, 41440, 41656.....22232]

结论:- PIL 原生支持 32 位有符号整数像素,但 ImageStat 不支持。

P.S.:- PIL/pillow 文档的当前状态不是很好,即它不太擅长解释......无论它正在尝试什么解释。因此,我们应该尽可能地为其添加更多的情报。因此,我建议您在 PIL repository on Github 上发布问题/拉取请求,关于 ImageStat 模块描述的改进。就像添加行,例如:-

Module does not have a native support for pixel values greater then 8 bits

或者其他类似的东西。

关于python - 为什么 ImageStat 返回有符号整数图像 (`mode=' I'`) 的错误统计信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56843624/

相关文章:

python - 如何在 Spyder(Anaconda 3) 上安装 PIL?

python - Pandas 中的条件累积和

python - 在 for 循环中追加数组

python - 如何在 Python 中实现平均感知器(不使用 Scikit-learn)

python - 添加 alpha channel 时图像不会改变

python - Pyinstaller 与 Pillow 的问题

python - 将包含多种字符串日期格式的列转换为 Spark 中的 DateTime

python - 如何在 Pygame 表面实现洪水填充

python - 实现多类骰子损失函数

python - Python 中 Matlab 的 'fread' 是什么?