COCO_02 二值分割数据集制作为COCO数据集

news2024/12/23 14:31:40

文章目录

  • 1 前言
    • 2 分割数据集格式
      • 2.1 原始图像
      • 2.2 分割标注
      • 2.3 文件名信息
  • 3 制作COCO格式基本流程
  • 4 根据分割标注制作COCO标注(核心)
  • Main

1 前言

最近要开始实例分割任务,由于实例分割是建立再目标检测基础之上的,因此需要制作能用于目标检测的数据集,选择通用的COCO格式数据集进行制作,COCO目标检测数据集简单介绍https://blog.csdn.net/qq_44776065/article/details/128695821,我们基于上述文章进行制作

2 分割数据集格式

分割数据集基本框架如图所示

在这里插入图片描述

单个病人由原图images和两个不同标签mask_0mask_1组成,每个IMG组成一个文件夹作为一个样例

2.1 原始图像

  • 单个样例images中的原始图片

在这里插入图片描述

  • 单个样例由二维的切片序列组成,且具有三维空间连续性

在这里插入图片描述

2.2 分割标注

标注部分如图所示,类似于二值图像,白色前景的像素值为255,黑色背景的像素值为0

在这里插入图片描述

2.3 文件名信息

每个样例文件夹下的文件名均为P1_1_IMG002_frame032.png组成,其中:

  • P1_1_IMG002为样例信息
  • frame032为顺序信息,用于图片的ID

3 制作COCO格式基本流程

制作原则:单个IMG制作一个标注文件,作为一个样例

根据输入图片的格式,制作的基本步骤为:

  1. 首先制作images中的内容,保存图片的基本信息,file_name的值需要采用相对于数据集根路径的文件名,idframe + 1000其中的1000来标记图片信息与P1_1_IMG002中的第二个1对齐,其属于某类文件,因为其文件个数不会超过999(数据集特性)
  2. 制作categories中的内容,这部分类是规定好的,直接指定ID和Name即可
  3. 制作annotations中的内容,这部分是核心内容,section4具体介绍;其基本思想就是提取标注的外轮廓,从而获取外接矩形信息,轮廓信息,面积信息

Code:

准备全局信息

annotations = {
    "images": [],
    "annotations": [],
    "categories": [
        {"id": 1, "name": "cerebral"},
        {"id": 2, "name": "stent"}
    ]
}

制作单个标注图像

def write_single_slice_anno(image_path, category=1):
    """
    根据单个图片的路径, 读取图片并制作annotations.json中的信息
    params: image_path文件的绝对路径, example: r"D:OCT_Dataset_Project/dataset/dataset_stent/P1_1_IMG002/images/P1_1_IMG002_frame032.png"
    params: category两种不同的标注
    """
    # 1. 制作images

    # 获取image_id 与 IMG信息
    _, filename = os.path.split(image_path)
    image_id = int(filename[-7:-4]) + 1000  # 1021 表示术后
    filename_dir = filename[0: -13]

    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

    # 由于两类图片的类型一致, 只写入一次images信息
    if category == 1:
        file_name = f"{filename_dir}/{filename}"
        height = image.shape[0]
        width = image.shape[1]
        
        annotations["images"].append({
            "file_name": file_name,
            "id": image_id,
            "height": height,
            "width": width
        })


    # 2 制作annotations
    # 第1类数据只有一个连通区域, 2类数据分别取出不同目标的连通区域
    if category == 1:
        imgs = [image]
    else:
        imgs = get_single_mask_from_image(image)

    # 对多个连通区域进行处理, 共同属于P1_1_IMG002_frame032的标注
    for img in imgs:

        # 使用全局变量ANNOTATION_NUMS, 作为标注的ID, 单个病人从1开始向后排
        global ANNOTATION_NUMS    
        ANNOTATION_NUMS += 1   # 更新ANNO_NUM, 标注的ID

        # 获取bbox, area, seg信息, seg为polygon
        bbox, area, seg = get_annotation_from_single_image(img, filename=image_path)
        annotations["annotations"].append({
            "segmentation": [seg],      # 这里物体是一体的,是二维数组 [[1, 2, ....]]
            "area": area,
            "bbox": bbox,    # 一维数组
            "iscrowd": 0,
            "image_id": image_id,
            "category_id": category,
            "id": ANNOTATION_NUMS
        })


