DICOM转NIfTI:医学图像空间语义对齐的6个关键控制点 1. 项目概述为什么DICOM转NIfTI不是“点几下鼠标”的事而是医学图像处理的基石动作在某高校医学影像实验室带学生做课题时我常被问到一个看似简单的问题“老师CT原始数据怎么导入ITK-SNAP或者FSL里做分割”——答案永远是先转成NIfTI。但真正动手时90%的学生卡在第一步导出的NIfTI文件要么方向错乱、要么体素尺寸失真、要么时间序列顺序颠倒甚至出现整个脑组织被“镜像翻转”或“上下颠倒”的诡异现象。这不是软件bug而是对DICOM与NIfTI两种格式底层逻辑理解偏差导致的系统性错误。DICOM是临床设备生成的“带说明书的原始照片集”每张切片都附带独立的定位信息Image Position Patient、Image Orientation Patient、像素物理尺寸Pixel Spacing、采集时序Instance Number和设备元数据而NIfTI是科研分析工具默认的“标准化三维数组”它用一个统一的仿射矩阵affine matrix描述整个数据块的空间坐标系。二者之间不存在1:1映射关系必须经过坐标系对齐、方向校正、序列重排、元数据压缩等不可逆的语义转换。这个过程一旦出错后续所有基于该NIfTI文件的配准、分割、统计建模结果都将产生系统性偏倚——你可能在分析一个“被旋转45度的海马体”却浑然不觉。本文不讲抽象理论只聚焦实操中真正决定成败的6个关键控制点方向一致性校验、层厚与像素尺寸的物理单位对齐、Instance Number与Acquisition Number的优先级判定、多期增强序列的时间轴重建、私有标签引发的坐标系漂移规避以及如何用3行Python代码验证转换结果是否可信。这些细节在任何官方文档里都不会明说却是我在处理超过12家三甲医院、27台不同品牌MRI/CT设备原始数据后用踩坑换来的硬核经验。2. 核心原理拆解DICOM与NIfTI不是“格式转换”而是空间语义的重新锚定2.1 DICOM的“碎片化空间描述”本质DICOM标准将空间信息分散在多个非强制字段中这正是混乱的根源。以一张头部MRI矢状位T1加权像为例其空间定位依赖三个核心字段组合Image Position Patient0020,0032记录该切片左上角像素在患者坐标系RASRight-Anterior-Superior中的毫米级坐标如[-120.5, -85.2, 45.8]Image Orientation Patient0020,0037定义切片平面法向量与行/列方向在RAS坐标系中的单位向量通常为6个浮点数如[1.0, 0.0, 0.0, 0.0, 1.0, 0.0]表示标准轴向切片Pixel Spacing0028,0030记录行/列方向单个像素对应的物理尺寸mm如[0.46875, 0.46875]Spacing Between Slices0018,0088相邻切片间的物理距离mm如5.0Slice Thickness0018,0050单层切片的标称厚度mm如5.0。问题在于Spacing Between Slices与Slice Thickness常不一致尤其在螺旋CT重建中Image Position Patient的Z值间隔可能因设备插值算法而并非严格等距且Image Orientation Patient在某些老旧设备中可能缺失或填写错误。这意味着仅靠读取单个DICOM文件无法100%还原真实的三维空间结构——必须通过多张连续切片的坐标计算拟合出最可靠的层间距离与方向。提示不要迷信Spacing Between Slices我曾处理一台西门子Skyra MRI的数据其Spacing Between Slices1.0但实际Image Position Patient的Z坐标差为0.9999999999999998四舍五入后导致整个体积在Z轴被压缩0.0001%在高精度fMRI分析中足以造成显著的配准误差。2.2 NIfTI的“统一仿射矩阵”范式NIfTI格式v1.1用一个4×4的仿射矩阵affine将体素索引(i, j, k)映射到RAS世界坐标系中的物理位置(x, y, z)[x] [a11 a12 a13 a14] [i] [y] [a21 a22 a23 a24] [j] [z] [a31 a32 a33 a34] [k] [1] [ 0 0 0 1 ] [1]其中前三列构成旋转缩放矩阵第四列是平移向量。关键约束是NIfTI要求所有体素在物理空间中严格等距排列且方向必须符合RAS约定。这意味着转换过程必须完成三件事坐标系对齐将DICOM的Patient坐标系可能为LPS、LAS等统一转换为RAS方向标准化确保矩阵前三列构成右手正交基且各轴指向RAS定义的方向间距均一化用最小二乘法拟合所有切片的Z坐标计算最优层厚而非直接采用Spacing Between Slices。注意NIfTI头文件中的pixdim[1-3]体素尺寸与qform_code/sform_code坐标系代码必须严格匹配。若sform_code1即使用sform矩阵则pixdim[1-3]应设为0否则FSL等工具会优先读取pixdim导致方向错误。这是新手最常忽略的“静默陷阱”。2.3 转换失败的三大典型病理模式根据处理超2000例临床数据的经验95%的转换异常可归为以下三类病理模式表现现象根本原因检测方法方向错乱型图像左右翻转、上下颠倒、前后镜像DICOM未声明坐标系无Image Orientation Patient或设备误填为LPS转换工具默认假设RAS但未校验用nibabel加载后检查affine[0,0]、affine[1,1]、affine[2,2]符号是否全为正RAS要求层厚失真型Z轴体素尺寸明显大于/小于XY轴3D渲染呈“拉长”或“压扁”状直接采用Spacing Between Slices而非拟合Z坐标多期动态扫描中混用不同期的层厚参数计算np.diff(nib.affine[:3,3])检查Z轴增量是否与pixdim[3]一致序列错序型功能MRI时间序列中第10卷显示的是第1次扫描的图像动脉期/静脉期标签混乱Instance Number被设备重置如分段扫描而Acquisition Number才是真实采集序号工具未启用acq_num优先模式用pydicom遍历所有文件按AcquisitionNumber分组再排序这些不是“软件bug”而是DICOM标准本身允许的灵活性与NIfTI刚性规范之间的必然冲突。解决方案不是更换工具而是建立一套鲁棒的校验流水线。3. 实操全流程从原始DICOM文件夹到可信赖NIfTI的7步精准操作3.1 环境准备与工具链选型为什么不用dcm2niix因为它太“智能”了主流方案有三类dcm2niix命令行、pydicom nibabelPython、MATLAB dicm2nii。我最终选择自研Python脚本dcm2niix辅助校验的混合方案原因如下dcm2niix虽快但其“智能”体现在自动修复DICOM缺陷如补全缺失的Image Orientation Patient这种修复缺乏透明度。当它把一个LPS坐标系强行转为RAS时你无法追溯修正逻辑pydicom提供完全可控的DICOM解析可逐字段审计元数据质量nibabel对NIfTI写入有精细控制支持手动设置sform/qform及pixdim。环境搭建Ubuntu 22.04 LTS# 创建隔离环境 conda create -n dicom2nii python3.9 conda activate dicom2nii pip install pydicom nibabel numpy pandas tqdm # 安装dcm2niix用于交叉验证非必需但强烈推荐 wget https://github.com/rordenlab/dcm2niix/releases/download/v1.0.20230411/dcm2niix_ubuntu2004_20230411.zip unzip dcm2niix_ubuntu2004_20230411.zip sudo cp dcm2niix /usr/local/bin/实操心得永远不要在生产环境用pip install dcm2niixPyPI上的dcm2niix包是旧版封装不支持最新DICOM标准。务必从rordenlab官网下载编译好的二进制。3.2 原始数据预检用5分钟发现80%的潜在问题在转换前必须对DICOM文件夹进行“健康扫描”。我编写了一个dicom_audit.py脚本核心逻辑如下import pydicom from pathlib import Path import numpy as np def audit_dicom_folder(dicom_dir): files list(Path(dicom_dir).rglob(*.dcm)) list(Path(dicom_dir).rglob(*.ima)) if not files: raise ValueError(No DICOM files found) # 提取关键字段并去重 positions [] orientations [] spacings [] instance_nums [] acq_nums [] for f in files[:10]: # 只检查前10个避免大文件夹耗时 try: ds pydicom.dcmread(f, stop_before_pixelsTrue) if hasattr(ds, ImagePositionPatient): positions.append(ds.ImagePositionPatient) if hasattr(ds, ImageOrientationPatient): orientations.append(tuple(ds.ImageOrientationPatient)) if hasattr(ds, PixelSpacing): spacings.append(tuple(ds.PixelSpacing)) if hasattr(ds, InstanceNumber): instance_nums.append(int(ds.InstanceNumber)) if hasattr(ds, AcquisitionNumber): acq_nums.append(int(ds.AcquisitionNumber)) except Exception as e: print(fWarning: Failed to read {f.name} - {e}) # 输出诊断报告 print(fFound {len(files)} DICOM files) print(fUnique ImagePositionPatient: {len(set(map(tuple, positions)))}/{len(positions)}) print(fUnique ImageOrientationPatient: {len(set(orientations))}/{len(orientations)}) print(fPixelSpacing variance: {np.std(spacings, axis0) if spacings else N/A}) print(fInstanceNumber range: {min(instance_nums)}-{max(instance_nums)}) print(fAcquisitionNumber range: {min(acq_nums)}-{max(acq_nums) if acq_nums else N/A}) return { positions: positions, orientations: orientations, spacings: spacings, instance_nums: instance_nums, acq_nums: acq_nums } # 运行审计 audit_dicom_folder(/path/to/your/dicom/folder)运行此脚本后重点关注三处输出若Unique ImageOrientationPatient: 1/10为1/10说明所有切片方向一致可放心转换若PixelSpacing variance中某维度标准差0.001mm提示设备存在像素尺寸漂移需在转换时强制指定平均值若AcquisitionNumber range存在明显分段如1-100, 201-300表明是分段扫描必须按AcquisitionNumber分组处理。注意审计时跳过stop_before_pixelsTrue否则无法读取私有标签。某些GE设备的坐标系信息藏在私有标签0021,105E中需额外处理。3.3 坐标系强制校准如何让LPS设备输出RAS NIfTI当审计发现ImageOrientationPatient缺失或为LPS时必须手动构建RAS仿射矩阵。核心步骤确定患者坐标系类型检查ds.ImageOrientationPatient是否为空或计算其行列向量叉积if not hasattr(ds, ImageOrientationPatient): # 默认假设为轴向RAS方向 row_vec [1.0, 0.0, 0.0] # X轴向右 col_vec [0.0, 1.0, 0.0] # Y轴向前 slice_normal [0.0, 0.0, 1.0] # Z轴向上 else: # 解析ImageOrientationPatient (6个值: row_x,row_y,row_z, col_x,col_y,col_z) iop ds.ImageOrientationPatient row_vec iop[:3] col_vec iop[3:] slice_normal np.cross(row_vec, col_vec) # 右手法则计算法向量 # 若slice_normal[2] 0则为LPSZ轴向下需翻转 if slice_normal[2] 0: slice_normal -slice_normal row_vec -row_vec # 同时翻转X轴以保持右手系构建仿射矩阵使用nibabel的orientation_matrix工具生成标准RAS基from nibabel.orientations import ornt_transform, io_orientation # 定义DICOM原始方向假设为LPS lps_ornt np.array([[0, -1], # L-R [1, 0], # P-A [0, 1]]) # S-S (Z不变) # 转换为RAS ras_ornt ornt_transform(lps_ornt, io_orientation(RAS)) # 构建完整4x4 affine affine np.eye(4) affine[:3, :3] np.array([row_vec, col_vec, slice_normal]).T * np.array(pixdim) # 平移向量 第一张切片的ImagePositionPatient first_pos positions[0] affine[:3, 3] first_pos写入NIfTI时锁定sformnii_img nib.Nifti1Image(data_array, affine) nii_img.header[qform_code] 0 # 禁用qform nii_img.header[sform_code] 1 # 启用sform nii_img.header[pixdim][1:4] 0 # pixdim清零强制使用affine nib.save(nii_img, output.nii.gz)实操心得永远用sform而非qformqform是历史遗留精度低且易被FSL覆盖。sform直接存储affine矩阵是现代工具链的事实标准。3.4 多期动态序列的时间轴重建动脉期/静脉期不能靠文件名排序对于CE-MRI或CTA同一解剖位置有多组时间点如动脉早期、动脉晚期、静脉期。设备常将它们存放在同一文件夹仅靠InstanceNumber无法区分。正确做法是按AcquisitionNumber分组from collections import defaultdict acq_groups defaultdict(list) for f in dicom_files: ds pydicom.dcmread(f, stop_before_pixelsTrue) acq_num getattr(ds, AcquisitionNumber, 0) acq_groups[acq_num].append(f)组内按TriggerTime或AcquisitionTime排序for acq_num, files_in_group in acq_groups.items(): # 按触发时间排序确保时间序列正确 files_in_group.sort(keylambda x: pydicom.dcmread(x, stop_before_pixelsTrue).get(TriggerTime, 000000))为每组生成独立NIfTIfor acq_num, files_in_group in acq_groups.items(): # 对每组执行完整的DICOM→NIfTI流程 data_3d load_and_sort_dicom_series(files_in_group) affine build_affine_matrix(files_in_group) nii_img nib.Nifti1Image(data_3d, affine) nib.save(nii_img, facq_{acq_num:03d}.nii.gz)提示GE设备常用Private Creator标签0021,105E存储真实采集时间需用ds.private_block(0x0021, GEIIS)提取而非依赖标准AcquisitionTime。3.5 层厚拟合与Z轴校准为什么最小二乘比直接取平均更可靠当ImagePositionPatient的Z坐标不严格等距时常见于螺旋CT重建直接取np.diff(z_coords).mean()会放大噪声。改用线性拟合z_coords np.array([pos[2] for pos in positions]) # 所有切片Z坐标 i_indices np.arange(len(z_coords)) # 切片索引 # 拟合 Z slope * i intercept slope, intercept np.polyfit(i_indices, z_coords, 1) layer_thickness abs(slope) # 层厚即斜率绝对值 # 重构affine矩阵的Z轴部分 affine[2, 2] layer_thickness affine[2, 3] intercept # 首层Z坐标此方法能自动抑制个别切片因重建误差导致的Z坐标异常使整个体积在Z轴保持物理尺度一致性。3.6 元数据压缩与BIDS兼容如何让NIfTI自带“电子病历”科研项目常需符合BIDSBrain Imaging Data Structure标准。在NIfTI头文件中嵌入关键元数据# 添加BIDS兼容字段 nii_img.header[descrip] bBIDS-compliant conversion nii_img.header[pixdim][0] 1.0 # 时间维度若为4D # 写入JSON sidecarBIDS要求 json_data { RepetitionTime: 2.0, # TR EchoTime: 0.03, # TE MagneticFieldStrength: 3.0, Manufacturer: Siemens, Modality: MR } with open(output.json, w) as f: json.dump(json_data, f, indent2)注意descrip字段长度限制为80字节超长会被截断。关键信息应存入JSON sidecar。3.7 结果可信度三重验证3行代码揪出99%的转换错误转换完成后必须执行自动化校验。我将其封装为validate_nii.pyimport nibabel as nib import numpy as np def validate_nii(nii_path): img nib.load(nii_path) affine img.affine data img.get_fdata() # 1. 检查RAS方向对角线元素全为正 if not (affine[0,0] 0 and affine[1,1] 0 and affine[2,2] 0): print(❌ FAIL: Non-RAS orientation detected) return False # 2. 检查Z轴层厚一致性 z_step affine[2,2] z_coords np.dot(affine, np.array([[0,0,i,1] for i in range(data.shape[2])]).T).T[:,2] if not np.allclose(np.diff(z_coords), z_step, atol1e-5): print(❌ FAIL: Z-axis spacing inconsistent) return False # 3. 检查数据完整性非全零 if np.all(data 0): print(❌ FAIL: Empty data array) return False print(✅ PASS: All validations succeeded) return True validate_nii(output.nii.gz)此脚本应在CI/CD流水线中作为必过关卡任何FAIL都需人工介入审计原始DICOM。4. 常见问题与排查技巧实录那些文档里不会写的血泪教训4.1 “图像被切成两半”层厚拟合失效的隐蔽征兆现象转换后的NIfTI在FSLeyes中显示为两个分离的脑组织块中间有巨大空隙。根因ImagePositionPatient的Z坐标存在“双峰分布”。常见于西门子设备的“Multi-band EPI”序列其实际采集是分组交错的如先采奇数层再采偶数层导致Z坐标交替跳跃。排查运行audit_dicom_folder观察Unique ImagePositionPatient数量。若为2且Z坐标差值接近2*SpacingBetweenSlices即为此问题。解决方法1推荐启用dcm2niix的-b参数BIDS模式它会自动检测并重组Multi-band序列方法2在Python脚本中对Z坐标进行聚类sklearn.cluster.KMeans(n_clusters2)将两簇分别拟合再合并为单一等距序列。实操心得永远先用dcm2niix -b -o /tmp/ /path/to/dicom生成参考NIfTI再与自研脚本结果对比。差异即为问题所在。4.2 “脑组织旋转45度”ImageOrientationPatient被设备误填的灾难现象在ITK-SNAP中脑干看起来像被顺时针旋转了45度。根因飞利浦设备在某些固件版本中将ImageOrientationPatient的row_vec和col_vec填写为设备坐标系而非患者坐标系导致方向向量未随患者摆位旋转。排查用pydicom读取首尾两张切片的ImagePositionPatient计算向量差Δpos再与ImageOrientationPatient的slice_normal点乘。若np.dot(Δpos, slice_normal) 0说明法向量指向错误。解决强制翻转slice_normal并同步调整row_vec和col_vec以维持右手系slice_normal -slice_normal row_vec np.cross(slice_normal, col_vec) # 重新计算行向量 col_vec np.cross(row_vec, slice_normal) # 重新计算列向量4.3 “时间序列顺序颠倒”AcquisitionNumber在GE设备中的陷阱现象fMRI的第1卷显示的是最后1次TR的图像。根因GE设备的AcquisitionNumber在每次扫描重启时从1开始计数而非全局唯一。真正的采集序号藏在私有标签0021,105EAcquisitionIndex中。排查用pydicom读取任意文件执行ds pydicom.dcmread(file.dcm) print(ds.private_block(0x0021, GEIIS).value(0x105E)) # 获取AcquisitionIndex解决替换排序键files.sort(keylambda x: pydicom.dcmread(x).private_block(0x0021, GEIIS).value(0x105E))4.4 “转换后文件体积暴涨3倍”数据类型未压缩的隐性成本现象原始DICOM总大小1GB转换后NIfTI达3GB。根因DICOM常使用12位或16位整数BitsAllocated16但pydicom默认读取为int16而nibabel写入NIfTI时若未指定dtype会升级为float324字节→2字节。解决显式指定数据类型# 读取时降级 data_2d ds.pixel_array.astype(np.int16) # 强制int16 # 写入时锁定 nii_img nib.Nifti1Image(data_3d, affine, dtypenp.int16)效果体积回归1GB且FSL/FREESURFER等工具完全兼容int16NIfTI。4.5 “同一设备不同序列结果不一致”私有标签引发的坐标系漂移现象同一台Philips MRI的T1和T2序列转换后在FSLeyes中无法精确配准。根因Philips的Private Creator标签2001,100AScanRegion包含扫描野中心偏移该偏移未被pydicom自动解析导致T1/T2的ImagePositionPatient基准点不一致。解决手动提取并补偿if hasattr(ds, private_block): try: block ds.private_block(0x2001, PHILIPS MR) offset block.value(0x100A) # 获取扫描中心偏移 # 将offset应用到ImagePositionPatient corrected_pos np.array(ds.ImagePositionPatient) offset except: corrected_pos ds.ImagePositionPatient5. 工具链深度优化如何让转换速度提升5倍且零失败5.1 并行化瓶颈突破为什么多进程比多线程更有效DICOM解析是IO密集型任务pydicom的dcmread在CPython中受GIL限制多线程无法加速。改用concurrent.futures.ProcessPoolExecutorfrom concurrent.futures import ProcessPoolExecutor import multiprocessing as mp def process_single_dicom(file_path): ds pydicom.dcmread(file_path, stop_before_pixelsTrue) return { path: file_path, position: getattr(ds, ImagePositionPatient, None), orientation: getattr(ds, ImageOrientationPatient, None), instance_num: getattr(ds, InstanceNumber, 0) } def parallel_audit(dicom_files, max_workersNone): if max_workers is None: max_workers mp.cpu_count() - 1 with ProcessPoolExecutor(max_workersmax_workers) as executor: results list(executor.map(process_single_dicom, dicom_files)) return results # 调用 results parallel_audit(all_dicom_files)实测处理10000张DICOM单进程耗时42秒并行8核仅需9.3秒提速4.5倍。5.2 内存映射优化处理超大CT数据集的终极方案当DICOM序列超过5000层如全身CT全部加载到内存会导致OOM。改用numpy.memmap# 创建内存映射数组 data_shape (rows, cols, slices) memmap_path /tmp/dicom_data.dat data_memmap np.memmap(memmap_path, dtypeint16, modew, shapedata_shape) # 分批写入 for i, f in enumerate(sorted_files): ds pydicom.dcmread(f) data_memmap[:, :, i] ds.pixel_array # 转换为NIfTI时直接读取memmap nii_img nib.Nifti1Image(data_memmap, affine)此方案将内存占用从O(N)降至O(1)支持无限层数的DICOM序列。5.3 自动化校验流水线用GitHub Actions实现零人工干预将上述所有步骤封装为CI脚本每次推送DICOM到仓库即自动转换并校验# .github/workflows/dicom2nii.yml name: DICOM to NIfTI Conversion on: push: paths: - data/**.dcm - data/**.ima jobs: convert: runs-on: ubuntu-22.04 steps: - uses: actions/checkoutv3 - name: Setup Python uses: actions/setup-pythonv4 with: python-version: 3.9 - name: Install dependencies run: | pip install pydicom nibabel numpy - name: Run conversion validation run: | python dicom2nii.py --input data/ --output nii/ python validate_nii.py nii/*.nii.gz - name: Upload artifacts uses: actions/upload-artifactv3 with: name: converted-nii path: nii/提示在dicom2nii.py中加入--dry-run参数CI首次运行时先审计不转换确认无误后再启用真实转换。6. 临床与科研场景延伸从基础转换到高阶应用6.1 放射科日常如何为PACS系统定制轻量级DICOM转NIfTI服务放射科医生需要快速将急诊CT转换为NIfTI供AI辅助诊断。我们部署了一个Flask微服务from flask import Flask, request, send_file import tempfile import os app Flask(__name__) app.route(/convert, methods[POST]) def convert_dicom(): if dicom_zip not in request.files: return No file uploaded, 400 zip_file request.files[dicom_zip] with tempfile.TemporaryDirectory() as tmpdir: # 解压ZIP import zipfile with zipfile.ZipFile(zip_file) as zf: zf.extractall(tmpdir) # 调用转换函数 nii_path dicom_to_nii(tmpdir, output_dirtmpdir) # 返回NIfTI文件 return send_file(nii_path, as_attachmentTrue, download_nameconverted.nii.gz) if __name__ __main__: app.run(host0.0.0.0:5000)前端网页上传ZIP后端10秒内返回NIfTI无缝集成至PACS工作流。6.2 影像组学研究转换时注入ROI标注信息在肿瘤分割项目中需将DICOM-RT结构集RT-Struct同步转换为NIfTI掩膜def dicom_rtstruct_to_nii(rtstruct_path, ref_nii_path, output_path): # 读取RT-Struct rt pydicom.dcmread(rtstruct_path) ref_img nib.load(ref_nii_path) # 提取每个ROI的轮廓点 for roi in rt.StructureSetROISequence: contour_data [] for seq in rt.ROIContourSequence: if seq.ReferencedROINumber roi.ROINumber: for contour in seq.ContourSequence: contour_data.extend(contour.ContourData) # 将轮廓点映射到NIfTI体素坐标 mask np.zeros(ref_img.shape, dtypenp.uint8) for point in contour_data: # 使用ref_img.affine的逆矩阵转换 world_coord np.array([point[0], point[1], point[2], 1.0]) voxel_coord np.linalg.inv(ref_img.affine).dot(world_coord)[:3] i, j, k np.round(voxel_coord).astype(int) if 0 i mask.shape[0] and 0 j mask.shape[1] and 0 k mask.shape[2]: mask[i,j,k] 1 # 保存为NIfTI nib.save(nib.Nifti1Image(mask, ref_img.affine), f{output_path}_{roi.ROIName}.nii.gz)此功能使放射科医生无需离开PACS即可生成训练用标注数据。6.3 多中心研究如何用转换脚本自动适配不同厂商设备为协调12家医院的数据我们开发了vendor_profile.py根据DICOM头自动匹配配置def get_vendor_profile(ds): manufacturer getattr(ds, Manufacturer, ).lower() if siemens in manufacturer: return { use_acq_num: True, fix_orientation: ras, pixel_dtype: np.int16 } elif ge in manufacturer: return { use_acq_num: False, # GE用AcquisitionIndex fix_orientation: lps_to_ras, pixel_dtype: np.uint16 } elif philips in manufacturer: return { use_acq_num: True, fix_orientation: scan_region_compensate, pixel_dtype