Python 为什么ImageStat返回有符号整数图像的不正确统计信息(`mode=';I';`)?
我的深度图像具有非常大的值范围,大约为[0,10000],保存为PNG。默认情况下,这些图像加载为具有32位带符号整数像素的PIL图像,但具有一些意外行为 例如,显示一个空白的白色屏幕。这在某种程度上是意料之中的,因为我猜该函数期望输入[0,1]或[0,255],并截断图像中超出该范围的像素值 更令人担忧的是,大多数统计数据返回的值都不正确。我已经用从Python 为什么ImageStat返回有符号整数图像的不正确统计信息(`mode=';I';`)?,python,numpy,python-imaging-library,Python,Numpy,Python Imaging Library,我的深度图像具有非常大的值范围,大约为[0,10000],保存为PNG。默认情况下,这些图像加载为具有32位带符号整数像素的PIL图像,但具有一些意外行为 例如,显示一个空白的白色屏幕。这在某种程度上是意料之中的,因为我猜该函数期望输入[0,1]或[0,255],并截断图像中超出该范围的像素值 更令人担忧的是,大多数统计数据返回的值都不正确。我已经用从numpy和Matlab独立获得的结果确认了这两个值。对于更传统的RGB图像,mode='RGB',这种情况不会发生 问题: 这是怎么回事?这也是
numpy
和Matlab独立获得的结果确认了这两个值。对于更传统的RGB图像,mode='RGB'
,这种情况不会发生
问题:
这是怎么回事?这也是一个截断问题吗
MCVE
使用下图作为test.png
Matlab的结果与numpy相似
Image.show()
显示一个空白的白色屏幕
原因是Image.show()
使用临时缓冲区存储图像对象。然后将图像对象转换为.bmp
(位图),然后再显示。位图格式不支持32位单通道图像(灰度),因此通过show()
获得的结果是不可取的
ImageStat
返回的大多数统计数据的值不正确
在对ImageStat
模块进行源代码分析后,我了解到该模块是专门为处理0的图像而构建的≤ 采样空间>256,或像素值在范围内的图像(0≤ 价值≤ 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的值。i、 e(值∈ {0-255})
Stat
功能的实现方式是,仅当图像像素值的范围小于256时,它才能正常工作
这也是一个截断问题吗
否。在计算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
执行时的代码:-
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
我们得到实际的像素值:-
40384, 40384, 40384, 40384, 40384, 40600, 40600, 40600, 40808, 41016, 41232, 41440, 41656.....22232]
结论:-PIL
本机支持32位有符号整数像素,但ImageStat
不支持
p.S.:-PIL/pillow文档的当前状态不是很好,即它不太擅长解释……无论它试图解释什么。因此,我们应该尽可能地增加更多的英特尔。因此,我建议您发布一个关于改进ImageStat
模块描述的问题/请求。如添加行,例如:-
模块不支持大于8位的像素值
或者其他类似的东西