skimage.measure выдает странно высокую среднеквадратичную ошибку - PullRequest
0 голосов
/ 14 октября 2018

Рассмотрим следующий код

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 является экстремально высоким по сравнению с ванильной реализацией.

x и y в коде предназначены для имитации обычного изображения с 8-битной целочисленной глубиной данных.Копайте в github скимаджа :

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 величине, показанной выше?

1 Ответ

0 голосов
/ 14 октября 2018

Ваша функция MSE неправильно вычисляет значение.Расчет np.square(x - y) выполняется с типами данных входов x и y, что в данном случае составляет np.uint8.Если какое-либо из квадратов разностей превысит 255, они будут «обтекать», например:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...