目錄html
參考自@zhaonanpython
git clone https://github.com/pjreddie/darknet cd darknet
GPU=1 #0或1 CUDNN=1 #0或1 OPENCV=0 #0或1 OPENMP=0 DEBUG=0
make
wget https://pjreddie.com/media/files/yolov3.weights
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
用voc_label.py(位於./scripts)cat voc_label.py
共修改四處git
import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')] #替換爲本身的數據集 classes = ["head", "eye", "nose"] #修改成本身的類別 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(year, image_id): in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id)) #將數據集放於當前目錄下 out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, 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]) + '\n') wd = getcwd() for year, image_set in sets: if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)): os.makedirs('VOCdevkit/VOC%s/labels/'%(year)) image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split() list_file = open('%s_%s.txt'%(year, image_set), 'w') for image_id in image_ids: list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id)) convert_annotation(year, image_id) list_file.close() os.system("cat 2007_train.txt 2007_val.txt > train.txt") #修改成本身的數據集用做訓練
wget https://pjreddie.com/media/files/voc_label.py python voc_label.py
在VOCdevkit/VOC2007/labels/
中:github
learner@learner-pc:~/darknet/scripts$ ls 2007_test.txt #0 dice_label.sh imagenet_label.sh VOCdevkit_original 2007_train.txt #1 gen_tactic.sh train.txt #3 voc_label.py 2007_val.txt #2 get_coco_dataset.sh VOCdevkit
這時darknet須要一個txt文件,其中包含了全部的圖片網絡
cat 2007_train.txt 2007_val.txt 2012_*.txt > train.txt
classes= 3 #修改成本身的類別數 train = /home/learner/darknet/data/voc/train.txt #修改成本身的路徑 or /home/learner/darknet/scripts/2007_test.txt valid = /home/learner/darknet/data/voc/2007_test.txt #修改成本身的路徑 or /home/learner/darknet/scripts/2007_test.txt names = /home/learner/darknet/data/voc.names #修改見voc.names backup = /home/learner/darknet/backup #修改成本身的路徑,輸出的權重信息將存儲其內
head #本身須要探測的類別,一行一個 eye nose
wget https://pjreddie.com/media/files/darknet53.conv.74
[net] # Testing batch=64 subdivisions=32 #每批訓練的個數=batch/subvisions,根據本身GPU顯存進行修改,顯存不夠改大一些 # Training # batch=64 # subdivisions=16 width=416 height=416 channels=3 momentum=0.9 decay=0.0005 angle=0 saturation = 1.5 exposure = 1.5 hue=.1 learning_rate=0.001 burn_in=1000 max_batches = 50200 #訓練步數 policy=steps steps=40000,45000 #開始衰減的步數 scales=.1,.1 [convolutional] batch_normalize=1 filters=32 size=3 stride=1 pad=1 activation=leaky ..... [convolutional] size=1 stride=1 pad=1 filters=24 #filters = 3 * ( classes + 5 ) here,filters=3*(3+5) activation=linear [yolo] mask = 6,7,8 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 classes=3 #修改成本身的類別數 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1 [route] layers = -4 [convolutional] batch_normalize=1 filters=256 size=1 stride=1 pad=1 activation=leaky [upsample] stride=2 [route] layers = -1, 61 [convolutional] batch_normalize=1 filters=256 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=512 activation=leaky [convolutional] batch_normalize=1 filters=256 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=512 activation=leaky [convolutional] batch_normalize=1 filters=256 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=512 activation=leaky [convolutional] size=1 stride=1 pad=1 filters=24 #filters = 3 * ( classes + 5 ) here,filters=3*(3+5) activation=linear [yolo] mask = 3,4,5 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 classes=3 #修改成本身的類別數 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1 [route] layers = -4 [convolutional] batch_normalize=1 filters=128 size=1 stride=1 pad=1 activation=leaky [upsample] stride=2 [route] layers = -1, 36 [convolutional] batch_normalize=1 filters=128 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=256 activation=leaky [convolutional] batch_normalize=1 filters=128 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=256 activation=leaky [convolutional] batch_normalize=1 filters=128 size=1 stride=1 pad=1 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=256 activation=leaky [convolutional] size=1 stride=1 pad=1 filters=24 #filters = 3 * ( classes + 5 ) here,filters=3*(3+5) activation=linear [yolo] mask = 0,1,2 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 classes=3 #修改成本身的類別數 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1
1 單GPU訓練:./darknet -i <gpu_id> detector train <data_cfg> <train_cfg> <weights>
dom
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
2 多GPU訓練,格式爲0,1,2,3
:./darknet detector train <data_cfg> <model_cfg> <weights> -gpus <gpu_list>
ide
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1,2,3
./darknet detector test <data_cfg> <test_cfg> <weights> <image_file> #本次測試無opencv支持
<test_cfg>
文件中batch
和subdivisions
兩項必須爲1。-thresh
和-hier
選項指定對應參數。./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights Eminem.jpg
函數
yolov3-voc.cfg(cfg文件夾下)
文件中batch
和subdivisions
兩項必須爲1。測試
在detector.c中增長頭文件:優化
#include <unistd.h> /* Many POSIX functions (but not all, by a large margin) */ #include <fcntl.h> /* open(), creat() - and fcntl() */
在前面添加GetFilename(char p)函數
#include "darknet.h" #include <sys/stat.h> //需增長的頭文件 #include<stdio.h> #include<time.h> #include<sys/types.h> //需增長的頭文件 static int coco_ids[] = {1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90}; char *GetFilename(char *p) { static char name[30]={""}; char *q = strrchr(p,'/') + 1; strncpy(name,q,20); return name; }
用下面代碼替換detector.c文件(example文件夾下)的void test_detector函數(注意有3處要改爲本身的路徑)
void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen) { list *options = read_data_cfg(datacfg); char *name_list = option_find_str(options, "names", "data/names.list"); char **names = get_labels(name_list); image **alphabet = load_alphabet(); network *net = load_network(cfgfile, weightfile, 0); set_batch_network(net, 1); srand(2222222); double time; char buff[256]; char *input = buff; float nms=.45; int i=0; while(1){ if(filename){ strncpy(input, filename, 256); image im = load_image_color(input,0,0); image sized = letterbox_image(im, net->w, net->h); //image sized = resize_image(im, net->w, net->h); //image sized2 = resize_max(im, net->w); //image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h); //resize_network(net, sized.w, sized.h); layer l = net->layers[net->n-1]; float *X = sized.data; time=what_time_is_it_now(); network_predict(net, X); printf("%s: Predicted in %f seconds.\n", input, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); //printf("%d\n", nboxes); //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms); if (nms) do_nms_sort(dets, nboxes, l.classes, nms); draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes); free_detections(dets, nboxes); if(outfile) { save_image(im, outfile); } else{ save_image(im, "predictions"); #ifdef OPENCV cvNamedWindow("predictions", CV_WINDOW_NORMAL); if(fullscreen){ cvSetWindowProperty("predictions", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); } show_image(im, "predictions",0); cvWaitKey(0); cvDestroyAllWindows(); #endif } free_image(im); free_image(sized); if (filename) break; } else { printf("Enter Image Path: "); fflush(stdout); input = fgets(input, 256, stdin); if(!input) return; strtok(input, "\n"); list *plist = get_paths(input); char **paths = (char **)list_to_array(plist); printf("Start Testing!\n"); int m = plist->size; if(access("/home/learner/darknet/data/outv3tiny_dpj",0)==-1)//"/home/learner/darknet/data"修改爲本身的路徑 { if (mkdir("/home/learner/darknet/data/outv3tiny_dpj",0777))//"/home/learner/darknet/data"修改爲本身的路徑 { printf("creat file bag failed!!!"); } } for(i = 0; i < m; ++i){ char *path = paths[i]; image im = load_image_color(path,0,0); image sized = letterbox_image(im, net->w, net->h); //image sized = resize_image(im, net->w, net->h); //image sized2 = resize_max(im, net->w); //image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h); //resize_network(net, sized.w, sized.h); layer l = net->layers[net->n-1]; float *X = sized.data; time=what_time_is_it_now(); network_predict(net, X); printf("Try Very Hard:"); printf("%s: Predicted in %f seconds.\n", path, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); //printf("%d\n", nboxes); //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms); if (nms) do_nms_sort(dets, nboxes, l.classes, nms); draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes); free_detections(dets, nboxes); if(outfile){ save_image(im, outfile); } else{ char b[2048]; sprintf(b,"/home/learner/darknet/data/outv3tiny_dpj/%s",GetFilename(path));//"/home/leaner/darknet/data"修改爲本身的路徑 save_image(im, b); printf("save %s successfully!\n",GetFilename(path)); /* #ifdef OPENCV //cvNamedWindow("predictions", CV_WINDOW_NORMAL); if(fullscreen){ cvSetWindowProperty("predictions", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); } //show_image(im, "predictions"); //cvWaitKey(0); //cvDestroyAllWindows(); #endif*/ } free_image(im); free_image(sized); if (filename) break; } } } }
make clean make
./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights
/home/learner/darknet/data/voc/2007_test.txt # 完整路徑
./data/out
文件夾下生成預測結果
./darknet detector valid <data_cfg> <test_cfg> <weights> <out_file>
文件中
batch和
subdivisions兩項必須爲1。<data_cfg>
的results
指定的目錄下以<out_file>
開頭的若干文件中,若<data_cfg>
沒有指定results
,那麼默認爲<darknet_root>/results
。./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights
下載第三方庫:
git clone https://github.com/LianjiLi/yolo-compute-map.git
進行以下修改:
修改darknet/examples/detector.c中validate_detector()
char *valid_images = option_find_str(options, "valid", "./data/2007_test.txt");//改爲本身的測試文件路徑 if(!outfile) outfile = "comp4_det_test_"; fps = calloc(classes, sizeof(FILE *)); for(j = 0; j < classes; ++j){ snprintf(buff, 1024, "%s/%s.txt", prefix, names[j]);//刪除outfile參數以及對應的%s fps[j] = fopen(buff, "w");
從新編譯
make clean make
運行valid
darknet文件夾下運行./darknet detector valid cfg/voc.data cfg/yolov3-tiny.cfg backup/yolov3-tiny_164000.weights(改成本身的模型路徑)
在本文件夾下運行python compute_mAP.py
說明:compute_mAP.py中的test.txt文件內容只有文件名字,不帶絕對路徑,不帶後綴
darknet的淺層特徵可視化請參看:http://www.javashuo.com/article/p-gwtgqlbj-ka.html
AlexyAB大神總結的優化經驗請參看:http://www.javashuo.com/article/p-vdejxxdf-ew.html
如何使用Darknet進行分類請參看:http://www.javashuo.com/article/p-oybnqtcr-bv.html
Darknet loss可視化軟件請參看:http://www.javashuo.com/article/p-ovhillwt-gm.html
如何設計更改YOLO網絡結構:https://pprp.github.io/2018/09/20/tricks.html
YOLO詳細改進總結:https://pprp.github.io/2018/06/20/yolo.html
ps: 以上都是本身科研過程當中總結內容,可能不夠系統,歡迎留言討論
轉載請註明做者 ^_^, 若有問題請留言。