yolov3源码阅读(一) 从main开始到加载解析模型相关参数

144 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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);

放到下部分内容里吧。