darknet源码剖析(三) load_data_detection详细分析

本文深入剖析darknet框架中的数据加载过程,包括空间分配、图片预处理、标注框调整等关键步骤,揭示其背后的技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

load_data_detection是数据加载过程的最后一步。下面就来对他进行详细分析。

首先是空间分配过程:

    d.X.rows = n;
    d.X.vals = calloc(d.X.rows, sizeof(float*));
    d.X.cols = h*w*3;

    d.y = make_matrix(n, 5*boxes);

d是data类型数据, data定义如下:

typedef struct{
    int w, h;
    matrix X;
    matrix y;
    int shallow;
    int *num_boxes;
    box **boxes;
} data;

根据以上代码可以发现,加载检测数据,仅使用了X与y变量,X与y又是matrix类型的变量,下面来看matrix类型的定义:

typedef struct matrix{
    int rows, cols;
    float **vals;
} matrix;

其中X.rows为1,X.vals分配的空间为1个float*类型的地址空间,X.cols 的值为h*w*3为602112。

d.y使用make_matrix(src/matrix.c)进行初始化。

matrix make_matrix(int rows, int cols)
{
    int i;
    matrix m;
    m.rows = rows;
    m.cols = cols;
    m.vals = calloc(m.rows, sizeof(float *));
    for(i = 0; i < m.rows; ++i){
        m.vals[i] = calloc(m.cols, sizeof(float));
    }
    return m;
}

其中rows为1,cols为450,vals分配的空间共1×450个float的空间。

此处X.rows与y.rows的值都是1,应该是表示一组数据。

接下来就是数据加载的详细过程,上次没有分析清楚,这次做详细分析。

        image orig = load_image_color(random_paths[i], 0, 0);
        image sized = make_image(w, h, orig.c);
        fill_image(sized, .5);

load_image_color就是加载原图片,sized是网络的输入图片,448*448*3大小的,fill_image是用0.5填充sized图片。

        float dw = jitter * orig.w;
        float dh = jitter * orig.h;

        float new_ar = (orig.w + rand_uniform(-dw, dw)) / (orig.h + rand_uniform(-dh, dh));

dw、dy的值分别为原图w、h的0.2。new_ar的值是随机生成的,之后会以1为界进行调整。

        float scale = 1;

        float nw, nh;

        if(new_ar < 1){
            nh = scale * h;
            nw = nh * new_ar;
        } else {
            nw = scale * w;
            nh = nw / new_ar;
        }

        float dx = rand_uniform(0, w - nw);
        float dy = rand_uniform(0, h - nh);

若new_ar小于1,则nh为448,nw为小于448的一个值,dx为一个随机值,dy为0;若new_ar大于1,则nw为448,nh为小于448的一个值,dx为0,dy为一个随机值。

        place_image(orig, nw, nh, dx, dy, sized);

接下来的place_image、random_distort_image、fill_truth_detection的功能分析我主要是根据https://github.com/hgpvision/darknet/

看了他的解释后我还是没有完全理解。总之一句话place_image就是将orig的一部分放到sized上,nw、nh分别是中间图的宽度与高度,dx、dy分别是中间图插入到sized的x、y方向上的偏移。至于为什么需要插值运算计算中间图就不太清晰了。

过程可能不太理解,但可以通过实验的方式对程序运行结果进行验证。place_image的功能就是将图片调整为448*448大小,同时具有一定的平移功能。

为了进行上述实验,需要将example/detector.c文件中train_detector函数中的

    args.threads = 64;

改为

    args.threads = 1;

同时在src/data.c文件中load_data_detection函数中的place_image,后添加

   save_image(sized, "test");

将处理的中间结果保存下来。之所以要将args.threads改为1,是因为同时启动64个线程,结果会反复写入test.jpg中。

place_image效果如下:

原图片,大小为375*500:

经过place_image函数后的图片,大小为448*488:

如此就可以比较直观的place_image的功能了,首先是对图片进行了一定的比例缩放,然后还有一定的平移操作,最后图片的大小是448*448。

random_distort_image是对图片进行随机扭曲。如法炮制,对random_distort_image的结果进行绘制。

经过random_distort_image函数后的图片:

可以发现图片颜色有一些变化,但不是很明显。

fill_truth_detection是将标注框(ground truth)经过调整后存储到d.y.vals[i]。其中起主要作用的就是correct_boxes函数,该函数的作用就是调整标注框为调整后的图片的标注框。

在fill_truth_detection函数中,nw、nh分别代表调整后的图片大小,例如nw、nh的值分别为448、353。dx、dy的值分别为0、47,其中dy是0~(h-nh)的一个任意值。dx、dy表示调整后的图在x轴、y轴方向上的偏移。在本例中原图被缩放为448*353大小后,在y轴方向上还有一个47像素的偏移。理解了这部分信息也就基本理解了fill_truth_detection函数的参数dx、dy、sx、sy的含义,sx、sy分别代表缩放比例,而dx、dy分别代表距离图片左上角的偏移。

经过上述三个函数后一组图片与其对应的标注就加载完成了。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值