【coco】掩膜mask影像转coco格式txt(含python代码)

        最近在做实例分割,遇到二值掩膜影像——coco格式txt的实例分割转换问题,困扰很久,不知道怎么转换,转出来的txt没法用代码成功读取。一系列问题,索性记录下自己的结局路程,方便大家python代码自取。

 


目录

📞📞1.coco格式示例

📗 images模块

📘 categories模块

📙annotation模块

📷📷2.环境准备

📢📢3.maskToanno函数定义

⏰⏰4.images模块内容写入txt

📡📡5.categories模块内容写入txt

🛁🛁6.annotation模块内容写入txt

🔋🔋7.完整python代码

整理不易,欢迎一键三连!!!

送你们一条美丽的--分割线--


📞📞1.coco格式示例

        coco格式txt文件示例:

        主要包含三个模块:

  • images
  • categories
  • annotations

        其中每个模块都由好多个分块组成,images和categories比较简单。

📗 images模块

        images里主要记录的是每张image的长宽,id和文件名信息,注意此处的文件名必须是images文件名,labels也得是相同的文件名,不然索引不到。id从1开始,依次向下编号。

images[
{
    "height": 512,
    "width": 512,
    "id": 1,
    "file_name": "1.png"
}
...
...
...
{
    "height": 512,
    "width": 512,
    "id": 100,
    "file_name": "100.png"
}

]

📘 categories模块

        categories模块记录的是所有样本的类别信息,name为类别名称,id从1开始,依次向下编号,supercategory表示该类别的从属类别,理解起来比较简单,比如name为bus,supercategory就可以为car,name为cat,supercategory就可以为animal。如果没有多级类别,可以将name和supercategory写出相同的,像我下面写的。

"categories": [
{

    "supercategory": "land",
    "id": 1,
    "name": "land"
}
{

    "supercategory": "land",
    "id": 2,
    "name": "land2"
}
...
...
...
{

    "supercategory": "land",
    "id": n,
    "name": "landn"
}
],

📙annotation模块

         annotation模块主要记录的是label信息,也是最关键的内容,此处以实例分割为例进行讲解,因为coco格式可以做的任务太多,此处仅限实例分割或者语义分割。

annotation模块的一个完整内容包括:

  • segmentation记录目标的边界坐标点位置信息,可以是很长但是要记得是双[[...]];
  • area记录得是目标得面积信息,这个可以自动计算,后面会细讲;
  • iscrowd代表一个目标是否被切分成多块,比如一个猫得身体和尾巴被一只狗头挡住,分开成2部分。0代表没有切分,1代表切分;
  • image_id表示这个目标所对应得原始影像得id编号,与images模块里的id是一一对应的关系;
  • bbox指这个目标的外界矩形框的位置信息;
  • category_id表示这个目标的类别信息,与categories模块里的id是一一对应的关系;
  • id代表目标的编号信息,可以与images个数不一致,因为一张图上很可能会有多个目标。
