labelme目标框+关键点数据标注,json文件转yolo-txt文件

import argparse
import collections
import datetime
import glob
import json
import os
import os.path as osp
import sys
import uuid
import imgviz
import cv2
import numpy as np
import random
import shutil
from tqdm import tqdm
import labelme
import pycocotools.mask


def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument("--img_dir", default = r"图片以及Json文档保存位置的上级目录", help="input annotated directory")
    parser.add_argument("--Folders", default=["图片以及Json文档保存文件名"])
    parser.add_argument("--ClsLabels", default = [''], help="labels file") # '标签'
    parser.add_argument("--YOLOBoxOnly", default=True, help = " yolov8需要Segmetation一起训练 ")
    parser.add_argument("--Cencer_Points_Format", default = True, action="store_true")
    parser.add_argument("--threshold_and",  type=int, default=18)
    parser.add_argument("--threshold_or", type=int, default=7)
    parser.add_argument("--show_cencer_points", default = False, action="store_true")
    parser.add_argument("--EmptyPointFolder", default=r"D:\Desktop\EmptyPointFolder", action="store_true")
    args = parser.parse_args()
    return args

def main(args):
    for Folder in args.Folders:
        LabelNum = len(args.ClsLabels)
        output_dir = os.path.join(args.img_dir, Folder, "labels")
        ImgPath = os.path.join(args.img_dir, Folder, "images")
        jsonPath = ImgPath
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        if not os.path.exists(args.EmptyPointFolder):
            os.makedirs(args.EmptyPointFolder)

        class_name_to_id = {}
        if args.ClsLabels is str and args.ClsLabels.endwiths(".txt"):
            for i, line in enumerate(open(args.ClsLabels).readlines()):
                class_id = i
                class_name = line.strip()
                if class_id == -1:
                    assert class_name == "__ignore__"
                    continue
                class_name_to_id[class_name] = class_id
        else:
            for id, name in enumerate(args.ClsLabels):
                class_name_to_id[name] = id

        ImgItems = glob.glob(osp.join(ImgPath , "*.jpg"))+glob.glob(osp.join(ImgPath , "*.bmp"))+glob.glob(osp.join(ImgPath , "*.png"))

        for imgPath in tqdm(ImgItems):
            img = cv2.imread(imgPath)
            h, w = img.shape[0], img.shape[1]
            JsonPath = imgPath.split(".")[0]+".json"
            if not os.path.exists(JsonPath):
               out_txt_path = os.path.join(output_dir, os.path.basename(imgPath).split(".")[0]+".txt")
               out_txt_f = open(out_txt_path, 'w')
               out_txt_f.write('\n')
               continue
            data = json.load(open(JsonPath))
            # print(JsonPath)
            base = os.path.splitext(os.path.basename(JsonPath))[0]
            polygonData ={}
            EmptyPoint = 0
            box_list = []
            seg_list = []
            point_list = []
            # height = data['imageHeight']
            # width = data['imageWidth']
            for id, shape in enumerate(data['shapes']):
                label_name = shape['label']
                if shape['shape_type'] == 'rectangle':
                    box_list.append(shape)
                elif shape['shape_type'] == 'polygon':
                    if label_name not in class_name_to_id:
                        shape['label'] = label_name
                        print(label_name, "not in ClsLabels")
                        continue
                    seg_list.append(shape)
                elif shape['shape_type'] == 'point':
                    point_list.append(shape)
            if len(box_list):
                with open(os.path.join(output_dir, (base + ".txt")), 'w') as file:
                    for box_shape, point_shape in zip(box_list,point_list):
                        label_name = box_shape['label']
                        if label_name not in class_name_to_id:
                            print(label_name, "not in ClsLabels")
                            continue
                        cls_id = class_name_to_id[label_name]
                        label_point = box_shape['points']
                        label_point = np.array(label_point).astype(np.int32)
                        # print(label_point)
                        X0,Y0,X1,Y1 = label_point[0][0], label_point[0][1], label_point[1][0], label_point[1][1]
                        Xmin , Ymin = min(X0, X1), min(Y0, Y1)
                        Xmax , Ymax = max(X0, X1), max(Y0, Y1)
                        Xmin,Ymin,Xmax,Ymax = max(int(Xmin),0), max(int(Ymin),0), min(max(int(Xmax),0),w) , min(max(int(Ymax),0),h)
                        if (Xmax-Xmin)<args.threshold_and and (Ymax-Ymin)<args.threshold_and:
                            continue
                        if (Xmax-Xmin)<args.threshold_or or (Ymax-Ymin)<args.threshold_or:
                            continue
                        b_w = (Xmax - Xmin)
                        b_h = (Ymax - Ymin)
                        b_x = Xmin + b_w / 2
                        b_y = Ymin + b_h / 2
                        b = [cls_id] + [b_x / w, b_y / h, b_w / w, b_h / h]
                        KeyPoint = np.array(point_shape['points']).flatten().astype(np.int32)
                        KeyPoint_X, KeyPoint_Y = KeyPoint[0], KeyPoint[1]
                        c_x = round((KeyPoint_X / w), 3)
                        c_y = round((KeyPoint_Y / h), 3)
                        if args.Cencer_Points_Format:
                            box = b + [c_x] + [c_y]
                        else:
                            box = b
                        line = *(box),  # cls, box or segments
                        file.write(('%g ' * len(line)).rstrip() % line + '\n')
                        if args.show_cencer_points:
                            cv2.circle(img, (KeyPoint_X, KeyPoint_Y), radius=2, color=(0, 0, 255), thickness=2,
                                       lineType=cv2.LINE_AA)
                file.close()
                if args.show_cencer_points:
                    cv2.imwrite(os.path.join(output_dir, (base + ".png")), img)
            elif len(seg_list):
                for id, seg_shape in enumerate(seg_list):
                    ann = {}
                    label_name = seg_shape['label']
                    cls_id = class_name_to_id[label_name]
                    points = seg_shape["points"]
                    points = np.asarray(points).reshape((-1, 1, 2))
                    if args.YOLOBoxOnly:
                        coordinates = np.array(points).reshape(-1, 2)
                        x0 = np.min(coordinates[:, 0])
                        x1 = np.max(coordinates[:, 0])
                        y0 = np.min(coordinates[:, 1])
                        y1 = np.max(coordinates[:, 1])
                        b_w = (x1 - x0)
                        b_h = (y1 - y0)
                        b_x = x0 + b_w / 2
                        b_y = y0 + b_h / 2
                        b = [cls_id] + [b_x / w, b_y / h, b_w / w, b_h / h]
                        ann["box"] = b
                    ann["seg_int32"] = np.array(points).reshape(-1, 2)
                    s = (np.array(points).reshape(-1, 2) / np.array([w, h])).reshape(-1).tolist()
                    if not args.Cencer_Points_Format:
                        ann["segment"] = [cls_id] + s
                    else:
                        ann["segment"] = s
                        ann["cls_id"] = [cls_id]
                    polygonData[id] = ann
                if args.Cencer_Points_Format:
                    for point_shape in point_list:
                        points = point_shape["points"]
                        points = np.asarray(points).flatten().tolist()
                        for id, ann in polygonData.items():
                            seg = ann['seg_int32'].astype(np.int32)
                            result = cv2.pointPolygonTest(seg, tuple(points), False)
                            if result >= 0:
                                ann["center"]=points
                                c_x = round((ann["center"][0] / w), 3)
                                c_y = round((ann["center"][1] / h), 3)
                                ann["Cencer_Points"] = [c_x] + [c_y]
                                if args.show_cencer_points:
                                    cv2.circle(img, (int(ann["center"][0]),int(ann["center"][1])), radius=2, color=(0,0,255),thickness=2,lineType=cv2.LINE_AA)
                for id, ann in polygonData.items():
                    if args.Cencer_Points_Format:
                        if "Cencer_Points" not in ann.keys():
                            shutil.move(imgPath, os.path.join(args.EmptyPointFolder, os.path.basename(imgPath)))
                            shutil.move(JsonPath, os.path.join(args.EmptyPointFolder, os.path.basename(JsonPath)))
                            EmptyPoint = 1
                            break
                if not EmptyPoint:
                    with open(os.path.join(output_dir, (base + ".txt")), 'w') as file:
                        for id, ann in polygonData.items():
                            if args.YOLOBoxOnly:
                                if args.Cencer_Points_Format:
                                    box = ann["box"]+ann["Cencer_Points"]
                                else:
                                    box = ann["box"]
                                line = *(box),  # cls, box or segments
                                file.write(('%g ' * len(line)).rstrip() % line+'\n')
                            else:
                                if args.Cencer_Points_Format:
                                    segment = ann["Cencer_Points"] + ann["cls_id"] + ann["segment"]
                                else:
                                    segment = ann["segment"]
                                line = *(segment),  # cls, box or segments
                                file.write(('%g ' * len(line)).rstrip() % line + '\n')
                    file.close()
                    if args.show_cencer_points:
                        cv2.imwrite(os.path.join(output_dir,(base+".png")),img)
            else:
                with open(os.path.join(output_dir, (base + ".txt")), 'w') as file:
                    pass
                file.close()
    EmptyFiles = os.listdir(args.EmptyPointFolder)
    if len(EmptyFiles)==0:
        os.rmdir(args.EmptyPointFolder)

if __name__ == "__main__":
    args = parse_opt()
    main(args)

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值