在 Python 中使用 Nan 对图像进行高斯滤波 [英] Gaussian filtering a image with Nan in Python

查看:26
本文介绍了在 Python 中使用 Nan 对图像进行高斯滤波的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据二维坐标列表和第三个变量(速度),我创建了一个覆盖整个采样区域的二维 numpy 数组.我的目的是创建一个图像,其中每个像素都包含位于其中的点的平均速度.之后用高斯滤波器过滤该图像.

From a list of 2D coordinates, and a third variable (velocity), I have created a 2D numpy array covering the whole sampled area. My intention is to create an image, in which each pixel contains the mean velocity of the points lying within it. After that filter that image with a gaussian filter.

问题是该区域不是均匀采样的.因此,我在图像中间有几个没有信息的像素(Nan).当我尝试通过高斯滤波器过滤数组时,Nan 传播破坏了整个图像.

The problem is that the area is not uniformly sampled. Therefore I have several pixels without information (Nan) in the middle of the image. When I try to filter the array through a gaussian filter, the Nan propagate ruining the whole image.

我需要过滤这张图片,但拒绝所有没有信息的像素.换句话说,如果一个像素不包含信息,那么过滤就不应该考虑它.

I need to filter this image, but rejecting all pixels without information. In other words, If a pixel does not contain information, then it should be not taken into account for the filtering.

这是我的平均代码示例:

Here is an example of my code for averaging:

Mean_V = np.zeros([len(x_bins), len(y_bins)])

for i, x_bin in enumerate(x_bins[:-1]):
    bin_x = (x > x_bins[i]) & (x <= x_bins[i+1])
    for j, y_bin in enumerate(y_bins[:-1]):
        bin_xy = (y[bin_x] > y_bins[j]) & (y[bin_x] <= y_bins[j+1])
        if (sum(x > 0 for x in bin_xy) > 0) :
            Mean_V[i,j]=np.mean(V[bin_x][bin_xy])
        else:
            Mean_V[i,j]=np.nan

上网我已经结束了我在2013年提出的这个问题.这个问题的解决方案可以在astropy库中找到:

Surfing the web I have ended into this question I made in 2013. The solution to this problem can be found in the astropy library:

http://docs.astropy.org/en/stable/convolution/

Astropy 的卷积用相邻像素的核加权插值替换 NaN 像素.

Astropy's convolution replaces the NaN pixels with a kernel-weighted interpolation from their neighbors.

谢谢大家!!

推荐答案

文字:

忽略给定数组中的 NaN 的高斯滤波器 U 可以通过将标准高斯滤波器应用于两个辅助数组 VW 并取两者之比得到结果 Z.

A Gaussian filter which ignores NaNs in a given array U can be easily obtained by applying a standard Gaussian filter to two auxiliary arrays V and W and by taking the ratio of the two to get the result Z.

这里,V 是原始 U 的副本,NaN 被零替换,W 是一个数组,零表示位置原始 U 中的 NaN.

Here, V is copy of the original U with NaNs replaced by zeros and W is an array of ones with zeros indicating the positions of NaNs in the original U.

这个想法是用零替换 NaN 会在过滤后的数组中引入错误,但是可以通过将相同的高斯滤波器应用于另一个辅助数组并将两者结合来补偿.

The idea is that replacing the NaNs by zeros introduces an error in the filtered array which can, however, be compensated by applying the same Gaussian filter to another auxiliary array and combining the two.

在 Python 中:

import numpy as np
import scipy as sp
import scipy.ndimage

sigma=2.0                  # standard deviation for Gaussian kernel
truncate=4.0               # truncate filter at this many sigmas

U=sp.randn(10,10)          # random array...
U[U>2]=np.nan              # ...with NaNs for testing

V=U.copy()
V[np.isnan(U)]=0
VV=sp.ndimage.gaussian_filter(V,sigma=sigma,truncate=truncate)

W=0*U.copy()+1
W[np.isnan(U)]=0
WW=sp.ndimage.gaussian_filter(W,sigma=sigma,truncate=truncate)

Z=VV/WW

数字:

这里为了演示目的,高斯滤波器的系数设置为 [0.25,0.50,0.25],它们的总和为 0.25+0.50+0.25=1,不失一般性.

Here coefficients of the Gaussian filter are set to [0.25,0.50,0.25] for demonstration purposes and they sum up to one 0.25+0.50+0.25=1, without loss of generality.

在用零替换 NaN 并应用高斯滤波器(参见下面的 VV)后,很明显零引入了一个错误,即,由于缺失"数据,系数 0.25+0.50=0.75 没有相加到一个,因此低估了真实"的价值.

After replacing the NaNs by zeros and applying the Gaussian filter (cf. VV below) it is clear that the zeros introduce an error, i.e., due to the "missing" data the coefficients 0.25+0.50=0.75 do not sum up to one anymore and therefore underestimate the "true" value.

然而,这可以通过使用第二个辅助数组(参见下面的 WW)来补偿,在使用相同的高斯滤波后,它只包含系数的总和.

However, this can be compensated by using the second auxiliary array (cf. WW below) which, after filtering with the same Gaussian, just contains the sum of coefficients.

因此,将两个滤波后的辅助数组相除会重新调整系数,使它们总和为 1,而忽略 NaN 位置.

Therefore, dividing the two filtered auxiliary arrays rescales the coefficients such that they sum up to one while the NaN positions are ignored.

array U         1   2   NaN 1   2    
auxiliary V     1   2   0   1   2    
auxiliary W     1   1   0   1   1
position        a   b   c   d   e

filtered VV_b   = 0.25*V_a  + 0.50*V_b  + 0.25*V_c
                = 0.25*1    + 0.50*2    + 0
                = 1.25

filtered WW_b   = 0.25*W_a  + 0.50*W_b  + 0.25*W_c
                = 0.25*1    + 0.50*1    + 0
                = 0.75

ratio Z         = VV_b / WW_b  
                = (0.25*1 + 0.50*2) / (0.25*1    + 0.50*1)
                = 0.333*1 + 0.666*2
                = 1.666

更新 - 除以零:

以下内容包含@AndyL 和@amain 来自以下评论的有用问题和答案,谢谢!

The following incorporates useful questions and answers by @AndyL and @amain from the comments below, thanks!

当高斯核的支持范围内只有NaN条目时,NaN的大面积可能会导致某些位置的分母为零(WW=0)(理论上支持是无限的,但实际上核通常被截断,请参阅上面代码示例中的 'truncate' 参数).在这种情况下,提名者也变为零(VV = 0),因此 numpy 会抛出RuntimeWarning:在 true_divide 中遇到无效值"并在相应位置返回 NaN.

Large areas of NaNs may lead to a zero denominator (WW=0) at some positions when there are only NaN entries within the support of the Gaussian kernel (in theory that support is infinite, but in practice the kernel is usually truncated, see 'truncate' parameter in code example above). In that situation, the nominator becomes zero as well (VV=0) so that numpy throws a 'RuntimeWarning: invalid value encountered in true_divide' and returns NaN at the corresponding positions.

这可能是最一致/最有意义的结果,如果您能忍受一个麻木的警告,则无需进一步调整.

This is probably the most consistent/meaningful result and if you can live with a numpy warning, no further adjustments are required.

这篇关于在 Python 中使用 Nan 对图像进行高斯滤波的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