2013-12-24 106 views
9

附加圖像(test.tif)。 np.nan值是最白的區域。 如何使用一些使用來自鄰居的值的間隙填充算法來填充這些最白區域?使用numpy和scipy填充圖像上的空白

enter image description here

import scipy.ndimage 

data = ndimage.imread('test.tif') 
+0

查看scipy插值庫以找到適合您需求的函數。 http://docs.scipy.org/doc/scipy/reference/interpolate.html – M4rtini

回答

5

我認爲viena的問題更關係到inpainting問題。

這裏有一些想法:

  • 爲了填補在B/W圖象的空白,你可以使用一些填充算法像scipy.ndimage.morphology.binary_fill_holes。但是你有一個灰度級圖像,所以你不能使用它。

  • 我想你不想使用複雜的修復算法。我的第一個建議是:不要嘗試使用最近的灰度值(你不知道NaN像素的真實值)。使用最近的值會產生一個骯髒的算法。相反,我建議你用填補差距,並用一些其他值(例如該行的平均值)。您可以通過使用scikit-learn做沒有編碼:

Source:

>>> from sklearn.preprocessing import Imputer 
>>> imp = Imputer(strategy="mean") 
>>> a = np.random.random((5,5)) 
>>> a[(1,4,0,3),(2,4,2,0)] = np.nan 
>>> a 
array([[ 0.77473361, 0.62987193,   nan, 0.11367791, 0.17633671], 
    [ 0.68555944, 0.54680378,   nan, 0.64186838, 0.15563309], 
    [ 0.37784422, 0.59678177, 0.08103329, 0.60760487, 0.65288022], 
    [  nan, 0.54097945, 0.30680838, 0.82303869, 0.22784574], 
    [ 0.21223024, 0.06426663, 0.34254093, 0.22115931,   nan]]) 
>>> a = imp.fit_transform(a) 
>>> a 
array([[ 0.77473361, 0.62987193, 0.24346087, 0.11367791, 0.17633671], 
    [ 0.68555944, 0.54680378, 0.24346087, 0.64186838, 0.15563309], 
    [ 0.37784422, 0.59678177, 0.08103329, 0.60760487, 0.65288022], 
    [ 0.51259188, 0.54097945, 0.30680838, 0.82303869, 0.22784574], 
    [ 0.21223024, 0.06426663, 0.34254093, 0.22115931, 0.30317394]]) 
  • 骯髒的解決方案使用了最近的值可以是這樣的: 1)找到的周界點NaN區域 2)計算全部 NaN點與周界之間的距離 3)用NaN替代NaN e最近點灰度值
7

如果你想從最近的鄰居值,你可以從scipy.interpolate使用NearestNDInterpolator。也有other interpolators以及你可以考慮。

您可以找到X,對於NaN的Y索引值珍視同:

import numpy as np 

nan_locs = np.where(np.isnan(data)) 

有內插一些其他的選擇也是如此。一種選擇是用median filter的結果替換NaN值(但您的區域對此很大)。另一種選擇可能是grayscale dilation。正確的插值取決於您的最終域。

如果您之前沒有使用過SciPy ND插值器,則需要提供X,Y和值數據以適合插值器,然後爲X和Y數據插值。您可以使用上面的where示例作爲模板來執行此操作。

19

正如其他人所建議的,可以使用scipy.interpolate。但是,它需要進行相當廣泛的索引操作才能使其發揮作用。

完整的示例:

from pylab import * 
import numpy 
import scipy.ndimage 
import scipy.interpolate 
import pdb 

data = scipy.ndimage.imread('data.png') 

# a boolean array of (width, height) which False where there are missing values and True where there are valid (non-missing) values 
mask = ~((data[:,:,0] == 255) & (data[:,:,1] == 255) & (data[:,:,2] == 255)) 

# array of (number of points, 2) containing the x,y coordinates of the valid values only 
xx, yy = numpy.meshgrid(numpy.arange(data.shape[1]), numpy.arange(data.shape[0])) 
xym = numpy.vstack((numpy.ravel(xx[mask]), numpy.ravel(yy[mask]))).T 

# the valid values in the first, second, third color channel, as 1D arrays (in the same order as their coordinates in xym) 
data0 = numpy.ravel(data[:,:,0][mask]) 
data1 = numpy.ravel(data[:,:,1][mask]) 
data2 = numpy.ravel(data[:,:,2][mask]) 

# three separate interpolators for the separate color channels 
interp0 = scipy.interpolate.NearestNDInterpolator(xym, data0) 
interp1 = scipy.interpolate.NearestNDInterpolator(xym, data1) 
interp2 = scipy.interpolate.NearestNDInterpolator(xym, data2) 

# interpolate the whole image, one color channel at a time  
result0 = interp0(numpy.ravel(xx), numpy.ravel(yy)).reshape(xx.shape) 
result1 = interp1(numpy.ravel(xx), numpy.ravel(yy)).reshape(xx.shape) 
result2 = interp2(numpy.ravel(xx), numpy.ravel(yy)).reshape(xx.shape) 

# combine them into an output image 
result = numpy.dstack((result0, result1, result2)) 

imshow(result) 
show() 

輸出:

enter image description here

這傳遞給插所有值我們,不只是那些未來的缺失值(這可能是有點低效)。它也在輸出中每點插入,而不僅僅是缺失值(這是非常低效的)。更好的方法是隻插入缺失的值,然後將它們修補到原始圖像中。這只是一個快速開始的示例:)