如何通过脚本将位掩码(bit masked)图像转换为图像中的ROI
位掩码转闭合ROI的脚本实现方案

左图为原始0/1值位掩码(虚拟光阑),右图为目标闭合ROI效果示意
核心实现思路
- 预处理位掩码:读取仅含0/1值的二值掩码,通过小核形态学闭运算去除边缘孤立噪点、填补轮廓缺口,避免后续提取轮廓出现碎边。
- 提取主体外轮廓:调用二值轮廓提取接口,仅保留最外层闭合轮廓,自动过滤掩码内部孔洞、边缘杂点产生的无效小轮廓,锁定虚拟光阑的主体边界。
- 压缩轮廓顶点:原始逐像素提取的轮廓顶点量过大会拖慢计算速度,通过道格拉斯-普克算法做多边形逼近,按设定精度阈值压缩顶点数量,保证形状和原光阑误差控制在1像素以内即可。
- 封装可用ROI:将压缩后的轮廓顶点按所用处理框架的格式要求,封装为闭合多边形ROI对象,可直接叠加在原始图像上,也可传入后续SI-Map计算流程。
可直接复用的脚本示例
依赖安装命令:pip install opencv-python numpy hyperspy
import cv2 import numpy as np import hyperspy.api as hs def mask_to_closed_roi(mask_path, epsilon=1.0, invert_mask=False): """ 0/1值位掩码转闭合多边形ROI工具 参数: mask_path: 位掩码文件存储路径 epsilon: 轮廓逼近精度,单位为像素,值越大顶点数量越少 invert_mask: 若掩码中光阑区域为0、背景为1则设为True 返回: roi: 可直接对接SI-Map接口的闭合多边形ROI对象 contour_pts: ROI顶点坐标数组 """ # 读取并标准化二值掩码 mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) if invert_mask: mask = 255 - mask _, binary_mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY) # 形态学运算补全边缘小缺口 kernel = np.ones((3,3), np.uint8) binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel) # 提取最外层主体轮廓 contours, _ = cv2.findContours( binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) main_contour = max(contours, key=cv2.contourArea) # 多边形逼近压缩顶点 approx_contour = cv2.approxPolyDP( main_contour, epsilon=epsilon, closed=True ) contour_pts = approx_contour.squeeze() r_coords = contour_pts[:, 1] c_coords = contour_pts[:, 0] # 生成闭合ROI roi = hs.roi.PolygonROI(r=r_coords, c=c_coords) return roi, contour_pts # 调用示例 if __name__ == "__main__": # 替换为实际的位掩码文件路径 roi, pts = mask_to_closed_roi("virtual_aperture_mask.png", epsilon=1.2) print(f"生成ROI包含{len(pts)}个顶点") # 后续直接将roi传入SI-Map计算函数即可,无需额外格式转换
使用注意事项
- 精度调节:圆形虚拟光阑可将
epsilon设为1.5-2.0,进一步减少顶点数提升计算速度;不规则异形光阑建议设为0.5-1.0,保证形状匹配精度。 - 跨环境适配:如果使用GMS(DigitalMicrograph)脚本环境,只需将最后生成ROI的逻辑替换为DM自带的
NewROI()接口,传入提取到的顶点坐标即可,轮廓提取、顶点压缩的核心逻辑完全通用。 - 批量处理:该函数可直接嵌入4D-STEM自动化处理流程,掩码生成后自动转ROI传入SI-Map,全程无需手动交互,计算效率比逐像素遍历掩码高30%以上。
内容的提问来源于stack exchange,提问作者w4m
相关产品推荐
相关产品推荐

