一,环境配置
VS2015+显卡RtX2080ti+CUDA10.1+Opencv2.4.13+pthread
pthread:ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip
Darknet:https://github.com/pjreddie/darknet
二,编译过程
1.从官网下载源码,并下载所需配置文件
2.建立新项目
3.文件加载
将源码中的src、include和example文件夹放到项目目录下,并按照源码Makefile文件中所涉及的文件进行加载,将其包含到项目中,加载include下的文件
加载src文件夹中对应的.c和.h文件
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
加载example文件夹中对应的.c文件
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
加载src文件夹中对应的.cu文件
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
4.配置项目环境
附加包含目录,附加库目录;我使用的是C/C++下的附加包含目录和链接器中的附加库目录;当然也可以使用VC++目录下的附加包含目录,附加库目录,效果一样。
之后加载依赖项,有3部分组成,分别是OpenCV、Pthread和cuda中的lib文件
我的cuda文件为
cublas.lib
cuda.lib
cudadevrt.lib
cudart.lib
cudart_static.lib
cudnn.lib
cufft.lib
cufftw.lib
curand.lib
cusolver.lib
cusparse.lib
nppc.lib
nppial.lib
nppicc.lib
nppicom.lib
nppidei.lib
nppif.lib
nppig.lib
nppim.lib
nppist.lib
nppisu.lib
nppitc.lib
npps.lib
nvblas.lib
nvgraph.lib
nvml.lib
nvrtc.lib
OpenCL.lib
最后配置预处理器,使用OPENCV、GPU一定要加上,若是使用CUDNN则加上即可,其中WIN32要加上才能使用线程,若是出现了timespec未定义以及如下错误:
C:\Program Files(x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations\CUDA 10.0.targets(712,9): error MSB3721: 命令“"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin\nvcc.exe" -gencode=arch=compute_30,code=\"sm_30,compute_30\" -gencode=arch=compute_75,code=\"sm_75,compute_75\" --use-local-env -ccbin "D:\VS2015\VC\bin\x86_amd64" -x cu -IE:\darknet_source\darknet\darknet\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\include" -ID:\OPENCV\opencv\build\include -I"E:\darknet_source\pthread\Pre-built.2\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\include" --keep-dir x64\Release -maxrregcount=0 --machine 64 --compile -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -DGPU -DOPENCV -D_MBCS -Xcompiler "/EHsc /W3 /nologo /O2 /Fdx64\Release\vc140.pdb /FS /Zi /MD " -o x64\Release\im2col_kernels.cu.obj "E:\darknet_source\darknet\darknet\src\im2col_kernels.cu"”已退出,返回代码为 1。
则需要加上 _TIMESPEC_DEFINED;有些环境可能已经定义了timespec,那么有可能timespec重复定义,此时需要在预处理器中加上HAVE_STUCT_TIMESPEC;至于timespec的定义可以参考这篇博客;
另外由于高版本的visual studio默认不让使用scanf等函数,认为这些函数不够安全,而其相对应的代替函数为scanf_s等。如果在visual studio中使用scanf等那些visual studio认为不安全的函数,就会报错。以下几种方法可以解决该问题:
1、听visual studio的话,改用新版函数,但是有时候会比较麻烦。
2、在文件开头添加 #define _CRT_SECURE_NO_WARNINGS
3、在 项目->属性->C/C+±>预处理器->预处理器定义中添加
_CRT_SECURE_NO_WARNINGS。
5.编译并修改错误
(1)将出现**#include
#ifdef WIN32
#include
#else
#include
#endif
(2) 删除 #include
(3)在utils.c文件中,出现错误: *“error C2036: “void ”: 未知的大小”:**只需要在void类型的变量前,添加相应的类型即可,我加的是(char) arr
void sorta_shuffle(void *arr, size_t n, size_t size, size_t sections)
{
size_t i;
for(i = 0; i < sections; ++i){
size_t start = n*i/sections;
size_t end = n*(i+1)/sections;
size_t num = end-start;
shuffle((char*) arr+(start*size), num, size);
}
}
void shuffle(void *arr, size_t n, size_t size)
{
size_t i;
void *swp = calloc(1, size);
for(i = 0; i < n-1; ++i){
size_t j = i + rand()/(RAND_MAX / (n-i)+1);
memcpy(swp, (char*)arr+(j*size), size);
memcpy((char*)arr+(j*size), (char*)arr+(i*size), size);
memcpy((char*)arr+(i*size), swp, size);
}
}
(4)出现snprintf,popen,pclose,sleep无法解析的问题时,在其文件头部添加
#if _MSC_VER
#define sleep _sleep
#define popen _popen
#define pclose _pclose
#endif
(5)出现无法解析的外部符号"gettimeofday"&“timersub””时或者出现如下错误时:
go.c
1>examples\go.c(788): error C2065: “fd_set”: 未声明的标识符
1>examples\go.c(788): error C2146: 语法错误: 缺少“;”(在标识符“readfds”的前面)
1>examples\go.c(788): error C2065: “readfds”: 未声明的标识符
1>examples\go.c(789): error C2065: “readfds”: 未声明的标识符
1>examples\go.c(791): error C2079: “timeout”使用未定义的 struct“timeval”
1>examples\go.c(792): error C2224: “.tv_sec”的左侧必须具有结构/联合类型
1>examples\go.c(793): error C2224: “.tv_usec”的左侧必须具有结构/联合类型
在其文件头部加入下面代码即可
#include
int gettimeofday(struct timeval *tp, void *tzp)
{
time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm.tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = clock;
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
void timersub(struct timeval *a, struct timeval *b, struct timeval *res)
{
res = a - b;
}
(6)出现nind需使用常量的问题时,只需在头部重新定义即可,
//static const int nind = 10;
#define nind 10
(7)出现STDIN_FILENO未定义问题时,将相关代码注释即可,其是Linux下unisd.h中的模块,
int stdin_ready()
{
fd_set readfds;
FD_ZERO(&readfds);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
//FD_SET(STDIN_FILENO, &readfds);
// if (select(1, &readfds, NULL, NULL, &timeout)){
// return 1;
// }
// return 0;
}
(8)现在编译就可以成功了,如果出现文件类型和名称警告是可加入
#define _CRT_SECURE_NO_WARNINGS
忽略警告
6.测试
./darknet.exe detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights -i 0 -thresh 0.25 data/dog.jpg -ext_output
7.由于源码更新,所以在Windows下的版本已经过时,缺少了许多模块,所以需要重新编译,之后语义分割模块的训练会陆续更新。