skimage.measure 产生异常高的均方误差
skimage.measure produce strangely high mean square error
考虑以下代码
import numpy as np
from skimage import measure
def mse(x, y):
return np.mean(np.square(x - y))
def psnr(x, y):
return 10 * np.log10(255 ** 2 / mse(x, y))
x = (np.random.rand(512, 512) * 255).astype(np.uint8)
y = (np.random.rand(512, 512) * 255).astype(np.uint8)
print(type(x))
print('MSE (np)\t', mse(x, y))
print('MSE (sk)\t', measure.compare_mse(x, y))
print('PSNR(np)\t', psnr(x, y))
print('PSNR(sk)\t', measure.compare_psnr(x, y))
print('PSNR(dr)\t', measure.compare_psnr(x, y, data_range=255))
它产生(可能因随机而异):
MSE (np) 105.4649887084961
MSE (sk) 10802.859519958496
PSNR(np) 27.899720503741783
PSNR(sk) 7.7954163229186815
PSNR(dr) 7.7954163229186815
这很令人费解。
mean-squre error
与 vanilla numpy 实现相比非常高。
代码中的x
和y
是模拟一个8位整数数据深度的普通图像。
深入研究 github of skimage:
def _as_floats(im1, im2):
"""Promote im1, im2 to nearest appropriate floating point precision."""
float_type = np.result_type(im1.dtype, im2.dtype, np.float32)
im1 = np.asarray(im1, dtype=float_type)
im2 = np.asarray(im2, dtype=float_type)
return im1, im2
def compare_mse(im1, im2):
"""Compute the mean-squared error between two images.
Parameters
----------
im1, im2 : ndarray
Image. Any dimensionality.
Returns
-------
mse : float
The mean-squared error (MSE) metric.
"""
_assert_compatible(im1, im2)
im1, im2 = _as_floats(im1, im2)
return np.mean(np.square(im1 - im2), dtype=np.float64)
它将图像转换为 float32,然后再次重新转换为 float64,然后计算 MSE
。
这种方法是否会导致上面显示的 MSE
值飙升?
您的 MSE 函数是计算错误值的函数。计算 np.square(x - y)
是使用输入 x
和 y
的数据类型完成的,在本例中为 np.uint8
。如果任何平方差超过 255,它们将 "wrap around",例如
In [37]: a = np.array([2, 3, 225, 0], dtype=np.uint8)
In [38]: b = np.array([3, 2, 0, 65], dtype=np.uint8)
您已经可以看到减法中的问题:
In [39]: a - b
Out[39]: array([255, 1, 225, 191], dtype=uint8)
现在平方那些,又看到了更多的问题:
In [40]: np.square(a - b)
Out[40]: array([ 1, 1, 193, 129], dtype=uint8)
如果在调用函数之前将输入转换为浮点数,它与 skimage
函数一致:
In [41]: mse(x.astype(float), y.astype(float))
Out[41]: 10836.0170211792
In [42]: measure.compare_mse(x, y)
Out[42]: 10836.0170211792
考虑以下代码
import numpy as np
from skimage import measure
def mse(x, y):
return np.mean(np.square(x - y))
def psnr(x, y):
return 10 * np.log10(255 ** 2 / mse(x, y))
x = (np.random.rand(512, 512) * 255).astype(np.uint8)
y = (np.random.rand(512, 512) * 255).astype(np.uint8)
print(type(x))
print('MSE (np)\t', mse(x, y))
print('MSE (sk)\t', measure.compare_mse(x, y))
print('PSNR(np)\t', psnr(x, y))
print('PSNR(sk)\t', measure.compare_psnr(x, y))
print('PSNR(dr)\t', measure.compare_psnr(x, y, data_range=255))
它产生(可能因随机而异):
MSE (np) 105.4649887084961
MSE (sk) 10802.859519958496
PSNR(np) 27.899720503741783
PSNR(sk) 7.7954163229186815
PSNR(dr) 7.7954163229186815
这很令人费解。
mean-squre error
与 vanilla numpy 实现相比非常高。
代码中的x
和y
是模拟一个8位整数数据深度的普通图像。
深入研究 github of skimage:
def _as_floats(im1, im2):
"""Promote im1, im2 to nearest appropriate floating point precision."""
float_type = np.result_type(im1.dtype, im2.dtype, np.float32)
im1 = np.asarray(im1, dtype=float_type)
im2 = np.asarray(im2, dtype=float_type)
return im1, im2
def compare_mse(im1, im2):
"""Compute the mean-squared error between two images.
Parameters
----------
im1, im2 : ndarray
Image. Any dimensionality.
Returns
-------
mse : float
The mean-squared error (MSE) metric.
"""
_assert_compatible(im1, im2)
im1, im2 = _as_floats(im1, im2)
return np.mean(np.square(im1 - im2), dtype=np.float64)
它将图像转换为 float32,然后再次重新转换为 float64,然后计算 MSE
。
这种方法是否会导致上面显示的 MSE
值飙升?
您的 MSE 函数是计算错误值的函数。计算 np.square(x - y)
是使用输入 x
和 y
的数据类型完成的,在本例中为 np.uint8
。如果任何平方差超过 255,它们将 "wrap around",例如
In [37]: a = np.array([2, 3, 225, 0], dtype=np.uint8)
In [38]: b = np.array([3, 2, 0, 65], dtype=np.uint8)
您已经可以看到减法中的问题:
In [39]: a - b
Out[39]: array([255, 1, 225, 191], dtype=uint8)
现在平方那些,又看到了更多的问题:
In [40]: np.square(a - b)
Out[40]: array([ 1, 1, 193, 129], dtype=uint8)
如果在调用函数之前将输入转换为浮点数,它与 skimage
函数一致:
In [41]: mse(x.astype(float), y.astype(float))
Out[41]: 10836.0170211792
In [42]: measure.compare_mse(x, y)
Out[42]: 10836.0170211792