精华内容
下载资源
问答
  • CenterNets代码解析

    2020-06-02 17:07:34
  • FCN代码解析

    千次阅读 2017-04-09 16:20:00
    FCN代码解析

    网上有许多FCN网络的安装和训练教程,但却没有代码解读的详细教程,这让我这种刚刚入门深度学习的萌新不知所措;为了弄清楚FCN,不知走了多少弯路,想把它记录下来,给自己看看,也希望能帮助到那些和我一样刚刚入门的人。
    以下只是小弟的一些拙见,若有错误与不足欢迎指出~
    话不多说,上代码:


    首先是solve.py文件,fcn没有用sh脚本去写训练文件,应该是和他自己写的surgery.py和score.py有关;里面有两个问题我希望有大牛可以帮忙解决:
    1. for _ in range(50):
    solver.step(2000)
    发现设置完这个以后solver.prototxt中设置的 max_iter失效;
    2. score.seg_tests(solver, False, test, layer=’score_sem’, gt=’sem’)
    score.seg_tests(solver, False, test, layer=’score_geo’, gt=’geo’)
    语义分割和几何分割的解读

    #solve.py
    
    import caffe
    import surgery, score
    
    import numpy as np
    import os                  #os模块封装了操作系统的目录和文件操作
    import sys
    
    try:
        import setproctitle
        setproctitle.setproctitle(os.path.basename(os.getcwd()#获得当前路径)#返回最后的文件名)
        #比如os.getcwd()获得的当前路径为/home/zhangrf/fcn,则os.path.basename()为fcn;
        #setproctitle是用来修改进程入口名称,如C++中入口为main()函数
    except:
        pass
    
    weights = '../ilsvrc-nets/vgg16-fcn.caffemodel'                   #用来fine-tune的FCN参数
    vgg_weights = '../ilsvrc-nets/vgg16-fcn.caffemodel'               #训练好的VGGNet参数
    vgg_proto = '../ilsvrc-nets/VGG_ILSVRC_16_layers_deploy.prototxt' #VGGNet模型
    
    # init
    #caffe.set_device(int(sys.argv[1]))
    #获取命令行参数,其中sys.argv[0]为文件名,argv[1]为紧随其后的那个参数
    caffe.set_device(0) #GPU型号
    caffe.set_mode_gpu() #用GPU模式运行
    
    #solver.net.copy_from(weights)
    solver = caffe.SGDSolver('solver.prototxt') #调用SGD(随即梯度下降)Solver方法,solver.prototxt为所需参数
    vgg_net = caffe.Net(vgg_proto,vgg_weights,caffe.TRAIN) #vgg_net是原来的VGGNet模型(包括训练好的参数)
    surgery.transplant(solver.net,vgg_net) #FCN模型(参数)与原来的VGGNet模型之间的转化
    del vgg_net #删除VGGNet模型  
    
    
    # surgeries
    interp_layers = [k for k in solver.net.params.keys() if 'up' in k] #interp_layers为upscore层
    surgery.interp(solver.net, interp_layers) #将upscore层中每层的权重初始化为双线性内核插值。
    
    # scoring
    test = np.loadtxt('../data/sift-flow/test.txt', dtype=str) #载入测试图片信息
    
    for _ in range(50):
        solver.step(2000) #每2000次训练迭代执行后面的函数
        # N.B. metrics on the semantic labels are off b.c. of missing classes;
        # score manually from the histogram instead for proper evaluation
        score.seg_tests(solver, False, test, layer='score_sem', gt='sem') #测试图片语义特征
        score.seg_tests(solver, False, test, layer='score_geo', gt='geo') #测试图片几何特征
    

    surgery.py是精髓,全连接层参数到全卷积层的参数转化是靠它完成的,每一步都很巧妙,如沐春风~

    #surgery.py
    
    from __future__ import division #导入python未来支持的语言特征division(精确除法)
    import caffe #导入caffe
    import numpy as np #导入模块numpy并以np作为别名
    
    def transplant(new_net#FCN, net#VGGNet, suffix=''): #用于将VGGNet的参数转化给FCN(包括全连接层的参数)
        """
        Transfer weights by copying matching parameters, coercing parameters of
        incompatible shape, and dropping unmatched parameters.
        通过复制匹配的参数,强制转换不兼容形状的参数和丢弃不匹配的参数来达到传输(转化)权重的目的;
    
        The coercion is useful to convert fully connected layers to their
        equivalent convolutional layers, since the weights are the same and only
        the shapes are different.
        因为权重的个数是一样的仅仅是Blob的形状不一样,所以强制转换对于将全连接层转换为等效的卷积层是有用的;
    
        In particular, equivalent fully connected and convolution layers have shapes O x I and O x I x H x W respectively for O
        outputs channels, I input channels, H kernel height, and W kernel width.
        参数数量为O*I*H*W
        Both  `net` to `new_net` arguments must be instantiated `caffe.Net`s.
        参数一对一
        """
        for p in net.params: #net.params是字典形式,存放了所有的key-value,p为key
            p_new = p + suffix #将p赋给p_new
            if p_new not in new_net.params: #用来丢弃fc8(因为FCN中没有fc8)
                print 'dropping', p
                continue
            for i in range(len(net.params[p])):
                if i > (len(new_net.params[p_new]) - 1): #感觉没啥用?
                    print 'dropping', p, i
                    break
                if net.params[p][i].data.shape!= new_net.params[p_new][i].data.shape: 
                #Blob不一样转换(这边就是全连接层和卷积层的转换,很精髓!!!)
                    print 'coercing', p, i, 'from', net.params[p][i].data.shape, 'to', new_net.params[p_new][i].data.shape
                else: #形状一样则直接copy
                    print 'copying', p, ' -> ', p_new, i
                new_net.params[p_new][i].data.flat = net.params[p][i].data.flat #将参数按顺序赋值(flat函数只要保证参数个数相同,不用保证数组形状完全一样)
    
    def upsample_filt(size):
        """
        Make a 2D bilinear kernel suitable for upsampling of the given (h, w) size.
        上采样卷积核的制作
        """
        factor = (size + 1) // 2
        if size % 2 == 1:
            center = factor - 1
        else:
            center = factor - 0.5
        og = np.ogrid[:size, :size] #生成一列向量和一行向量
        return (1 - abs(og[0] - center) / factor) * \ #(64*1)的列向量和(1*64)行向量相乘则得到一个64*64的数组
               (1 - abs(og[1] - center) / factor)
    
    def interp(net, layers):
        """
        Set weights of each layer in layers to bilinear kernels for interpolation.
        将每一层的权重设置为双线性内核插值。
        """
        for l in layers:
            m, k, h, w = net.params[l][0].data.shape
            if m != k and k != 1:
                print 'input + output channels need to be the same or |output| == 1'
                raise
            if h != w:
                print 'filters need to be square'
                raise
            filt = upsample_filt(h) #初始化卷积核的参数(64*64*1)
            net.params[l][0].data[range(m), range(k), :, :] = filt #这边很关键!!!只有对于对应层的那层filter有参数,其余都为0,而且有filter参数的那层还都是相等的~
            #因为前一层已经是个分类器了,对分类器进行特征组合没有任何意义!所以这一层的上采样效果上而言只是对应的上采样(属于猴子还是属于猴子)
    
    def expand_score(new_net, new_layer, net, layer):#这个函数干啥用的没看懂- -貌似solve.py里没有这个函数的调用
        """
        Transplant an old score layer's parameters, with k < k' classes, into a new
        score layer with k classes s.t. the first k' are the old classes.
        """
        old_cl = net.params[layer][0].num
        new_net.params[new_layer][0].data[:old_cl][...] = net.params[layer][0].data
        new_net.params[new_layer][1].data[0,0,0,:old_cl][...] = net.params[layer][1].data

    score.py是评估文件,fcn不用caffe框架自带的test测试,而是自己写了个评估文件,里面有许多评估指标。不过小弟才疏学浅,对于很多评估指标的概念完全没接触过,比方说IU的概念,overall accuracy和mean accuracy的区别,希望有大牛可以科普,这部分由于对概念的不知以及数据量的巨大,没有很好的解读~实在有愧

    #score.py
    
    from __future__ import division
    import caffe
    import numpy as np
    import os
    import sys
    from datetime import datetime
    from PIL import Image
    
    def fast_hist(a, b, n):
        k = (a >= 0) & (a < n)
        return np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n)
    
    def compute_hist(net, save_dir#False, dataset, layer='score', gt='label'):
        n_cl = net.blobs[layer].channels #3通道的图
        if save_dir:
            os.mkdir(save_dir)
        hist = np.zeros((n_cl, n_cl)) #创建一个二维数组hist[3][3],元素都为0
        loss = 0
        for idx in dataset:
            net.forward()
            hist += fast_hist(net.blobs[gt].data[0, 0].flatten() #将数据拉为1列,
                                    net.blobs[layer].data[0].argmax(0).flatten(),
                                    n_cl)
            if save_dir: #是否需要保存图片
                im = Image.fromarray(net.blobs[layer].data[0].argmax(0).astype(np.uint8), mode='P')
                im.save(os.path.join(save_dir, idx + '.png'))
            # compute the loss as well
            loss += net.blobs['loss'].data.flat[0]
        return hist, loss / len(dataset)
    
    def seg_tests(solver#配置文件, save_format#False, dataset#test文件, layer='score'#实验输出, gt='label'#真实输出):
        print '>>>', datetime.now(), 'Begin seg tests'
        solver.test_nets[0].share_with(solver.net) #将solver.net复制给solver.test_net[0]
        do_seg_tests(solver.test_nets[0], solver.iter, save_format, dataset, layer, gt)
    
    def do_seg_tests(net, iter#累计迭代次数, save_format, dataset, layer='score', gt='label'):
        n_cl = net.blobs[layer].channels
        if save_format:
            save_format = save_format.format(iter) #format函数用来格式化数据;如果save_format为TRUE,则为1
        hist, loss = compute_hist(net, save_format, dataset, layer, gt)
        # mean loss
        print '>>>', datetime.now(), 'Iteration', iter, 'loss', loss #平均误差
        # overall accuracy
        acc = np.diag(hist).sum() / hist.sum()
        print '>>>', datetime.now(), 'Iteration', iter, 'overall accuracy', acc
        # per-class accuracy
        acc = np.diag(hist) / hist.sum(1)
        print '>>>', datetime.now(), 'Iteration', iter, 'mean accuracy', np.nanmean(acc)
        # per-class IU
        iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))
        print '>>>', datetime.now(), 'Iteration', iter, 'mean IU', np.nanmean(iu)
        freq = hist.sum(1) / hist.sum()
        print '>>>', datetime.now(), 'Iteration', iter, 'fwavacc', \
                (freq[freq > 0] * iu[freq > 0]).sum()
        return hist

    以上是我对fcn代码的一点拙见,这次经历也让我明白,未接触过的代码并不可怕,只要沉下心来,一条一条的进行调试,你也可以知其所以然,发现其中奥秘。在研究生生涯开始之际写下我的第一篇博客,希望自己能在今后的学习生涯中保持这份初心,送给自己,也送给看过这篇博客的有缘人。

    展开全文
  • AutoWare 代码解析

    千次阅读 2017-05-08 13:45:58
    Auto Ware 代码解析系列(1)Auto Ware 是日本名古屋大学的开源无人车项目,下图为ros仿真环境下的各个节点的关系图: 代码库地址为:https://github.com/CPFL/Autoware 上面有较为详细的仿真环境配置信息,建议...

    Auto Ware 代码解析系列(1)

    Auto Ware 是日本名古屋大学的开源无人车项目,下图为ros仿真环境下的各个节点的关系图:
    代码库地址为:https://github.com/CPFL/Autoware 上面有较为详细的仿真环境配置信息,建议硬件环境采用推荐标准,不然可能会跑不起来哦
    这里写图片描述

    后续将会对各个节点进行解析说明

    展开全文
  • YOLOv3:Darknet代码解析(一)安装Darknet YOLOv3:Darknet代码解析(二)代码初步 YOLOv3:Darknet代码解析(三)卷积操作 YOLOv3:Darknet代码解析(四)结构更改与训练 YOLOv3:Darknet代码解析(五)权重与...

    背景:我们在linux上安装了DarkNet。

    目的:初步解读darknet源码

    相关文章:

    YOLOv3:Darknet代码解析(一)安装Darknet

    YOLOv3:Darknet代码解析(二)代码初步

    YOLOv3:Darknet代码解析(三)卷积操作

    YOLOv3:Darknet代码解析(四)结构更改与训练

    YOLOv3:Darknet代码解析(五)权重与特征存储

    YOLOv3:Darknet代码解析(六)简化的程序与卷积拆分

    目录

    1. srand(time(0));

    1.1 srand(unsigned seed)

    1.2 time(0)

    1.3 clock()

    2. Thread

    3.结构体中.与->的区别

    4.堆与栈

    5. enum

    6.结构体中的指针

    7. #pragma

    8.  运行tiny_yolo相关代码

    8.1 主函数相关


    yolo.c

    //run_yolo
    void run_yolo(int argc, char **argv)
    {
        char *prefix = find_char_arg(argc, argv, "-prefix", 0);
        float thresh = find_float_arg(argc, argv, "-thresh", .2);
        int cam_index = find_int_arg(argc, argv, "-c", 0);
        int frame_skip = find_int_arg(argc, argv, "-s", 0);
        if(argc < 4){
            fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
            return;
        }
    
        int avg = find_int_arg(argc, argv, "-avg", 1);
        char *cfg = argv[3];
        char *weights = (argc > 4) ? argv[4] : 0;
        char *filename = (argc > 5) ? argv[5]: 0;
        if(0==strcmp(argv[2], "test")) test_yolo(cfg, weights, filename, thresh);
        else if(0==strcmp(argv[2], "train")) train_yolo(cfg, weights);
        else if(0==strcmp(argv[2], "valid")) validate_yolo(cfg, weights);
        else if(0==strcmp(argv[2], "recall")) validate_yolo_recall(cfg, weights);
        else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, cam_index, filename, voc_names, 20, frame_skip, prefix, avg, .5, 0,0,0,0);
    }

     

    训练函数

     

    //train_yolo
    void train_yolo(char *cfgfile, char *weightfile)
    {
        char *train_images = "/data/voc/train.txt";
        char *backup_directory = "/home/pjreddie/backup/";
        srand(time(0));
        char *base = basecfg(cfgfile);
        printf("%s\n", base);
        float avg_loss = -1;
        network *net = load_network(cfgfile, weightfile, 0);
        printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
        int imgs = net->batch*net->subdivisions;
        int i = *net->seen/imgs;
        data train, buffer;
    
    
        layer l = net->layers[net->n - 1];
    
        int side = l.side;
        int classes = l.classes;
        float jitter = l.jitter;
    
        list *plist = get_paths(train_images);
        //int N = plist->size;
        char **paths = (char **)list_to_array(plist);
    
        load_args args = {0};
        args.w = net->w;
        args.h = net->h;
        args.paths = paths;
        args.n = imgs;
        args.m = plist->size;
        args.classes = classes;
        args.jitter = jitter;
        args.num_boxes = side;
        args.d = &buffer;
        args.type = REGION_DATA;
    
        args.angle = net->angle;
        args.exposure = net->exposure;
        args.saturation = net->saturation;
        args.hue = net->hue;
    
        pthread_t load_thread = load_data_in_thread(args);
        clock_t time;
        //while(i*imgs < N*120){
        while(get_current_batch(net) < net->max_batches){
            i += 1;
            time=clock();
            pthread_join(load_thread, 0);
            train = buffer;
            load_thread = load_data_in_thread(args);
    
            printf("Loaded: %lf seconds\n", sec(clock()-time));
    
            time=clock();
            float loss = train_network(net, train);
            if (avg_loss < 0) avg_loss = loss;
            avg_loss = avg_loss*.9 + loss*.1;
    
            printf("%d: %f, %f avg, %f rate, %lf seconds, %d images\n", i, loss, avg_loss, get_current_rate(net), sec(clock()-time), i*imgs);
            if(i%1000==0 || (i < 1000 && i%100 == 0)){
                char buff[256];
                sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
                save_weights(net, buff);
            }
            free_data(train);
        }
        char buff[256];
        sprintf(buff, "%s/%s_final.weights", backup_directory, base);
        save_weights(net, buff);
    }
    

    1. srand(time(0));

    1.1 srand(unsigned seed)

    通过参数seed改变系统提供的种子值,从而可以使得每次调用rand函数生成的伪随机数序列不同,从而实现真正意义上的“随机”。通常可以利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列

    srand和rand()配合使用产生伪随机数序列。

    1.2 time(0)

    时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数

    在C语言中可以通过time()函数获取到当前的秒数 参数为0则函数返回值即为结果,若参数不为0则结果保存在参数中

    1.3 clock()

    clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t。clock_t clock(void) ;该程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock);若挂钟时间不可取,则返回-1。其中clock_t是用来保存时间的数据类型。

    //example about clock
    #include<time.h>
    #include<stdio.h>
    #include<windows.h>
    int main()
    {
    	int h=0,m=0,s=0;
    	int t=0;
    	while(1)
    	{
    		t=time(0);  //获取总秒数	 
    		s=t%60;
    		m=t%3600/60;	//1h= 3600s不足1h的除60即为分钟	 
    		h=(t%(24*3600)/3600+8)%24; //1天24h 得到当天小时数+8为东八区区时 避免出现大于24h的情况对24取余 
    		 
    		printf("%02d:%02d:%02d\r",h,m,s); // %02d是将数字按宽度为2,采用右对齐方式输出,若数据位数不到2位,则左边补0 \r到当前行最左 
    		//while(t==time(0)); 
    		Sleep(1000);//程序执行较快 对时间进行控制 执行挂起1s 
    	}
    	return 0;
     } 

    2. Thread

    线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪阻塞运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

    线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程

    layer make_yolo_layer(int batch, int w, int h, int n, int total, int *mask, int classes)
    {
        int i;
        layer l = {0};
        l.type = YOLO;
    
        l.n = n;
        l.total = total;
        l.batch = batch;
        l.h = h;
        l.w = w;
        l.c = n*(classes + 4 + 1);
        l.out_w = l.w;
        l.out_h = l.h;
        l.out_c = l.c;
        l.classes = classes;
        l.cost = calloc(1, sizeof(float));
        l.biases = calloc(total*2, sizeof(float));
        if(mask) l.mask = mask;
        else{
            l.mask = calloc(n, sizeof(int));
            for(i = 0; i < n; ++i){
                l.mask[i] = i;
            }
        }
        l.bias_updates = calloc(n*2, sizeof(float));
        l.outputs = h*w*n*(classes + 4 + 1);
        l.inputs = l.outputs;
        l.truths = 90*(4 + 1);
        l.delta = calloc(batch*l.outputs, sizeof(float));
        l.output = calloc(batch*l.outputs, sizeof(float));
        for(i = 0; i < total*2; ++i){
            l.biases[i] = .5;
        }
    
        l.forward = forward_yolo_layer;
        l.backward = backward_yolo_layer;
    #ifdef GPU
        l.forward_gpu = forward_yolo_layer_gpu;
        l.backward_gpu = backward_yolo_layer_gpu;
        l.output_gpu = cuda_make_array(l.output, batch*l.outputs);
        l.delta_gpu = cuda_make_array(l.delta, batch*l.outputs);
    #endif
    
        fprintf(stderr, "yolo\n");
        srand(0);
    
        return l;
    }
    
    void resize_yolo_layer(layer *l, int w, int h)
    {
        l->w = w;
        l->h = h;
    
        l->outputs = h*w*l->n*(l->classes + 4 + 1);
        l->inputs = l->outputs;
    
        l->output = realloc(l->output, l->batch*l->outputs*sizeof(float));
        l->delta = realloc(l->delta, l->batch*l->outputs*sizeof(float));
    
    #ifdef GPU
        cuda_free(l->delta_gpu);
        cuda_free(l->output_gpu);
    
        l->delta_gpu =     cuda_make_array(l->delta, l->batch*l->outputs);
        l->output_gpu =    cuda_make_array(l->output, l->batch*l->outputs);
    #endif
    }

    3.结构体中.与->的区别

    如果有个变量MyStruct s,那么使用其中的成员元素时可以用
    s.member_a = 1;
    如果采用指针方法访问,比如MyStruct * ps,那么同样的访问就必须使用如下形式:
    (*ps).member_a = 1;
    或者

    ps->member_a = 1;

    定义如下:
    A *p则:p->play()使用; 左边是结构指针。
    A p 则:p.paly()使用; 左边是结构变量。
    总结:
    箭头(->):左边必须为指针;

    点号(.):左边必须为实体。

    所以我们在创建层的时候用的是结构体layer l,在resize时只用对已有的layer改变其大小,所以用的是指针。layer *l

    4.堆与栈

    数据结构中的堆与栈与操作系统中的堆与栈很不一样。直接声明的变量储存的区域叫做栈(stack),使用malloc获得的区域叫堆(heap)。

    栈是连续高速而小的(1M,2M的都有,一般不超过2M),堆是不连续低速但容量极大的。

    什么是堆:堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程 初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。

    什么是栈:栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。

       栈是由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。

       堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。也可能造成内存泄漏。

    5. enum

    enum是计算机编程语言中的一种数据类型。枚举类型:在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等等。

    枚举类型定义的一般形式为:

    enum 枚举名{ 枚举值表 };

    在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。

    如同结构体(struct)和共用体(union)一样,枚举变量也可用不同的方式说明,即先定义后说明,同时定义说明或直接说明。

    设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式:

    enum weekday{sun,mon,tue,wed,thu,fri,sat};
    enum weekday a,b,c;
    //或者为:
    enum weekday{sun,mon,tue,wed,thu,fri,sat}a,b,c;
    //或者为:
    enum{sun,mon,tue,wed,thu,fri,sat}a,b,c;
    //darknet.h
    typedef enum{
        LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN
    } ACTIVATION;
    
    typedef enum{
        MULT, ADD, SUB, DIV
    } BINARY_ACTIVATION;

    6.结构体中的指针

    结构体中:

        void (*forward)   (struct layer, struct network);

    空指针即没有指向的指针,指向的地址是NULL源码中#define NULL    ((void *)0)

    void *类型的指针是不确定类型的指针,其指向的内容不确定,后期一般会进行强制类型转换的。

    7. #pragma

    在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

    8.  运行tiny_yolo相关代码

    8.1 主函数相关

    我们的linux命令行为

    ./darknet detect cfg/yolov3-tiny.cfg yolov3-tiny.weights data/dog.jpg

     

     

     

     

     

    展开全文
  • Tensorflow 代码解析

    千次阅读 2017-03-21 16:28:47
    转自 『深度长文』Tensorflow代码解析(一) 原文如下 摘要 2015年11月9日,Google发布深度学习框架TensorFlow并宣布开源,并迅速得到广泛关注,在图形分类、音频处理、推荐系统和自然语言处理等场景下都被大面积...
  • uvc摄像头代码解析

    千次阅读 2014-11-11 15:37:03
    uvc摄像头代码解析
  • YOLOv3:Darknet代码解析(四)结构更改与训练

    万次阅读 热门讨论 2018-08-01 14:19:53
    背景:我们需要降低YOLOv2-...YOLOv3:Darknet代码解析(一)安装Darknet YOLOv3:Darknet代码解析(二)代码初步 YOLOv3:Darknet代码解析(三)卷积操作 YOLOv3:Darknet代码解析(四)结构更改与训练 YOLO...
  • YOLOv3:Darknet代码解析(一)安装Darknet

    万次阅读 多人点赞 2018-07-03 09:25:54
    背景:github源码地址 ... ... 目的:安装并运行Darknet 相关文章: YOLOv3:Darknet代码解析(一)安装Darknet YOLOv3:Darknet代码解析(二)代码初步 YOLOv3:Darknet代码解析(三)卷积操作 YOL...
  • SIFT matlab源代码解析

    万次阅读 多人点赞 2015-02-08 20:58:35
    SIFT matlab源代码解析sift是目前常用的local feature的描述子。sift特征匹配算法可以处理两幅图像之间发生一些平移、旋转、仿射等匹配问题。因为早前自己要做一个图像拼接的问题,所以用到了sift。写这篇blog,是...
  • 代码解析:Adaptive Affinity Field for Semantic Segmentation代码解析数据预处理模型细节损失函数参数更新模型保存以及损失输出 代码解析 代码: Adaptive Affinity Fields for Semantic Segmentation. 数据...
  • DeblurGAN-V2源代码解析

    千次阅读 热门讨论 2020-01-19 18:00:11
    DeblurGAN-V2源代码解析(pytorch) DeblurGAN-V2是DeblurGAN的改进版,主要解决的是去图像运动模糊的问题,相比于DeblurGAN而言有速度更快,效果更好的优点。 论文:https://arxiv.org/pdf/1908.03826.pdf 代码:...
  • Tensorflow YOLO代码解析(1)

    千次阅读 2019-02-21 22:24:20
    YOLO (You Only Look Once:Unified,Real-Time Object Detection) 提出了一种实时端到端的目标...下面所涉及到的相关完整代码放在github:YOLO代码解析完整代码。 本例的源代码来自github,对作者的开源分享表示感谢...
  • Inception V3论文解读和代码解析

    千次阅读 2018-08-19 10:40:42
    代码解析 小结 论文解读 在介绍inception V2时提到过,inception V3的论文依据是Rethinking the Inception Architecture for Computer Vision 虽然此文中介绍的网络结构叫做inception V2,但是在代码的实现...
  • 目的:读懂YOLO_v3中的卷积操作以及相关语句 相关:YOLOv3:Darknet代码解析(六)简化的程序与卷积拆分 ...YOLOv3:Darknet代码解析(一)安装Darknet YOLOv3:Darknet代码解析(二)代码初步 YOLOv3:Da...
  • GMapping代码解析

    千次阅读 2018-09-27 11:17:45
     代码的入口依然是main函数,但GMapping代码中由很多是没有用的,所以并 不需要挨个看,可以说代码的作者代码能力挺强但代码风格却是不敢恭维。这里就 不带大家挨个文件度代码,只是对几个主要的 函数进行介绍。 ...
  • Hector SLAM算法学习与代码解析

    千次阅读 2018-06-13 15:15:27
    Hector SLAM算法学习与代码解析最初了解到Hector SLAM 是从https://www.youtube.com/embed/F8pdObV_df4看到手持激光建图,被吸引到了也就想看一下具体的实现。关于Hector SLAM算法有一篇论文:A Flexible and ...
  • Spring源代码解析

    2010-12-05 21:48:00
    <br />Spring源代码解析(一):Spring中的事务处理  http://www.gbsou.com/2009/08/11/212.html2<br />Spring源代码解析(二):ioc容器在Web容器中的启动  ...Spring JDBC  ...
  • 【代码】CenterNet代码解析

    万次阅读 多人点赞 2019-06-14 16:56:16
    这篇文章主要就是介绍一些用到的重要的函数,只介绍detection部分。 0.网站 https://github.com/xingyizhou/CenterNet install: https://github.com/xingyizhou/CenterNet/blob/master/readme/INSTALL.md ...
  • lua 源代码解析

    千次阅读 2012-05-13 19:52:41
    lua 源代码解析  源代码版本:lua-5.2.0  一、概览  1、lua脚本中暴露的库相关  lbaselib.c - 基础函数库(方便使用lua内部的功能)  lbitlib.c - 位运算库  lcorolib.c - 协程库  lstrlib.c - 字符...
  • 后端有时候返回的数据是如下的: <div>啦啦啦啦啦啦啦啦<h2>哦哦哦哦哦哦</h2></div>...但是,微信小程序里面使用...解析html代码(将html代码解析成 微信小程序的标签) (1-1)找到github...
  • Spring源代码解析(收藏)

    千次阅读 2013-08-13 12:56:58
    Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339  Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.iteye.com/topic/86594  Spring源代码解析(三):...Spring源代码解析(四):S
  • Java 代码解析 maven pom.xml 文件

    千次阅读 2018-12-27 17:38:03
    在某些情况下需要使用java代码解析pom.xml文件。 使用方式如下 maven依赖 &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.apache.maven&amp;lt;/groupId&amp;gt; &amp;lt;...
  • GRBL三:gcode代码解析

    万次阅读 多人点赞 2015-06-30 16:16:20
    GRBL三:gcode代码解析 1.G00X_Y_Z_ :快速定位指令,_代表具体数值  可以同时针对X轴Y轴Z轴移动,只快速定位,不切削加工,相当于快速的移动到那个点上去  数值代表绝对位置 2.G01X_Y_Z_F_:直线差补 F指定进给...
  • 百度apollo - Apollo代码解析:3. 命令行参数传递google gflags 百度apollo - Apollo代码解析:2. log系统google glog PS: 代码注释github:https://github.com/DinnerHowe/apollo_read 首先来看看整体的逻辑图:...
  • bert代码解析

    千次阅读 2019-01-08 20:08:42
    http://www.manongjc.com/article/30232.html https://daiwk.github.io/posts/nlp-bert-code-annotated-framework.html#get-pooled-output https://blog.csdn.net/weixin_39470744/article/details/84401339......
  • PnP算法简介与代码解析-柴政

    千次阅读 2018-09-17 17:26:20
    PnP算法简介与代码解析-柴政 PnP求解算法是指通过多对3D与2D匹配点,在已知或者未知相机内参的情况下,利用最小化重投影误差来求解相机外参的算法。PnP求解算法是SLAM前端位姿跟踪部分中常用的算法之一,本次公开课...
  • halcon代码解析合集

    千次阅读 2019-03-16 17:50:07
    更多系统性的代码分享,请关注公众号: 一. Halcon颜色识别 1. 颜色识别示例color_simple.hdev解析 https://dwz.cn/E2BVL7uZ 2. 颜色识别示例color_fuses.hdev https://dwz.cn/KpOXDiOG 3. 颜色识别示例...
  • LaTeX常用代码解析

    千次阅读 2018-07-05 00:03:35
    标题以及纸张边距设置 \documentclass{article} \title{tutorials} \author{winycg} ...\usepackage[a5paper, left=10mm, right=10mm, ...top=15mm, bottom=15mm]{geometry} % 设置纸张大小和页边距 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,702
精华内容 45,880
关键字:

代码解析