load_data_in_thread()线程中,启动load_thread线程,加载图片,加载图片流程图如下:
1.load_data_in_thread():
test_classifier()函数38行调用load_data_in_thread():
load_args args = { 0 };
args.w = 448/*net.w*/;
args.h = 448 /*net.h*/;
args.paths = paths;
args.classes = classes;
args.n = 64/*net.batch*/;
args.m = 0;
args.labels = 0;
args.d = &buffer;
args.type = OLD_CLASSIFICATION_DATA;
pthread_t load_thread = load_data_in_thread(args);
load_data_in_thread()函数:
pthread_t load_data_in_thread(load_args args)
{
pthread_t thread;
struct load_args* ptr = (load_args*)calloc(1, sizeof(struct load_args));
*ptr = args;
if(pthread_create(&thread, 0, load_thread, ptr)) error("Thread creation failed");
return thread;
}
load_data_in_thread()函数创建线程load_thread(),load_thread()函数如下:
void *load_thread(void *ptr)
{
//srand(time(0));
//printf("Loading data: %d\n", random_gen());
load_args a = *(struct load_args*)ptr;
if(a.exposure == 0) a.exposure = 1;
if(a.saturation == 0) a.saturation = 1;
if(a.aspect == 0) a.aspect = 1;
if (a.type == OLD_CLASSIFICATION_DATA){
*a.d = load_data_old(a.paths, a.n, a.m, a.labels, a.classes, a.w, a.h);
} else if (a.type == CLASSIFICATION_DATA){
2.load_data_old()
在test_classifier()中type为OLD_CLASSIFICATION_DATA,所以调用load_data_old():
其中参数:
args.w = 448/*net.w*/;
args.h = 448 /*net.h*/;
args.paths = paths;
args.classes = classes;
args.n = 64/*net.batch*/;
args.m = 0;
args.labels = 0;
data load_data_old(char **paths, int n, int m, char **labels, int k, int w, int h)
{
if(m) paths = get_random_paths(paths, n, m);
data d = {0};
d.shallow = 0;
d.X = load_image_paths(paths, n, w, h);
d.y = load_labels_paths(paths, n, labels, k, 0);
if(m) free(paths);
return d;
}
data定义如下:
// matrix.h
typedef struct matrix {
int rows, cols;
float **vals;
} matrix;
// data.h
typedef struct data {
int w, h;
matrix X;
matrix y;
int shallow;
int *num_boxes;
box **boxes;
} data;
1.解读load_data_old(),get_random_paths():图片乱序
char **get_random_paths(char **paths, int n, int m)
{
char** random_paths = (char**)calloc(n, sizeof(char*));
int i;
pthread_mutex_lock(&mutex);
//printf("n = %d \n", n);
for(i = 0; i < n; ++i){
do {
int index = random_gen() % m;
random_paths[i] = paths[index];
//if(i == 0) printf("%s\n", paths[index]);
//printf("grp: %s\n", paths[index]);
if (strlen(random_paths[i]) <= 4) printf(" Very small path to the image: %s \n", random_paths[i]);
} while (strlen(random_paths[i]) == 0);
}
pthread_mutex_unlock(&mutex);
return random_paths;
}
n为网络配置文件中19884.txt中的batch=64,m=0.
该函数的功能是对这64张图片路径乱序。
2.解读load_data_old(),load_image_paths:加载图片
load_image_paths()加载图片
matrix load_image_paths(char **paths, int n, int w, int h)
{
int i;
matrix X;
X.rows = n;
X.vals = (float**)calloc(X.rows, sizeof(float*));
X.cols = 0;
for(i = 0; i < n; ++i){
image im = load_image_color(paths[i], w, h);
X.vals[i] = im.data;
X.cols = im.h*im.w*im.c;
}
return X;
}
matrix定义如下:
// matrix.h
typedef struct matrix {
int rows, cols;
float **vals;
} matrix;
其中rows:保存图片张数;
cols:保存每张图片的数据总数,宽*高*通道
vals保存图片数据,
load_image_color()代码:
image load_image_color(char *filename, int w, int h)
{
return load_image(filename, w, h, 3);
}
load_image()代码:
image load_image(char *filename, int w, int h, int c)
{
#ifdef OPENCV
//image out = load_image_stb(filename, c);
image out = load_image_cv(filename, c);
#else
image out = load_image_stb(filename, c); // without OpenCV
#endif // OPENCV
if((h && w) && (h != out.h || w != out.w)){
image resized = resize_image(out, w, h);
free_image(out);
out = resized;
}
return out;
}
如果定义了OPENCV采用opencv读取图片,否则,采用std_image读取图片。
结构体image定义如下:
// image.h
typedef struct image {
int w;
int h;
int c;
float *data;
} image;
关于load_image(),独立写了一篇博客:darknet加载图片函数:load_image()
3.解读load_data_old(),load_labels_paths:
load_labels_paths对应的调用参数:
*a.d = load_data_old(a.paths, a.n, a.m, a.labels, a.classes, a.w, a.h);
a.paths:图片的路径列表
a.n:对应net.batch的cfg文件配置参数,此处为64
a.m=0 a.labels=0 a.classes =2
a.w = net.width,cfg文件配置的图片宽度
a.w = net.height,cfg文件配置的图片高度。
data load_data_old(char **paths, int n, int m, char **labels, int k, int w, int h)
{
if(m) paths = get_random_paths(paths, n, m);
data d = {0};
d.shallow = 0;
d.X = load_image_paths(paths, n, w, h);
d.y = load_labels_paths(paths, n, labels, k, 0);
if(m) free(paths);
return d;
}
此处:n=64,k=2,labels=2
load_labels_paths源代码:
matrix load_labels_paths(char **paths, int n, char **labels, int k, tree *hierarchy)
{
matrix y = make_matrix(n, k);
int i;
for(i = 0; i < n && labels; ++i){
fill_truth(paths[i], labels, k, y.vals[i]);
if(hierarchy){
fill_hierarchy(y.vals[i], k, hierarchy);
}
}
return y;
}
make_matrix():创建matrix对象。
matrix make_matrix(int rows, int cols)
{
int i;
matrix m;
m.rows = rows;
m.cols = cols;
m.vals = (float**)calloc(m.rows, sizeof(float*));
for(i = 0; i < m.rows; ++i){
m.vals[i] = (float*)calloc(m.cols, sizeof(float));
}
return m;
}