YOLO
如果檔案太大,可以不要下載test2017.zip 以及 unlabeled2017.zip (我也僅用 train(64K images) 以及 val (26K images)做,大概就有40GB左右了)
mkdir coco
cd coco
mkdir images
cd images
wget -c http://images.cocodataset.org/zips/train2017.zip
wget -c http://images.cocodataset.org/zips/val2017.zip
wget -c http://images.cocodataset.org/zips/test2017.zip
wget -c http://images.cocodataset.org/zips/unlabeled2017.zip
unzip train2017.zip
unzip val2017.zip
unzip test2017.zip
unzip unlabeled2017.zip
rm train2017.zip
rm val2017.zip
rm test2017.zip
rm unlabeled2017.zip
cd ../
wget -c http://images.cocodataset.org/annotations/annotations_trainval2017.zip
wget -c http://images.cocodataset.org/annotations/stuff_annotations_trainval2017.zip
wget -c http://images.cocodataset.org/annotations/image_info_test2017.zip
wget -c http://images.cocodataset.org/annotations/image_info_unlabeled2017.zip
unzip annotations_trainval2017.zip
unzip stuff_annotations_trainval2017.zip
unzip image_info_test2017.zip
unzip image_info_unlabeled2017.zip
rm annotations_trainval2017.zip
rm stuff_annotations_trainval2017.zip
rm image_info_test2017.zip
rm image_info_unlabeled2017.zip
cd coco
vim convert2xml.py
加入內容如下:
import os
from shutil import copyfile
from pycocotools.coco import COCO
from xml.dom.minidom import parseString
from lxml.etree import Element, SubElement, tostring
from IPython.display import clear_output
def update_progress(progress):
bar_length = 20
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
if progress < 0:
progress = 0
if progress >= 1:
progress = 1
block = int(round(bar_length * progress))
clear_output(wait = True)
text = "Progress: [{0}] {1:.1f}%".format( "#" * block + "-" * (bar_length - block), progress * 100)
print(text)
current_path = os.path.abspath(os.getcwd())
COCO_ANNOTATIONS_PATH = current_path + "/annotations/instances_val2017.json"
COCO_IMAGES_DIRECTORY = current_path + "/images/val2017/"
EXTRACTED_SAVING_PATH = current_path + "/test_coco_format/"
SAVE_FOLDER = EXTRACTED_SAVING_PATH.split('/')[len(EXTRACTED_SAVING_PATH.split('/'))-2]
if not os.path.exists(EXTRACTED_SAVING_PATH):
os.mkdir(EXTRACTED_SAVING_PATH)
coco = COCO(COCO_ANNOTATIONS_PATH)
cats = coco.loadCats(coco.getCatIds())
nms=[cat['name'] for cat in cats]
target_classes = []
with open(current_path + '/classes.txt', 'r') as f:
for line in f.readlines():
target_classes.append(line.strip())
img_dict = {}
for classes in target_classes:
catIds = coco.getCatIds(catNms=[classes])
imgIds = coco.getImgIds(catIds=catIds)
for imgID in imgIds:
try:
content = ''
content = img_dict[imgID] + ','
except:
pass
img_dict[imgID] = content + classes
total_progress = len(img_dict)
progress = 0
for img_id in img_dict:
progress +=1
annotation_ids = coco.getAnnIds(img_id)
annotations = coco.loadAnns(annotation_ids)
image_meta = coco.loadImgs(annotations[0]["image_id"])[0]
node_root = Element('annotation')
node_folder = SubElement(node_root, 'folder')
node_folder.text = SAVE_FOLDER
node_filename = SubElement(node_root, 'filename')
node_filename.text = image_meta['file_name']
node_size = SubElement(node_root, 'size')
node_width = SubElement(node_size, 'width')
node_width.text = str(image_meta['width'])
node_height = SubElement(node_size, 'height')
node_height.text = str(image_meta['height'])
node_depth = SubElement(node_size, 'depth')
node_depth.text = '3'
for i in range(len(annotations)):
entity_id = annotations[i]["category_id"]
entity = coco.loadCats(entity_id)[0]["name"]
if entity in target_classes:
node_object = SubElement(node_root, 'object')
node_name = SubElement(node_object, 'name')
node_name.text = entity
node_difficult = SubElement(node_object, 'difficult')
node_difficult.text = '0'
node_bndbox = SubElement(node_object, 'bndbox')
node_xmin = SubElement(node_bndbox, 'xmin')
node_xmin.text = str(round(annotations[i]['bbox'][0]))
node_ymin = SubElement(node_bndbox, 'ymin')
node_ymin.text = str(round(annotations[i]['bbox'][1]))
node_xmax = SubElement(node_bndbox, 'xmax')
node_xmax.text = str(round(annotations[i]['bbox'][0]+annotations[i]['bbox'][2]))
node_ymax = SubElement(node_bndbox, 'ymax')
node_ymax.text = str(round(annotations[i]['bbox'][1]+annotations[i]['bbox'][3]))
xml = tostring(node_root, pretty_print=True)
dom = parseString(xml)
with open( EXTRACTED_SAVING_PATH + image_meta['file_name'].split('.')[0] + '.xml','w') as xml_file:
xml_file.write(dom.toxml())
copyfile(COCO_IMAGES_DIRECTORY + image_meta['file_name'],
EXTRACTED_SAVING_PATH + image_meta['file_name'])
update_progress(progress/total_progress)
COCO_ANNOTATIONS_PATH // COCO ANNOTATIONS
COCO_IMAGES_DIRECTORY // COCO IMAGES
EXTRACTED_SAVING_PAT // 轉換後的路徑
vim classes.txt
from bs4 import BeautifulSoup
import os
import shutil
from IPython.display import clear_output
status_dic = {'person':0} #用dictionary 記錄label的名稱
def getYoloFormat(filename, label_path, img_path, yolo_path, newname):
with open(label_path+filename, 'r') as f:
soup = BeautifulSoup(f.read(), 'xml')
imgname = soup.select_one('filename').text #讀取xml
image_w = soup.select_one('width').text
image_h = soup.select_one('height').text
ary = []
for obj in soup.select('object'): #取出xmin, xmax, ymin, ymax及name
xmin = int(obj.select_one('xmin').text) #並且用status_dictionary 來轉換name,good =>2
xmax = int(obj.select_one('xmax').text)
ymin = int(obj.select_one('ymin').text)
ymax = int(obj.select_one('ymax').text)
objclass = status_dic.get(obj.select_one('name').text)
x = (xmin + (xmax-xmin)/2) * 1.0 / float(image_w) #YOLO吃的參數檔有固定的格式
y = (ymin + (ymax-ymin)/2) * 1.0 / float(image_h) #先照YOLO的格式訂好x,y,w,h
w = (xmax-xmin) * 1.0 / float(image_w)
h = (ymax-ymin) * 1.0 / float(image_h)
ary.append(' '.join([str(objclass), str(x), str(y), str(w), str(h)]))
if os.path.exists(img_path+imgname+'.jpg'): # 圖片本來在image裡面,把圖片移到yolo資料夾下
shutil.copyfile(img_path+imgname+'.jpg', yolo_path+newname+'.jpg') #同時把yolo參數檔寫到yolo之下
with open(yolo_path+newname+'.txt', 'w') as f:
f.write('\n'.join(ary))
elif os.path.exists(img_path+imgname): #有的labelImg名稱有自動加上.jpg
shutil.copyfile(img_path+imgname, yolo_path+newname+'.jpg')
with open(yolo_path+newname+'.txt', 'w') as f:
f.write('\n'.join(ary))
def update_progress(progress):
bar_length = 20
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
if progress < 0:
progress = 0
if progress >= 1:
progress = 1
block = int(round(bar_length * progress))
clear_output(wait = True)
text = "Progress: [{0}] {1:.1f}%".format( "#" * block + "-" * (bar_length - block), progress * 100)
print(text)
labelpath = '/home/jim93073/coco/test_coco_format/' #設定路徑
imgpath = '/home/jim93073/coco/test_coco_format/'
yolopath = '/home/jim93073/coco/test_yolo_person/'
ary = []
total_progress = len(os.listdir(labelpath))
progress = 0
for idx, f in enumerate(os.listdir(labelpath)): #透過getYoloFormat將圖像和參數檔全部寫到YOLO下
progress += 1
try:
if f.split('.')[1] == 'xml':
getYoloFormat(f, labelpath, imgpath, yolopath, str(idx))
except Exception as e:
print(e)
update_progress(progress/total_progress)
labelpath // 放置 xml 檔案的地方
imgpath // 放置 image 的地方
yolopath // 輸出成 yolo 格式的地方
import os
import random
save_path = '/home/jim93073/coco/test_yolo_person/'
create_txt_path = '/home/jim93073/coco/cfg/test_person.txt'
datasets = [save_path + f for f in os.listdir(save_path) if f.endswith('.jpg')]
random.shuffle(datasets)
len_dataset = int(len(datasets) * 1.0)
random.shuffle(datasets)
print('All data length',len(datasets))
print(len_dataset)
# print(len(datasets)-len_dataset)
with open(create_txt_path, 'w') as f:
f.write('\n'.join(datasets[:len_dataset]))
save_path // 要訓練的 image 路徑
create_txt_path //轉乘 txt 的檔案名稱