"annotations": [
{

    "segmentation": [
        [
            276,
            286,
            275,
            287,
            274,
            287,
            273,
            287,
        ]
    ],
    "area": 2148,
    "iscrowd": 0,
    "image_id": 2,
    "bbox": [
        233.0,
        286.0,
        49.0,
        68.0
    ],
    "category_id": 1,
    "id": 1
},

...

{

    "segmentation": [
        [
            276,
            286,
            275,
            287,
            274,
            287,
            273,
            287,
        ]
    ],
    "area": 248,
    "iscrowd": 0,
    "image_id": 5,
    "bbox": [
        233.0,
        286.0,
        49.0,
        68.0
    ],
    "category_id": 2,
    "id":100
},

📷📷2.环境准备

        代码所需环境包有:json、numpy、pycocotools、OpenCV、os、sys

        包导入命令:

import json

import numpy as np

from pycocotools import mask

import cv2

import os

import sys

📢📢3.maskToanno函数定义

输入:round_truth_binary_mask, ann_count, category_id

输出:annotations

        python代码如下:

def maskToanno(ground_truth_binary_mask, ann_count, category_id):
    contours, _ = cv2.findContours(ground_truth_binary_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)  # 根据二值图找轮廓
    annotations = [] #一幅图片所有的annotatons
    global segmentation_id
    # print(ann_count)
    # 对每个实例进行处理
    for i in range(len(contours)):
        # print(i)
        # 生成二值的黑色图片
        x = np.zeros((512, 512))
        cv2.drawContours(x, contours, i, (1, 1, 1), -1)  # 将单个mask表示为二值图的形式
        ground_truth_binary_mask_id = np.array(x, dtype=object).astype(np.uint8)
        fortran_ground_truth_binary_mask = np.asfortranarray(ground_truth_binary_mask_id)
        # 求每个mask的面积和框
        encoded_ground_truth = mask.encode(fortran_ground_truth_binary_mask)
        ground_truth_area = mask.area(encoded_ground_truth)
        ground_truth_bounding_box = mask.toBbox(encoded_ground_truth)
        contour, _ = cv2.findContours(ground_truth_binary_mask_id, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
        # contour = measure.find_contours(ground_truth_binary_mask_id, 0.5)
        # print(contour)
        annotation = {
            "segmentation": [],
            "area": ground_truth_area.tolist(),
            "iscrowd": 0,
            "image_id": ann_count,
            "bbox": ground_truth_bounding_box.tolist(),
            "category_id": category_id,
            "id": segmentation_id
        }
        #print(contour)
        # 求segmentation部分
        contour = np.flip(contour, axis=0)
        segmentation = contour.ravel().tolist()
        if len(segmentation)<=4:
        	continue
        annotation["segmentation"].append(segmentation)
        annotations.append(annotation)
        segmentation_id = segmentation_id + 1
    return annotations

⏰⏰4.images模块内容写入txt

输入:jsonpath

输出:jsonpath

        将jsonpath路径下的txt文件打开,若image存在且对应文件名的label文件存在,就可以写image的images模块信息,python代码如下:

with io.open(jsonPath, 'w', encoding='utf8') as output:
    # 那就全部写在一个文件夹好了
    # 先写images的信息
    output.write(unicode('{\n'))
    output.write(unicode('"images": [\n'))
    for image in rgb_image_files:
 
        if os.path.exists(os.path.join(block_mask_path, image)):
            output.write(unicode('{'))
            annotation = {
                "height": 512,
                "width": 512,
                "id": imageCount,
                "file_name": image
            }
            str_ = json.dumps(annotation, indent=4)
            str_ = str_[1:-1]
            if len(str_) > 0:
                output.write(unicode(str_))
                imageCount = imageCount + 1
            if (image == rgb_image_files[-1]):
                output.write(unicode('}\n'))
            else:
                output.write(unicode('},\n'))

📡📡5.categories模块内容写入txt

输入:jsonpath

输出:jsonpath

        将jsonpath路径下的txt文件打开,将categories模块里的supercategory、id、name信息写入txt,此处的categories信息只是示例,可以根据自己的类别信息修改,python代码如下:

with io.open(jsonPath, 'w', encoding='utf8') as output:
 output.write(unicode('"categories": [\n'))
    output.write(unicode('{\n'))
    categories = {
        "supercategory": "land",
        "id": 1,
        "name": "land"
    }
    str_ = json.dumps(categories, indent=4)
    str_ = str_[1:-1]
    if len(str_) > 0:
        output.write(unicode(str_))
    output.write(unicode('}\n'))
    output.write(unicode('],\n'))

🛁🛁6.annotation模块内容写入txt

输入:jsonpath

输出:jsonpath

        将jsonpath路径下的txt文件打开,若label存在且对应文件名的image文件存在,就可以把annotation模块里的信息写入txt,python代码如下:

with io.open(jsonPath, 'w', encoding='utf8') as output:
    output.write(unicode('"annotations": [\n'))
    for i in range(len(block_mask_image_files)):
        if os.path.exists(os.path.join(path, block_mask_image_files[i])):
            block_image = block_mask_image_files[i]
            # 读取二值图像
            block_im = cv2.imread(os.path.join(block_mask_path, block_image), 0)
            _, block_im = cv2.threshold(block_im, 100, 1, cv2.THRESH_BINARY)
            if not block_im is None:
                block_im = np.array(block_im, dtype=object).astype(np.uint8)
                block_anno = maskToanno(block_im, annCount, 1)
                for b in block_anno:
                    str_block = json.dumps(b, indent=4)
                    str_block = str_block[1:-1]
                    if len(str_block) > 0:
                        output.write(unicode('{\n'))
                        output.write(unicode(str_block))
                        if (block_image == rgb_image_files[-1] and b == block_anno[-1]):
                            output.write(unicode('}\n'))
                        else:
                            output.write(unicode('},\n'))
                annCount = annCount + 1
            else:
                print(block_image)

🔋🔋7.完整python代码

        二值掩膜mask影像转coco格式的实例分割txt完整python代码如下:

import json
import numpy as np
from pycocotools import mask
import cv2
import os
import sys

if sys.version_info[0] >= 3:
    unicode = str


import io
# 实例的id,每个图像有多个物体每个物体的唯一id
global segmentation_id
segmentation_id = 1
# annotations部分的实现
def maskToanno(ground_truth_binary_mask, ann_count, category_id):
    contours, _ = cv2.findContours(ground_truth_binary_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)  # 根据二值图找轮廓
    annotations = [] #一幅图片所有的annotatons
    global segmentation_id
    # print(ann_count)
    # 对每个实例进行处理
    for i in range(len(contours)):
        # print(i)
        # 生成二值的黑色图片
        x = np.zeros((512, 512))
        cv2.drawContours(x, contours, i, (1, 1, 1), -1)  # 将单个mask表示为二值图的形式
        ground_truth_binary_mask_id = np.array(x, dtype=object).astype(np.uint8)
        fortran_ground_truth_binary_mask = np.asfortranarray(ground_truth_binary_mask_id)
        # 求每个mask的面积和框
        encoded_ground_truth = mask.encode(fortran_ground_truth_binary_mask)
        ground_truth_area = mask.area(encoded_ground_truth)
        ground_truth_bounding_box = mask.toBbox(encoded_ground_truth)
        contour, _ = cv2.findContours(ground_truth_binary_mask_id, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
        # contour = measure.find_contours(ground_truth_binary_mask_id, 0.5)
        # print(contour)
        annotation = {
            "segmentation": [],
            "area": ground_truth_area.tolist(),
            "iscrowd": 0,
            "image_id": ann_count,
            "bbox": ground_truth_bounding_box.tolist(),
            "category_id": category_id,
            "id": segmentation_id
        }
        #print(contour)
        # 求segmentation部分
        contour = np.flip(contour, axis=0)
        segmentation = contour.ravel().tolist()
        if len(segmentation)<=4:
        	continue
        annotation["segmentation"].append(segmentation)
        annotations.append(annotation)
        segmentation_id = segmentation_id + 1
    return annotations

# mask图像路径
block_mask_path = '/labels_512'
block_mask_image_files = sorted(os.listdir(block_mask_path))

# coco json保存的位置
jsonPath = "/data/temp.json"
annCount = 1
imageCount = 1
# 原图像的路径, 原图像和mask图像的名称是一致的。
path = "/images_512"
rgb_image_files = sorted(os.listdir(path))

with io.open(jsonPath, 'w', encoding='utf8') as output:
    # 那就全部写在一个文件夹好了
    # 先写images的信息
    output.write(unicode('{\n'))
    output.write(unicode('"images": [\n'))
    for image in rgb_image_files:
        if os.path.exists(os.path.join(block_mask_path, image)):
            output.write(unicode('{'))
            annotation = {
                "height": 512,
                "width": 512,
                "id": imageCount,
                "file_name": image
            }
            str_ = json.dumps(annotation, indent=4)
            str_ = str_[1:-1]
            if len(str_) > 0:
                output.write(unicode(str_))
                imageCount = imageCount + 1
            if (image == rgb_image_files[-1]):
                output.write(unicode('}\n'))
            else:
                output.write(unicode('},\n'))
    output.write(unicode('],\n'))


# 接下来写cate
    output.write(unicode('"categories": [\n'))
    output.write(unicode('{\n'))
    categories = {
        "supercategory": "land",
        "id": 1,
        "name": "land"
    }
    str_ = json.dumps(categories, indent=4)
    str_ = str_[1:-1]
    if len(str_) > 0:
        output.write(unicode(str_))
    output.write(unicode('}\n'))
    output.write(unicode('],\n'))


# 写annotations
    output.write(unicode('"annotations": [\n'))
    for i in range(len(block_mask_image_files)):
        if os.path.exists(os.path.join(path, block_mask_image_files[i])):
            block_image = block_mask_image_files[i]
            # 读取二值图像
            block_im = cv2.imread(os.path.join(block_mask_path, block_image), 0)
            _, block_im = cv2.threshold(block_im, 100, 1, cv2.THRESH_BINARY)
            if not block_im is None:
                block_im = np.array(block_im, dtype=object).astype(np.uint8)
                block_anno = maskToanno(block_im, annCount, 1)
                for b in block_anno:
                    str_block = json.dumps(b, indent=4)
                    str_block = str_block[1:-1]
                    if len(str_block) > 0:
                        output.write(unicode('{\n'))
                        output.write(unicode(str_block))
                        if (block_image == rgb_image_files[-1] and b == block_anno[-1]):
                            output.write(unicode('}\n'))
                        else:
                            output.write(unicode('},\n'))
                annCount = annCount + 1
            else:
                print(block_image)
            
    output.write(unicode(']\n'))
    output.write(unicode('}\n'))



有问题,欢迎评论区交流~~~

整理不易,欢迎一键三连!!!

送你们一条美丽的--分割线--


🌷🌷🍀🍀🌾🌾🍓🍓🍂🍂🙋🙋🐸🐸🙋🙋💖💖🍌🍌🔔🔔🍉🍉🍭🍭🍋🍋🍇🍇🏆🏆📸📸⛵⛵⭐⭐🍎🍎👍👍🌷🌷

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python开发运维:Python调用K8S API实现资源管理

目录 一、实验 1.Python操作K8S API获取资源 2.Python操作K8S API创建deployment资源 3.Python操作K8S API删除k8s资源 4.Python操作K8S API修改k8s资源 5.Python操作K8S API查看k8s资源 二、问题 1.Windows11安装kubernetes报错 2.Python通过调用哪些方法实现Pod和De…

C4D云渲染怎么提升速度小技巧?C4D云渲染速度提升技巧

当许多C4D用户转向云渲染时&#xff0c;他们常常会发现渲染速度并没有预期中的提升&#xff0c;这让人产生疑问&#xff0c;为什么使用云渲染服务后&#xff0c;渲染时间依然没有显著缩短&#xff0c;C4D云渲染情况取决于多个因素&#xff0c;如&#xff1a;渲染任务特点以及所…

图的搜索(二):贝尔曼-福特算法、狄克斯特拉算法和A*算法

图的搜索&#xff08;二&#xff09;&#xff1a;贝尔曼-福特算法、狄克斯特拉算法和A*算法 贝尔曼-福特算法 贝尔曼-福特&#xff08;Bellman-Ford&#xff09;算法是一种在图中求解最短路径问题的算法。最短路径问题就是在加权图指定了起点和终点的前提下&#xff0c;寻找从…

代码上传的gitee平台

1.首先我们访问工作台 - Gitee.com进行注册和登录 2.我们创建一个仓库&#xff1a; 3.在本地创建我们的项目 在这文件夹里面我们打开git bush,执行 一下操作&#xff1a; git init &#xff1a;初始化仓库 git status&#xff1a;检查状态 git add . &#xff1a;将当前文件…

【wimdows电脑上管理员账户与管理员身份的区别】

管理员账户 在控制面板的用户账户中&#xff0c;点击更改账户类型&#xff0c;可以看到目前的账户是“管理员账户”还是“标准账户”。 管理员身份 在快捷方式上右击&#xff0c;可以看到&#xff0c;可以选择以管理员身份运行该软件。 如何查看某个应用是否以管理员身份…

6.Jetson Orin Nano 系统在NVME SSD上备份与恢复

Jetson Orin Nano 系统在NVME SSD上备份与恢复 刚开始我也参考其它博主写的系统备份与恢复&#xff0c;由于我Jetson 的系统盘是1t的&#xff0c;用dd命令拷贝的到另外一个1t的硬盘里面时&#xff0c;总会出现硬盘空间不足的情况出现。只能从小硬盘容量往大硬盘容量拷贝&#…

单通道led线性驱动芯片推荐:SM2082EGS

单通道LED线性驱动芯片是一种用于控制LED灯的芯片&#xff0c;它能够提供恒定的电流输出&#xff0c;从而实现LED灯的稳定亮度调节。这种芯片主要由输入端、控制电路、放大器和输出端构成&#xff0c;通过控制输入端的电压和信号来调节LED的亮度。 单通道led线性驱动芯片推荐&a…

JAVA:乘除窗体的实现

目录 题目要求&#xff1a; 窗口的实现&#xff1a; try 和 catch 的用法&#xff1a; 思路大意&#xff1a; 关键代码的实现&#xff1a; 题目要求&#xff1a; 使用 try 和catch 方法完成乘法除法的异常处理和窗体的实现&#xff0c;如下图所示&#xff1a; 窗口的实…

国际著名书画艺术家敖特:连续三届荣获世界美术大赛金奖

敖特 敖特是一位备受国际认可的蒙古族书画艺术家&#xff0c;以其卓越的才华和杰出的艺术成就而脱颖而出。他的艺术简历显示了他在国内外艺术大赛中多次荣获金奖&#xff0c;并获得了白俄罗斯、俄罗斯等国的最高艺术成就奖项&#xff0c;进一步证明了他在国际艺术界的卓越地位…

MidJourney笔记(7)-Seeds

我相信很多人在使用MidJourney的时候,都会遇到一个问题,就是如何保持生成图像的一致性,或者相对一致性,差异性不是很大。此时,我们就需要引入一个seed值,类似给这个提示词生成的图片做一个id标识。 那这个seed值怎么使用? 其实,在我们每次生成的图片,都有有一个seed值…

【Spring教程27】Spring框架实战:一文教你轻松掌握PostMan工具的安装与使用技巧!轻松搞定API测试!!!

目录 1 PostMan简介2 PostMan安装3 PostMan使用3.1 创建WorkSpace工作空间3.2 发送请求3.3 保存当前请求 4 发送步骤总结 欢迎大家回到《Java教程之Spring30天快速入门》&#xff0c;本教程所有示例均基于Maven实现&#xff0c;如果您对Maven还很陌生&#xff0c;请移步本人的博…

【C语言:文件操作】

文章目录 1. 什么是文件1.1为什么有文件&#xff1f;1.2什么是文件1.3文件的分类1.4文件缓冲区 2.文件的打开与关闭2.1文件的打开(fopen)2.2文件的关闭(fclose) 3.顺序读写数据文件3.1读写字符3.2读写字符串3.3格式化读写3.4二进制读写 4.文件的随机读写4.1fseek4.2ftell4.3rew…

【docker】镜像使用(Nginx 示例)

查看本地镜像列表 docker images删除本地镜像 # docker rmi [容器 ID]docker rmi a6bd71f48f68 查找镜像 docker search nginx 参数介绍 NAME: 镜像仓库源的名称DESCRIPTION: 镜像的描述OFFICIAL: 是否 docker 官方发布STARS: 点赞、喜欢AUTOMATED: 自动构建。 拉去镜像 …

shopify商城开发 引用谷歌字体库 fonts.google.com

引用谷歌字体库 https://fonts.google.com/ <link rel"preconnect" href"https://fonts.googleapis.com"> <link rel"preconnect" href"https://fonts.gstatic.com" crossorigin> <link href"https://fonts.goo…

C语言——K /C语言内存函数

一、memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数 memcpy 从 source 的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果source和destination有…

了解一下DHCP

DHCP的工作原理 本质&#xff1a; 1、物理网卡自身集成了DHCP的功能&#xff0c;为了请求获取合法、可用的IP 2、DHCP服务端核心功能在于&#xff1a;通过自定义的网段的地址池&#xff0c;来给与新加入的网络环境的设备以租约的方式分配合法IP 1.什么是DHCP 1.1DHCP定义 …

Java获取当前用户当前工作目录

方法一&#xff1a;使用System.getProperty(“user.dir”)函数可以获取用户当前工作目录 例如&#xff0c;Java工程的文件布局如下&#xff1a; 主类文件&#xff0c;获取用户当前的工作目录&#xff1a; package com.thb;public class Test5 {public static void main(Stri…

如何在Kali Linux安装Xrdp+cpolar内网穿透实现远程访问Kali系统

文章目录 前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于&#xff0c;它允许用户从远程位置访问Kali系统&#xff0c;而无需直接物理访…

HTTP 301错误:永久重定向,大勇的冒险之旅

大家好&#xff0c;我是大勇&#xff0c;一个喜欢冒险的程序员。今天&#xff0c;我要和大家分享一个我在互联网世界中的冒险故事——如何处理HTTP 301错误&#xff1a;永久重定向。 那天&#xff0c;我像往常一样&#xff0c;打开我的代码编辑器&#xff0c;准备开始一天的工…

基于Java SSM框架实现列车火车高铁票务信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现列车火车高铁票务信息管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被…