Darknet函数分析

本文详细分析了Darknet框架中的核心函数,包括随机打乱数据、im2col实现、计算IOU、NMS处理bounding boxes、YOLO层的运作、卷积层参数的保存与加载,以及forward、route、reorg和shortcut操作的细节。通过对这些函数的理解,有助于深入掌握Darknet的工作原理。
摘要由CSDN通过智能技术生成

Darknet中函数分析

随机打乱数据

代码在data.c源文件中

void randomize_data(data d)
{
   
    int i;
    for(i = d.X.rows-1; i > 0; --i){
    // 从最后一个元素位置开始,当前位置为i
        int index = rand()%i;// 从i(不包括)之前的所有位置随机选择一个位置index
        float *swap = d.X.vals[index]; // 交换index和i处的指针
        d.X.vals[index] = d.X.vals[i];
        d.X.vals[i] = swap;

        swap = d.y.vals[index];
        d.y.vals[index] = d.y.vals[i];
        d.y.vals[i] = swap;
    }
}

可以看到整个打乱过程只有指针指向在不断发生变化,数据在内存中的位置不变。


im2col实现

代码在im2col.c源文件中

float im2col_get_pixel(float *im, int height, int width, int channels,
                        int row, int col, int channel, int pad)
{
   
    row -= pad;
    col -= pad;

    if (row < 0 || col < 0 ||
        row >= height || col >= width) return 0;
    return im[col + width*(row + height*channel)];
}

//From Berkeley Vision's Caffe!
//https://github.com/BVLC/caffe/blob/master/LICENSE
void im2col_cpu(float* data_im, // 输入的图像数据,内存中按行排列成一维
     int channels,  // 通道数
     int height, int width, // 图像的高和宽
     int ksize,  // 卷积核的高和宽,这里默认卷积核高和宽大小一样
     int stride, // 卷积时的步长,这里默认高和宽两个方向上步长一样
     int pad, // 图像的填充,这里默认高和宽上填充一样
     float* data_col // 最终输出的数据
) {
   
    int c,h,w;
    int height_col = (height + 2*pad - ksize) / stride + 1; // 卷积后的图像尺寸,可以想象,其中每个点对应图像的一个卷积区域,卷积区域大小是channels * ksize * ksize,即下面的channels_col。
    int width_col = (width + 2*pad - ksize) / stride + 1;

    int channels_col = channels * ksize * ksize; // 图像上每个卷积区域展成一列后的大小,比如                                                          // ksize=3,图像通道数为3,那么channels_col为27
    for (c = 0; c < channels_col; ++c) {
   
        int w_offset = c % ksize; // 0, 1, 2, 0, 1, 2, 0, 1, 2, ... 宽的相对偏移
        int h_offset = (c / ksize) % ksize; // 0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, ...高的相对偏移
        int c_im = c / ksize / ksize; // 9个0, 9个1, 9个2 通道序号,(c_im, h_offset, w_offset)是卷积区域的相对坐标
        for (h = 0; h < height_col; ++h) {
    // 有height_col * width_col个卷积区域,遍历每一个卷积区域,对于每个区域,计算它的c位置处的图像像素值
            for (w = 0; w < width_col; ++w) {
   
                int im_row = h_offset + h * stride; // 相对于图像的行坐标
                int im_col = w_offset + w * stride; // 相对于图像的列坐标
                int col_index = (c * height_col + h) * width_col + w; // 
                data_col[col_index] = im2col_get_pixel(data_im, height, width, channels,
                        im_row, im_col, c_im, pad);
            }
        }
    }
}

这是caffe中卷积操作之前的关键步骤,对三维图像进行变形,将传统卷积操作变成矩阵形式的卷积操作。

简便起见,设channels = 1,即图像是个单通道图。data_im为
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 \begin{matrix} 0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 \\ 5 &amp; 6 &amp; 7 &amp; 8 &amp; 9 \\ 10 &amp; 11 &amp; 12 &amp; 13 &amp; 14 \\ 15 &amp; 16 &amp; 17 &amp; 18 &amp; 19 \\ 20 &amp; 21 &amp; 22 &amp; 23 &amp; 24 \\ \end{matrix} 0510152016111621271217223813182349141924
kernel大小为 3 × 3 3\times3 3×3,stride = 1, pad = 0。经过上面函数的处理后,data_col为
0 1 2 5 6 7 10 11 12 1 2 3 6 7 8 11 12 13 2 3 4 7 8 9 12 13 14 5 6 7 10 11 12 15 16 17 6 7 8 11 12 13 16 17 18 7 8 9 12 13 14 17 18 19 10 11 12 15 16 17 20 21 22 11 12 13 16 17 18 21 22 23 12 13 14 17 18 19 22 23 24 \begin{matrix} 0 &amp; 1 &amp; 2 &amp; 5 &amp; 6 &amp; 7 &amp; 10 &amp; 11 &amp; 12 \\ 1 &amp; 2 &amp; 3 &amp; 6 &amp; 7 &amp; 8 &amp; 11 &amp; 12 &amp; 13 \\ 2 &amp; 3 &amp; 4 &amp; 7 &amp; 8 &amp; 9 &amp; 12 &amp; 13 &amp; 14 \\ 5 &amp; 6 &amp; 7 &amp; 10 &amp; 11 &amp; 12 &amp; 15 &amp; 16 &amp; 17 \\ 6 &amp; 7 &amp; 8 &amp; 11 &amp; 12 &amp; 13 &amp; 16 &amp; 17 &amp; 18 \\ 7 &amp; 8 &amp; 9 &amp; 12 &amp; 13 &amp; 14 &amp; 17 &amp; 18 &amp; 19 \\ 10 &amp; 11 &amp; 12 &amp; 15 &amp; 16 &amp; 17 &amp; 20 &amp; 21 &amp; 22 \\ 11 &amp; 12 &amp; 13 &amp; 16 &amp; 17 &amp; 18 &amp; 21 &amp; 22 &amp; 23 \\ 12 &amp; 13 &amp; 14 &amp; 17 &amp; 18 &amp; 19 &amp; 22 &amp; 23 &amp; 24 \\ \end{matrix} 012567101112123678111213234789121314567101112151617678111213161718789121314171819

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值