You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中实现基于整块中值滤波的图像下采样?

解决中值滤波式图像下采样的问题

我完全懂你的痛点——skimage.measure.block_reduce的逐轴计算逻辑确实和咱们要的整块中值下采样不是一回事。你举的例子里,它会先对行轴分块取中值,再对列轴分块取中值,这和直接对2x2块取整体中值的结果天差地别,断言失败太正常了。

推荐的两种解决方案

方法1:纯Numpy实现(高效简洁)

利用Numpy的reshape把图像拆分成规整的块,直接在块维度上取中值,完全符合你的预期:

import numpy as np

image = np.array([[4, 6, 6, 2],
                  [6, 7, 9, 9],
                  [3, 0, 9, 0],
                  [0, 6, 6, 4]])
block_size = (2, 2)

# 把图像reshape成 (块行数, 块高度, 块列数, 块宽度) 的结构
reshaped_img = image.reshape(
    image.shape[0] // block_size[0], block_size[0],
    image.shape[1] // block_size[1], block_size[1]
)
# 对每个块的高度和宽度维度取中值
downsampled = reshaped_img.median(axis=(1, 3))

# 验证结果和预期一致
expected = np.array([
    [np.median(image[0:2,0:2]), np.median(image[0:2,2:4])],
    [np.median(image[2:4,0:2]), np.median(image[2:4,2:4])]
])
assert np.array_equal(downsampled, expected)  # 这次断言会成功!

方法2:用skimage的view_as_blocks(直观易懂)

skimage的view_as_blocks可以直接把图像分割成非重叠的块,然后对每个块取中值,逻辑更直观:

from skimage.util import view_as_blocks
import numpy as np

image = np.array([[4, 6, 6, 2],
                  [6, 7, 9, 9],
                  [3, 0, 9, 0],
                  [0, 6, 6, 4]])
block_size = (2, 2)

# 生成块视图,形状为 (块行数, 块列数, 块高, 块宽)
blocks = view_as_blocks(image, block_size=block_size)
# 对每个块的内部维度取中值
downsampled = blocks.median(axis=(2, 3))

# 验证结果
expected = np.array([
    [np.median(image[0:2,0:2]), np.median(image[0:2,2:4])],
    [np.median(image[2:4,0:2]), np.median(image[2:4,2:4])]
])
assert np.array_equal(downsampled, expected)

为什么block_reduce不行?

简单说,block_reduce是逐轴依次应用函数,而不是对整个块一次性计算:

  1. 先沿行轴(axis=0)把图像分成2行一组的块,对每个块的每一列取中值,得到一个2×4的中间数组;
  2. 再沿列轴(axis=1)把中间数组分成2列一组的块,对每个块的每一行取中值,最终得到2×2的结果。
    这个过程和直接对2×2块取整体中值的计算逻辑完全不同,所以结果自然不一致。

内容的提问来源于stack exchange,提问作者jan bernlöhr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:43:42