如何批量获取MRI分割图像中各肌肉的个体像素面积?
批量统计MRI肌肉mask的左右个体像素面积
针对你的需求,直接用连通区域分析+区域属性统计就能批量处理,无需手动ROI,也能应对跨中线的肌肉区域,具体方案如下:
核心思路
分割后的mask中,每块独立的肌肉是一个连通区域,先标记所有连通区域,再统计每个区域的像素面积,最后通过区域重心或像素坐标判断左右归属;对于跨中线的区域,可拆分左右部分分别统计。
具体实现(Python)
1. 依赖库导入
import numpy as np from scipy import ndimage from skimage import measure
2. 单张图像处理逻辑
假设result是你的2D mask数组(非零像素为肌肉区域):
# 复制mask避免修改原数据 mask = result.copy() # 获取图像宽度中点(用于判断左右) image_mid_x = mask.shape[1] / 2 # 步骤1:标记所有连通肌肉区域 labeled_mask, num_regions = ndimage.label(mask) # 步骤2:提取每个区域的属性(面积、重心等) regions = measure.regionprops(labeled_mask) # 步骤3:遍历区域统计面积与位置 for region in regions: # 统计区域总像素面积 total_area = region.area # 获取区域重心的x坐标(centroid格式为(y, x)) centroid_x = region.centroid[1] # 方案A:按重心判断整体归属 side = "左侧" if centroid_x < image_mid_x else "右侧" print(f"肌肉区域 {region.label}: 总面积={total_area} 像素, 归属={side}") # 方案B:拆分跨中线区域的左右面积(可选) coords = region.coords # 区域内所有像素的(y, x)坐标 left_area = len(coords[coords[:, 1] < image_mid_x]) right_area = len(coords[coords[:, 1] >= image_mid_x]) print(f"肌肉区域 {region.label}: 左侧面积={left_area} 像素, 右侧面积={right_area} 像素")
3. 多类肌肉的处理(如果mask含不同肌肉标签)
如果你的mask是语义分割结果(不同肌肉用不同像素值标记,比如1=股四头肌、2=腘绳肌),可先按类别拆分再处理:
# 获取所有非背景的肌肉类别 muscle_classes = np.unique(mask)[1:] for cls in muscle_classes: # 提取当前类别的mask cls_mask = (mask == cls).astype(np.int32) labeled_cls, num_regions = ndimage.label(cls_mask) regions = measure.regionprops(labeled_cls) print(f"\n=== 肌肉类别 {cls} ===") for region in regions: total_area = region.area centroid_x = region.centroid[1] side = "左侧" if centroid_x < image_mid_x else "右侧" print(f"区域 {region.label}: 面积={total_area} 像素, 归属={side}")
4. 批量处理数百张图像
把上述逻辑封装成函数,遍历图像文件列表(比如读取文件夹中的npy/png文件),结果可保存为CSV方便后续分析:
import csv import os def process_single_mask(mask_path): # 读取mask(根据你的存储格式调整,比如npy或图像) mask = np.load(mask_path) image_mid_x = mask.shape[1] / 2 labeled_mask, num_regions = ndimage.label(mask) regions = measure.regionprops(labeled_mask) # 生成当前图像的统计结果 results = [] for region in regions: total_area = region.area centroid_x = region.centroid[1] side = "左侧" if centroid_x < image_mid_x else "右侧" results.append({ "图像名称": os.path.basename(mask_path), "区域标签": region.label, "面积": total_area, "归属": side }) return results # 遍历文件夹中所有mask文件 mask_dir = "你的mask文件夹路径" all_results = [] for filename in os.listdir(mask_dir): if filename.endswith(".npy"): # 根据你的文件格式调整 mask_path = os.path.join(mask_dir, filename) all_results.extend(process_single_mask(mask_path)) # 保存结果到CSV with open("肌肉面积统计.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["图像名称", "区域标签", "面积", "归属"]) writer.writeheader() writer.writerows(all_results)
关键注意事项
- 确保mask中的每个独立肌肉是一个连通区域(如果分割结果有断裂,可先做小范围的形态学闭运算修复:
ndimage.binary_closing(mask, structure=np.ones((3,3)))) - 跨中线区域的处理可根据你的研究需求选择方案A或B
- 批量处理时注意路径和文件格式的统一
内容的提问来源于stack exchange,提问作者rchow
相关产品推荐
相关产品推荐