制作整个样例

def write_patient_IMG_anno(dataset_root, patient_img_dir):
    # 用于查找符合patient_img_dir的re_str_path
    re_path = fr'D:\Learning\OCT\oct-dataset-master\dataset\dataset_stent\{patient_img_dir}\masks_0\{patient_img_dir}_frame*.png'
    filepaths = glob.glob(re_path)
    
    # 遍历文件路径进行处理
    for filepath in filepaths:
        # 处理第一类标注
        masks_0_filepath = filepath
        write_single_slice_anno(image_path=masks_0_filepath, category=1)

        # 处理第二类标注
        masks_1_filepath = filepath.replace("masks_0", "masks_1")
        write_single_slice_anno(image_path=masks_1_filepath, category=2)

    # 写入json
    json_file = f'{dataset_root}/{patient_img_dir}_annotations.json'
    with open(json_file, 'w') as f:
        json.dump(annotations, fp=f)

4 根据分割标注制作COCO标注(核心)

根据二值分割标注制作COCO格式,基本思路:

  1. 对标注图像进行阈值化处理,防止出现除0或者255之外的值,本次处理的图像都是8bit,单通道灰度图

  2. 对于阈值化处理之后的图像,再对不同类型的标注图像进行处理,category_id=1的图像只允许由一个连通区域(标注特性);category_id=2的图像有多个连通区域,分别提取这些连通区域,将单个连通区域绘制为单个二值图像后返回

  3. 对于阈值处理之后的图像,提取其轮廓,方式为:提取所有轮廓并保留,保留轮廓关键点;关于轮廓提取方式参考:https://blog.csdn.net/weixin_43869605/article/details/119921444

  4. 提取的轮廓获取其最大外接矩形,获取轮廓的面积,将轮廓点转化为coco polygon格式,并返回获取的bbox,area,segmentation信息

Code:

获取连通区域的图片

# 获取连通区域
def get_masks_from_image(stent_image):
    # 提取标签和数目
    num, labels = cv2.connectedComponents(image=stent_image)  # 直接提取图片的连通区域    #num检测的值为2

    # 数目作为类型,保存到字典中
    labels_dict = {i: [] for i in range(1, num)}     # num多检测了一个

    # 遍历像素点,label像素值在label_dict中, 保存到类型字典的数组中
    for h in range(stent_image.shape[0]):
        for w in range(stent_image.shape[1]):
            if labels[h, w] in labels_dict:
                labels_dict[labels[h, w]].append([h, w])

    # 绘制支架点所在的区域
    imgs = []
    for key in labels_dict:
        # 如何取得拿块区域
        img = np.zeros(stent_image.shape, dtype=np.uint8)
        for point in labels_dict[key]:
            img[point[0], point[1]] = 255
        imgs.append(img)
    # imgs.pop()    # 不知道为什么,图像中数组元素多一个
    return imgs

获取标注信息

# 获取标注信息
def get_annotations_from_single_image(image, filename):

    ## 对图片进行阈值处理
    ret, thresh = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY_INV)

    # 取轮廓方式  检测所有的轮廓(RETR_TREE), 以只保留重点部分的形式输出轮廓
    contours, hierarchy = cv2.findContours(thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE) 

    # 标注异常检测1: 输出有多个区域的情况,进行检测
    if len(contours) > 2:
        print("contour > 2 :", filename)


    main_contour = contours[1]  # 取第一个轮廓

    # 标注异常检测2: 检测是否有单个点
    if len(main_contour) < 5:
        print("main_contour points is low", filename)

    # 计算最外面的矩形边界
    x, y, w, h = cv2.boundingRect(main_contour)
    bbox = [float(x), float(y), float(w), float(h)]

    # 计算轮廓的面积
    main_contour_area = cv2.contourArea(main_contour)

    # 取多边形的点,组成segmentation格式
    seg = []
    for pt in main_contour:
        seg.append(float(pt[0][0]))
        seg.append(float(pt[0][1]))

    return bbox, main_contour_area, seg

