大致原理
处理医学图像最常见的是MRI格式,但是MRI是三维的,如果想用detecron2或者maskrcnn跑类似的三维图片需要先进行切片,然后为切片制作coco格式的json文件,下面我们就来介绍一下如何把三维图像转成二维的,并为二维切片制作json文件。
本教程同样适用于二维图片,只是少了一个三维切片的过程。
大致原理就是:
- 把三维的原始MRI标注文件切片
- 依次处理每一张切片,因为我的任务是一个多分类的任务,所以每一张图片上都有多个类别。处理的时候,要单独处理每一个类别,为每一个类别生成对应的mask
- 如何生成mask? 底层实现的时候调用contour函数,这个函数可以把一个二值图像中值为1的区域轮廓表示出来,也就是coco数据格式中的mask数组。
参考教程
COCO数据集–分割数据定义及标注信心
将彩色RGB分割标注图像数据集转换为COCO格式的json文件
外国官方教程(推荐)
安装pycococreator遇到的问题
在windows安装pycococreator时可能会报编译器版本低的错误,这是下只需要下载一个visual studio installer 安装一下编译器即可,安装的时候要选择如下几个选项
借助pycococreatortools生成标注
def genSeaCoco():
# 读取要处理的文件列表
data_txt = '/home/shicao/hjf/datasets/sea/01.txt'
mask_list = []
with open(data_txt, 'r') as f:
# 读取文件中的第一行
line = f.readline()
# 读取文件中的所有行,并消除回车
for line in f.readlines():
line = line.strip('\n')
mask_list.append(line)
img_dir = '/home/shicao/hjf/datasets/sea/images'
mask_dir = '/home/shicao/hjf/datasets/sea/processed_masks'
image_id = 1
annotation_id = 1
coco_output = {
"info": INFO,
"licenses": LICENSES,
"categories": CATEGORIES,
"images": [],
"annotations": []
}
# 依次处理每张图片
print('处理总数', len(mask_list))
for mask_name in mask_list:
image_name = mask_name[: -3] + 'jpg'
print('正在处理', image_name)
image = Image.open(os.path.join(img_dir, image_name))
image_info = pycococreatortools.create_image_info(image_id, os.path.basename(image_name), image.size)
coco_output["images"].append(image_info)
# 读取mask图像
mask = np.array(cv2.imread(os.path.join(mask_dir, mask_name), cv2.IMREAD_GRAYSCALE)).astype(np.uint8)
for class_id in range(8):
binary_mask = copy.deepcopy(mask) # 深拷贝
binary_mask[binary_mask != class_id] = 0
binary_mask[binary_mask == class_id] = 1
category_info = {'id': class_id, 'is_crowd': 0}
# 直接按颜色划分
if class_id in [0, 1, 2, 3, 7]:
annotation_info = pycococreatortools.create_annotation_info(
annotation_id, image_id, category_info, binary_mask, image.size, tolerance=2)
# 只有当标签不为空时,掩码id才会自增
if annotation_info is not None:
coco_output["annotations"].append(annotation_info)
annotation_id = annotation_id + 1
else:
# 寻找轮廓,为每个轮廓生成一个标注
contours, hierarchy = cv2.findContours(binary_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contours_len = len(contours)
if contours_len != 0:
# 遍历所有的轮廓,一个轮廓就是一个实例
for id, contour in enumerate(contours):
# 实例二值掩码
instance_binary_mask = np.zeros(binary_mask.shape)
polys = []
poly = np.array(contour, dtype=np.int32).reshape((len(contour), 2))
polys.append(poly)
# 多边形填充,生成二值图像,去生成掩码
cv2.fillPoly(instance_binary_mask, polys, 1)
# cv2.imwrite('/home/shicao/hjf/datasets/sea/{}.png'.format(id), (instance_binary_mask * 255).astype(np.uint8))
# 如果这个轮廓太小,则放弃
if np.count_nonzero(instance_binary_mask) < 20:
continue
# 为实例创建标注
annotation_info = pycococreatortools.create_annotation_info(
annotation_id, image_id, category_info, instance_binary_mask, image.size, tolerance=2)
# 只有当标签不为空时,掩码id才会自增
if annotation_info is not None:
coco_output["annotations"].append(annotation_info)
annotation_id = annotation_id + 1
image_id = image_id + 1
print('总的实例数', annotation_id)
with open('/home/shicao/hjf/datasets/sea/annotation.json', 'w') as output_json_file:
json.dump(coco_output, output_json_file, indent=2)