GPU版本编译
如图,按照官网方式直接编译darknet,实际上默认是CPU版本,测试后,比较慢,如图:
所以这里我们直接将其编译为GPU版本,需要更改以下几个地方:
1. 更改Makefile前两行GPU和CUDNN的配置:
GPU=1
CUDNN=1
(OPENCV 可以不修改,亲测可以,修改为1也行)
2. 更改CUDA的路径
48~51行,在"ifeq ($(GPU), 1)"语句块中修改为自己的CUDA安装路径,更改前默认路径如下:
ifeq ($(GPU), 1)
COMMON+= -DGPU -I/usr/local/cuda/include/
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
例如修改为:
ifeq ($(GPU), 1)
COMMON+= -DGPU -I/usr/local/cuda-9.0/include
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda-9.0/lib64 -lcuda -lcudart -lcublas -lcurand
endif
23行,修改NVCC的路径:
NVCC=/usr/local/cuda-9.0/bin/nvcc
完整的如下:
GPU=1
CUDNN=1
OPENCV=1
OPENMP=0
DEBUG=0
ARCH= -gencode arch=compute_30,code=sm_30 \
-gencode arch=compute_35,code=sm_35 \
-gencode arch=compute_50,code=[sm_50,compute_50] \
-gencode arch=compute_52,code=[sm_52,compute_52]
# -gencode arch=compute_20,code=[sm_20,sm_21] \ This one is deprecated?
# This is what I use, uncomment if you know your arch and want to specify
#ARCH= -gencode arch=compute_52,code=compute_52
VPATH=./src/:./examples
SLIB=libdarknet.so
ALIB=libdarknet.a
EXEC=darknet
OBJDIR=./obj/
CC=gcc
CPP=g++
NVCC=/usr/local/cuda-9.0/bin/nvcc
AR=ar
ARFLAGS=rcs
OPTS=-Ofast
LDFLAGS= -lm -pthread
COMMON= -Iinclude/ -Isrc/
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC
ifeq ($(OPENMP), 1)
CFLAGS+= -fopenmp
endif
ifeq ($(DEBUG), 1)
OPTS=-O0 -g
endif
CFLAGS+=$(OPTS)
ifeq ($(OPENCV), 1)
COMMON+= -DOPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` -lstdc++
COMMON+= `pkg-config --cflags opencv`
endif
ifeq ($(GPU), 1)
COMMON+= -DGPU -I/usr/local/cuda-9.0/include
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda-9.0/lib64 -lcuda -lcudart -lcublas -lcurand
endif
ifeq ($(CUDNN), 1)
COMMON+= -DCUDNN
CFLAGS+= -DCUDNN
LDFLAGS+= -lcudnn
endif
OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o detection_layer.o route_layer.o upsample_layer.o box.o normalization_layer.o avgpool_layer.o layer.o local_layer.o shortcut_layer.o logistic_layer.o activation_layer.o rnn_layer.o gru_layer.o crnn_layer.o demo.o batchnorm_layer.o region_layer.o reorg_layer.o tree.o lstm_layer.o l2norm_layer.o yolo_layer.o iseg_layer.o image_opencv.o
EXECOBJA=captcha.o lsd.o super.o art.o tag.o cifar.o go.o rnn.o segmenter.o regressor.o classifier.o coco.o yolo.o detector.o nightmare.o instance-segmenter.o darknet.o
ifeq ($(GPU), 1)
LDFLAGS+= -lstdc++
OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o avgpool_layer_kernels.o
endif
EXECOBJ = $(addprefix $(OBJDIR), $(EXECOBJA))
OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard src/*.h) Makefile include/darknet.h
all: obj backup results $(SLIB) $(ALIB) $(EXEC)
#all: obj results $(SLIB) $(ALIB) $(EXEC)
$(EXEC): $(EXECOBJ) $(ALIB)
$(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(ALIB)
$(ALIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $^
$(SLIB): $(OBJS)
$(CC) $(CFLAGS) -shared $^ -o $@ $(LDFLAGS)
$(OBJDIR)%.o: %.cpp $(DEPS)
$(CPP) $(COMMON) $(CFLAGS) -c $< -o $@
$(OBJDIR)%.o: %.c $(DEPS)
$(CC) $(COMMON) $(CFLAGS) -c $< -o $@
$(OBJDIR)%.o: %.cu $(DEPS)
$(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@
obj:
mkdir -p obj
backup:
mkdir -p backup
results:
mkdir -p results
.PHONY: clean
clean:
rm -rf $(OBJS) $(SLIB) $(ALIB) $(EXEC) $(EXECOBJ) $(OBJDIR)/*
然而测试的时候还是有坑,如下:
网上一堆解决办法,无果,最后修改了下配置文件:
打开yolov3.cfg,注释掉Training配置,同时Testing配置取消注释。
完美解决,最后,速度飞速提升:
【注:】以上是原生态的darknet,其处理图片性能很强,但是对于视频处理,由于封装原因,需要经过转换,显然是不太方便的,解决方案如下:
python调用Darknet接口处理视频
或者最新的,可以直接使用这个。
https://blog.youkuaiyun.com/lilai619/article/details/79695109(主要看yolov3.cfg中的问题)
https://blog.youkuaiyun.com/u012420309/article/details/79993870(Yolov3.cfg中的问题)
https://juejin.im/post/5b3d943ef265da0fa332cd66(代码中的解释)
https://blog.youkuaiyun.com/zzhang_12/article/details/80393448(可以再看看darknet制作)
训练新数据
STEP
(0)数据集制作:
A.制作VOC格式的xml文件
工具:LabelImg 【群文件提供了exe免安装版本以及使用说明】
B.将VOC格式的xml文件转换成YOLO格式的txt文件
脚本:voc_label.py,根据自己的数据集修改就行了。
最简单是因为把数据整理成以下的样子就可以开始训练:
path/to/img1.jpg 50,100,150,200,0 30,50,200,120,3
path/to/img2.jpg 120,300,250,600,2
也就是:地址,xmin,ymin,xmax,ymax,类别ID然后空格下一个box,每张图一行。
例子:
images/images_all/86900fb6gy1fl4822o7qmj22ao328qv7.jpg 10,259,399,580,27
images/images_all/b95fe9cbgw1eyw88vlifjj20c70hsq46.jpg 10,353,439,640,29
images/images_all/005CsCZ0jw1f1n8kcj8m1j30ku0kumz6.jpg 75,141,343,321,27
(1)文件修改:
(A)关于 .data .names 两个文件修改非常简单,参考官网或者群文件YOLOv3.txt连接中的文件。
(B)关于cfg修改,以6类目标检测为例,主要有以下几处调整(蓝色标出),也可参考我上传的文件,里面对应的是4类。
A.filters数目是怎么计算的:3x(classes数目+5),和聚类数目分布有关,论文中有说明;
B.如果想修改默认anchors数值,使用k-means即可;
C.如果显存很小,将random设置为0,关闭多尺度训练;
D.其他参数如何调整,有空再补;
E.前100次迭代loss较大,后面会很快收敛;
Region xx: cfg文件中yolo-layer的索引;
Avg IOU:当前迭代中,预测的box与标注的box的平均交并比,越大越好,期望数值为1;
Class: 标注物体的分类准确率,越大越好,期望数值为1;
obj: 越大越好,期望数值为1;
No obj: 越小越好;
.5R: 以IOU=0.5为阈值时候的recall; recall = 检出的正样本/实际的正样本
0.75R: 以IOU=0.75为阈值时候的recall;
count:正样本数目。
附:几个经典的实现
1. yolov3
YOLOV3训练自己的数据集(PyTorch版本)
参考文献:
1.https://blog.youkuaiyun.com/maweifei/article/details/81137563
2.https://blog.youkuaiyun.com/sinat_26917383/article/details/85614247
3.https://blog.youkuaiyun.com/luoying_ontheroad/article/details/81136973