【教程】VOC数据集制作

news2024/11/16 11:36:02

语义分割任务中VOC数据集的制作,任务中只有一种标签:gas

文章目录

  • 1、由黑白图像识别为txt标签
  • 2、txt转json
  • 3、数据集转VOC格式

1、由黑白图像识别为txt标签

由于使用CycleGAN网络进行风格迁移学习,生成了大量伪标签图像,因此需要自动提取出标签,标签格式为YOLOv8训练所需要的语义分割的标签格式
例如:提取出下图中白色的区域的标签信息
在这里插入图片描述
txt标签:
在这里插入图片描述

import os
import cv2
import numpy as np
'''
该段代码读取文件夹中的二值图像,输出白色区域的标注信息
格式为YOLOv8图像分割的txt格式
'''
def process_images(input_folder, output_folder):
    # 如果输出文件夹不存在,则创建它
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    # 列出输入文件夹中的所有图像文件
    image_files = [f for f in os.listdir(input_folder) if f.endswith(('.png', '.jpg', '.jpeg', '.bmp'))]
    total_images = len(image_files)
    print(f"在文件夹'{input_folder}'中找到了 {total_images} 张图像。")
    # 处理每张图像
    for idx, filename in enumerate(image_files, 1):
        print(f"正在处理图像 {idx} / {total_images} : {filename}")
        # 加载图像
        image_path = os.path.join(input_folder, filename)
        image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
        # 检查图像是否正确加载
        if image is None:
            print(f"图像 {filename} 未能正确加载。")
            continue
        # 对图像进行阈值处理以获得二值图像
        _, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
        # 寻找轮廓
        contours, _ = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # 初始化一个列表来存储轮廓坐标
        contour_coordinates = []
        # 获取图像的尺寸以进行归一化
        height, width = image.shape
        # 遍历轮廓以提取归一化坐标
        for contour in contours:
            # 初始化一个列表来存储单个轮廓的坐标
            coords = ['0']  # 开头的数字0(没有小数点)
            for point in contour:
                # 归一化x和y坐标并添加到列表中
                x_normalized = point[0][0] / width
                y_normalized = point[0][1] / height
                coords.extend([f"{x_normalized:.6f}", f"{y_normalized:.6f}"])
            # 将单个轮廓的坐标添加到主列表中
            contour_coordinates.append(' '.join(coords))
        # 定义输出文本文件的路径
        output_file_path = os.path.join(output_folder, os.path.splitext(filename)[0] + '.txt')
        # 将坐标写入文本文件
        with open(output_file_path, 'w') as file:
            file.write('\n'.join(contour_coordinates))
# 输入和输出文件夹路径(请替换为实际路径)
input_folder_path = 'D:\Desktop\\test0326'  # 替换为实际的输入图片文件夹
output_folder_path = 'D:\Desktop\\test0326'  # 替换为实际的输出txt标签文件夹
# 调用函数以处理图像
process_images(input_folder_path, output_folder_path)

2、txt转json

由txt文件转换为labelme标注的json格式,本人的labelme版本为5.3.1,json文件内涵图像数据,具体格式为:

json_data = {
            "version": "5.3.1",
            "flags": {},
            "shapes": [],
            "imagePath": img_filename,
            "imageData": encoded_string,
            "imageHeight": height,
            "imageWidth": width
        }

代码如下:

import os
import json
import base64
from PIL import Image
import io

# 文件夹路径
label_folder = 'D:\\Desktop\\Unet\\dataset\\500txt'   # txt标签文件夹
image_folder = 'D:\\Desktop\\Unet\\dataset\\500images'  # 图像文件夹
output_folder = 'D:\\Desktop\\Unet\\dataset\\500jsons'  # json标签输出的文件夹

# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)
# 遍历文件夹中的所有 txt 文件
for filename in os.listdir(label_folder):
    if filename.endswith('.txt'):
        # 构造完整的文件路径
        txt_path = os.path.join(label_folder, filename)
        # 构造对应的图像文件路径
        img_filename = filename.replace('.txt', '.jpg')
        img_path = os.path.join(image_folder, img_filename)
        # 读取图像尺寸并转换为 base64
        with Image.open(img_path) as img:
            width, height = img.size
            buffered = io.BytesIO()
            img.save(buffered, format="JPEG")
            encoded_string = base64.b64encode(buffered.getvalue()).decode('utf-8')

        # 初始化 JSON 数据结构
        json_data = {
            "version": "5.3.1",
            "flags": {},
            "shapes": [],
            "imagePath": img_filename,
            "imageData": encoded_string,
            "imageHeight": height,
            "imageWidth": width
        }
        # 读取 txt 文件并解析多边形坐标
        with open(txt_path, 'r') as file:
            for line in file:
                parts = line.strip().split()
                label_index = parts[0]  # 假设第一部分是类别索引
                if len(parts) < 3 or len(parts) % 2 == 0:
                    print(f"Unexpected format in {filename}")
                    continue
                # 将相对坐标转换为实际坐标(像素值)
                label = 'gas' if label_index == '0' else 'unknown'
                points = [(float(parts[i]) * width, float(parts[i + 1]) * height) for i in range(1, len(parts), 2)]
                shape_data = {
                    "label": label,
                    "points": points,
                    "group_id": None,
                    "description": "",
                    "shape_type": "polygon",
                    "flags": {}
                }
                json_data["shapes"].append(shape_data)
        # 输出 JSON 文件
        output_path = os.path.join(output_folder, filename.replace('.txt', '.json'))
        with open(output_path, 'w') as jsonfile:
            json.dump(json_data, jsonfile, indent=2)
            print(f"文件 {output_path} 已转换完成!")

print("Conversion to JSON completed.")

3、数据集转VOC格式

准备好原图和json格式的标签后,转换为VOC所需的语义分割数据集
还需要准备一个labels.txt文件,里面写上所有的类别,格式如下:

__ignore__
_background_
gas

由于我的任务中只有gas这一类,所以只需要写gas,如果是多类,则依次往下添加即可,“ignore”和“background”这两行不要动,准备好labels.txt文件后还需要将路径填到下方转换代码中注明的位置:

from __future__ import print_function
import argparse
import glob
import os
import os.path as osp
import sys
import imgviz
import numpy as np
import labelme


def main(args):
    if osp.exists(args.output_dir):
        print("Output directory already exists:", args.output_dir)
        sys.exit(1)
    os.makedirs(args.output_dir)
    os.makedirs(osp.join(args.output_dir, "JPEGImages"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClassnpy"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClass"))
    if not args.noviz:
        os.makedirs(
            osp.join(args.output_dir, "SegmentationClassVisualization")
        )
    print("Creating dataset:", args.output_dir)
    class_names = []
    class_name_to_id = {}
    for i, line in enumerate(open(args.labels).readlines()):
        class_id = i - 1  # starts with -1
        class_name = line.strip()
        class_name_to_id[class_name] = class_id
        if class_id == -1:
            assert class_name == "__ignore__"
            continue
        elif class_id == 0:
            assert class_name == "_background_"
        class_names.append(class_name)
    class_names = tuple(class_names)
    print("class_names:", class_names)
    out_class_names_file = osp.join(args.output_dir, "class_names.txt")
    with open(out_class_names_file, "w") as f:
        f.writelines("\n".join(class_names))
    print("Saved class_names:", out_class_names_file)
    for filename in glob.glob(osp.join(args.input_dir, "*.json")):
        print("Generating dataset from:", filename)
        label_file = labelme.LabelFile(filename=filename)
        base = osp.splitext(osp.basename(filename))[0]
        out_img_file = osp.join(args.output_dir, "JPEGImages", base + ".jpg")
        out_lbl_file = osp.join(
            args.output_dir, "SegmentationClassnpy", base + ".npy"
        )
        out_png_file = osp.join(
            args.output_dir, "SegmentationClass", base + ".png"
        )
        if not args.noviz:
            out_viz_file = osp.join(
                args.output_dir,
                "SegmentationClassVisualization",
                base + ".jpg",
            )
        with open(out_img_file, "wb") as f:
            f.write(label_file.imageData)
        img = labelme.utils.img_data_to_arr(label_file.imageData)
        lbl, _ = labelme.utils.shapes_to_label(
            img_shape=img.shape,
            shapes=label_file.shapes,
            label_name_to_value=class_name_to_id,
        )
        labelme.utils.lblsave(out_png_file, lbl)
        np.save(out_lbl_file, lbl)
        if not args.noviz:
            viz = imgviz.label2rgb(
                label=lbl,
                # img=imgviz.rgb2gray(img),
                # img=img,
                font_size=15,
                label_names=class_names,
                loc="rb",
            )
            imgviz.io.imsave(out_viz_file, viz)

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--input_dir", default="D:\Desktop\\Unet\dataset\\500jsons", type=str,   ## 在这里输入json标签文件夹
                        help="input annotated directory")
    parser.add_argument("--output_dir", default="D:\Desktop\\Unet\dataset\VOC500images\\", type=str,  ## 在这里输入图片文件夹 
                        help="output dataset directory")
    parser.add_argument("--labels", default="D:\Desktop\\Unet\\dataset\\labels.txt", type=str,   ## 输入labels.txt文件所在的路径
    help="labels file")
    parser.add_argument("--noviz", help="no visualization", action="store_true")
    args = parser.parse_args()
    return args
