34

我有基本的二维 numpy 数组,我想将它们“下采样”到更粗略的分辨率。是否有一个简单的 numpy 或 scipy 模块可以轻松做到这一点?我还应该注意,这个数组是通过 Basemap 模块在地理上显示的。

样本: 在此处输入图像描述

4

8 回答 8

14

scikit-image已经实现了downsampling这里的工作版本,尽管如果我理解正确的话,他们回避称它downsampling不是 DSP 方面的下采样:

http://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.block_reduce

但它工作得很好,而且它是downsampler我在Python中发现的唯一可以np.nan在图像中处理的。我很快就用这个对巨大的图像进行了下采样。

于 2015-03-17T00:54:35.677 回答
10

下采样时,插值是错误的做法。始终使用聚合方法。

我使用块手段来做到这一点,使用“因素”来降低分辨率。

import numpy as np
from scipy import ndimage

def block_mean(ar, fact):
    assert isinstance(fact, int), type(fact)
    sx, sy = ar.shape
    X, Y = np.ogrid[0:sx, 0:sy]
    regions = sy/fact * (X/fact) + Y/fact
    res = ndimage.mean(ar, labels=regions, index=np.arange(regions.max() + 1))
    res.shape = (sx/fact, sy/fact)
    return res

例如,使用因子 5(5x5 块)的 (100, 200) 形状数组会产生 (20, 40) 数组结果:

ar = np.random.rand(20000).reshape((100, 200))
block_mean(ar, 5).shape  # (20, 40)
于 2013-09-09T23:09:33.140 回答
6

imresizendimage.interpolation.zoom看起来像他们做你想做的事

我以前没有尝试过 imresize 但这是我使用 ndimage.interpolation.zoom 的方式

a = np.array(64).reshape(8,8)
a = ndimage.interpolation.zoom(a,.5) #decimate resolution

a 是一个 4x4 矩阵,其中包含插值

于 2013-09-06T20:30:27.460 回答
3

最简单的方法:您可以使用array[0::2]仅考虑每隔一个索引的表示法。例如

array= np.array([[i+j for i in range(0,10)] for j in range(0,10)])
down_sampled=array[0::2,0::2]

print("array \n", array)
print("array2 \n",down_sampled)

有输出:

array 
[[ 0  1  2  3  4  5  6  7  8  9]
 [ 1  2  3  4  5  6  7  8  9 10]
 [ 2  3  4  5  6  7  8  9 10 11]
 [ 3  4  5  6  7  8  9 10 11 12]
 [ 4  5  6  7  8  9 10 11 12 13]
 [ 5  6  7  8  9 10 11 12 13 14]
 [ 6  7  8  9 10 11 12 13 14 15]
 [ 7  8  9 10 11 12 13 14 15 16]
 [ 8  9 10 11 12 13 14 15 16 17]
 [ 9 10 11 12 13 14 15 16 17 18]]
array2 
[[ 0  2  4  6  8]
 [ 2  4  6  8 10]
 [ 4  6  8 10 12]
 [ 6  8 10 12 14]
 [ 8 10 12 14 16]]
于 2019-07-29T08:28:25.957 回答
3

xarray 的“coarsen”方法可以对 xarray.Dataset 或 xarray.DataArray 进行下采样

例如:

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15,5))

# Create a 10x10 array of random numbers
a = xr.DataArray(np.random.rand(10,10)*100, dims=['x', 'y'])

# "Downscale" the array, mean of blocks of size (2x2)
b = a.coarsen(x=2, y=2).mean()

# "Downscale" the array, mean of blocks of size (5x5)
c = a.coarsen(x=5, y=5).mean()


# Plot and cosmetics
a.plot(ax=ax1)
ax1.set_title("Full Data")

b.plot(ax=ax2)
ax2.set_title("mean of (2x2) boxes")

c.plot(ax=ax3)
ax3.set_title("mean of (5x5) boxes")

在此处输入图像描述

于 2020-04-10T04:16:57.887 回答
3

因为 OP 只想要更粗的分辨率,所以我想我会分享我的方法,将每个维度的像素数减少一半。我取 2x2 块的平均值。这可以多次应用以减少 2 倍。

from scipy.ndimage import convolve
array_downsampled = convolve(array, 
                 np.array([[0.25,0.25],[0.25,0.25]]))[:array.shape[0]:2,:array.shape[1]:2]
于 2017-10-12T13:51:35.017 回答
1

这可能不是你要找的,但我想我会为了完整性而提到它。

您可以尝试安装scikits.samplerate( docs ),它是 libsamplerate 的 Python 包装器。它提供了很好的、高质量的重采样算法——但据我所知,它只适用于一维。您可能能够先沿一个轴然后沿另一个轴重新采样您的 2D 信号,但我认为这可能会抵消高质量重采样的好处。

于 2013-09-06T21:54:50.987 回答
1

这将获取任何分辨率的图像,并通过获取图像数组的第 4 个索引仅返回其大小的四分之一。

import cv2
import numpy as np

def quarter_res_drop(im):

    resized_image = im[0::4, 0::4]
    cv2.imwrite('resize_result_image.png', resized_image)

    return resized_image

im = cv2.imread('Your_test_image.png', 1)

quarter_res_drop(im)
于 2020-02-21T16:36:02.553 回答