Оценка шума / Измерение шума на изображении - PullRequest
13 голосов
/ 14 марта 2010

Я хочу оценить шум на изображении.

Давайте предположим модель изображения + белый шум. Теперь я хочу оценить дисперсию шума.

Мой метод состоит в том, чтобы вычислить локальную дисперсию (от 3 * 3 до 21 * 21 блоков) изображения, а затем найти области, где локальная дисперсия является довольно постоянной (путем вычисления локальной дисперсии матрицы локальной дисперсии). Я предполагаю, что эти области "плоские", следовательно, дисперсия почти "чистый" шум.

Пока я не получаю постоянных результатов.

Есть ли лучший способ?

Спасибо.

P.S. Я ничего не могу предположить об изображении, кроме независимого шума (что не соответствует действительности для реального изображения, но давайте предположим, что это).

Ответы [ 3 ]

10 голосов
/ 22 августа 2014

Вы можете использовать следующий метод для оценки дисперсии шума (эта реализация работает только для изображений в оттенках серого):

def estimate_noise(I):

  H, W = I.shape

  M = [[1, -2, 1],
       [-2, 4, -2],
       [1, -2, 1]]

  sigma = np.sum(np.sum(np.absolute(convolve2d(I, M))))
  sigma = sigma * math.sqrt(0.5 * math.pi) / (6 * (W-2) * (H-2))

  return sigma

Ссылка: Дж. Иммеркер, «Быстрая оценка дисперсии шума», Компьютерное зрение и понимание изображений, Vol. 64, № 2, с. 300-302, сентябрь 1996 г. [ PDF ]

4 голосов
/ 14 марта 2010

Проблема характеризации сигнала от шума не проста. Исходя из вашего вопроса, первой попыткой было бы охарактеризовать статистику второго порядка: известно, что естественные изображения имеют попиксельные корреляции, которые по определению отсутствуют в белом шуме.

В фурье-пространстве корреляция соответствует энергетическому спектру. Известно, что для естественных изображений оно уменьшается как 1 / f ^ 2. Поэтому для количественной оценки шума я бы порекомендовал рассчитать коэффициент корреляции спектра вашего изображения с использованием обеих гипотез (плоская и 1 / f ^ 2), чтобы вы извлекли коэффициент.

Некоторые функции для запуска:

import numpy
def get_grids(N_X, N_Y):
    from numpy import mgrid
    return mgrid[-1:1:1j*N_X, -1:1:1j*N_Y]

def frequency_radius(fx, fy):
    R2 = fx**2 + fy**2
    (N_X, N_Y) = fx.shape
    R2[N_X/2, N_Y/2]= numpy.inf

    return numpy.sqrt(R2)

def enveloppe_color(fx, fy, alpha=1.0):
    # 0.0, 0.5, 1.0, 2.0 are resp. white, pink, red, brown noise
    # (see http://en.wikipedia.org/wiki/1/f_noise )
    # enveloppe
    return 1. / frequency_radius(fx, fy)**alpha #

import scipy
image = scipy.lena()
N_X, N_Y = image.shape
fx, fy = get_grids(N_X, N_Y)
pink_spectrum = enveloppe_color(fx, fy)

from scipy.fftpack import fft2
power_spectrum = numpy.abs(fft2(image))**2

Я рекомендую эту замечательную бумагу для более подробной информации.

1 голос
/ 27 июня 2018

Scikit Image имеет функцию оценки сигма, которая работает очень хорошо:

http://scikit -image.org / документы / DEV / API / skimage.restoration.html # skimage.restoration.estimate_sigma

он также работает с цветными изображениями, вам просто нужно установить multichannel=True и average_sigmas=True:

import cv2
from skimage.restoration import estimate_sigma

def estimate_noise(image_path):
    img = cv2.imread(image_path)
    return estimate_sigma(img, multichannel=True, average_sigmas=True)

Большие числа означают низкий уровень шума.

...