图像标签格式转换
在做图像检测的时候,不同打标签软件得到的标签格式可能会不一样,此处提供lableimg(txt格式)和lableme(json格式)的互换。
json →txt
import os
import json
import cv2
import base64
import argparse
def parse_opt():
parser = argparse.ArgumentParser()
# 根据你的路径进行修改
parser.add_argument('--img_path', type=str, default='img/')
parser.add_argument('--txt_path', type=str, default='labels/test.txt')
parser.add_argument('--json_path', type=str, default='json/')
parser.add_argument('--class_names', type=str, default='[your class name]') # 修改为你的类别名称
opt = parser.parse_args()
return opt
def decode_txt_file(txt_path, img_path, json_path, class_names):
class_name = {i: name for i, name in enumerate(class_names)}
dic = {}
dic['version'] = '5.0.2'
dic['flags'] = {}
dic['shapes'] = []
img_name = os.path.basename(txt_path).replace('.txt', '.jpg')
img = cv2.imread(os.path.join(img_path, img_name))
imageHeight, imageWidth, _ = img.shape
with open(txt_path) as f:
datas = f.readlines()
for data in datas:
shape = {}
data = data.strip().split(' ')
class_id = int(data[0])
shape['label'] = class_name[class_id]
x = float(data[1]) * imageWidth
y = float(data[2]) * imageHeight
w = float(data[3]) * imageWidth
h = float(data[4]) * imageHeight
x1 = x - w / 2
y1 = y - h / 2
x2 = x1 + w
y2 = y1 + h
shape['points'] = [[x1, y1], [x2, y2]]
shape['shape_type'] = 'rectangle'
shape['flags'] = {}
dic['shapes'].append(shape)
dic['imagePath'] = img_name
dic['imageData'] = base64.b64encode(
open(os.path.join(img_path, img_name), 'rb').read()).decode('utf-8')
dic['imageHeight'] = imageHeight
dic['imageWidth'] = imageWidth
json_file = os.path.join(json_path, os.path.basename(txt_path).replace('.txt', '.json'))
with open(json_file, 'w') as fw:
json.dump(dic, fw)
print(f'Saved {json_file}.')
if __name__ == '__main__':
opt = parse_opt()
img_path = opt.img_path
txt_path = opt.txt_path
json_path = opt.json_path
class_names = opt.class_names.split(',')
if txt_path.endswith('.txt'): # 单个文件转换
decode_txt_file(txt_path, img_path, json_path, class_names)
print('The conversion of single txt to json is complete')
else:
txt_names = os.listdir(txt_path) # 多个文件转换
for txt_name in txt_names:
txt_file = os.path.join(txt_path, txt_name)
decode_txt_file(txt_file, img_path, json_path, class_names)
print('The conversion of txt to json is complete')
txt → json
import os
import json
import cv2
import base64
import argparse
def parse_opt():
# Parse command line arguments.
parser = argparse.ArgumentParser()
parser.add_argument('--img_path', type=str, default='img/')
parser.add_argument('--txt_path', type=str, default='labels')
parser.add_argument('--json_path', type=str, default='json/')
parser.add_argument('--class_names', type=str, default='[your class name]') # 修改为你的类别名称
opt = parser.parse_args()
return opt
def decode_txt_file(txt_path, img_path, json_path, class_names):
# Convert a txt file to a json file.
class_name = {i: name for i, name in enumerate(class_names)}
dic = {}
dic['version'] = '5.0.2'
dic['flags'] = {}
dic['shapes'] = []
img_name = os.path.basename(txt_path).replace('.txt', '.jpg')
img = cv2.imread(os.path.join(img_path, img_name))
imageHeight, imageWidth, _ = img.shape
with open(txt_path) as f:
datas = f.readlines()
for data in datas:
shape = {}
data = data.strip().split(' ')
class_id = int(data[0])
shape['label'] = class_name[class_id]
x = float(data[1]) * imageWidth
y = float(data[2]) * imageHeight
w = float(data[3]) * imageWidth
h = float(data[4]) * imageHeight
x1 = x - w / 2
y1 = y - h / 2
x2 = x1 + w
y2 = y1 + h
shape['points'] = [[x1, y1], [x2, y2]]
shape['shape_type'] = 'rectangle'
shape['flags'] = {}
dic['shapes'].append(shape)
dic['imagePath'] = img_name
dic['imageData'] = base64.b64encode(
open(os.path.join(img_path, img_name), 'rb').read()).decode('utf-8')
dic['imageHeight'] = imageHeight
dic['imageWidth'] = imageWidth
json_file = os.path.join(json_path, os.path.basename(txt_path).replace('.txt', '.json'))
with open(json_file, 'w') as fw:
json.dump(dic, fw)
print(f'Saved {json_file}.')
def convert(img_size, box):
# Convert absolute coordinates to relative coordinates.
dw = 1. / (img_size[0])
dh = 1. / (img_size[1])
x = (box[0] + box[2]) / 2.0 - 1
y = (box[1] + box[3]) / 2.0 - 1
w = box[2] - box[0]
h = box[3] - box[1]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)
def decode_json(json_path, json_name, txt_path):
# Convert a json file to a txt file.
class_name = {name: i for i, name in enumerate(class_names)}
txt_file = open(os.path.join(txt_path, json_name[0:-5] + '.txt'), 'w')
json_path = os.path.join(json_path, json_name)
data = json.load(open(json_path, 'r', encoding='gb2312', errors='ignore'))
img_w = data['imageWidth']
img_h = data['imageHeight']
for i in data['shapes']:
label_name = i['label']
if (i['shape_type'] == 'rectangle'):
x1 = int(i['points'][0][0])
y1 = int(i['points'][0][1])
x2 = int(i['points'][1][0])
y2 = int(i['points'][1][1])
bb = (x1, y1, x2, y2)
bbox = convert((img_w, img_h), bb)
txt_file.write(str(class_name[label_name]) + " " + " ".join([str(a) for a in bbox]) + '\n')
print(f"Saved{json_name[0:-5] + '.txt'}")
txt_file.close()
if __name__ == '__main__':
opt = parse_opt()
img_path = opt.img_path
txt_path = opt.txt_path
json_path = opt.json_path
class_names = opt.class_names.split(',')
# Convert txt files to json files.
if txt_path.endswith('.txt'):
decode_txt_file(txt_path, img_path, json_path, class_names)
print('The conversion of single txt to json is complete')
else:
txt_names = os.listdir(txt_path)
for txt_name in txt_names:
txt_file = os.path.join(txt_path, txt_name)
decode_txt_file(txt_file, img_path, json_path, class_names)
print('The conversion of txt to json is complete')