if __name__ == "__main__":
    args = get_args()
    main(args)

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

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

相关文章

阿里云ICP备案工信部短信核验详细流程,1分钟搞定教程!

网站ICP备案或APP备案通过云厂商的备案初审后&#xff0c;需要在工信部完成短信核验操作&#xff0c;本文云服务器吧yunfuwuqiba.com以阿里云备案为例&#xff0c;来详细说明工信部短信核验详细流程&#xff0c;非常简单&#xff1a; 阿里云备案提交到阿里云初审&#xff0c;初…

学习操作系统之OS的作用

OS是用户与计算机硬件之间的接口 OS处于用户和硬件系统之间,用户通过OS来使用计算机硬件系统.即用户可以在OS的帮助下方便、快捷、可靠的操作计算机硬件和运行自己的程序。 下图是我对于操作系统的简单理解 OS是计算机系统资源的管理者 一个计算机系统包含四类硬件资源&…

angular—mooc课学习笔记

1.angular工程目录 2.设置标签元素样式 3.fex布局 4.事件绑定 5. 双向数据传输 6. 键盘实现方法 7.内置指令拉选框 8. ngFor指令

RocketMQ建Topic

# 查看集群状况 ./mqadmin clusterList -n localhost:9876 # 创建topic ./mqadmin updateTopic -b localhost:10911 -t my_topic -n localhost:9876 # 查看所有topic ./mqadmin topicList -n localhost:9876参考 Admin Tool

ESP32S3网络编程学习笔记(1)—— Wi-Fi扫描实验

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动/单片机/RTOS的实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff…

计算机服务器中了helper勒索病毒怎么办,helper勒索病毒解密流程步骤

随着网络技术在企业中的不断应用&#xff0c;越来越多的企业离不开网络&#xff0c;网络为企业提供了极大便利&#xff0c;大大提升了生产运营效率&#xff0c;由此而产生的网络数据安全问题也成为了企业关心的主要话题。近期&#xff0c;云天数据恢复中心接到多家企业的求助&a…

在虚拟机尝试一次用启动盘重装系统

在虚拟机尝试一次用启动盘重装系统 没有自己重装过系统&#xff0c;也不敢对自己的笔记本下手&#xff0c;用虚拟机重装玩玩试试。 先设置成u盘启动 从boot中选择相应的创建的硬盘即可&#xff08;刚刚突然发现图片不能上传了&#xff0c;经过乱七八糟的尝试后&#xff0c;开一…

90天玩转Python—06—基础知识篇:Python中的七大基础数据类

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

js的qq换肤效果

文章目录 1. 演示效果2. 分析思路3. 代码实现3.1. 方式一3.2. 方式二3.3. 整体代码 1. 演示效果 2. 分析思路 先编写样式&#xff0c;弄好布局和排版。遍历这个集合&#xff0c;对每个图片元素&#xff08;img&#xff09;添加一个点击事件监听器。可以使用 for 或者 forEach …

