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

基于质心居中的Numpy 3D数组分块需求:从中间分割为指定子数组

实现Numpy数组的质心居中分割

我来帮你搞定这个围绕质心居中分割Numpy数组的需求!核心就是要让原数组的中心点精准落在某个子数组的中心,同时保证所有子块均匀分布,咱们一步步来实现。

核心逻辑拆解

首先得明确几个关键数值:

  • 原数组的中心点索引:因为原数组各维度都是奇数(比如101、151),直接用每个维度长度整除2就能得到(比如101//2=50,151//2=70),这是咱们分割的基准点。
  • 子数组的半长:同样子数组是奇数尺寸,比如21的半长是(21-1)//2=10,这样子数组的中心到边缘的元素数完全一致,方便对齐原数组的中心点。
  • 子块分布规则:从中心子块开始,向原数组的前后/左右/上下均匀扩展子块,要么刚好衔接,要么在边缘补全覆盖(如果原数组长度不能被子块尺寸整除的话)。

具体代码实现

咱们直接上可运行的代码,每一步都给你注释清楚:

import numpy as np

# ---------------------- 自定义参数 ----------------------
# 原数组的尺寸,这里是题目给出的(101, 151, 101)
orig_shape = (101, 151, 101)
# 子数组的目标尺寸,示例为(21,21,21),可替换为任意奇数尺寸
sub_shape = (21, 21, 21)

# 创建测试用原数组(实际使用时替换成你的真实数组即可)
orig_array = np.random.rand(*orig_shape)
# -------------------------------------------------------

# 计算原数组各维度的中心点索引(0-based)
orig_centers = [dim // 2 for dim in orig_shape]
# 计算子数组各维度的半长(中心到边缘的元素个数)
sub_halfs = [(sub_dim - 1) // 2 for sub_dim in sub_shape]

def get_sub_starts(orig_len, sub_len, orig_center, sub_half):
    """生成单个维度上所有子块的起始索引,保证中心子块对齐原数组中心"""
    # 中心子块的起始索引:原中心点 - 子块半长
    center_start = orig_center - sub_half
    
    # 向左扩展子块:每次往前挪一个子块长度,直到超出数组左边界
    left_starts = []
    current_start = center_start - sub_len
    while current_start >= 0:
        left_starts.append(current_start)
        current_start -= sub_len
    # 反转一下,让左半部分的子块从左到右排列
    left_starts = left_starts[::-1]
    
    # 向右扩展子块:每次往后挪一个子块长度,直到超出数组右边界
    right_starts = []
    current_start = center_start + sub_len
    while current_start + sub_len <= orig_len:
        right_starts.append(current_start)
        current_start += sub_len
    
    # 合并所有起始索引:左半部分 → 中心 → 右半部分
    all_starts = left_starts + [center_start] + right_starts
    
    # 可选:补全边缘子块,确保覆盖整个原数组
    if all_starts[0] != 0:
        all_starts.insert(0, 0)
    last_end = all_starts[-1] + sub_len
    if last_end != orig_len:
        all_starts.append(orig_len - sub_len)
    
    return all_starts

# 获取三个维度各自的子块起始索引列表
starts_z = get_sub_starts(orig_shape[0], sub_shape[0], orig_centers[0], sub_halfs[0])
starts_y = get_sub_starts(orig_shape[1], sub_shape[1], orig_centers[1], sub_halfs[1])
starts_x = get_sub_starts(orig_shape[2], sub_shape[2], orig_centers[2], sub_halfs[2])

# 遍历所有起始索引组合,提取所有子数组
sub_arrays = []
for z_start in starts_z:
    for y_start in starts_y:
        for x_start in starts_x:
            # 生成每个维度的切片(左闭右开)
            z_slice = slice(z_start, z_start + sub_shape[0])
            y_slice = slice(y_start, y_start + sub_shape[1])
            x_slice = slice(x_start, x_start + sub_shape[2])
            # 提取子数组并加入列表
            sub_arr = orig_array[z_slice, y_slice, x_slice]
            sub_arrays.append(sub_arr)

验证与细节说明

验证中心点对齐

你可以运行下面的代码,确认原数组的中心点和中心子数组的中心点完全重合:

# 找到中心子块在列表中的位置
center_z_idx = starts_z.index(orig_centers[0] - sub_halfs[0])
center_y_idx = starts_y.index(orig_centers[1] - sub_halfs[1])
center_x_idx = starts_x.index(orig_centers[2] - sub_halfs[2])
center_sub_idx = center_z_idx * len(starts_y) * len(starts_x) + center_y_idx * len(starts_x) + center_x_idx

# 获取中心子数组
center_sub_arr = sub_arrays[center_sub_idx]

# 对比原数组中心点和中心子数组中心点的数值
orig_center_val = orig_array[orig_centers[0], orig_centers[1], orig_centers[2]]
sub_center_val = center_sub_arr[sub_halfs[0], sub_halfs[1], sub_halfs[2]]

print(f"原数组中心点数值: {orig_center_val:.6f}")
print(f"中心子数组中心点数值: {sub_center_val:.6f}")
print(f"中心点是否对齐: {np.isclose(orig_center_val, sub_center_val)}")  # 应该输出True

关键细节

  • 灵活性:子数组尺寸可以替换为任意奇数(比如(11,11,11)、(31,31,31)),代码会自动计算对应的半长和起始索引。
  • 边缘处理:代码里的补全边缘子块是可选的,如果你的需求不需要覆盖整个原数组,只需要均匀分布的子块,可以去掉那部分判断逻辑。
  • 均匀分布:子块之间以子数组尺寸为步长扩展,保证相邻子块的间距一致,实现均匀分布的效果。

内容的提问来源于stack exchange,提问作者ssm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:36:32