[Python scipy] 2次元データのアップスケール/ダウンスケール


単語帳.毎回検索するのが面倒なので転載多め.元URLあり.

ときどき混乱するので:

  • アップスケール:解像度を粗くする
  • ダウンスケール:解像度を細かくする

値の内挿はここにまとめられている:
SciPy.org: Interpolation (scipy.interpolate)

この内アップスケール/ダウンスケールでよく使われるのは

  • interp2d
    • 2次元のみ.
    • kind = ‘linear’, ‘cubic’, ‘quintic’
  • RegularGridInterpolator
    • 2次元以外も使える
    • "regular grid"である必要(等間隔である必要はない)
    • method = 'linear', 'nearest'
    • こちらで良いならintrep2dよりも高速

RegularGridInterpolatorを使った例

stackoverflow: Scipy interpolation with masked data?
が分かりやすい.
MaskedArrayの場合は,(マスクされた部分をnp.nanで埋めるよりも)マスク自体を変換する方が高速.

import numpy as np
from scipy import interpolate

def conv_resol(arr, newshape, *args, **kwargs):
    '''
    Args:
        arr [2d ndarray or MaskedArray]
        newshape [tuple of int]
        *args, **kwargs: for interpolate.RegularGridInterpolator
    '''
    nx0, ny0 = arr.shape
    nx1, ny1 = newshape
    x0 = np.linspace(0, 1, nx0)
    y0 = np.linspace(0, 1, ny0)
    x1 = np.linspace(0, 1, nx1)
    y1 = np.linspace(0, 1, ny1)
    x1, y1 = np.meshgrid(x1, y1) # x1 [ny1,nx1], y1 [ny1, nx1]
    xy1 = np.array((x1, y1)).T   # xy1 [nx1, ny1, 2]
    arr1 = interpolate.RegularGridInterpolator((x0, y0), arr, *args, **kwargs)(xy1)
    if isinstance(arr, np.ma.MaskedArray):
        mask1 = interpolate.RegularGridInterpolator((x0, y0), arr.mask.astype('float'), *args, **kwargs)(xy1) > 0.0
        return np.ma.masked_array(arr1, mask=mask1)
    return arr1

テスト

import matplotlib.pyplot as plt


nx0, ny0 = 10, 20
arr0 = np.arange(nx0 * ny0).reshape(nx0, ny0) * (1.0 / (nx0 * ny0))

nx1, ny1 = 5, 10
arr1 = conv_resol(arr0, (nx1, ny1))

nx2, ny2 = 20, 40
arr2 = conv_resol(arr0, (nx2, ny2))

plt.figure(figsize=(12,8))
plt.subplot(2,2,1)
plt.imshow(arr0, vmin=0.0, vmax=1.0)
plt.subplot(2,2,3)
plt.imshow(arr1, vmin=0.0, vmax=1.0)
plt.subplot(2,2,4)
plt.imshow(arr2, vmin=0.0, vmax=1.0)