Darknetはcoco 2017データセットを使用してyolov 3を訓練する(親測定が利用可能)


その前にまずpycocootoolsをインストールする必要があります.ネット上では直接sudo pip installがインストールできないと言われています.gitにcocoのapiをダウンロードしてpythonのインタフェースをコンパイルしますが、私はこのような方法で問題が発生しました.最後に確かにcythonをインストールしてからsudo pip install pycocoolsという方法でインストールしました(ところで、winはサポートしていないそうですが、私も試したことがないので分かりません)、ここではpycocoolsがどのようにインストールされているのかを自分で調べてみてください.
次の手順を実行すると面倒になるかもしれませんが、間違いはありません.環境はpython 2です.3を使用する場合は、コードを変更するか、ライブラリ関数を変更します.
1最初のステップ:
まずデータセットCOCO 2017をダウンロードします.ここでは私用のdarknetフレームワークなのでtrain(118287枚)とval(5000枚)しか使いません.テストセットと検証セットを一緒にテストセットとして使用することができます(ここでは、カパスのsplitを使用してtrain、val、testを再分割することをお勧めします).このようにテストすると、より効果的です.
2ステップ2:
cocoのinstances_をval(train)2017.jsonラベルはvoc(.xml)のラベルに変わります.
まずcoco jsonデータラベルを貼ってvocのxmlラベルに変換するコードを貼ります.
from pycocotools.coco import COCO
import os
import shutil
from tqdm import tqdm
import skimage.io as io
import matplotlib.pyplot as plt
import cv2
from PIL import Image, ImageDraw
savepath="/home/test/darknet/VOC2020/"
datasets_list=['val2017']    ##        train2017     
img_dir=savepath+'images/'         #####                ,        val2017       ,             image       val2017
anno_dir=savepath+'annotations/'       #         annotations     xml,       
classes_names =['person','bicycle', 'car','motorcycle','airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog','horse', 'sheep','cow','elephant','bear', 'zebra', 'giraffe','backpack','umbrella', 'handbag','tie', 'suitcase', 'frisbee', 'skis', 'snowboard','sports ball', 'kite', 'baseball bat', 'baseball glove','skateboard', 'surfboard', 'tennis racket','bottle', 'wine glass', 'cup', 'fork','knife', 'spoon', 'bowl', 'banana','apple', 'sandwich', 'orange','broccoli', 'carrot', 'hot dog', 'pizza','donut', 'cake', 'chair', 'couch', 'potted plant', 'bed','dining table', 'toilet','tv','laptop', 'mouse','remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
dataDir= '/home/test/darknet/coco2017' #######    coco    
headstr = """\

    VOC
    %s
    
        My Database
        COCO
        flickr
        NULL
    
    
        NULL
        company
    
    
        %d
        %d
        %d
    
    0
"""
objstr = """\
    
        %s
        Unspecified
        0
        0
        
            %d
            %d
            %d
            %d
        
    
"""
 
tailstr = '''\

'''
def mkr(path):
    if os.path.exists(path):
        shutil.rmtree(path)
        os.mkdir(path)
    else:
        os.mkdir(path)
mkr(img_dir)
mkr(anno_dir)
def id2name(coco):
    classes=dict()
    for cls in coco.dataset['categories']:
        classes[cls['id']]=cls['name']
    return classes
 
def write_xml(anno_path,head, objs, tail):
    f = open(anno_path, "w")
    f.write(head)
    for obj in objs:
        f.write(objstr%(obj[0],obj[1],obj[2],obj[3],obj[4]))
    f.write(tail)
 
 
def save_annotations_and_imgs(coco,dataset,filename,objs):
    anno_path=anno_dir+filename[:-3]+'xml'
    print('anno_path:%s'%anno_path)
    #img_path=dataDir+'/'+'images'+'/'+dataset+'/'+filename
    img_path=dataDir+'/'+dataset+'/'+filename
    print('img_path:%s'%img_path)
    print('step3-image-path-OK')
    dst_imgpath=img_dir+filename
 
    img=cv2.imread(img_path)
    '''if (img.shape[2] == 1):
        print(filename + " not a RGB image")     
        return''' 
    print('img_path:%s'%img_path)
    print('dst_imgpath:%s'%dst_imgpath)
    shutil.copy(img_path, dst_imgpath)
 
    head=headstr % (filename, img.shape[1], img.shape[0], img.shape[2])
    tail = tailstr
    write_xml(anno_path,head, objs, tail)
 
 
def showimg(coco,dataset,img,classes,cls_id,show=True):
    global dataDir
    #I=Image.open('%s/%s/%s/%s'%(dataDir,'images',dataset,img['file_name']))
    I=Image.open('%s/%s/%s'%(dataDir,dataset,img['file_name']))  ########may be you can changed
    annIds = coco.getAnnIds(imgIds=img['id'], catIds=cls_id, iscrowd=None)
    anns = coco.loadAnns(annIds)
    objs = []
    for ann in anns:
        class_name=classes[ann['category_id']]
        if class_name in classes_names:
            print(class_name)
            if 'bbox' in ann:
                bbox=ann['bbox']
                xmin = int(bbox[0])
                ymin = int(bbox[1])
                xmax = int(bbox[2] + bbox[0])
                ymax = int(bbox[3] + bbox[1])
                obj = [class_name, xmin, ymin, xmax, ymax]
                objs.append(obj)
                #draw = ImageDraw.Draw(I)
                #draw.rectangle([xmin, ymin, xmax, ymax])
    # if show:
        # plt.figure()
        # plt.axis('off')
        # plt.imshow(I)
        # plt.show()
    return objs
 
for dataset in datasets_list:
    annFile='{}/annotations_1/instances_{}.json'.format(dataDir,dataset) #   json     
    print('annFile:%s'%annFile)  
    coco = COCO(annFile)         
    '''
    loading annotations into memory...
    Done (t=0.81s)
    creating index...
    index created!
    '''
    classes = id2name(coco)                     
    print("classes:%s"%classes)
    classes_ids = coco.getCatIds(catNms=classes_names)
    print(classes_ids)
    for cls in classes_names:
        cls_id=coco.getCatIds(catNms=[cls])
        img_ids=coco.getImgIds(catIds=cls_id)
        print(cls,len(img_ids))
        # imgIds=img_ids[0:10]
        for imgId in tqdm(img_ids):
            img = coco.loadImgs(imgId)[0]
            filename = img['file_name']
            #print(filename)
            objs=showimg(coco, dataset, img, classes,classes_ids,show=False)  
            #print(objs)
            save_annotations_and_imgs(coco, dataset, filename, objs)

ネット上にはたくさんのdemoがありますが、私は午后になって、最后にこれが一番いいことに気づきました.また、何かを书いたブログが直接copy人のコードで、すべてbugで、経路が散らかっていて、重ねても修正しないでください.肝心なのは使ったことがないから使ってもいいと言って、私は上に行って彼に大きな口をあげたいと思っています.はい、私もツッコミを入れるためではありません.後でみんながコードを書くことを望んでいます.貼らないか、貼った後に注釈をつけることができます.このようにむやみに貼ると、子弟が人の時間を遅らせるのは本当によくありません.プレッシャーがかかります.
3ステップ3:
trainのxmlとvalのxmlをそれぞれ得た後,スクリプトを用いてxmlをtxtに変換し,二つの部分に分けた.
3.1第一部分
すべてのxmlのパスを取り出してtrain_に配置しますall.txt中
ここで私は以前train 2017の中の画像経路をすべてtrain_all.txtの中の、しかし問題があって、画像から読み出したのは118287の経路があって、しかしxmlから117266だけあります.2千枚足りないのに,なぜか分からない.val 2017でも本来は5000ですが、生成されたのは4852枚のみです.
ここではデフォルトでtrain 2017とval 2017をJPEGImagesのフォルダの下に配置しました
import os
from os import getcwd
wd =getcwd()
mulu=['/'+'annotations_train_xml','/'+'annotations_val_xml']
count=0
for i in mulu:
    count+=1
    dir =wd+i
    print(dir)
    filenames=os.listdir(dir)
    if count==1:
        f=open('train_all.txt','w')
        count_1=0
        for filename in filenames:
            count_1+=1
            out_path=dir+'/'+filename.replace('xml','jpg')
            out_path=out_path.replace('annotations_train_xml','JPEGImages/train2017')
            f.write(out_path+'
') f.close() print('done!,total:%s'%count_1) elif count==2: f=open('val_all.txt','w') count_1=0 for filename in filenames: count_1+=1 out_path=dir+'/'+filename.replace('xml','jpg') out_path=out_path.replace('annotations_val_xml','JPEGImages/val2017') f.write(out_path+'
') f.close() print('done!,total:%s'%count_1)

3.2第二部分
そして得られたファイルをまとめ、xmlごとに対応するtxtラベルを生成する
ここでもまずtrainを実行してからtrainをvalに変更して実行を続けます.###の3つの部分を打つパスです.
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
#20190227@new-only 2007 data
#sets=[('2007', 'train'), ('2007', 'val'), ('2007_test', 'test')]
sets =['train']
#classes = ['1', '2', '3','4','5','6','7','8','9','10','11', '12', '13','14','15','16','17','18','19','20']
classes = ['person','bicycle', 'car','motorcycle','airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog','horse', 'sheep','cow','elephant','bear', 'zebra', 'giraffe','backpack','umbrella', 'handbag','tie', 'suitcase', 'frisbee', 'skis', 'snowboard','sports ball', 'kite', 'baseball bat', 'baseball glove','skateboard', 'surfboard', 'tennis racket','bottle', 'wine glass', 'cup', 'fork','knife', 'spoon', 'bowl', 'banana','apple', 'sandwich', 'orange','broccoli', 'carrot', 'hot dog', 'pizza','donut', 'cake', 'chair', 'couch', 'potted plant', 'bed','dining table', 'toilet','tv','laptop', 'mouse','remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'] 
 
def convert(size, box):
    dw = 1./(size[0])
    dh = 1./(size[1])
    x = (box[0] + box[1])/2.0 - 1
    y = (box[2] + box[3])/2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)
 
def convert_annotation(image_id):
    #print("2-open annotations")
    #print('image_id:%s'%image_id)
    #image_id_1 = image_id.split('/')[-1]
    #print('image_id:%s'%image_id)
    #imade_id = image_id_1.replace("jpg","xml")
    #print('image_id:%s'%image_id)
    #in_file = open('/home/test/darknet/VOC2020/annotations_val_xml/%s.xml'%(image_id))
    #print('infile:','/home/test/darknet/VOC2020/annotations_val_xml/%s'%(image_id))
    in_file = open('/home/test/darknet/VOC2020/annotations_train_xml/%s.xml'%(image_id))    ##########
    #print("3-convert to txt")
    out_file = open('/home/test/darknet/VOC2020/annotations_train_txt/%s.txt'%(image_id), 'w') #######
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
 
    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult)==1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '
') #print("write ok") #wd = getcwd() wd = " " for image_set in sets: image_ids = open('train_all.txt').read().strip().split() ###### # image_ids = open('%s.txt'%(image_set)).read().strip().split() print("start ") #list_file = open('%s.txt'%(image_set), 'w') for image_id in image_ids: #print("again write") #print('image_id:%s'%image_id) #list_file.write('%s/%s.jpg
'%(wd, image_id)) id = image_id.split('/')[-1].replace('jpg','xml') id =id.split('.')[0] print('id:%s'%id) convert_annotation(id) #list_file.close()

もともとこのスクリプトは直接生成の第一歩を実現できるtrain_all.txtですが、debugはファイルを生成するたびに面倒だと思います.
最後に生成したtxtラベルをVOC 2020のlabelsのtrain 2017とval 2017の下に置くとdarknetのトレーニングが開始されます.
注意voc.の修正namesはcocoです.names.またyolo層の前のボリュームコアの数とclassの数もあり、cocoも80カテゴリなのでボリュームコアは255に対応する
https://blog.csdn.net/weixin_42731241/article/details/81352013