C#本地将labelme数据集转换为机器视觉yolo数据集格式

C#本地,将labelme数据集转换为机器视觉yolo数据集格式

csharp 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.RegularExpressions;
using System.Text.Unicode;
using System.Threading.Tasks;
using System.Windows.Ink;
using System.Windows.Media.Media3D;

namespace WpfAppYolo11_test1
{
    /// <summary>
    /// 将labelme数据集转换为yolo数据集格式
    /// </summary>
    public class LabelmeToYoloDataSetUtils
    {
        Dictionary<string, short> labels = new Dictionary<string, short>();


        /// <summary>
        /// 转换后保存目录
        /// </summary>
        const string outDir = "D:\\yoloTrainDataSet";
        const int saveLength = 10;

        /// <summary>
        /// labelme转yolo格式数据,要转换的目录
        /// </summary>
        /// <param name="inputDir"></param>
        /// 2025-3-4 00:45:38,
        public void FileConvert(string inputDir)
        {
            //labels.Clear();
            var files = System.IO.Directory.GetFiles(inputDir, "*.json");
            if (files == null || files.Length == 0)
            {
                return;
            }


            //获取目录中文件夹,以数字升序命名最新的训练文件夹
            var folders = Directory.GetDirectories(outDir);
            int lastNum = 1;
            if (folders != null && folders.Length > 0)
            {
                List<DirectoryInfo> dirList = new List<DirectoryInfo>();
                foreach (var item in folders)
                {
                    DirectoryInfo directoryInfo = new DirectoryInfo(item);
                    dirList.Add(directoryInfo);
                }
                var lastDir = dirList.OrderByDescending(g => g.CreationTime).FirstOrDefault();
                //获取文件夹后缀
                var lastNumStr = Regex.Match(lastDir.Name, "\\d*$").Value;
                lastNum = Convert.ToInt32(lastNumStr) + 1;
            }
            //此次训练保存的文件夹
            string newTrainDir = "train" + lastNum;

            //string dirNew = "train" + Guid.NewGuid().ToString("n");
            string dirNew = outDir + "\\" + newTrainDir + "\\train";
            //处理json文件
            foreach (var item in files)
            {
                //处理单个json文件
                SingleFileConvert(item, dirNew);
            }

            //挑选训练图片前两个图片作为验证集
            //创建val文件夹
            string val = Path.Combine(outDir, newTrainDir, "val");                      
           
            var files21 = System.IO.Directory.GetFiles(inputDir, "*.jpg");
            var files22 = System.IO.Directory.GetFiles(inputDir, "*.png");
            var fileContainer = files21.Union(files22).ToList();
            var first1 = fileContainer[0];
            var first2 = fileContainer[1];

            //将训练图片全部复制到train中
            var trainImgNew = Path.Combine(dirNew, "images");
            if (!Directory.Exists(trainImgNew))
            {
                Directory.CreateDirectory(trainImgNew);
            }
            foreach (var itemImg in fileContainer)
            {
                string fileNew2  = Path.Combine(trainImgNew, Path.GetFileName(itemImg));
                File.Copy(itemImg, fileNew2);
            }
            //只有2个样本时,将训练的文件夹作为验证
            if (files.Length <= 2)
            {
                val = dirNew;
                goto Val_done;
            }
            if (!Directory.Exists(val))
            {
                Directory.CreateDirectory(val);
            }
            //图片文件夹
            string valImage = Path.Combine(val, "images");
            if (!Directory.Exists(valImage))
            {
                Directory.CreateDirectory(valImage);
            }
            string file1Name = Path.GetFileName(first1);
            string file2Name = Path.GetFileName(first2);
            string img1 = Path.Combine(valImage, file1Name);
            File.Copy(first1, img1);
            string img2 = Path.Combine(valImage, file2Name);
            File.Copy(first2, img2);

            //坐标数据
            string vallabels = Path.Combine(val, "labels");
            if (!Directory.Exists(vallabels))
            {
                Directory.CreateDirectory(vallabels);
            }
            //找到train目录中的坐标数据
            string vallabels2 = Path.Combine(dirNew, "labels");
            string txt1 = Path.GetFileNameWithoutExtension(file1Name) + ".txt";
            string txt2 = Path.GetFileNameWithoutExtension(file2Name) + ".txt";
            string fileLabel1 = Path.Combine(vallabels2, txt1);
            string fileLabel2 = Path.Combine(vallabels2, txt2);
            if (File.Exists(fileLabel1))
            {
                string fileLabelTxt1 = Path.Combine(vallabels, txt1);
                File.Copy(fileLabel1, fileLabelTxt1);
            }
            if (File.Exists(fileLabel2))
            {
                string fileLabelTxt2 = Path.Combine(vallabels, txt2);
                File.Copy(fileLabel2, fileLabelTxt2);
            }

        Val_done:
            //生成data.yaml
            string dir = dirNew;//Path.Combine(outDir, newTrainDir);
            dir = dir.Replace("\\", "/");
            val = val.Replace("\\", "/");

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("train: " + dir);
            sb.AppendLine("val: " + val);
            sb.AppendLine("test: " + val);
            sb.AppendLine("");
            sb.AppendLine("nc: " + labels.Count);

            //设置编码支持中文
            string labelName = System.Text.Json.JsonSerializer.Serialize(labels.Keys,
                     new System.Text.Json.JsonSerializerOptions()
                     {
                         Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
                     }
                );
            labelName = labelName.Replace("\"", "'");//替换双引号为单引号
            sb.AppendLine("names: " + labelName);

            //保存
            //var arr = inputDir.Split("\\");
            //var lastDir = arr.Last();
            //string newDir = inputDir.TrimEnd(lastDir.ToArray());
            //string filePath = Path.Combine(newDir, "yoloTrainDataSet", "data.yaml");
            string yamlDir = outDir + "\\" + newTrainDir;
            string filePath = Path.Combine(yamlDir, "data.yaml");
            System.IO.File.WriteAllText(filePath, sb.ToString());


        }

