我的深度图像具有非常大的值范围,大约为 [0, 10,000],保存为 png。这些默认加载为 PIL 图像 mode='I'
,32 位有符号整数像素,但有一些意外的行为。
例如,Image.show()
显示空白屏幕。这在某种程度上是预料之中的,因为我猜测该函数需要输入 [0, 1] 或 [0, 255],并且会截断图像中超出该范围的像素值。
更令人担忧的是,ImageStat
对于大多数统计数据返回不正确的值。我已经通过从 numpy 和 Matlab 独立获得的结果确认了这两个值。对于更传统的 RGB 图像 mode='RGB'
,不会发生这种情况。
问题
这是怎么回事?这也是一个截断问题吗?
MCVE
使用以下图像作为test.png
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 supportI
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/