파이썬

[AI, python] AI HUB 데이터셋의 어노테이션(Annotation, label)을 darknet format으로 변환하기 (BBOX일 경우)

Heeyeon Choi 2023. 8. 16. 17:36
728x90

https://www.aihub.or.kr/

 

AI-Hub

자세히보기 AI 허브가 추천하는 검색어입니다. 태그를 클릭하여 검색결과를 확인하세요.

www.aihub.or.kr

AI HUB의 데이터셋의 어노테이션 파일을 yolo darknet format으로 변경하는 방법을 소개하고자 합니다.

Annotation 파일은 보통 json으로 라벨링 되어 있습니다.

 

<json 예시>

{
	"info": {
		"description": "JSON file",
		"url": "",
		"version": "1.0",
		"year": 2021,
		"contributor": "",
		"date_created": ""
	},
	"images": {
		"file_name": 95.png",
		"height": 720,
		"width": 1280,
		"id": 1
	},
	"annotations": [
		{
			"segmentation": [],
			"polyline": [],
			"image_id": 1,
			"bbox": [
				274.59016393442624,
				199.1803278688525,
				55.73770491803276,
				198.7704918032787
			],
			"category_id": 2,
			"area": 11079.011018543399,
			"is_crowd": 0,
			"id": 1
		},
		{
			"segmentation": [],
			"polyline": [],
			"image_id": 1,
			"bbox": [
				5.037313432835821,
				343.84328358208955,
				53.17164179104477,
				7.089552238805936
			],
			"category_id": 10,
			"area": 376.9631321006887,
			"is_crowd": 0,
			"id": 7
		}
	],
	"categories": [
		{
			"id": 1,
			"name": "Animals(Dolls)"
		},
		{
			"id": 2,
			"name": "Person"
		},
		{
			"id": 3,
			"name": "Garbage bag & sacks"
		},
		{
			"id": 4,
			"name": "Construction signs & Parking prohibited board"
		},
		{
			"id": 5,
			"name": "Traffic cone"
		},
		{
			"id": 6,
			"name": "Box"
		},
		{
			"id": 7,
			"name": "Stones on road"
		},
		{
			"id": 8,
			"name": "Pothole on road"
		},
		{
			"id": 9,
			"name": "Filled pothole"
		},
		{
			"id": 10,
			"name": "Manhole"
		}
	]
}

 

<darknet format>

yolo의 darknet format은 classID, x1 / xres, y1/yres, bbox_width /xres, bbox_height / yres  입니다.

 

<darknet format 예시>

2 0.8027344 0.2204861 0.140625 0.3159722
2 0.7978515899999999 0.70833335 0.09960938 0.2708333
2 0.29980465 0.19444444 0.1425781 0.3125
0 0.57031255 0.2586806 0.1914063 0.2743056
0 0.51171875 0.609375 0.1601563 0.21875

- 우선 클래스 아이디는 annotation[i]["category_id"] 에 있습니다.

bbox = annotation[i]["bbox"]
width = images["width"]
height = images["height"]
xRes = float(width) 로, 사진의 너비입니다. width는 string형으로, float으로 바꿔줍니다.
yRes = float(height) 로. 사진의 높이입니다.height는 string형으로, float으로 바꿔줍니다.

 

boxWidth = float(bbox[2]) / xRes
boxHeight = float(bbox[3])/ yRes
xCenter = float(bbox[0]) / xRes
yCenter = float(bbox[1])/ yRes

 

<python 최종 코드>

import os
import shutil
import json

rootpath = "C:/Users/heeye/Desktop/Mainroad_B03/1/"

file_lst = os.listdir(rootpath)


for file in file_lst:
    if file.endswith("BBOX.json") :
        # 현재 디렉토리내에 각각의 파일을 출력
        print(file+"\n")
        with open (rootpath+file,"r") as f :          
            data = json.load(f)
            annotation = data["annotations"]
            images =  data["images"]
            num = len(annotation)
            imgFileName = images["file_name"]
            splitimgFileName = imgFileName.split('.')[0]
           
            f= open(rootpath+splitimgFileName+ ".txt","w+")
               
            for i in range(num):
                classID = annotation[i]["category_id"]
                bbox = annotation[i]["bbox"]
                width = images["width"]
                height = images["height"]
                xRes = float(width)
                yRes = float(height)
               
                if ((classID is None ) or  (bbox is None)  or  width == 0 or  height == 0):
                    print("null 값 입니다."+"\n")
                    break
               
                boxWidth = float(bbox[2]) / xRes
                boxHeight = float(bbox[3])/ yRes
                xCenter = float(bbox[0]) / xRes
                yCenter = float(bbox[1])/ yRes
               
                f.write(str(classID)+" "+str(xCenter)+" "+str(yCenter)+" "+str(boxWidth)+" "+str(boxHeight)+"\n")
            f.close()
        os.remove(rootpath+file)
728x90