开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
yolov3源码阅读(一) 从main开始到加载解析模型相关参数
主函数main() 在examples下面的Darknet.c文件下
打开该文件,开启源码阅读之路
以训练模型输入为例
./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23
在终端输入上述指令时,运行main() ./darknet 是执行当前文件下面已经编译好的darknet文件
int main(int argc, char **argv)
Linux操作系统中C/C++的main函数标准写法。 argc和argv参数在用命令行编译程序时有用。 第一个参数,int型的argc,为整型,用来统计程序运行时发送给main函数的命令行参数的个数 第二个参数,char*型的argv[],为字符串数组,用来存放指向的字符串参数的指针数组 即
argv[0]=darknet
argv[1]=detector
argv[2]=train
argv[3]=cfg/voc.data
argv[4]=cfg/yolo-voc.cfg
argv[5]=darknet19_448.conv.23
继续看
if(argc < 2){//如果参数小于2
fprintf(stderr, "usage: %s <function>\n", argv[0]);//在屏幕打印
return 0;
}
参数不对时打印相关信息
gpu_index = find_int_arg(argc, argv, "-i", 0);//多GPU时指定参与训练的GPU编号
if(find_arg(argc, argv, "-nogpu")) {//设置无gpu格式
gpu_index = -1;
}
根据指令 决定gpu_index的值是多少。当没有相关设置时gpu_index=0。
#ifndef GPU //makefile中的配置
gpu_index = -1; //不用GPU 值为 -1 不配置cuda
#else
if(gpu_index >= 0){
cuda_set_device(gpu_index);//配置cuda
}
#endif
根据makefile中的GPU配置 与指令gpu_index的值 配置cuda 然后就是根据指令进入不同的函数
if (0 == strcmp(argv[1], "average")){
average(argc, argv);
} else if (0 == strcmp(argv[1], "yolo")){
run_yolo(argc, argv);
} else if (0 == strcmp(argv[1], "super")){
run_super(argc, argv);
} else if (0 == strcmp(argv[1], "lsd")){
run_lsd(argc, argv);
} else if (0 == strcmp(argv[1], "detector")){
run_detector(argc, argv);
后面的部分内容。argv[1]=detector,直接进入 run_detector(argc, argv)函数分析。 该函数在darknet\examples文件夹下的detector.c中 这个函数中前面的参数在训练指令中都没有,主要完成从参数中取到该值赋值,没有附默认值 可以直接看后半部分 argv[2]=train 所以关心这条语句即可
else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear);
执行train_detector函数,其中参数从上面代码得到
char *datacfg = argv[3];//cfg/voc.data
char *cfg = argv[4];//cfg/yolo-voc.cfg
char *weights = (argc > 5) ? argv[5] : 0;//darknet19_448.conv.23
int clear = find_arg(argc, argv, "-clear");//clear=0
gpu = gpu_index;//0
gpus = &gpu;
ngpus = 1;
接下来看train_detector函数,该函数是训练目标检测器的入口函数
void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear)
list *options = read_data_cfg(datacfg);//解析datacfg文件
datacfg = argv[3];//cfg/voc.data
就是加载voc.data并解析该文件将各变量赋值到options下
voc.data文件实例及解释
怎么解析的有时间再细看,很多list的操作。
char *train_images = option_find_str(options, "train", "data/train.list");//判断options里是否含有train信息,没有默认为为"data/train.list"
*train_images 就是训练图片的名字(不带后缀)
char *backup_directory = option_find_str(options, "backup", "/backup/");//判断options里是否含有backup信息,没有默认为为""/backup/""
*backup_directory就是模型存放的路径
char *base = basecfg(cfgfile);//解析cfgfile文件
char *cfg = argv[4];//cfg/yolo-voc.cfg
cfg/yolo-voc.cfg文件实例,就是模型的配置参数
加载解析了相关文件,下一步就要用这些参数构建网络了。
主要函数
nets[i] = load_network(cfgfile, weightfile, clear);
放到下部分内容里吧。