计算机毕业设计java 基于Android的拼图游戏app

当今社会&#xff0c;随着电子信息技术的发展&#xff0c;电子游戏也成为人们日常生活的一部分。这种娱乐方式结合了日新月异的技术&#xff0c;在游戏软件中结合了多种复杂技术。拼图游戏流行在各种电子产品上&#xff0c;从计算机&#xff0c;掌上游戏机到如今的手机&#xf…

番茄 短abogus补环境

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章…

849. Dijkstra求最短路 I

tips&#xff1a; 采用0x3f3f3f3f作为一个极大值&#xff1a; 1061109567 //是一个很大的数&#xff0c;可以用来代表∞&#xff1b; 在memset里0x3f表示为0x3f3f3f3f memset(a, 0x3f, sizeof a); //0x是十六进制的意思&#xff1b; memset()是对char操作&#xff0c;即一个…

Vue3组件基础示例

组件是vue中最推崇的&#xff0c;也是最强大的功能之一&#xff0c;就是为了提高重用性&#xff0c;减少重复性的开发。 如何使用原生HTML方法实现组件化 在使用原生HTML开发时&#xff0c;我们也会遇到一些常见的功能、模块&#xff0c;那么如何在原生HTML中使用组件化呢&am…

再聊一聊AUC指标

关于模型评估的指标&#xff0c;之前已经写过不少这方面的文章&#xff0c;最近在实践中又有了一点新的思考&#xff0c;本文对模型评估中的AUC指标再进行一些简单的探讨。 情况一&#xff0c;以下图中的数据为例&#xff0c;1代表用户发生逾期&#xff0c;标记为坏样本&#x…

Java | Leetcode Java题解之第5题最长回文子串

题目&#xff1a; 题解&#xff1a; class Solution {public String longestPalindrome(String s) {int start 0, end -1;StringBuffer t new StringBuffer("#");for (int i 0; i < s.length(); i) {t.append(s.charAt(i));t.append(#);}t.append(#);s t.to…

递归学习第一个课

一、递归定义 基本定义 函数自己调用自己&#xff08;通俗第一印象&#xff09;大问题可以拆分小问题&#xff08;拆分&#xff0c;边界&#xff09;大问题与小问题的关系&#xff08;递归关系&#xff09; 为什么拆分小问题&#xff1f; 小问题更容易求解大问题与小问题内部…

LeetCode 热题 100 | 动态规划(一)

目录 1 70. 爬楼梯 1.1 基本思路 1.2 官方题解 2 118. 杨辉三角 3 198. 打家劫舍 菜鸟做题&#xff0c;语言是 C 1 70. 爬楼梯 核心思想&#xff1a;把总问题拆解为若干子问题。 总问题&#xff1a;上到 5 楼的方式有多少种子问题&#xff1a;上到 4 楼的方式有多…

k8s安全控制、授权管理介绍,全网最新

3.ABAC 4.Webhook 5.Node 6.RBAC 三.Role解释 1.Role和ClusterRole 2.Rolebinding和ClusterBinding 3.Rolebinding和ClusterRole 四.准入控制 1.命令格式 2.可配置控制器 五.例子 1.生成签署证书 2.设置用户和上下文信息 3.为sulibao用户授权 一.Kubernetes安全控…

4.7学习总结

java学习 一.Stream流 (一.)概念: Stream将要处理的元素集合看作一种流&#xff0c;在流的过程中&#xff0c;借助Stream API对流中的元素进行操作&#xff0c;比如&#xff1a;筛选、排序、聚合等。Stream流是对集合&#xff08;Collection&#xff09;对象功能的增强&…

如何使用Java和RabbitMQ实现延迟队列?

前言 今天我们使用Java和RabbitMQ实现消息队列的延迟功能。 前期准备&#xff0c;需要安装好docker、docker-compose的运行环境。 需要安装RabbitMQ的可以看下面这篇文章。 如何使用PHP和RabbitMQ实现消息队列&#xff1f;-CSDN博客 今天讲的是依赖RabbitMQ的延迟插件实现…