Main

if __name__ == "__main__":
    dataset_root = '../dataset/dataset_stent_coco'
    # 每个文件单独执行
    # P1_1_IMG002
    write_patient_IMG_anno(dataset_root=dataset_root, patient_img_dir="P1_1_IMG002")   

参考:

COCO_01 数据集介绍 COCO目标检测分割数据集格式: https://blog.csdn.net/qq_44776065/article/details/128695821

cv2.findContours(): https://blog.csdn.net/weixin_43869605/article/details/119921444

python-opencv 实现连通域处理函数 cv2.connectedComponentsWithStats()和cv2.connectedComponents()
https://blog.csdn.net/qq_40784418/article/details/106023288


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两道一年级数学题把我干废了

目录一、背景二、题目三、过程第一解&#xff1a;第二解&#xff1a;第三解&#xff1a;四、总结五、升华一、背景 最近在看小学一年级数学课本的时候&#xff0c;其中两道题让我感叹现在小学教育题的伟大和深厚&#xff0c;并且从中领悟到了…哈哈哈&#xff0c;先卖个官司&a…

【Ansible】Ansible 角色

Ansible 角色 文章目录Ansible 角色一、Ansible Roles 介绍二、Roles 结构三、role 的制作过程四、如何在PlayBook中使用 Role1. 经典&#xff08;原始&#xff09;方式2. 新方式五、如何使用 Galaxy一、Ansible Roles 介绍 一个数据中心有可能存在好多类型的服务器。比如&…

【博客588】ipvs nat模式下独立于iptables与conntrack的连接跟踪表和NAT机制

ipvs nat模式下独立于iptables与conntrack的连接跟踪表和NAT机制 ipvs的连接跟踪表和NAT机制 ipvs只有DNAT和de-DNAT功能 ,它独立与iptables和conntrack,实现了自己的一套连接跟踪表和NAT机制。ipvs仅仅在做DNAT后对conntrack连接进行更新,防止回包因为没有记录而被丢弃。 i…

邂逅Vue.js开发

1、认识Vue Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式 JavaScript框架。 全称是Vue.js或者Vuejs&#xff1b;它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff1b;帮助你高效地开发用户…

学习笔记 一天学完JavaScript基础语法(全)

JavaScript 文章目录JavaScript第一章——初始JavaScript1.1 浏览器执行 JS 简介1.2 JS的组成1.2.1 ECMAScript1.2.2 DOM ——文档对象模型1.2.3 BOM ——浏览器对象模型1.3 JS的写法1.3.1 行内式写法1.3.2 内嵌式写法1.3.3 外部js文件1.4 注释1.5 变量1.5.1 变量声明1.5.2 变量…

【源码解析】Nacos配置中心的源码解析

POM文件添加依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>在依赖中查看自动装配文件spring.factories org.springframework.cloud.bootstr…

String类详解

在Java编程中&#xff0c;除Object类外&#xff0c;最常用的类就是String类了。本文将从String类源码出发&#xff0c;对String类进行一个全面的分析&#xff0c;以帮忙我们更好的理解和使用String类。 String类概述 Java 使用 String 类代表字符串。Java 中的所有字符串字面…

已解决MemoryError

已解决Python读取20GB超大文件报错&#xff1a;MemoryError 文章目录报错问题报错翻译报错原因解决方法1解决方法2&#xff08;推荐使用&#xff09;帮忙解决报错问题 日常数据分析工作中&#xff0c;难免碰到数据量特别大的情况&#xff0c;动不动就2、3千万行&#xff0c;…

Linux——网络配置篇

