Source code for pyradar.filters.frost
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2012 - 2013
# Matías Herranz <matiasherranz@gmail.com>
# Joaquín Tita <joaquintita@gmail.com>
#
# https://github.com/PyRadar/pyradar
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
from scipy.stats import variation
from utils import assert_window_size
from utils import assert_indices_in_range
COEF_VAR_DEFAULT = 0.01
[docs]def compute_coef_var(image, x_start, x_end, y_start, y_end):
"""
Compute coefficient of variation in a window of [x_start: x_end] and
[y_start:y_end] within the image.
"""
assert x_start >= 0, 'ERROR: x_start must be >= 0.'
assert y_start >= 0, 'ERROR: y_start must be >= 0.'
x_size, y_size = image.shape
x_overflow = x_end > x_size
y_overflow = y_end > y_size
assert not x_overflow, 'ERROR: invalid parameters cause x window overflow.'
assert not y_overflow, 'ERROR: invalid parameters cause y window overflow.'
window = image[x_start:x_end, y_start:y_end]
coef_var = variation(window, None)
if not coef_var: # dirty patch
coef_var = COEF_VAR_DEFAULT
# print "squared_coef was equal zero but replaced by %s" % coef_var
assert coef_var > 0, 'ERROR: coeffient of variation cannot be zero.'
return coef_var
[docs]def calculate_all_Mi(window_flat, factor_A, window):
"""
Compute all the weights of pixels in the window.
"""
N, M = window.shape
center_pixel = np.float64(window[N / 2, M / 2])
window_flat = np.float64(window_flat)
distances = np.abs(window_flat - center_pixel)
weights = np.exp(-factor_A * distances)
return weights
[docs]def calculate_local_weight_matrix(window, factor_A):
"""
Returns an array with the weights for the pixels in the given window.
"""
weights_array = np.zeros(window.size)
window_flat = window.flatten()
weights_array = calculate_all_Mi(window_flat, factor_A, window)
return weights_array
[docs]def frost_filter(img, damping_factor=2.0, win_size=3):
"""
Apply frost filter to a numpy matrix containing the image, with a window of
win_size x win_size.
By default, the window size is 3x3.
"""
assert_window_size(win_size)
img_filtered = np.zeros_like(img)
N, M = img.shape
win_offset = win_size / 2
for i in xrange(0, N):
xleft = i - win_offset
xright = i + win_offset
if xleft < 0:
xleft = 0
if xright >= N:
xright = N - 1
for j in xrange(0, M):
yup = j - win_offset
ydown = j + win_offset
if yup < 0:
yup = 0
if ydown >= M:
ydown = M - 1
assert_indices_in_range(N, M, xleft, xright, yup, ydown)
# inspired by http://www.pcigeomatics.com/cgi-bin/pcihlp/FFROST
variation_coef = compute_coef_var(img, xleft, xright, yup, ydown)
window = img[xleft:xright, yup:ydown]
window_mean = window.mean()
sigma_zero = variation_coef / window_mean # var / u^2
factor_A = damping_factor * sigma_zero
weights_array = calculate_local_weight_matrix(window, factor_A)
pixels_array = window.flatten()
weighted_values = weights_array * pixels_array
img_filtered[i, j] = weighted_values.sum() / weights_array.sum()
return img_filtered