目標(biāo)檢測(cè)標(biāo)注文件yolov5(txt)格式轉(zhuǎn)coco(json)格式詳解及代碼實(shí)現(xiàn)
Reference:https://blog.csdn.net/qq_39686950/article/details/119153685
前言
正好自己做目標(biāo)檢測(cè)任務(wù)更換模型需要使用不同格式的標(biāo)注文件,所以在網(wǎng)上找了半天類(lèi)似博文,發(fā)現(xiàn)大多都只有代碼或者解釋不全,對(duì)新手不夠友好,我在轉(zhuǎn)換的過(guò)程中就debug了半天才轉(zhuǎn)換成功,所以寫(xiě)下這篇博文以求盡可能的全面的解釋轉(zhuǎn)換過(guò)程,讓其他同學(xué)少走彎路。
1.yolo v5格式(txt)
yolo v5的標(biāo)注文件格式比較簡(jiǎn)單,如下圖所示:
每一張圖片對(duì)應(yīng)一個(gè).txt文件,每一行表示該圖片的一個(gè)標(biāo)注框,該圖片有多少標(biāo)注框就有多少行數(shù)據(jù),每一行有五列,分別表示:類(lèi)別代號(hào)、標(biāo)注框橫向的相對(duì)中心坐標(biāo)x_center、標(biāo)注框縱向的相對(duì)中心坐標(biāo)y_center、標(biāo)注框相對(duì)寬度w、標(biāo)注框相對(duì)高度h。注意x_center、y_center、w、h為真實(shí)像素值除以圖片的高和寬之后的值。
2.coco格式(json)
本文所描述的coco格式為標(biāo)準(zhǔn)coco數(shù)據(jù)集里的object instances格式,coco的坐標(biāo)信息為(xmin,ymin,w,h),(xmin,ymin)表示標(biāo)注框的左上角坐標(biāo),這四個(gè)值都是絕對(duì)值,coco格式的基本信息描述如下:
{
"info": info, #描述數(shù)據(jù)集的相關(guān)信息,內(nèi)部由字典組成
"licenses": [license], #列表形式,內(nèi)部由字典組成
"images": [image], #描述圖片信息,列表形式,內(nèi)部由字典組成,字典數(shù)量為圖片數(shù)量
"annotations": [annotation], #描述bounding box信息列表形式,內(nèi)部由字典組成,字典數(shù)量為bounding box數(shù)量
"categories": [category] # 描述圖片類(lèi)別信息,列表形式 ,內(nèi)部由字典組成,字典數(shù)量為類(lèi)別個(gè)數(shù)
}
和yolo v5標(biāo)注文件不同的是,coco標(biāo)注文件的格式為.json文件,且所有圖片的標(biāo)注信息在一個(gè).json文件里,該json文件由上面描述的字典組成,該字典有五個(gè)key,下面將描述每個(gè)key對(duì)應(yīng)value的詳細(xì)信息:
info{
"year": int, #年份
"version": str, #數(shù)據(jù)集版本
"description": str, #數(shù)據(jù)集描述
"contributor": str, #數(shù)據(jù)集的提供者
"url": str, #數(shù)據(jù)集的下載地址
"date_created": datetime, #數(shù)據(jù)集的創(chuàng)建日期
}
license{
"id": int,
"name": str,
"url": str,
}
image{
"id": int, #圖片標(biāo)識(shí),相當(dāng)于圖片的身份證
"width": int, #圖片寬度
"height": int, #圖片高度
"file_name": str, #圖片名稱(chēng),注意不是圖片的路徑,僅僅是名稱(chēng)
"license": int,
"flickr_url": str, #flicker網(wǎng)絡(luò)地址
"coco_url": str, #網(wǎng)絡(luò)地址路徑
"date_captured": datetime, #圖片獲取日期
}
annotation{
"id": int, #bounding box標(biāo)識(shí),相當(dāng)于bounding box身份證
"image_id": int, #圖片標(biāo)識(shí),和image中的"id"對(duì)應(yīng)
"category_id": int, #類(lèi)別id
"segmentation": RLE or [polygon], #描述分割信息,iscrowd=0,則segmentation是polygon格式;iscrowd=1,則segmentation就是RLE格式
"area": float, #標(biāo)注框面積
"bbox": [x,y,width,height], #標(biāo)注框坐標(biāo)信息,前文有描述
"iscrowd": 0 or 1, #是否有遮擋,無(wú)遮擋為0,有遮擋為1
}
category{
"id": int, #類(lèi)別id,注意從1開(kāi)始,而不是從0開(kāi)始
"name": str, #類(lèi)別名稱(chēng)
"supercategory": str, #該類(lèi)別的超類(lèi)是什么
}
上述就是coco數(shù)據(jù)集的詳細(xì)解析。
二、代碼
這一部分是重點(diǎn),我將盡可能全面講解需要更改的地方
由第一節(jié)分析可知,yolo v5格式只有圖片名稱(chēng)、類(lèi)別、bounding box坐標(biāo)信息,而coco格式的信息更豐富,而開(kāi)源代碼基本也只關(guān)注yolo v5格式里所提供的信息,因此我們不必過(guò)于糾結(jié)coco格式的多余信息。
詳細(xì)代碼及注釋信息如下:
import os
import json
import cv2
import random
import time
from PIL import Image
coco_format_save_path='D:\\yolov5\\CCTSDB-2021\\train\\' #要生成的標(biāo)準(zhǔn)coco格式標(biāo)簽所在文件夾
yolo_format_classes_path='D:\\yolov5\\CCTSDB-2021\\names.txt' #類(lèi)別文件,一行一個(gè)類(lèi)
yolo_format_annotation_path='D:\\yolov5\\CCTSDB-2021\\labels\\train\\' #yolo格式標(biāo)簽所在文件夾
img_pathDir='D:\\yolov5\\CCTSDB-2021\\images\\train\\' #圖片所在文件夾
with open(yolo_format_classes_path,'r') as fr: #打開(kāi)并讀取類(lèi)別文件
lines1=fr.readlines()
# print(lines1)
categories=[] #存儲(chǔ)類(lèi)別的列表
for j,label in enumerate(lines1):
label=label.strip()
categories.append({'id':j+1,'name':label,'supercategory':'None'}) #將類(lèi)別信息添加到categories中
# print(categories)
write_json_context=dict() #寫(xiě)入.json文件的大字典
write_json_context['info']= {'description': '', 'url': '', 'version': '', 'year': 2022, 'contributor': '純粹ss', 'date_created': '2022-07-8'}
write_json_context['licenses']=[{'id':1,'name':None,'url':None}]
write_json_context['categories']=categories
write_json_context['images']=[]
write_json_context['annotations']=[]
#接下來(lái)的代碼主要添加'images'和'annotations'的key值
imageFileList=os.listdir(img_pathDir) #遍歷該文件夾下的所有文件,并將所有文件名添加到列表中
for i,imageFile in enumerate(imageFileList):
imagePath = os.path.join(img_pathDir,imageFile) #獲取圖片的絕對(duì)路徑
image = Image.open(imagePath) #讀取圖片,然后獲取圖片的寬和高
W, H = image.size
img_context={} #使用一個(gè)字典存儲(chǔ)該圖片信息
#img_name=os.path.basename(imagePath) #返回path最后的文件名。如果path以/或\結(jié)尾,那么就會(huì)返回空值
img_context['file_name']=imageFile
img_context['height']=H
img_context['width']=W
img_context['date_captured']='2022-07-8'
img_context['id']=i #該圖片的id
img_context['license']=1
img_context['color_url']=''
img_context['flickr_url']=''
write_json_context['images'].append(img_context) #將該圖片信息添加到'image'列表中
txtFile=imageFile[:5]+'.txt' #獲取該圖片獲取的txt文件
with open(os.path.join(yolo_format_annotation_path,txtFile),'r') as fr:
lines=fr.readlines() #讀取txt文件的每一行數(shù)據(jù),lines2是一個(gè)列表,包含了一個(gè)圖片的所有標(biāo)注信息
for j,line in enumerate(lines):
bbox_dict = {} #將每一個(gè)bounding box信息存儲(chǔ)在該字典中
# line = line.strip().split()
# print(line.strip().split(' '))
class_id,x,y,w,h=line.strip().split(' ') #獲取每一個(gè)標(biāo)注框的詳細(xì)信息
class_id,x, y, w, h = int(class_id), float(x), float(y), float(w), float(h) #將字符串類(lèi)型轉(zhuǎn)為可計(jì)算的int和float類(lèi)型
xmin=(x-w/2)*W #坐標(biāo)轉(zhuǎn)換
ymin=(y-h/2)*H
xmax=(x+w/2)*W
ymax=(y+h/2)*H
w=w*W
h=h*H
bbox_dict['id']=i*10000+j #bounding box的坐標(biāo)信息
bbox_dict['image_id']=i
bbox_dict['category_id']=class_id+1 #注意目標(biāo)類(lèi)別要加一
bbox_dict['iscrowd']=0
height,width=abs(ymax-ymin),abs(xmax-xmin)
bbox_dict['area']=height*width
bbox_dict['bbox']=[xmin,ymin,w,h]
bbox_dict['segmentation']=[[xmin,ymin,xmax,ymin,xmax,ymax,xmin,ymax]]
write_json_context['annotations'].append(bbox_dict) #將每一個(gè)由字典存儲(chǔ)的bounding box信息添加到'annotations'列表中
name = os.path.join(coco_format_save_path,"train"+ '.json')
with open(name,'w') as fw: #將字典信息寫(xiě)入.json文件中
json.dump(write_json_context,fw,indent=2)
重點(diǎn)
重點(diǎn)
重點(diǎn)
代碼中你可能存在疑問(wèn)的地方
①
coco_format_save_path='D:\\yolov5\\CCTSDB-2021\\train\\' #要生成的標(biāo)準(zhǔn)coco格式標(biāo)簽所在文件夾
yolo_format_classes_path='D:\\yolov5\\CCTSDB-2021\\names.txt' #類(lèi)別文件,一行一個(gè)類(lèi)
yolo_format_annotation_path='D:\\yolov5\\CCTSDB-2021\\labels\\train\\' #yolo格式標(biāo)簽所在文件夾
img_pathDir='D:\\yolov5\CCTSDB-2021\\images\\train\\' #圖片所在文件夾
1#coco_format_save_path 這里是你自己設(shè)置的一個(gè)路徑,像我在存放yolo數(shù)據(jù)集和標(biāo)簽的路徑下新建了兩個(gè)文件夾train和val來(lái)存放新生成的coco(json)格式文件,因?yàn)槲业膇mages和labels文件夾下有兩個(gè)文件分別是存放訓(xùn)練集和驗(yàn)證集的圖片,第一輪運(yùn)行代碼的時(shí)候coco_format_save_path,yolo_format_classes_path,img_pathDir路徑最后都寫(xiě)train,這樣生成的訓(xùn)練集的json文件就存放在新建文件夾train里,第二輪運(yùn)行之前路徑最后都改成val,這樣生成的驗(yàn)證集的json文件就存放在新建文件夾val里了。
2#yolo_format_classes_path這里用txt文件寫(xiě)就行,這里是要你自己新建一個(gè)txt寫(xiě)的,因?yàn)橹皼](méi)有,形式要寫(xiě)成一行一類(lèi),不知道的可以看著圖片與對(duì)應(yīng)的labels對(duì)照一下,要按照順序?qū)?。我下面放個(gè)圖看起來(lái)就會(huì)明白了。
txtFile=`imageFile[:5]`+'.txt' #代碼在第49行的位置
這里txtFile
讀取的是你的圖片名字,像我的圖片名字使用數(shù)字表示如圖
我標(biāo)簽名字也是用對(duì)應(yīng)的數(shù)字表示如圖
我讀的時(shí)候單獨(dú)打印了一下,imageFile
打印出來(lái)是圖片名字加圖片格式比如15454.jpg
,而這一行代碼是要將圖片名與標(biāo)簽對(duì)應(yīng)上,所以需要去掉.jpg
加上標(biāo)簽的格式.txt
所以imageFile[:5]
這里的索引要你自己設(shè)置,你只需要要取你圖片的名字而不能加上格式,像我的數(shù)據(jù)集就是[:5]
正好取到15454
.
好了大概需要注意的地方就是這些了,都是一些可能會(huì)有疑問(wèn)以及容易出錯(cuò)的地方,希望能給與需要的人一些幫助。
對(duì)你有幫助的話還請(qǐng)點(diǎn)贊收藏哦嘻嘻文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-443187.html
總結(jié)
??以上就是我對(duì)目標(biāo)檢測(cè)中yolo v5格式和coco格式的理解和代碼實(shí)現(xiàn),大家如果有更深層的理解和更好的代碼實(shí)現(xiàn)可以留言或私信討論哦。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-443187.html
到了這里,關(guān)于目標(biāo)檢測(cè)標(biāo)注文件yolov5(txt)格式轉(zhuǎn)coco(json)格式詳解及代碼實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!