        /// <summary>
        /// 单个json文件转换
        /// </summary>
        public void SingleFileConvert(string file, string inputDir)
        {
            string json = System.IO.File.ReadAllText(file);
            var data2 = System.Text.Json.JsonSerializer.Deserialize<LabelMeView>(json);
            if (data2 == null || data2.shapes == null || data2.shapes.Count == 0)
            {
                return;
            }
            StringBuilder stringBuilder = new StringBuilder();

            //读取每个形状
            foreach (var item in data2.shapes)
            {
                //忽略没名称的形状
                if (string.IsNullOrEmpty(item.label))
                {
                    continue;
                }
                labels.TryAdd(item.label, 1);

                double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
                if (item.shape_type == "rectangle")
                {
                    x1 = item.points[0][0];
                    y1 = item.points[0][1];

                    x2 = item.points[1][0];
                    y2 = item.points[1][1];
                }
                else if (item.shape_type == "polygon")
                {
                    x1 = item.points.Select(g => g[0]).Min();
                    y1 = item.points.Select(g => g[1]).Min();

                    x2 = item.points.Select(g => g[0]).Max();
                    y2 = item.points.Select(g => g[1]).Max();
                }
                //中心点
                double x_center = (x1 + x2) / (double)2 / data2.imageWidth;
                double y_center = (y1 + y2) / (double)2 / data2.imageHeight;
                double width = Math.Abs((x2 - x1) / data2.imageWidth);
                double height = Math.Abs((y2 - y1) / data2.imageHeight);
                 
                //获取对象id
                int classId = labels.Keys.ToList().IndexOf(item.label);

                stringBuilder.AppendLine($"{classId} {x_center} {y_center} {width} {height}");
            }
            //保存txt文件
            //var arr = inputDir.Split("\\");
            //var lastDir = arr.Last();
            //string newDir = inputDir.TrimEnd(lastDir.ToArray());
            // string dir = System.IO.Path.Combine( outDir, "labels");
            string dir = System.IO.Path.Combine(inputDir, "labels");
            if (!System.IO.Directory.Exists(dir))
            {
                System.IO.Directory.CreateDirectory(dir);
            }
            //string fileName = Path.GetFileName(file) + "_" + Guid.NewGuid().ToString("n") + ".txt";
            string fileName = Path.GetFileNameWithoutExtension(file) + ".txt";
            string filePath = System.IO.Path.Combine(dir, fileName);
            File.WriteAllText(filePath, stringBuilder.ToString());
        }
    }

    public class LabelMeView
    {
        public string version { get; set; }
        public List<ShapeView> shapes { get; set; }
        public string imagePath { get; set; }

        /// <summary>
        /// 图片高度,px
        /// </summary>
        public int imageHeight { get; set; }

        /// <summary>
        /// 图片宽度,px
        /// </summary>
        public int imageWidth { get; set; }
    }

    public class ShapeView
    {
        /// <summary>
        /// 对象说明,标签
        /// </summary>
        public string label { get; set; }

        /// <summary>
        /// 形状描述;rectangle;polygon
        /// </summary>
        public string shape_type { get; set; }
        public object flags { get; set; }

        /// <summary>
        /// 坐标点
        /// </summary>
        public List<double[]> points { get; set; }
        public string version { get; set; }
    }

}
相关推荐
智驱力人工智能1 小时前
加油站静电夹检测 视觉分析技术的安全赋能与实践 静电夹检测 加油站静电夹状态监测 静电接地报警器检测
人工智能·深度学习·算法·安全·yolo·边缘计算
不想起名字呢4 小时前
Yolov5 RKNN 后处理拆分-知其然知其所以然
yolo·rknn
FL16238631294 小时前
[C#][winform]基于yolov11的水下目标检测系统C#源码+onnx模型+评估指标曲线+精美GUI界面
人工智能·yolo·目标检测
Dingdangcat864 小时前
篮球场景目标检测与识别实时定位与分类YoloV8分割改进AIFI原创
yolo·目标检测·分类
牙牙要健康5 小时前
【YOLOv8-Ultralytics】 【目标检测】【v8.3.235版本】 模型专用预测器代码predict.py解析
yolo·目标检测·目标跟踪
wfeqhfxz25887825 小时前
YOLOv10n-GoldYolo:多旋翼无人机目标检测与识别实战指南_1
yolo·目标检测·无人机
Coding茶水间17 小时前
基于深度学习的反光衣检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
图像处理·人工智能·深度学习·yolo·目标检测·机器学习·计算机视觉
零小陈上(shouhou6668889)20 小时前
YOLOv8+PyQt5车辆类型检测(可以重新训练,yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)
yolo
AI街潜水的八角1 天前
基于YOLOv12农作物检测系统1:农作物检测数据集说明(含下载链接)
yolo
AAD555888991 天前
农业机械检测与识别46基于YOLOv8-SPPF-LSKA的Supperseeder和拖拉机目标检测系统_1
yolo·目标检测·目标跟踪