1、前情提要&#xff1a; 今晚在配置Linux &#xff08;CentOS7完整版&#xff09;的时候 明明已经配好了网络环境&#xff0c;重启虚拟机后&#xff0c;又出现了Ping不通 主机、Ping不通网关&#xff0c;外网的情况 &#xff08;NAT&#xff09;。 让我很费解的一个情况是&am…

数据结构与算法基础(王卓)(8):线性表的应用

PPT&#xff1a;第二章P173&#xff1b; 并集集合&#xff1a;线性表的合并&#xff08;无需有序&#xff0c;不能重复&#xff09; 线性表&#xff1a; Status Union(Sqlist& A, Sqlist& B)//并集 {int len_A A.length;int len_B B.length;for (int i 1; i < …

SpringCloud学习(1)

SpringCloud学习 软件架构演进之路 对于单体架构&#xff0c;我们根据设计期和开发实现期的不同模式和划分结构&#xff0c;可以分为&#xff1a; 简单单体模式&#xff1a; 代码层面没有拆分&#xff0c;所有的业务逻辑都在一个项目&#xff08;Project&#xff09;里打包…

​力扣解法汇总2293. 极大极小游戏

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a; 力扣 描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 n…

伪随机码序列

伪随机码又称伪随机序列&#xff0c;是用确定性方法产生的在一段周期内具有类似白噪声的随机特性的二&#xff08;或多&#xff09;进制数据序列。 伪随机序列在码分复用、码分多址和扩频通信中都有重要应用。常用的伪随机序列有m序列、M序列和Gold序列。 作为地址码和扩频码…

pycharm中commit/push撤销+分支合并

一、现在想撤销到打印3怎么操作&#xff1f; 1复制修订号 2鼠标右键 3去项目下执行git bash here&#xff0c;再输入git push -f 4此时&#xff0c;github中的push就已经回退成功&#xff1b;再进行一次新代码的commit和push&#xff0c;master分支的颜色就变成黄色了&#x…

Windows中安装 MySQL8.0.30 数据库

下载安装文件 访问MySQL官网下载安装文件https://downloads.mysql.com/archives/community/。 如下图所示&#xff0c;点击页面中的“DOWNLOAD”按钮。 然后&#xff0c;会出现如下所示页面&#xff0c;点击页面底部的“No thanks, just start my download”&#xff0c;就可…

Vue3商店后台管理系统设计文稿篇(四)

记录使用vscode构建Vue3商店后台管理系统&#xff0c;这是第四篇&#xff0c;主要记录使用git与vscode将代码同步提交到GitHub上面 文章目录一、Git与Github建立连接二、配置开发工具三、实用Git命令仓库相关命令分支相关命令正文内容&#xff1a; 一、Git与Github建立连接 使…

从0到1【建站:AWS+Ubuntu+Python+Django+uwsgi+nginx+ssl】

目录一、创建服务器1、进入AWS官网2、启动实例3、创建新密钥对4、选择密钥对5、网络设置6、配置存储7、启动实例8、查看实例9、配置安全组二、连接服务器1、在AWS官网进行连接2、使用Xshell7进行连接3、设置允许root登录三、域名解析1、进行腾讯云官网2、管理域名解析3、绑定公…

xilinx ZYNQ 7000 XADC 片上模拟转数字模块

上图所示&#xff0c;XADC 属于 PL部分的资源 XADC是一种硬逻辑实现&#xff0c;位于PL功率域。PS- xadc接口是PS的一部分&#xff0c;可以被PS APU访问&#xff0c;而不需要对PL进行编程。PL必须上电才能配置PS-XADC接口、使用PL- jtag或DRP接口以及操作XADC。 上面的机构图能…

通关算法题之 ⌈回溯算法⌋

回溯算法 子集组合排列 78. 子集 给你一个整数数组 nums&#xff0c;数组中的元素互不相同 &#xff0c;返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集不能包含重复的子集&#xff0c;你可以按任意顺序 返回解集。 输入&#xff1a;nums [1,2,3] 输出&…

LeetCode 5. 最长回文子串

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 5. 最长回文子串&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCode 5…