本文主要从测试的角度进行讨论,测试一张图片,通过valid接口进行测试,测试代码如下,测试的入口函数如下
测试代码:./darknet detector valid cfg/target.data cfg/target.cfg backup/target.weights -out ""-i 1
测试入口函数:examples/detector.c/validate_detector(datacfg, cfg, weights, outfile)
读取数据入口函数以及需要提前知晓的配置如下
需要知晓的配置
examples/detector.c/validate_detector 函数中
args.w = net->w;
args.h = net->h;
args.type = LETTERBOX_DATA;
读取数据入口函数
src/data.c/load_data_in_thread(load_args args)
其数据读取到输入网络预处理步骤大致如下:每一步骤的数据可以参考博客进行数据打印
读取原图 -> 原图数据归一化 -> 原图数据保持长宽比例不变进行resize -> 根据网络输入对图像进行padding
步骤1:读取原图
函数调用:
src/data.c/load_data_in_thread(load_args args)
-> src/data.c/load_thread(void *ptr) 根据数据类型a.type == LETTERBOX_DATA
-> src/image.c/load_image_color(char *filename, int w, int h)
-> src/image.c/load_image(char *filename, int w, int h, int c) 根据是否安装opencv
-> src/image.c/load_image_stb(char *filename, int channels)
-> src/image.c/stbi_load(filename, &w, &h, &c, channels)
步骤2:原图数据归一化
函数调用:
src/data.c/load_data_in_thread(load_args args)
-> src/data.c/load_thread(void *ptr) 根据数据类型a.type == LETTERBOX_DATA
-> src/image.c/load_image_color(char *filename, int w, int h)
-> src/image.c/load_image(char *filename, int w, int h, int c) 根据是否安装opencv
-> src/image.c/load_image_stb(char *filename, int channels)
注意:
load_image函数在执行完load_image_stb函数之后因为此时h=0 and w=0,因此下面的resize函数并未执行,直接返回load_image_stb函数结果。
步骤3:原图数据保持长宽比例不变进行resize
函数调用:
src/data.c/load_data_in_thread(load_args args)
-> src/data.c/letterbox_image(image im, int w, int h)
-> src/data.c/resize_image(image im, int w, int h) 此时是保持长宽比例等比例放缩
注意:
resize未采用库函数,主要分为两个步骤,先通过横向缩放,再进行纵向缩放,具体代码如下:
image resize_image(image im, int w, int h)
{
image resized = make_image(w, h, im.c);
image part = make_image(w, im.h, im.c);
int r, c, k;
float w_scale = (float)(im.w - 1) / (w - 1);
float h_scale = (float)(im.h - 1) / (h - 1);
//横向缩放
for(k = 0; k < im.c; ++k){
for(r = 0; r < im.h; ++r){
for(c = 0; c < w; ++c){
float val = 0;
if(c == w-1 || im.w == 1){
val = get_pixel(im, im.w-1, r, k);
} else {
float sx = c*w_scale;
int ix = (int) sx;
float dx = sx - ix;
val = (1 - dx) * get_pixel(im, ix, r, k) + dx * get_pixel(im, ix+1, r, k); //加权平均
}
set_pixel(part, c, r, k, val);
}
}
}
//纵向缩放
for(k = 0; k < im.c; ++k){
for(r = 0; r < h; ++r){
float sy = r*h_scale;
int iy = (int) sy;
float dy = sy - iy;
for(c = 0; c < w; ++c){
float val = (1-dy) * get_pixel(part, c, iy, k);
set_pixel(resized, c, r, k, val);
}
if(r == h-1 || im.h == 1) continue;
for(c = 0; c < w; ++c){
float val = dy * get_pixel(part, c, iy+1, k);
add_pixel(resized, c, r, k, val);
}
}
}
free_image(part);
return resized;
}
步骤4: 根据网络输入对图像进行padding
函数调用:
src/data.c/load_data_in_thread(load_args args)
-> src/data.c/letterbox_image(image im, int w, int h)
-> src/image.c/embed_image(image source, image dest, int dx, int dy) //padding值统一为0.5
参考链接:
https://www.jianshu.com/p/dfcde9ce7927
https://blog.csdn.net/xunan003/article/details/94736136
https://blog.csdn.net/zwx1995zwx/article/details/80113076?utm_source=blogxgwz9