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

如何沿Z轴归一化3D脊柱地标数据以实现脊柱曲率分类?

脊柱3D地标缩放问题

我在一项研究项目中,需要利用椎体的3D地标对不同类型的脊柱曲率进行分类。现有:

  • 2名患者脊柱地标的3D图
  • 期望的可视化效果示例

由于仅关注曲率特征,而患者身高体型存在差异,我需要沿Z轴缩放/归一化3D数据,但不确定如何在保持X、Y轴与Z轴关联的前提下完成Z轴缩放。

数据情况

我用来输出数据的代码:

print(spine_landmark_data_x.head(1).T)
print(spine_landmark_data_y.head(1).T)
print(spine_landmark_data_z.head(1).T)

输出的DataFrame里,X、Y、Z坐标分属三个独立的DataFrame。

我尝试的缩放代码

test_x = spine_landmark_data_x.copy()
test_y = spine_landmark_data_y.copy()
test_z = spine_landmark_data_z.copy()

# Scale each patient z-axis from 0 to 1
for row in range(spine_landmark_data.shape[0]):
    test_z.iloc[row] = spine_landmark_data_z.iloc[row] - spine_landmark_data_z.iloc[row].min()
    test_z.iloc[row] = test_z.iloc[row] / test_z.iloc[row].max()
    
    test_y.iloc[row] = spine_landmark_data_y.iloc[row] - spine_landmark_data_y.iloc[row].min()
    test_y.iloc[row] = test_y.iloc[row] / test_y.iloc[row].max()
    
    test_x.iloc[row] = spine_landmark_data_x.iloc[row] - spine_landmark_data_x.iloc[row].min()
    test_x.iloc[row] = test_x.iloc[row] / test_x.iloc[row].max()

运行这段代码后生成的可视化效果不符合预期。


解决方案

你之前的做法错在对X、Y、Z三个轴做了独立归一化,这会彻底破坏脊柱曲率的空间关联性——毕竟曲率是X/Y相对于Z轴的变化关系,单独缩放X/Y会把原本的弯曲形态扭曲掉。正确的思路是仅基于Z轴的缩放比例,对X和Y轴做等比例缩放,这样就能保留脊柱的相对曲率特征。

具体实现步骤

  1. 对每个患者的Z轴数据做归一化(比如缩放到0-1范围),算出该患者Z轴的缩放系数;
  2. 用同一个缩放系数处理该患者的X、Y轴数据,同时保持X/Y的相对位置不变。

修正后的代码

test_x = spine_landmark_data_x.copy()
test_y = spine_landmark_data_y.copy()
test_z = spine_landmark_data_z.copy()

for row in range(spine_landmark_data.shape[0]):
    # 处理Z轴:归一化到0-1区间,记录Z轴的长度范围
    z_vals = spine_landmark_data_z.iloc[row]
    z_min = z_vals.min()
    z_range = z_vals.max() - z_min
    
    # 避免Z轴值全相同导致除0错误
    if z_range == 0:
        test_z.iloc[row] = z_vals
        test_x.iloc[row] = spine_landmark_data_x.iloc[row]
        test_y.iloc[row] = spine_landmark_data_y.iloc[row]
        continue
    
    test_z.iloc[row] = (z_vals - z_min) / z_range
    
    # 用Z轴的缩放比例处理X轴:保留X轴的相对位置,仅缩放比例
    x_vals = spine_landmark_data_x.iloc[row]
    x_center = x_vals.mean()  # 以X轴中心为基准,避免整体偏移
    test_x.iloc[row] = (x_vals - x_center) / z_range + x_center
    
    # 同理处理Y轴
    y_vals = spine_landmark_data_y.iloc[row]
    y_center = y_vals.mean()
    test_y.iloc[row] = (y_vals - y_center) / z_range + y_center

关键说明

  • 如果不需要保留X/Y的绝对中心位置,也可以选择对齐X/Y的最小值后再缩放,但核心原则不变:X/Y的缩放比例必须和Z轴的缩放比例一致;
  • 要是你的目标是让所有患者的Z轴长度统一(比如都缩到0-1),那X/Y的缩放因子就是1/z_range,这样脊柱的弯曲形态会完整保留;
  • 绝对不能对X/Y做独立的归一化操作,这会直接丢失曲率的空间相关性,导致可视化和后续分类都出现偏差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:10:35