From aed5b3c995e0fa30efddd0b8ae860a622afff4e4 Mon Sep 17 00:00:00 2001 From: Scheaven <xuepengqiang> Date: 星期四, 17 六月 2021 09:54:33 +0800 Subject: [PATCH] bug --- lib/detecter_tools/darknet/data.c | 4586 ++++++++++++++++++++++++++++++----------------------------- 1 files changed, 2,326 insertions(+), 2,260 deletions(-) diff --git a/lib/detecter_tools/darknet/data.c b/lib/detecter_tools/darknet/data.c index 3afdfc5..d33f219 100644 --- a/lib/detecter_tools/darknet/data.c +++ b/lib/detecter_tools/darknet/data.c @@ -1,2260 +1,2326 @@ -#include "data.h" -#include "utils.h" -#include "image.h" -#include "dark_cuda.h" -#include "box.h" -#include "http_stream.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -extern int check_mistakes; - -#define NUMCHARS 37 - -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -list *get_paths(char *filename) -{ - char *path; - FILE *file = fopen(filename, "r"); - if(!file) file_error(filename); - list *lines = make_list(); - while((path=fgetl(file))){ - list_insert(lines, path); - } - fclose(file); - return lines; -} - -/* -char **get_random_paths_indexes(char **paths, int n, int m, int *indexes) -{ - char **random_paths = calloc(n, sizeof(char*)); - int i; - pthread_mutex_lock(&mutex); - for(i = 0; i < n; ++i){ - int index = random_gen()%m; - indexes[i] = index; - random_paths[i] = paths[index]; - if(i == 0) printf("%s\n", paths[index]); - } - pthread_mutex_unlock(&mutex); - return random_paths; -} -*/ - -char **get_sequential_paths(char **paths, int n, int m, int mini_batch, int augment_speed) -{ - int speed = rand_int(1, augment_speed); - if (speed < 1) speed = 1; - char** sequentia_paths = (char**)xcalloc(n, sizeof(char*)); - int i; - pthread_mutex_lock(&mutex); - //printf("n = %d, mini_batch = %d \n", n, mini_batch); - unsigned int *start_time_indexes = (unsigned int *)xcalloc(mini_batch, sizeof(unsigned int)); - for (i = 0; i < mini_batch; ++i) { - start_time_indexes[i] = random_gen() % m; - //printf(" start_time_indexes[i] = %u, ", start_time_indexes[i]); - } - - for (i = 0; i < n; ++i) { - do { - int time_line_index = i % mini_batch; - unsigned int index = start_time_indexes[time_line_index] % m; - start_time_indexes[time_line_index] += speed; - - //int index = random_gen() % m; - sequentia_paths[i] = paths[index]; - //if(i == 0) printf("%s\n", paths[index]); - //printf(" index = %u - grp: %s \n", index, paths[index]); - if (strlen(sequentia_paths[i]) <= 4) printf(" Very small path to the image: %s \n", sequentia_paths[i]); - } while (strlen(sequentia_paths[i]) == 0); - } - free(start_time_indexes); - pthread_mutex_unlock(&mutex); - return sequentia_paths; -} - -char **get_random_paths(char **paths, int n, int m) -{ - char** random_paths = (char**)xcalloc(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; -} - -char **find_replace_paths(char **paths, int n, char *find, char *replace) -{ - char** replace_paths = (char**)xcalloc(n, sizeof(char*)); - int i; - for(i = 0; i < n; ++i){ - char replaced[4096]; - find_replace(paths[i], find, replace, replaced); - replace_paths[i] = copy_string(replaced); - } - return replace_paths; -} - -matrix load_image_paths_gray(char **paths, int n, int w, int h) -{ - int i; - matrix X; - X.rows = n; - X.vals = (float**)xcalloc(X.rows, sizeof(float*)); - X.cols = 0; - - for(i = 0; i < n; ++i){ - image im = load_image(paths[i], w, h, 3); - - image gray = grayscale_image(im); - free_image(im); - im = gray; - - X.vals[i] = im.data; - X.cols = im.h*im.w*im.c; - } - return X; -} - -matrix load_image_paths(char **paths, int n, int w, int h) -{ - int i; - matrix X; - X.rows = n; - X.vals = (float**)xcalloc(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 load_image_augment_paths(char **paths, int n, int use_flip, int min, int max, int w, int h, float angle, float aspect, float hue, float saturation, float exposure, int dontuse_opencv) -{ - int i; - matrix X; - X.rows = n; - X.vals = (float**)xcalloc(X.rows, sizeof(float*)); - X.cols = 0; - - for(i = 0; i < n; ++i){ - int size = w > h ? w : h; - image im; - if(dontuse_opencv) im = load_image_stb_resize(paths[i], 0, 0, 3); - else im = load_image_color(paths[i], 0, 0); - - image crop = random_augment_image(im, angle, aspect, min, max, size); - int flip = use_flip ? random_gen() % 2 : 0; - if (flip) - flip_image(crop); - random_distort_image(crop, hue, saturation, exposure); - - image sized = resize_image(crop, w, h); - - //show_image(im, "orig"); - //show_image(sized, "sized"); - //show_image(sized, paths[i]); - //wait_until_press_key_cv(); - //printf("w = %d, h = %d \n", sized.w, sized.h); - - free_image(im); - free_image(crop); - X.vals[i] = sized.data; - X.cols = sized.h*sized.w*sized.c; - } - return X; -} - - -box_label *read_boxes(char *filename, int *n) -{ - box_label* boxes = (box_label*)xcalloc(1, sizeof(box_label)); - FILE *file = fopen(filename, "r"); - if (!file) { - printf("Can't open label file. (This can be normal only if you use MSCOCO): %s \n", filename); - //file_error(filename); - FILE* fw = fopen("bad.list", "a"); - fwrite(filename, sizeof(char), strlen(filename), fw); - char *new_line = "\n"; - fwrite(new_line, sizeof(char), strlen(new_line), fw); - fclose(fw); - if (check_mistakes) { - printf("\n Error in read_boxes() \n"); - getchar(); - } - - *n = 0; - return boxes; - } - float x, y, h, w; - int id; - int count = 0; - while(fscanf(file, "%d %f %f %f %f", &id, &x, &y, &w, &h) == 5){ - boxes = (box_label*)xrealloc(boxes, (count + 1) * sizeof(box_label)); - boxes[count].id = id; - boxes[count].x = x; - boxes[count].y = y; - boxes[count].h = h; - boxes[count].w = w; - boxes[count].left = x - w/2; - boxes[count].right = x + w/2; - boxes[count].top = y - h/2; - boxes[count].bottom = y + h/2; - ++count; - } - fclose(file); - *n = count; - return boxes; -} - -void randomize_boxes(box_label *b, int n) -{ - int i; - for(i = 0; i < n; ++i){ - box_label swap = b[i]; - int index = random_gen()%n; - b[i] = b[index]; - b[index] = swap; - } -} - -void correct_boxes(box_label *boxes, int n, float dx, float dy, float sx, float sy, int flip) -{ - int i; - for(i = 0; i < n; ++i){ - if(boxes[i].x == 0 && boxes[i].y == 0) { - boxes[i].x = 999999; - boxes[i].y = 999999; - boxes[i].w = 999999; - boxes[i].h = 999999; - continue; - } - if ((boxes[i].x + boxes[i].w / 2) < 0 || (boxes[i].y + boxes[i].h / 2) < 0 || - (boxes[i].x - boxes[i].w / 2) > 1 || (boxes[i].y - boxes[i].h / 2) > 1) - { - boxes[i].x = 999999; - boxes[i].y = 999999; - boxes[i].w = 999999; - boxes[i].h = 999999; - continue; - } - boxes[i].left = boxes[i].left * sx - dx; - boxes[i].right = boxes[i].right * sx - dx; - boxes[i].top = boxes[i].top * sy - dy; - boxes[i].bottom = boxes[i].bottom* sy - dy; - - if(flip){ - float swap = boxes[i].left; - boxes[i].left = 1. - boxes[i].right; - boxes[i].right = 1. - swap; - } - - boxes[i].left = constrain(0, 1, boxes[i].left); - boxes[i].right = constrain(0, 1, boxes[i].right); - boxes[i].top = constrain(0, 1, boxes[i].top); - boxes[i].bottom = constrain(0, 1, boxes[i].bottom); - - boxes[i].x = (boxes[i].left+boxes[i].right)/2; - boxes[i].y = (boxes[i].top+boxes[i].bottom)/2; - boxes[i].w = (boxes[i].right - boxes[i].left); - boxes[i].h = (boxes[i].bottom - boxes[i].top); - - boxes[i].w = constrain(0, 1, boxes[i].w); - boxes[i].h = constrain(0, 1, boxes[i].h); - } -} - -void fill_truth_swag(char *path, float *truth, int classes, int flip, float dx, float dy, float sx, float sy) -{ - char labelpath[4096]; - replace_image_to_label(path, labelpath); - - int count = 0; - box_label *boxes = read_boxes(labelpath, &count); - randomize_boxes(boxes, count); - correct_boxes(boxes, count, dx, dy, sx, sy, flip); - float x,y,w,h; - int id; - int i; - - for (i = 0; i < count && i < 30; ++i) { - x = boxes[i].x; - y = boxes[i].y; - w = boxes[i].w; - h = boxes[i].h; - id = boxes[i].id; - - if (w < .0 || h < .0) continue; - - int index = (4+classes) * i; - - truth[index++] = x; - truth[index++] = y; - truth[index++] = w; - truth[index++] = h; - - if (id < classes) truth[index+id] = 1; - } - free(boxes); -} - -void fill_truth_region(char *path, float *truth, int classes, int num_boxes, int flip, float dx, float dy, float sx, float sy) -{ - char labelpath[4096]; - replace_image_to_label(path, labelpath); - - int count = 0; - box_label *boxes = read_boxes(labelpath, &count); - randomize_boxes(boxes, count); - correct_boxes(boxes, count, dx, dy, sx, sy, flip); - float x,y,w,h; - int id; - int i; - - for (i = 0; i < count; ++i) { - x = boxes[i].x; - y = boxes[i].y; - w = boxes[i].w; - h = boxes[i].h; - id = boxes[i].id; - - if (w < .001 || h < .001) continue; - - int col = (int)(x*num_boxes); - int row = (int)(y*num_boxes); - - x = x*num_boxes - col; - y = y*num_boxes - row; - - int index = (col+row*num_boxes)*(5+classes); - if (truth[index]) continue; - truth[index++] = 1; - - if (id < classes) truth[index+id] = 1; - index += classes; - - truth[index++] = x; - truth[index++] = y; - truth[index++] = w; - truth[index++] = h; - } - free(boxes); -} - -int fill_truth_detection(const char *path, int num_boxes, float *truth, int classes, int flip, float dx, float dy, float sx, float sy, - int net_w, int net_h) -{ - char labelpath[4096]; - replace_image_to_label(path, labelpath); - - int count = 0; - int i; - box_label *boxes = read_boxes(labelpath, &count); - int min_w_h = 0; - float lowest_w = 1.F / net_w; - float lowest_h = 1.F / net_h; - randomize_boxes(boxes, count); - correct_boxes(boxes, count, dx, dy, sx, sy, flip); - if (count > num_boxes) count = num_boxes; - float x, y, w, h; - int id; - int sub = 0; - - for (i = 0; i < count; ++i) { - x = boxes[i].x; - y = boxes[i].y; - w = boxes[i].w; - h = boxes[i].h; - id = boxes[i].id; - - // not detect small objects - //if ((w < 0.001F || h < 0.001F)) continue; - // if truth (box for object) is smaller than 1x1 pix - char buff[256]; - if (id >= classes) { - printf("\n Wrong annotation: class_id = %d. But class_id should be [from 0 to %d], file: %s \n", id, (classes-1), labelpath); - sprintf(buff, "echo %s \"Wrong annotation: class_id = %d. But class_id should be [from 0 to %d]\" >> bad_label.list", labelpath, id, (classes-1)); - system(buff); - if (check_mistakes) getchar(); - ++sub; - continue; - } - if ((w < lowest_w || h < lowest_h)) { - //sprintf(buff, "echo %s \"Very small object: w < lowest_w OR h < lowest_h\" >> bad_label.list", labelpath); - //system(buff); - ++sub; - continue; - } - if (x == 999999 || y == 999999) { - printf("\n Wrong annotation: x = 0, y = 0, < 0 or > 1, file: %s \n", labelpath); - sprintf(buff, "echo %s \"Wrong annotation: x = 0 or y = 0\" >> bad_label.list", labelpath); - system(buff); - ++sub; - if (check_mistakes) getchar(); - continue; - } - if (x <= 0 || x > 1 || y <= 0 || y > 1) { - printf("\n Wrong annotation: x = %f, y = %f, file: %s \n", x, y, labelpath); - sprintf(buff, "echo %s \"Wrong annotation: x = %f, y = %f\" >> bad_label.list", labelpath, x, y); - system(buff); - ++sub; - if (check_mistakes) getchar(); - continue; - } - if (w > 1) { - printf("\n Wrong annotation: w = %f, file: %s \n", w, labelpath); - sprintf(buff, "echo %s \"Wrong annotation: w = %f\" >> bad_label.list", labelpath, w); - system(buff); - w = 1; - if (check_mistakes) getchar(); - } - if (h > 1) { - printf("\n Wrong annotation: h = %f, file: %s \n", h, labelpath); - sprintf(buff, "echo %s \"Wrong annotation: h = %f\" >> bad_label.list", labelpath, h); - system(buff); - h = 1; - if (check_mistakes) getchar(); - } - if (x == 0) x += lowest_w; - if (y == 0) y += lowest_h; - - truth[(i-sub)*5+0] = x; - truth[(i-sub)*5+1] = y; - truth[(i-sub)*5+2] = w; - truth[(i-sub)*5+3] = h; - truth[(i-sub)*5+4] = id; - - if (min_w_h == 0) min_w_h = w*net_w; - if (min_w_h > w*net_w) min_w_h = w*net_w; - if (min_w_h > h*net_h) min_w_h = h*net_h; - } - free(boxes); - return min_w_h; -} - - -void print_letters(float *pred, int n) -{ - int i; - for(i = 0; i < n; ++i){ - int index = max_index(pred+i*NUMCHARS, NUMCHARS); - printf("%c", int_to_alphanum(index)); - } - printf("\n"); -} - -void fill_truth_captcha(char *path, int n, float *truth) -{ - char *begin = strrchr(path, '/'); - ++begin; - int i; - for(i = 0; i < strlen(begin) && i < n && begin[i] != '.'; ++i){ - int index = alphanum_to_int(begin[i]); - if(index > 35) printf("Bad %c\n", begin[i]); - truth[i*NUMCHARS+index] = 1; - } - for(;i < n; ++i){ - truth[i*NUMCHARS + NUMCHARS-1] = 1; - } -} - -data load_data_captcha(char **paths, int n, int m, 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 = make_matrix(n, k*NUMCHARS); - int i; - for(i = 0; i < n; ++i){ - fill_truth_captcha(paths[i], k, d.y.vals[i]); - } - if(m) free(paths); - return d; -} - -data load_data_captcha_encode(char **paths, int n, int m, 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.X.cols = 17100; - d.y = d.X; - if(m) free(paths); - return d; -} - -void fill_truth(char *path, char **labels, int k, float *truth) -{ - int i; - memset(truth, 0, k*sizeof(float)); - int count = 0; - for(i = 0; i < k; ++i){ - if(strstr(path, labels[i])){ - truth[i] = 1; - ++count; - } - } - if (count != 1) { - printf("Too many or too few labels: %d, %s\n", count, path); - count = 0; - for (i = 0; i < k; ++i) { - if (strstr(path, labels[i])) { - printf("\t label %d: %s \n", count, labels[i]); - count++; - } - } - } -} - -void fill_truth_smooth(char *path, char **labels, int k, float *truth, float label_smooth_eps) -{ - int i; - memset(truth, 0, k * sizeof(float)); - int count = 0; - for (i = 0; i < k; ++i) { - if (strstr(path, labels[i])) { - truth[i] = (1 - label_smooth_eps); - ++count; - } - else { - truth[i] = label_smooth_eps / (k - 1); - } - } - if (count != 1) { - printf("Too many or too few labels: %d, %s\n", count, path); - count = 0; - for (i = 0; i < k; ++i) { - if (strstr(path, labels[i])) { - printf("\t label %d: %s \n", count, labels[i]); - count++; - } - } - } -} - -void fill_hierarchy(float *truth, int k, tree *hierarchy) -{ - int j; - for(j = 0; j < k; ++j){ - if(truth[j]){ - int parent = hierarchy->parent[j]; - while(parent >= 0){ - truth[parent] = 1; - parent = hierarchy->parent[parent]; - } - } - } - int i; - int count = 0; - for(j = 0; j < hierarchy->groups; ++j){ - //printf("%d\n", count); - int mask = 1; - for(i = 0; i < hierarchy->group_size[j]; ++i){ - if(truth[count + i]){ - mask = 0; - break; - } - } - if (mask) { - for(i = 0; i < hierarchy->group_size[j]; ++i){ - truth[count + i] = SECRET_NUM; - } - } - count += hierarchy->group_size[j]; - } -} - -matrix load_labels_paths(char **paths, int n, char **labels, int k, tree *hierarchy, float label_smooth_eps) -{ - matrix y = make_matrix(n, k); - int i; - for(i = 0; i < n && labels; ++i){ - fill_truth_smooth(paths[i], labels, k, y.vals[i], label_smooth_eps); - if(hierarchy){ - fill_hierarchy(y.vals[i], k, hierarchy); - } - } - return y; -} - -matrix load_tags_paths(char **paths, int n, int k) -{ - matrix y = make_matrix(n, k); - int i; - int count = 0; - for(i = 0; i < n; ++i){ - char label[4096]; - find_replace(paths[i], "imgs", "labels", label); - find_replace(label, "_iconl.jpeg", ".txt", label); - FILE *file = fopen(label, "r"); - if(!file){ - find_replace(label, "labels", "labels2", label); - file = fopen(label, "r"); - if(!file) continue; - } - ++count; - int tag; - while(fscanf(file, "%d", &tag) == 1){ - if(tag < k){ - y.vals[i][tag] = 1; - } - } - fclose(file); - } - printf("%d/%d\n", count, n); - return y; -} - -char **get_labels_custom(char *filename, int *size) -{ - list *plist = get_paths(filename); - if(size) *size = plist->size; - char **labels = (char **)list_to_array(plist); - free_list(plist); - return labels; -} - -char **get_labels(char *filename) -{ - return get_labels_custom(filename, NULL); -} - -void free_data(data d) -{ - if(!d.shallow){ - free_matrix(d.X); - free_matrix(d.y); - }else{ - free(d.X.vals); - free(d.y.vals); - } -} - -data load_data_region(int n, char **paths, int m, int w, int h, int size, int classes, float jitter, float hue, float saturation, float exposure) -{ - char **random_paths = get_random_paths(paths, n, m); - int i; - data d = {0}; - d.shallow = 0; - - d.X.rows = n; - d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); - d.X.cols = h*w*3; - - - int k = size*size*(5+classes); - d.y = make_matrix(n, k); - for(i = 0; i < n; ++i){ - image orig = load_image_color(random_paths[i], 0, 0); - - int oh = orig.h; - int ow = orig.w; - - int dw = (ow*jitter); - int dh = (oh*jitter); - - int pleft = rand_uniform(-dw, dw); - int pright = rand_uniform(-dw, dw); - int ptop = rand_uniform(-dh, dh); - int pbot = rand_uniform(-dh, dh); - - int swidth = ow - pleft - pright; - int sheight = oh - ptop - pbot; - - float sx = (float)swidth / ow; - float sy = (float)sheight / oh; - - int flip = random_gen()%2; - image cropped = crop_image(orig, pleft, ptop, swidth, sheight); - - float dx = ((float)pleft/ow)/sx; - float dy = ((float)ptop /oh)/sy; - - image sized = resize_image(cropped, w, h); - if(flip) flip_image(sized); - random_distort_image(sized, hue, saturation, exposure); - d.X.vals[i] = sized.data; - - fill_truth_region(random_paths[i], d.y.vals[i], classes, size, flip, dx, dy, 1./sx, 1./sy); - - free_image(orig); - free_image(cropped); - } - free(random_paths); - return d; -} - -data load_data_compare(int n, char **paths, int m, int classes, int w, int h) -{ - if(m) paths = get_random_paths(paths, 2*n, m); - int i,j; - data d = {0}; - d.shallow = 0; - - d.X.rows = n; - d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); - d.X.cols = h*w*6; - - int k = 2*(classes); - d.y = make_matrix(n, k); - for(i = 0; i < n; ++i){ - image im1 = load_image_color(paths[i*2], w, h); - image im2 = load_image_color(paths[i*2+1], w, h); - - d.X.vals[i] = (float*)xcalloc(d.X.cols, sizeof(float)); - memcpy(d.X.vals[i], im1.data, h*w*3*sizeof(float)); - memcpy(d.X.vals[i] + h*w*3, im2.data, h*w*3*sizeof(float)); - - int id; - float iou; - - char imlabel1[4096]; - char imlabel2[4096]; - find_replace(paths[i*2], "imgs", "labels", imlabel1); - find_replace(imlabel1, "jpg", "txt", imlabel1); - FILE *fp1 = fopen(imlabel1, "r"); - - while(fscanf(fp1, "%d %f", &id, &iou) == 2){ - if (d.y.vals[i][2*id] < iou) d.y.vals[i][2*id] = iou; - } - - find_replace(paths[i*2+1], "imgs", "labels", imlabel2); - find_replace(imlabel2, "jpg", "txt", imlabel2); - FILE *fp2 = fopen(imlabel2, "r"); - - while(fscanf(fp2, "%d %f", &id, &iou) == 2){ - if (d.y.vals[i][2*id + 1] < iou) d.y.vals[i][2*id + 1] = iou; - } - - for (j = 0; j < classes; ++j){ - if (d.y.vals[i][2*j] > .5 && d.y.vals[i][2*j+1] < .5){ - d.y.vals[i][2*j] = 1; - d.y.vals[i][2*j+1] = 0; - } else if (d.y.vals[i][2*j] < .5 && d.y.vals[i][2*j+1] > .5){ - d.y.vals[i][2*j] = 0; - d.y.vals[i][2*j+1] = 1; - } else { - d.y.vals[i][2*j] = SECRET_NUM; - d.y.vals[i][2*j+1] = SECRET_NUM; - } - } - fclose(fp1); - fclose(fp2); - - free_image(im1); - free_image(im2); - } - if(m) free(paths); - return d; -} - -data load_data_swag(char **paths, int n, int classes, float jitter) -{ - int index = random_gen()%n; - char *random_path = paths[index]; - - image orig = load_image_color(random_path, 0, 0); - int h = orig.h; - int w = orig.w; - - data d = {0}; - d.shallow = 0; - d.w = w; - d.h = h; - - d.X.rows = 1; - d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); - d.X.cols = h*w*3; - - int k = (4+classes)*30; - d.y = make_matrix(1, k); - - int dw = w*jitter; - int dh = h*jitter; - - int pleft = rand_uniform(-dw, dw); - int pright = rand_uniform(-dw, dw); - int ptop = rand_uniform(-dh, dh); - int pbot = rand_uniform(-dh, dh); - - int swidth = w - pleft - pright; - int sheight = h - ptop - pbot; - - float sx = (float)swidth / w; - float sy = (float)sheight / h; - - int flip = random_gen()%2; - image cropped = crop_image(orig, pleft, ptop, swidth, sheight); - - float dx = ((float)pleft/w)/sx; - float dy = ((float)ptop /h)/sy; - - image sized = resize_image(cropped, w, h); - if(flip) flip_image(sized); - d.X.vals[0] = sized.data; - - fill_truth_swag(random_path, d.y.vals[0], classes, flip, dx, dy, 1./sx, 1./sy); - - free_image(orig); - free_image(cropped); - - return d; -} - -void blend_truth(float *new_truth, int boxes, float *old_truth) -{ - const int t_size = 4 + 1; - int count_new_truth = 0; - int t; - for (t = 0; t < boxes; ++t) { - float x = new_truth[t*(4 + 1)]; - if (!x) break; - count_new_truth++; - - } - for (t = count_new_truth; t < boxes; ++t) { - float *new_truth_ptr = new_truth + t*t_size; - float *old_truth_ptr = old_truth + (t - count_new_truth)*t_size; - float x = old_truth_ptr[0]; - if (!x) break; - - new_truth_ptr[0] = old_truth_ptr[0]; - new_truth_ptr[1] = old_truth_ptr[1]; - new_truth_ptr[2] = old_truth_ptr[2]; - new_truth_ptr[3] = old_truth_ptr[3]; - new_truth_ptr[4] = old_truth_ptr[4]; - } - //printf("\n was %d bboxes, now %d bboxes \n", count_new_truth, t); -} - - -void blend_truth_mosaic(float *new_truth, int boxes, float *old_truth, int w, int h, float cut_x, float cut_y, int i_mixup, - int left_shift, int right_shift, int top_shift, int bot_shift) -{ - const int t_size = 4 + 1; - int count_new_truth = 0; - int t; - for (t = 0; t < boxes; ++t) { - float x = new_truth[t*(4 + 1)]; - if (!x) break; - count_new_truth++; - - } - int new_t = count_new_truth; - for (t = count_new_truth; t < boxes; ++t) { - float *new_truth_ptr = new_truth + new_t*t_size; - new_truth_ptr[0] = 0; - float *old_truth_ptr = old_truth + (t - count_new_truth)*t_size; - float x = old_truth_ptr[0]; - if (!x) break; - - float xb = old_truth_ptr[0]; - float yb = old_truth_ptr[1]; - float wb = old_truth_ptr[2]; - float hb = old_truth_ptr[3]; - - - - // shift 4 images - if (i_mixup == 0) { - xb = xb - (float)(w - cut_x - right_shift) / w; - yb = yb - (float)(h - cut_y - bot_shift) / h; - } - if (i_mixup == 1) { - xb = xb + (float)(cut_x - left_shift) / w; - yb = yb - (float)(h - cut_y - bot_shift) / h; - } - if (i_mixup == 2) { - xb = xb - (float)(w - cut_x - right_shift) / w; - yb = yb + (float)(cut_y - top_shift) / h; - } - if (i_mixup == 3) { - xb = xb + (float)(cut_x - left_shift) / w; - yb = yb + (float)(cut_y - top_shift) / h; - } - - int left = (xb - wb / 2)*w; - int right = (xb + wb / 2)*w; - int top = (yb - hb / 2)*h; - int bot = (yb + hb / 2)*h; - - /* - { - // fix out of Mosaic-bound - float left_bound = 0, right_bound = 0, top_bound = 0, bot_bound = 0; - if (i_mixup == 0) { - left_bound = 0; - right_bound = cut_x; - top_bound = 0; - bot_bound = cut_y; - } - if (i_mixup == 1) { - left_bound = cut_x; - right_bound = w; - top_bound = 0; - bot_bound = cut_y; - } - if (i_mixup == 2) { - left_bound = 0; - right_bound = cut_x; - top_bound = cut_y; - bot_bound = h; - } - if (i_mixup == 3) { - left_bound = cut_x; - right_bound = w; - top_bound = cut_y; - bot_bound = h; - } - - - if (left < left_bound) { - //printf(" i_mixup = %d, left = %d, left_bound = %f \n", i_mixup, left, left_bound); - left = left_bound; - } - if (right > right_bound) { - //printf(" i_mixup = %d, right = %d, right_bound = %f \n", i_mixup, right, right_bound); - right = right_bound; - } - if (top < top_bound) top = top_bound; - if (bot > bot_bound) bot = bot_bound; - - - xb = ((float)(right + left) / 2) / w; - wb = ((float)(right - left)) / w; - yb = ((float)(bot + top) / 2) / h; - hb = ((float)(bot - top)) / h; - } - */ - - { - // fix out of bound - if (left < 0) { - float diff = (float)left / w; - xb = xb - diff / 2; - wb = wb + diff; - } - - if (right > w) { - float diff = (float)(right - w) / w; - xb = xb - diff / 2; - wb = wb - diff; - } - - if (top < 0) { - float diff = (float)top / h; - yb = yb - diff / 2; - hb = hb + diff; - } - - if (bot > h) { - float diff = (float)(bot - h) / h; - yb = yb - diff / 2; - hb = hb - diff; - } - - left = (xb - wb / 2)*w; - right = (xb + wb / 2)*w; - top = (yb - hb / 2)*h; - bot = (yb + hb / 2)*h; - } - - // leave only within the image - if(left >= 0 && right <= w && top >= 0 && bot <= h && - wb > 0 && wb < 1 && hb > 0 && hb < 1 && - xb > 0 && xb < 1 && yb > 0 && yb < 1) - { - new_truth_ptr[0] = xb; - new_truth_ptr[1] = yb; - new_truth_ptr[2] = wb; - new_truth_ptr[3] = hb; - new_truth_ptr[4] = old_truth_ptr[4]; - new_t++; - } - } - //printf("\n was %d bboxes, now %d bboxes \n", count_new_truth, t); -} - -#ifdef OPENCV - -#include "http_stream.h" - -data load_data_detection(int n, char **paths, int m, int w, int h, int c, int boxes, int classes, int use_flip, int use_gaussian_noise, int use_blur, int use_mixup, - float jitter, float resize, float hue, float saturation, float exposure, int mini_batch, int track, int augment_speed, int letter_box, int show_imgs) -{ - const int random_index = random_gen(); - c = c ? c : 3; - - if (use_mixup == 2 || use_mixup == 4) { - printf("\n cutmix=1 - isn't supported for Detector (use cutmix=1 only for Classifier) \n"); - if (check_mistakes) getchar(); - if(use_mixup == 2) use_mixup = 0; - else use_mixup = 3; - } - if (use_mixup == 3 && letter_box) { - printf("\n Combination: letter_box=1 & mosaic=1 - isn't supported, use only 1 of these parameters \n"); - if (check_mistakes) getchar(); - exit(0); - } - if (random_gen() % 2 == 0) use_mixup = 0; - int i; - - int *cut_x = NULL, *cut_y = NULL; - if (use_mixup == 3) { - cut_x = (int*)calloc(n, sizeof(int)); - cut_y = (int*)calloc(n, sizeof(int)); - const float min_offset = 0.2; // 20% - for (i = 0; i < n; ++i) { - cut_x[i] = rand_int(w*min_offset, w*(1 - min_offset)); - cut_y[i] = rand_int(h*min_offset, h*(1 - min_offset)); - } - } - - data d = {0}; - d.shallow = 0; - - d.X.rows = n; - d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); - d.X.cols = h*w*c; - - float r1 = 0, r2 = 0, r3 = 0, r4 = 0, r_scale = 0; - float resize_r1 = 0, resize_r2 = 0; - float dhue = 0, dsat = 0, dexp = 0, flip = 0, blur = 0; - int augmentation_calculated = 0, gaussian_noise = 0; - - d.y = make_matrix(n, 5*boxes); - int i_mixup = 0; - for (i_mixup = 0; i_mixup <= use_mixup; i_mixup++) { - if (i_mixup) augmentation_calculated = 0; // recalculate augmentation for the 2nd sequence if(track==1) - - char **random_paths; - if (track) random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed); - else random_paths = get_random_paths(paths, n, m); - - for (i = 0; i < n; ++i) { - float *truth = (float*)xcalloc(5 * boxes, sizeof(float)); - const char *filename = random_paths[i]; - - int flag = (c >= 3); - mat_cv *src; - src = load_image_mat_cv(filename, flag); - if (src == NULL) { - printf("\n Error in load_data_detection() - OpenCV \n"); - fflush(stdout); - if (check_mistakes) { - getchar(); - } - continue; - } - - int oh = get_height_mat(src); - int ow = get_width_mat(src); - - int dw = (ow*jitter); - int dh = (oh*jitter); - - float resize_down = resize, resize_up = resize; - if (resize_down > 1.0) resize_down = 1 / resize_down; - int min_rdw = ow*(1 - (1 / resize_down)) / 2; // < 0 - int min_rdh = oh*(1 - (1 / resize_down)) / 2; // < 0 - - if (resize_up < 1.0) resize_up = 1 / resize_up; - int max_rdw = ow*(1 - (1 / resize_up)) / 2; // > 0 - int max_rdh = oh*(1 - (1 / resize_up)) / 2; // > 0 - //printf(" down = %f, up = %f \n", (1 - (1 / resize_down)) / 2, (1 - (1 / resize_up)) / 2); - - if (!augmentation_calculated || !track) - { - augmentation_calculated = 1; - resize_r1 = random_float(); - resize_r2 = random_float(); - - r1 = random_float(); - r2 = random_float(); - r3 = random_float(); - r4 = random_float(); - - r_scale = random_float(); - - dhue = rand_uniform_strong(-hue, hue); - dsat = rand_scale(saturation); - dexp = rand_scale(exposure); - - flip = use_flip ? random_gen() % 2 : 0; - - if (use_blur) { - int tmp_blur = rand_int(0, 2); // 0 - disable, 1 - blur background, 2 - blur the whole image - if (tmp_blur == 0) blur = 0; - else if (tmp_blur == 1) blur = 1; - else blur = use_blur; - } - - if (use_gaussian_noise && rand_int(0, 1) == 1) gaussian_noise = use_gaussian_noise; - else gaussian_noise = 0; - } - - int pleft = rand_precalc_random(-dw, dw, r1); - int pright = rand_precalc_random(-dw, dw, r2); - int ptop = rand_precalc_random(-dh, dh, r3); - int pbot = rand_precalc_random(-dh, dh, r4); - - if (resize < 1) { - // downsize only - pleft += rand_precalc_random(min_rdw, 0, resize_r1); - pright += rand_precalc_random(min_rdw, 0, resize_r2); - ptop += rand_precalc_random(min_rdh, 0, resize_r1); - pbot += rand_precalc_random(min_rdh, 0, resize_r2); - } - else { - pleft += rand_precalc_random(min_rdw, max_rdw, resize_r1); - pright += rand_precalc_random(min_rdw, max_rdw, resize_r2); - ptop += rand_precalc_random(min_rdh, max_rdh, resize_r1); - pbot += rand_precalc_random(min_rdh, max_rdh, resize_r2); - } - - //printf("\n pleft = %d, pright = %d, ptop = %d, pbot = %d, ow = %d, oh = %d \n", pleft, pright, ptop, pbot, ow, oh); - - //float scale = rand_precalc_random(.25, 2, r_scale); // unused currently - - if (letter_box) - { - float img_ar = (float)ow / (float)oh; - float net_ar = (float)w / (float)h; - float result_ar = img_ar / net_ar; - //printf(" ow = %d, oh = %d, w = %d, h = %d, img_ar = %f, net_ar = %f, result_ar = %f \n", ow, oh, w, h, img_ar, net_ar, result_ar); - if (result_ar > 1) // sheight - should be increased - { - float oh_tmp = ow / net_ar; - float delta_h = (oh_tmp - oh)/2; - ptop = ptop - delta_h; - pbot = pbot - delta_h; - //printf(" result_ar = %f, oh_tmp = %f, delta_h = %d, ptop = %f, pbot = %f \n", result_ar, oh_tmp, delta_h, ptop, pbot); - } - else // swidth - should be increased - { - float ow_tmp = oh * net_ar; - float delta_w = (ow_tmp - ow)/2; - pleft = pleft - delta_w; - pright = pright - delta_w; - //printf(" result_ar = %f, ow_tmp = %f, delta_w = %d, pleft = %f, pright = %f \n", result_ar, ow_tmp, delta_w, pleft, pright); - } - - //printf("\n pleft = %d, pright = %d, ptop = %d, pbot = %d, ow = %d, oh = %d \n", pleft, pright, ptop, pbot, ow, oh); - } - - /* - // move each 2nd image to the corner - so that most of it was visible - if (use_mixup == 3 && random_gen() % 2 == 0) { - if (flip) { - if (i_mixup == 0) pleft += pright, pright = 0, pbot += ptop, ptop = 0; - if (i_mixup == 1) pright += pleft, pleft = 0, pbot += ptop, ptop = 0; - if (i_mixup == 2) pleft += pright, pright = 0, ptop += pbot, pbot = 0; - if (i_mixup == 3) pright += pleft, pleft = 0, ptop += pbot, pbot = 0; - } - else { - if (i_mixup == 0) pright += pleft, pleft = 0, pbot += ptop, ptop = 0; - if (i_mixup == 1) pleft += pright, pright = 0, pbot += ptop, ptop = 0; - if (i_mixup == 2) pright += pleft, pleft = 0, ptop += pbot, pbot = 0; - if (i_mixup == 3) pleft += pright, pright = 0, ptop += pbot, pbot = 0; - } - } - */ - - int swidth = ow - pleft - pright; - int sheight = oh - ptop - pbot; - - float sx = (float)swidth / ow; - float sy = (float)sheight / oh; - - float dx = ((float)pleft / ow) / sx; - float dy = ((float)ptop / oh) / sy; - - - int min_w_h = fill_truth_detection(filename, boxes, truth, classes, flip, dx, dy, 1. / sx, 1. / sy, w, h); - - if ((min_w_h / 8) < blur && blur > 1) blur = min_w_h / 8; // disable blur if one of the objects is too small - - image ai = image_data_augmentation(src, w, h, pleft, ptop, swidth, sheight, flip, dhue, dsat, dexp, - gaussian_noise, blur, boxes, truth); - - if (use_mixup == 0) { - d.X.vals[i] = ai.data; - memcpy(d.y.vals[i], truth, 5 * boxes * sizeof(float)); - } - else if (use_mixup == 1) { - if (i_mixup == 0) { - d.X.vals[i] = ai.data; - memcpy(d.y.vals[i], truth, 5 * boxes * sizeof(float)); - } - else if (i_mixup == 1) { - image old_img = make_empty_image(w, h, c); - old_img.data = d.X.vals[i]; - //show_image(ai, "new"); - //show_image(old_img, "old"); - //wait_until_press_key_cv(); - blend_images_cv(ai, 0.5, old_img, 0.5); - blend_truth(d.y.vals[i], boxes, truth); - free_image(old_img); - d.X.vals[i] = ai.data; - } - } - else if (use_mixup == 3) { - if (i_mixup == 0) { - image tmp_img = make_image(w, h, c); - d.X.vals[i] = tmp_img.data; - } - - if (flip) { - int tmp = pleft; - pleft = pright; - pright = tmp; - } - - const int left_shift = min_val_cmp(cut_x[i], max_val_cmp(0, (-pleft*w / ow))); - const int top_shift = min_val_cmp(cut_y[i], max_val_cmp(0, (-ptop*h / oh))); - - const int right_shift = min_val_cmp((w - cut_x[i]), max_val_cmp(0, (-pright*w / ow))); - const int bot_shift = min_val_cmp(h - cut_y[i], max_val_cmp(0, (-pbot*h / oh))); - - - int k, x, y; - for (k = 0; k < c; ++k) { - for (y = 0; y < h; ++y) { - int j = y*w + k*w*h; - if (i_mixup == 0 && y < cut_y[i]) { - int j_src = (w - cut_x[i] - right_shift) + (y + h - cut_y[i] - bot_shift)*w + k*w*h; - memcpy(&d.X.vals[i][j + 0], &ai.data[j_src], cut_x[i] * sizeof(float)); - } - if (i_mixup == 1 && y < cut_y[i]) { - int j_src = left_shift + (y + h - cut_y[i] - bot_shift)*w + k*w*h; - memcpy(&d.X.vals[i][j + cut_x[i]], &ai.data[j_src], (w-cut_x[i]) * sizeof(float)); - } - if (i_mixup == 2 && y >= cut_y[i]) { - int j_src = (w - cut_x[i] - right_shift) + (top_shift + y - cut_y[i])*w + k*w*h; - memcpy(&d.X.vals[i][j + 0], &ai.data[j_src], cut_x[i] * sizeof(float)); - } - if (i_mixup == 3 && y >= cut_y[i]) { - int j_src = left_shift + (top_shift + y - cut_y[i])*w + k*w*h; - memcpy(&d.X.vals[i][j + cut_x[i]], &ai.data[j_src], (w - cut_x[i]) * sizeof(float)); - } - } - } - - blend_truth_mosaic(d.y.vals[i], boxes, truth, w, h, cut_x[i], cut_y[i], i_mixup, left_shift, right_shift, top_shift, bot_shift); - - free_image(ai); - ai.data = d.X.vals[i]; - } - - - if (show_imgs && i_mixup == use_mixup) // delete i_mixup - { - image tmp_ai = copy_image(ai); - char buff[1000]; - //sprintf(buff, "aug_%d_%d_%s_%d", random_index, i, basecfg((char*)filename), random_gen()); - sprintf(buff, "aug_%d_%d_%d", random_index, i, random_gen()); - int t; - for (t = 0; t < boxes; ++t) { - box b = float_to_box_stride(d.y.vals[i] + t*(4 + 1), 1); - if (!b.x) break; - int left = (b.x - b.w / 2.)*ai.w; - int right = (b.x + b.w / 2.)*ai.w; - int top = (b.y - b.h / 2.)*ai.h; - int bot = (b.y + b.h / 2.)*ai.h; - draw_box_width(tmp_ai, left, top, right, bot, 1, 150, 100, 50); // 3 channels RGB - } - - save_image(tmp_ai, buff); - if (show_imgs == 1) { - //char buff_src[1000]; - //sprintf(buff_src, "src_%d_%d_%s_%d", random_index, i, basecfg((char*)filename), random_gen()); - //show_image_mat(src, buff_src); - show_image(tmp_ai, buff); - wait_until_press_key_cv(); - } - printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Click on window and press ESC button \n"); - free_image(tmp_ai); - } - - release_mat(&src); - free(truth); - } - if (random_paths) free(random_paths); - } - - - return d; -} -#else // OPENCV -void blend_images(image new_img, float alpha, image old_img, float beta) -{ - int data_size = new_img.w * new_img.h * new_img.c; - int i; - #pragma omp parallel for - for (i = 0; i < data_size; ++i) - new_img.data[i] = new_img.data[i] * alpha + old_img.data[i] * beta; -} - -data load_data_detection(int n, char **paths, int m, int w, int h, int c, int boxes, int classes, int use_flip, int gaussian_noise, int use_blur, int use_mixup, - float jitter, float resize, float hue, float saturation, float exposure, int mini_batch, int track, int augment_speed, int letter_box, int show_imgs) -{ - const int random_index = random_gen(); - c = c ? c : 3; - char **random_paths; - char **mixup_random_paths = NULL; - if(track) random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed); - else random_paths = get_random_paths(paths, n, m); - - //assert(use_mixup < 2); - if (use_mixup == 2) { - printf("\n cutmix=1 - isn't supported for Detector \n"); - exit(0); - } - if (use_mixup == 3 || use_mixup == 4) { - printf("\n mosaic=1 - compile Darknet with OpenCV for using mosaic=1 \n"); - exit(0); - } - int mixup = use_mixup ? random_gen() % 2 : 0; - //printf("\n mixup = %d \n", mixup); - if (mixup) { - if (track) mixup_random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed); - else mixup_random_paths = get_random_paths(paths, n, m); - } - - int i; - data d = { 0 }; - d.shallow = 0; - - d.X.rows = n; - d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); - d.X.cols = h*w*c; - - float r1 = 0, r2 = 0, r3 = 0, r4 = 0, r_scale; - float resize_r1 = 0, resize_r2 = 0; - float dhue = 0, dsat = 0, dexp = 0, flip = 0; - int augmentation_calculated = 0; - - d.y = make_matrix(n, 5 * boxes); - int i_mixup = 0; - for (i_mixup = 0; i_mixup <= mixup; i_mixup++) { - if (i_mixup) augmentation_calculated = 0; - for (i = 0; i < n; ++i) { - float *truth = (float*)xcalloc(5 * boxes, sizeof(float)); - char *filename = (i_mixup) ? mixup_random_paths[i] : random_paths[i]; - - image orig = load_image(filename, 0, 0, c); - - int oh = orig.h; - int ow = orig.w; - - int dw = (ow*jitter); - int dh = (oh*jitter); - - float resize_down = resize, resize_up = resize; - if (resize_down > 1.0) resize_down = 1 / resize_down; - int min_rdw = ow*(1 - (1 / resize_down)) / 2; - int min_rdh = oh*(1 - (1 / resize_down)) / 2; - - if (resize_up < 1.0) resize_up = 1 / resize_up; - int max_rdw = ow*(1 - (1 / resize_up)) / 2; - int max_rdh = oh*(1 - (1 / resize_up)) / 2; - - if (!augmentation_calculated || !track) - { - augmentation_calculated = 1; - resize_r1 = random_float(); - resize_r2 = random_float(); - - r1 = random_float(); - r2 = random_float(); - r3 = random_float(); - r4 = random_float(); - - r_scale = random_float(); - - dhue = rand_uniform_strong(-hue, hue); - dsat = rand_scale(saturation); - dexp = rand_scale(exposure); - - flip = use_flip ? random_gen() % 2 : 0; - } - - int pleft = rand_precalc_random(-dw, dw, r1); - int pright = rand_precalc_random(-dw, dw, r2); - int ptop = rand_precalc_random(-dh, dh, r3); - int pbot = rand_precalc_random(-dh, dh, r4); - - if (resize < 1) { - // downsize only - pleft += rand_precalc_random(min_rdw, 0, resize_r1); - pright += rand_precalc_random(min_rdw, 0, resize_r2); - ptop += rand_precalc_random(min_rdh, 0, resize_r1); - pbot += rand_precalc_random(min_rdh, 0, resize_r2); - } - else { - pleft += rand_precalc_random(min_rdw, max_rdw, resize_r1); - pright += rand_precalc_random(min_rdw, max_rdw, resize_r2); - ptop += rand_precalc_random(min_rdh, max_rdh, resize_r1); - pbot += rand_precalc_random(min_rdh, max_rdh, resize_r2); - } - - if (letter_box) - { - float img_ar = (float)ow / (float)oh; - float net_ar = (float)w / (float)h; - float result_ar = img_ar / net_ar; - //printf(" ow = %d, oh = %d, w = %d, h = %d, img_ar = %f, net_ar = %f, result_ar = %f \n", ow, oh, w, h, img_ar, net_ar, result_ar); - if (result_ar > 1) // sheight - should be increased - { - float oh_tmp = ow / net_ar; - float delta_h = (oh_tmp - oh) / 2; - ptop = ptop - delta_h; - pbot = pbot - delta_h; - //printf(" result_ar = %f, oh_tmp = %f, delta_h = %d, ptop = %f, pbot = %f \n", result_ar, oh_tmp, delta_h, ptop, pbot); - } - else // swidth - should be increased - { - float ow_tmp = oh * net_ar; - float delta_w = (ow_tmp - ow) / 2; - pleft = pleft - delta_w; - pright = pright - delta_w; - //printf(" result_ar = %f, ow_tmp = %f, delta_w = %d, pleft = %f, pright = %f \n", result_ar, ow_tmp, delta_w, pleft, pright); - } - } - - int swidth = ow - pleft - pright; - int sheight = oh - ptop - pbot; - - float sx = (float)swidth / ow; - float sy = (float)sheight / oh; - - image cropped = crop_image(orig, pleft, ptop, swidth, sheight); - - float dx = ((float)pleft / ow) / sx; - float dy = ((float)ptop / oh) / sy; - - image sized = resize_image(cropped, w, h); - if (flip) flip_image(sized); - distort_image(sized, dhue, dsat, dexp); - //random_distort_image(sized, hue, saturation, exposure); - - fill_truth_detection(filename, boxes, truth, classes, flip, dx, dy, 1. / sx, 1. / sy, w, h); - - if (i_mixup) { - image old_img = sized; - old_img.data = d.X.vals[i]; - //show_image(sized, "new"); - //show_image(old_img, "old"); - //wait_until_press_key_cv(); - blend_images(sized, 0.5, old_img, 0.5); - blend_truth(truth, boxes, d.y.vals[i]); - free_image(old_img); - } - - d.X.vals[i] = sized.data; - memcpy(d.y.vals[i], truth, 5 * boxes * sizeof(float)); - - if (show_imgs)// && i_mixup) - { - char buff[1000]; - sprintf(buff, "aug_%d_%d_%s_%d", random_index, i, basecfg(filename), random_gen()); - - int t; - for (t = 0; t < boxes; ++t) { - box b = float_to_box_stride(d.y.vals[i] + t*(4 + 1), 1); - if (!b.x) break; - int left = (b.x - b.w / 2.)*sized.w; - int right = (b.x + b.w / 2.)*sized.w; - int top = (b.y - b.h / 2.)*sized.h; - int bot = (b.y + b.h / 2.)*sized.h; - draw_box_width(sized, left, top, right, bot, 1, 150, 100, 50); // 3 channels RGB - } - - save_image(sized, buff); - if (show_imgs == 1) { - show_image(sized, buff); - wait_until_press_key_cv(); - } - printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Press Enter: \n"); - //getchar(); - } - - free_image(orig); - free_image(cropped); - free(truth); - } - } - free(random_paths); - if (mixup_random_paths) free(mixup_random_paths); - return d; -} -#endif // OPENCV - -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){ - *a.d = load_data_augment(a.paths, a.n, a.m, a.labels, a.classes, a.hierarchy, a.flip, a.min, a.max, a.w, a.h, a.angle, a.aspect, a.hue, a.saturation, a.exposure, a.mixup, a.blur, a.show_imgs, a.label_smooth_eps, a.dontuse_opencv); - } else if (a.type == SUPER_DATA){ - *a.d = load_data_super(a.paths, a.n, a.m, a.w, a.h, a.scale); - } else if (a.type == WRITING_DATA){ - *a.d = load_data_writing(a.paths, a.n, a.m, a.w, a.h, a.out_w, a.out_h); - } else if (a.type == REGION_DATA){ - *a.d = load_data_region(a.n, a.paths, a.m, a.w, a.h, a.num_boxes, a.classes, a.jitter, a.hue, a.saturation, a.exposure); - } else if (a.type == DETECTION_DATA){ - *a.d = load_data_detection(a.n, a.paths, a.m, a.w, a.h, a.c, a.num_boxes, a.classes, a.flip, a.gaussian_noise, a.blur, a.mixup, a.jitter, a.resize, - a.hue, a.saturation, a.exposure, a.mini_batch, a.track, a.augment_speed, a.letter_box, a.show_imgs); - } else if (a.type == SWAG_DATA){ - *a.d = load_data_swag(a.paths, a.n, a.classes, a.jitter); - } else if (a.type == COMPARE_DATA){ - *a.d = load_data_compare(a.n, a.paths, a.m, a.classes, a.w, a.h); - } else if (a.type == IMAGE_DATA){ - *(a.im) = load_image(a.path, 0, 0, a.c); - *(a.resized) = resize_image(*(a.im), a.w, a.h); - }else if (a.type == LETTERBOX_DATA) { - *(a.im) = load_image(a.path, 0, 0, a.c); - *(a.resized) = letterbox_image(*(a.im), a.w, a.h); - } else if (a.type == TAG_DATA){ - *a.d = load_data_tag(a.paths, a.n, a.m, a.classes, a.flip, a.min, a.max, a.w, a.h, a.angle, a.aspect, a.hue, a.saturation, a.exposure); - } - free(ptr); - return 0; -} - -pthread_t load_data_in_thread(load_args args) -{ - pthread_t thread; - struct load_args* ptr = (load_args*)xcalloc(1, sizeof(struct load_args)); - *ptr = args; - if(pthread_create(&thread, 0, load_thread, ptr)) error("Thread creation failed"); - return thread; -} - -static const int thread_wait_ms = 5; -static volatile int flag_exit; -static volatile int * run_load_data = NULL; -static load_args * args_swap = NULL; -static pthread_t* threads = NULL; - -pthread_mutex_t mtx_load_data = PTHREAD_MUTEX_INITIALIZER; - -void *run_thread_loop(void *ptr) -{ - const int i = *(int *)ptr; - - while (!custom_atomic_load_int(&flag_exit)) { - while (!custom_atomic_load_int(&run_load_data[i])) { - if (custom_atomic_load_int(&flag_exit)) { - free(ptr); - return 0; - } - this_thread_sleep_for(thread_wait_ms); - } - - pthread_mutex_lock(&mtx_load_data); - load_args *args_local = (load_args *)xcalloc(1, sizeof(load_args)); - *args_local = args_swap[i]; - pthread_mutex_unlock(&mtx_load_data); - - load_thread(args_local); - - custom_atomic_store_int(&run_load_data[i], 0); - } - free(ptr); - return 0; -} - -void *load_threads(void *ptr) -{ - //srand(time(0)); - int i; - load_args args = *(load_args *)ptr; - if (args.threads == 0) args.threads = 1; - data *out = args.d; - int total = args.n; - free(ptr); - data* buffers = (data*)xcalloc(args.threads, sizeof(data)); - if (!threads) { - threads = (pthread_t*)xcalloc(args.threads, sizeof(pthread_t)); - run_load_data = (volatile int *)xcalloc(args.threads, sizeof(int)); - args_swap = (load_args *)xcalloc(args.threads, sizeof(load_args)); - fprintf(stderr, " Create %d permanent cpu-threads \n", args.threads); - - for (i = 0; i < args.threads; ++i) { - int* ptr = (int*)xcalloc(1, sizeof(int)); - *ptr = i; - if (pthread_create(&threads[i], 0, run_thread_loop, ptr)) error("Thread creation failed"); - } - } - - for (i = 0; i < args.threads; ++i) { - args.d = buffers + i; - args.n = (i + 1) * total / args.threads - i * total / args.threads; - - pthread_mutex_lock(&mtx_load_data); - args_swap[i] = args; - pthread_mutex_unlock(&mtx_load_data); - - custom_atomic_store_int(&run_load_data[i], 1); // run thread - } - for (i = 0; i < args.threads; ++i) { - while (custom_atomic_load_int(&run_load_data[i])) this_thread_sleep_for(thread_wait_ms); // join - } - - /* - pthread_t* threads = (pthread_t*)xcalloc(args.threads, sizeof(pthread_t)); - for(i = 0; i < args.threads; ++i){ - args.d = buffers + i; - args.n = (i+1) * total/args.threads - i * total/args.threads; - threads[i] = load_data_in_thread(args); - } - for(i = 0; i < args.threads; ++i){ - pthread_join(threads[i], 0); - } - */ - - *out = concat_datas(buffers, args.threads); - out->shallow = 0; - for(i = 0; i < args.threads; ++i){ - buffers[i].shallow = 1; - free_data(buffers[i]); - } - free(buffers); - //free(threads); - return 0; -} - -void free_load_threads(void *ptr) -{ - load_args args = *(load_args *)ptr; - if (args.threads == 0) args.threads = 1; - int i; - if (threads) { - custom_atomic_store_int(&flag_exit, 1); - for (i = 0; i < args.threads; ++i) { - pthread_join(threads[i], 0); - } - free((void*)run_load_data); - free(args_swap); - free(threads); - threads = NULL; - custom_atomic_store_int(&flag_exit, 0); - } -} - -pthread_t load_data(load_args args) -{ - pthread_t thread; - struct load_args* ptr = (load_args*)xcalloc(1, sizeof(struct load_args)); - *ptr = args; - if(pthread_create(&thread, 0, load_threads, ptr)) error("Thread creation failed"); - return thread; -} - -data load_data_writing(char **paths, int n, int m, int w, int h, int out_w, int out_h) -{ - if(m) paths = get_random_paths(paths, n, m); - char **replace_paths = find_replace_paths(paths, n, ".png", "-label.png"); - data d = {0}; - d.shallow = 0; - d.X = load_image_paths(paths, n, w, h); - d.y = load_image_paths_gray(replace_paths, n, out_w, out_h); - if(m) free(paths); - int i; - for(i = 0; i < n; ++i) free(replace_paths[i]); - free(replace_paths); - return d; -} - -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, 0); - if(m) free(paths); - return d; -} - -/* - data load_data_study(char **paths, int n, int m, char **labels, int k, int min, int max, int size, float angle, float aspect, float hue, float saturation, float exposure) - { - data d = {0}; - d.indexes = calloc(n, sizeof(int)); - if(m) paths = get_random_paths_indexes(paths, n, m, d.indexes); - d.shallow = 0; - d.X = load_image_augment_paths(paths, n, flip, min, max, size, angle, aspect, hue, saturation, exposure); - d.y = load_labels_paths(paths, n, labels, k); - if(m) free(paths); - return d; - } - */ - -data load_data_super(char **paths, int n, int m, int w, int h, int scale) -{ - if(m) paths = get_random_paths(paths, n, m); - data d = {0}; - d.shallow = 0; - - int i; - d.X.rows = n; - d.X.vals = (float**)xcalloc(n, sizeof(float*)); - d.X.cols = w*h*3; - - d.y.rows = n; - d.y.vals = (float**)xcalloc(n, sizeof(float*)); - d.y.cols = w*scale * h*scale * 3; - - for(i = 0; i < n; ++i){ - image im = load_image_color(paths[i], 0, 0); - image crop = random_crop_image(im, w*scale, h*scale); - int flip = random_gen()%2; - if (flip) flip_image(crop); - image resize = resize_image(crop, w, h); - d.X.vals[i] = resize.data; - d.y.vals[i] = crop.data; - free_image(im); - } - - if(m) free(paths); - return d; -} - -data load_data_augment(char **paths, int n, int m, char **labels, int k, tree *hierarchy, int use_flip, int min, int max, int w, int h, float angle, float aspect, float hue, float saturation, float exposure, int use_mixup, int use_blur, int show_imgs, float label_smooth_eps, int dontuse_opencv) -{ - char **paths_stored = paths; - if(m) paths = get_random_paths(paths, n, m); - data d = {0}; - d.shallow = 0; - d.X = load_image_augment_paths(paths, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv); - d.y = load_labels_paths(paths, n, labels, k, hierarchy, label_smooth_eps); - - if (use_mixup && rand_int(0, 1)) { - char **paths_mix = get_random_paths(paths_stored, n, m); - data d2 = { 0 }; - d2.shallow = 0; - d2.X = load_image_augment_paths(paths_mix, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv); - d2.y = load_labels_paths(paths_mix, n, labels, k, hierarchy, label_smooth_eps); - free(paths_mix); - - data d3 = { 0 }; - d3.shallow = 0; - data d4 = { 0 }; - d4.shallow = 0; - if (use_mixup >= 3) { - char **paths_mix3 = get_random_paths(paths_stored, n, m); - d3.X = load_image_augment_paths(paths_mix3, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv); - d3.y = load_labels_paths(paths_mix3, n, labels, k, hierarchy, label_smooth_eps); - free(paths_mix3); - - char **paths_mix4 = get_random_paths(paths_stored, n, m); - d4.X = load_image_augment_paths(paths_mix4, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv); - d4.y = load_labels_paths(paths_mix4, n, labels, k, hierarchy, label_smooth_eps); - free(paths_mix4); - } - - - // mix - int i, j; - for (i = 0; i < d2.X.rows; ++i) { - - int mixup = use_mixup; - if (use_mixup == 4) mixup = rand_int(2, 3); // alternate CutMix and Mosaic - - // MixUp ----------------------------------- - if (mixup == 1) { - // mix images - for (j = 0; j < d2.X.cols; ++j) { - d.X.vals[i][j] = (d.X.vals[i][j] + d2.X.vals[i][j]) / 2.0f; - } - - // mix labels - for (j = 0; j < d2.y.cols; ++j) { - d.y.vals[i][j] = (d.y.vals[i][j] + d2.y.vals[i][j]) / 2.0f; - } - } - // CutMix ----------------------------------- - else if (mixup == 2) { - const float min = 0.3; // 0.3*0.3 = 9% - const float max = 0.8; // 0.8*0.8 = 64% - const int cut_w = rand_int(w*min, w*max); - const int cut_h = rand_int(h*min, h*max); - const int cut_x = rand_int(0, w - cut_w - 1); - const int cut_y = rand_int(0, h - cut_h - 1); - const int left = cut_x; - const int right = cut_x + cut_w; - const int top = cut_y; - const int bot = cut_y + cut_h; - - assert(cut_x >= 0 && cut_x <= w); - assert(cut_y >= 0 && cut_y <= h); - assert(cut_w >= 0 && cut_w <= w); - assert(cut_h >= 0 && cut_h <= h); - - assert(right >= 0 && right <= w); - assert(bot >= 0 && bot <= h); - - assert(top <= bot); - assert(left <= right); - - const float alpha = (float)(cut_w*cut_h) / (float)(w*h); - const float beta = 1 - alpha; - - int c, x, y; - for (c = 0; c < 3; ++c) { - for (y = top; y < bot; ++y) { - for (x = left; x < right; ++x) { - int j = x + y*w + c*w*h; - d.X.vals[i][j] = d2.X.vals[i][j]; - } - } - } - - //printf("\n alpha = %f, beta = %f \n", alpha, beta); - // mix labels - for (j = 0; j < d.y.cols; ++j) { - d.y.vals[i][j] = d.y.vals[i][j] * beta + d2.y.vals[i][j] * alpha; - } - } - // Mosaic ----------------------------------- - else if (mixup == 3) - { - const float min_offset = 0.2; // 20% - const int cut_x = rand_int(w*min_offset, w*(1 - min_offset)); - const int cut_y = rand_int(h*min_offset, h*(1 - min_offset)); - - float s1 = (float)(cut_x * cut_y) / (w*h); - float s2 = (float)((w - cut_x) * cut_y) / (w*h); - float s3 = (float)(cut_x * (h - cut_y)) / (w*h); - float s4 = (float)((w - cut_x) * (h - cut_y)) / (w*h); - - int c, x, y; - for (c = 0; c < 3; ++c) { - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - int j = x + y*w + c*w*h; - if (x < cut_x && y < cut_y) d.X.vals[i][j] = d.X.vals[i][j]; - if (x >= cut_x && y < cut_y) d.X.vals[i][j] = d2.X.vals[i][j]; - if (x < cut_x && y >= cut_y) d.X.vals[i][j] = d3.X.vals[i][j]; - if (x >= cut_x && y >= cut_y) d.X.vals[i][j] = d4.X.vals[i][j]; - } - } - } - - for (j = 0; j < d.y.cols; ++j) { - const float max_s = 1;// max_val_cmp(s1, max_val_cmp(s2, max_val_cmp(s3, s4))); - - d.y.vals[i][j] = d.y.vals[i][j] * s1 / max_s + d2.y.vals[i][j] * s2 / max_s + d3.y.vals[i][j] * s3 / max_s + d4.y.vals[i][j] * s4 / max_s; - } - } - } - - free_data(d2); - - if (use_mixup >= 3) { - free_data(d3); - free_data(d4); - } - } - -#ifdef OPENCV - if (use_blur) { - int i; - for (i = 0; i < d.X.rows; ++i) { - if (random_gen() % 2) { - image im = make_empty_image(w, h, 3); - im.data = d.X.vals[i]; - int ksize = use_blur; - if (use_blur == 1) ksize = 17; - image blurred = blur_image(im, ksize); - free_image(im); - d.X.vals[i] = blurred.data; - //if (i == 0) { - // show_image(im, "Not blurred"); - // show_image(blurred, "blurred"); - // wait_until_press_key_cv(); - //} - } - } - } -#endif // OPENCV - - if (show_imgs) { - int i, j; - for (i = 0; i < d.X.rows; ++i) { - image im = make_empty_image(w, h, 3); - im.data = d.X.vals[i]; - char buff[1000]; - sprintf(buff, "aug_%d_%s_%d", i, basecfg((char*)paths[i]), random_gen()); - save_image(im, buff); - - char buff_string[1000]; - sprintf(buff_string, "\n Classes: "); - for (j = 0; j < d.y.cols; ++j) { - if (d.y.vals[i][j] > 0) { - char buff_tmp[100]; - sprintf(buff_tmp, " %d (%f), ", j, d.y.vals[i][j]); - strcat(buff_string, buff_tmp); - } - } - printf("%s \n", buff_string); - - if (show_imgs == 1) { - show_image(im, buff); - wait_until_press_key_cv(); - } - } - printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Click on window and press ESC button \n"); - } - - if (m) free(paths); - - return d; -} - -data load_data_tag(char **paths, int n, int m, int k, int use_flip, int min, int max, int w, int h, float angle, float aspect, float hue, float saturation, float exposure) -{ - if(m) paths = get_random_paths(paths, n, m); - data d = {0}; - d.w = w; - d.h = h; - d.shallow = 0; - d.X = load_image_augment_paths(paths, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, 0); - d.y = load_tags_paths(paths, n, k); - if(m) free(paths); - return d; -} - -matrix concat_matrix(matrix m1, matrix m2) -{ - int i, count = 0; - matrix m; - m.cols = m1.cols; - m.rows = m1.rows+m2.rows; - m.vals = (float**)xcalloc(m1.rows + m2.rows, sizeof(float*)); - for(i = 0; i < m1.rows; ++i){ - m.vals[count++] = m1.vals[i]; - } - for(i = 0; i < m2.rows; ++i){ - m.vals[count++] = m2.vals[i]; - } - return m; -} - -data concat_data(data d1, data d2) -{ - data d = {0}; - d.shallow = 1; - d.X = concat_matrix(d1.X, d2.X); - d.y = concat_matrix(d1.y, d2.y); - return d; -} - -data concat_datas(data *d, int n) -{ - int i; - data out = {0}; - for(i = 0; i < n; ++i){ - data newdata = concat_data(d[i], out); - free_data(out); - out = newdata; - } - return out; -} - -data load_categorical_data_csv(char *filename, int target, int k) -{ - data d = {0}; - d.shallow = 0; - matrix X = csv_to_matrix(filename); - float *truth_1d = pop_column(&X, target); - float **truth = one_hot_encode(truth_1d, X.rows, k); - matrix y; - y.rows = X.rows; - y.cols = k; - y.vals = truth; - d.X = X; - d.y = y; - free(truth_1d); - return d; -} - -data load_cifar10_data(char *filename) -{ - data d = {0}; - d.shallow = 0; - long i,j; - matrix X = make_matrix(10000, 3072); - matrix y = make_matrix(10000, 10); - d.X = X; - d.y = y; - - FILE *fp = fopen(filename, "rb"); - if(!fp) file_error(filename); - for(i = 0; i < 10000; ++i){ - unsigned char bytes[3073]; - fread(bytes, 1, 3073, fp); - int class_id = bytes[0]; - y.vals[i][class_id] = 1; - for(j = 0; j < X.cols; ++j){ - X.vals[i][j] = (double)bytes[j+1]; - } - } - //translate_data_rows(d, -128); - scale_data_rows(d, 1./255); - //normalize_data_rows(d); - fclose(fp); - return d; -} - -void get_random_batch(data d, int n, float *X, float *y) -{ - int j; - for(j = 0; j < n; ++j){ - int index = random_gen()%d.X.rows; - memcpy(X+j*d.X.cols, d.X.vals[index], d.X.cols*sizeof(float)); - memcpy(y+j*d.y.cols, d.y.vals[index], d.y.cols*sizeof(float)); - } -} - -void get_next_batch(data d, int n, int offset, float *X, float *y) -{ - int j; - for(j = 0; j < n; ++j){ - int index = offset + j; - memcpy(X+j*d.X.cols, d.X.vals[index], d.X.cols*sizeof(float)); - memcpy(y+j*d.y.cols, d.y.vals[index], d.y.cols*sizeof(float)); - } -} - -void smooth_data(data d) -{ - int i, j; - float scale = 1. / d.y.cols; - float eps = .1; - for(i = 0; i < d.y.rows; ++i){ - for(j = 0; j < d.y.cols; ++j){ - d.y.vals[i][j] = eps * scale + (1-eps) * d.y.vals[i][j]; - } - } -} - -data load_all_cifar10() -{ - data d = {0}; - d.shallow = 0; - int i,j,b; - matrix X = make_matrix(50000, 3072); - matrix y = make_matrix(50000, 10); - d.X = X; - d.y = y; - - - for(b = 0; b < 5; ++b){ - char buff[256]; - sprintf(buff, "data/cifar/cifar-10-batches-bin/data_batch_%d.bin", b+1); - FILE *fp = fopen(buff, "rb"); - if(!fp) file_error(buff); - for(i = 0; i < 10000; ++i){ - unsigned char bytes[3073]; - fread(bytes, 1, 3073, fp); - int class_id = bytes[0]; - y.vals[i+b*10000][class_id] = 1; - for(j = 0; j < X.cols; ++j){ - X.vals[i+b*10000][j] = (double)bytes[j+1]; - } - } - fclose(fp); - } - //normalize_data_rows(d); - //translate_data_rows(d, -128); - scale_data_rows(d, 1./255); - smooth_data(d); - return d; -} - -data load_go(char *filename) -{ - FILE *fp = fopen(filename, "rb"); - matrix X = make_matrix(3363059, 361); - matrix y = make_matrix(3363059, 361); - int row, col; - - if(!fp) file_error(filename); - char *label; - int count = 0; - while((label = fgetl(fp))){ - int i; - if(count == X.rows){ - X = resize_matrix(X, count*2); - y = resize_matrix(y, count*2); - } - sscanf(label, "%d %d", &row, &col); - char *board = fgetl(fp); - - int index = row*19 + col; - y.vals[count][index] = 1; - - for(i = 0; i < 19*19; ++i){ - float val = 0; - if(board[i] == '1') val = 1; - else if(board[i] == '2') val = -1; - X.vals[count][i] = val; - } - ++count; - free(label); - free(board); - } - X = resize_matrix(X, count); - y = resize_matrix(y, count); - - data d = {0}; - d.shallow = 0; - d.X = X; - d.y = y; - - - fclose(fp); - - return d; -} - - -void randomize_data(data d) -{ - int i; - for(i = d.X.rows-1; i > 0; --i){ - int index = random_gen()%i; - float *swap = d.X.vals[index]; - 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; - } -} - -void scale_data_rows(data d, float s) -{ - int i; - for(i = 0; i < d.X.rows; ++i){ - scale_array(d.X.vals[i], d.X.cols, s); - } -} - -void translate_data_rows(data d, float s) -{ - int i; - for(i = 0; i < d.X.rows; ++i){ - translate_array(d.X.vals[i], d.X.cols, s); - } -} - -void normalize_data_rows(data d) -{ - int i; - for(i = 0; i < d.X.rows; ++i){ - normalize_array(d.X.vals[i], d.X.cols); - } -} - -data get_data_part(data d, int part, int total) -{ - data p = {0}; - p.shallow = 1; - p.X.rows = d.X.rows * (part + 1) / total - d.X.rows * part / total; - p.y.rows = d.y.rows * (part + 1) / total - d.y.rows * part / total; - p.X.cols = d.X.cols; - p.y.cols = d.y.cols; - p.X.vals = d.X.vals + d.X.rows * part / total; - p.y.vals = d.y.vals + d.y.rows * part / total; - return p; -} - -data get_random_data(data d, int num) -{ - data r = {0}; - r.shallow = 1; - - r.X.rows = num; - r.y.rows = num; - - r.X.cols = d.X.cols; - r.y.cols = d.y.cols; - - r.X.vals = (float**)xcalloc(num, sizeof(float*)); - r.y.vals = (float**)xcalloc(num, sizeof(float*)); - - int i; - for(i = 0; i < num; ++i){ - int index = random_gen()%d.X.rows; - r.X.vals[i] = d.X.vals[index]; - r.y.vals[i] = d.y.vals[index]; - } - return r; -} - -data *split_data(data d, int part, int total) -{ - data* split = (data*)xcalloc(2, sizeof(data)); - int i; - int start = part*d.X.rows/total; - int end = (part+1)*d.X.rows/total; - data train ={0}; - data test ={0}; - train.shallow = test.shallow = 1; - - test.X.rows = test.y.rows = end-start; - train.X.rows = train.y.rows = d.X.rows - (end-start); - train.X.cols = test.X.cols = d.X.cols; - train.y.cols = test.y.cols = d.y.cols; - - train.X.vals = (float**)xcalloc(train.X.rows, sizeof(float*)); - test.X.vals = (float**)xcalloc(test.X.rows, sizeof(float*)); - train.y.vals = (float**)xcalloc(train.y.rows, sizeof(float*)); - test.y.vals = (float**)xcalloc(test.y.rows, sizeof(float*)); - - for(i = 0; i < start; ++i){ - train.X.vals[i] = d.X.vals[i]; - train.y.vals[i] = d.y.vals[i]; - } - for(i = start; i < end; ++i){ - test.X.vals[i-start] = d.X.vals[i]; - test.y.vals[i-start] = d.y.vals[i]; - } - for(i = end; i < d.X.rows; ++i){ - train.X.vals[i-(end-start)] = d.X.vals[i]; - train.y.vals[i-(end-start)] = d.y.vals[i]; - } - split[0] = train; - split[1] = test; - return split; -} +#include "data.h" +#include "utils.h" +#include "image.h" +#include "dark_cuda.h" +#include "box.h" +#include "http_stream.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +extern int check_mistakes; + +#define NUMCHARS 37 + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +list *get_paths(char *filename) +{ + char *path; + FILE *file = fopen(filename, "r"); + if(!file) file_error(filename); + list *lines = make_list(); + while((path=fgetl(file))){ + list_insert(lines, path); + } + fclose(file); + return lines; +} + +/* +char **get_random_paths_indexes(char **paths, int n, int m, int *indexes) +{ + char **random_paths = calloc(n, sizeof(char*)); + int i; + pthread_mutex_lock(&mutex); + for(i = 0; i < n; ++i){ + int index = random_gen()%m; + indexes[i] = index; + random_paths[i] = paths[index]; + if(i == 0) printf("%s\n", paths[index]); + } + pthread_mutex_unlock(&mutex); + return random_paths; +} +*/ + +char **get_sequential_paths(char **paths, int n, int m, int mini_batch, int augment_speed, int contrastive) +{ + int speed = rand_int(1, augment_speed); + if (speed < 1) speed = 1; + char** sequentia_paths = (char**)xcalloc(n, sizeof(char*)); + int i; + pthread_mutex_lock(&mutex); + //printf("n = %d, mini_batch = %d \n", n, mini_batch); + unsigned int *start_time_indexes = (unsigned int *)xcalloc(mini_batch, sizeof(unsigned int)); + for (i = 0; i < mini_batch; ++i) { + if (contrastive && (i % 2) == 1) start_time_indexes[i] = start_time_indexes[i - 1]; + else start_time_indexes[i] = random_gen() % m; + + //printf(" start_time_indexes[i] = %u, ", start_time_indexes[i]); + } + + for (i = 0; i < n; ++i) { + do { + int time_line_index = i % mini_batch; + unsigned int index = start_time_indexes[time_line_index] % m; + start_time_indexes[time_line_index] += speed; + + //int index = random_gen() % m; + sequentia_paths[i] = paths[index]; + //printf(" index = %d, ", index); + //if(i == 0) printf("%s\n", paths[index]); + //printf(" index = %u - grp: %s \n", index, paths[index]); + if (strlen(sequentia_paths[i]) <= 4) printf(" Very small path to the image: %s \n", sequentia_paths[i]); + } while (strlen(sequentia_paths[i]) == 0); + } + free(start_time_indexes); + pthread_mutex_unlock(&mutex); + return sequentia_paths; +} + +char **get_random_paths_custom(char **paths, int n, int m, int contrastive) +{ + char** random_paths = (char**)xcalloc(n, sizeof(char*)); + int i; + pthread_mutex_lock(&mutex); + int old_index = 0; + //printf("n = %d \n", n); + for(i = 0; i < n; ++i){ + do { + int index = random_gen() % m; + if (contrastive && (i % 2 == 1)) index = old_index; + else old_index = index; + 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; +} + +char **get_random_paths(char **paths, int n, int m) +{ + return get_random_paths_custom(paths, n, m, 0); +} + +char **find_replace_paths(char **paths, int n, char *find, char *replace) +{ + char** replace_paths = (char**)xcalloc(n, sizeof(char*)); + int i; + for(i = 0; i < n; ++i){ + char replaced[4096]; + find_replace(paths[i], find, replace, replaced); + replace_paths[i] = copy_string(replaced); + } + return replace_paths; +} + +matrix load_image_paths_gray(char **paths, int n, int w, int h) +{ + int i; + matrix X; + X.rows = n; + X.vals = (float**)xcalloc(X.rows, sizeof(float*)); + X.cols = 0; + + for(i = 0; i < n; ++i){ + image im = load_image(paths[i], w, h, 3); + + image gray = grayscale_image(im); + free_image(im); + im = gray; + + X.vals[i] = im.data; + X.cols = im.h*im.w*im.c; + } + return X; +} + +matrix load_image_paths(char **paths, int n, int w, int h) +{ + int i; + matrix X; + X.rows = n; + X.vals = (float**)xcalloc(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 load_image_augment_paths(char **paths, int n, int use_flip, int min, int max, int w, int h, float angle, float aspect, float hue, float saturation, float exposure, int dontuse_opencv, int contrastive) +{ + int i; + matrix X; + X.rows = n; + X.vals = (float**)xcalloc(X.rows, sizeof(float*)); + X.cols = 0; + + for(i = 0; i < n; ++i){ + int size = w > h ? w : h; + image im; + const int img_index = (contrastive) ? (i / 2) : i; + if(dontuse_opencv) im = load_image_stb_resize(paths[img_index], 0, 0, 3); + else im = load_image_color(paths[img_index], 0, 0); + + image crop = random_augment_image(im, angle, aspect, min, max, size); + int flip = use_flip ? random_gen() % 2 : 0; + if (flip) + flip_image(crop); + random_distort_image(crop, hue, saturation, exposure); + + image sized = resize_image(crop, w, h); + + //show_image(im, "orig"); + //show_image(sized, "sized"); + //show_image(sized, paths[img_index]); + //wait_until_press_key_cv(); + //printf("w = %d, h = %d \n", sized.w, sized.h); + + free_image(im); + free_image(crop); + X.vals[i] = sized.data; + X.cols = sized.h*sized.w*sized.c; + } + return X; +} + + +box_label *read_boxes(char *filename, int *n) +{ + box_label* boxes = (box_label*)xcalloc(1, sizeof(box_label)); + FILE *file = fopen(filename, "r"); + if (!file) { + printf("Can't open label file. (This can be normal only if you use MSCOCO): %s \n", filename); + //file_error(filename); + FILE* fw = fopen("bad.list", "a"); + fwrite(filename, sizeof(char), strlen(filename), fw); + char *new_line = "\n"; + fwrite(new_line, sizeof(char), strlen(new_line), fw); + fclose(fw); + if (check_mistakes) { + printf("\n Error in read_boxes() \n"); + getchar(); + } + + *n = 0; + return boxes; + } + const int max_obj_img = 4000;// 30000; + const int img_hash = (custom_hash(filename) % max_obj_img)*max_obj_img; + //printf(" img_hash = %d, filename = %s; ", img_hash, filename); + float x, y, h, w; + int id; + int count = 0; + while(fscanf(file, "%d %f %f %f %f", &id, &x, &y, &w, &h) == 5){ + boxes = (box_label*)xrealloc(boxes, (count + 1) * sizeof(box_label)); + boxes[count].track_id = count + img_hash; + //printf(" boxes[count].track_id = %d, count = %d \n", boxes[count].track_id, count); + boxes[count].id = id; + boxes[count].x = x; + boxes[count].y = y; + boxes[count].h = h; + boxes[count].w = w; + boxes[count].left = x - w/2; + boxes[count].right = x + w/2; + boxes[count].top = y - h/2; + boxes[count].bottom = y + h/2; + ++count; + } + fclose(file); + *n = count; + return boxes; +} + +void randomize_boxes(box_label *b, int n) +{ + int i; + for(i = 0; i < n; ++i){ + box_label swap = b[i]; + int index = random_gen()%n; + b[i] = b[index]; + b[index] = swap; + } +} + +void correct_boxes(box_label *boxes, int n, float dx, float dy, float sx, float sy, int flip) +{ + int i; + for(i = 0; i < n; ++i){ + if(boxes[i].x == 0 && boxes[i].y == 0) { + boxes[i].x = 999999; + boxes[i].y = 999999; + boxes[i].w = 999999; + boxes[i].h = 999999; + continue; + } + if ((boxes[i].x + boxes[i].w / 2) < 0 || (boxes[i].y + boxes[i].h / 2) < 0 || + (boxes[i].x - boxes[i].w / 2) > 1 || (boxes[i].y - boxes[i].h / 2) > 1) + { + boxes[i].x = 999999; + boxes[i].y = 999999; + boxes[i].w = 999999; + boxes[i].h = 999999; + continue; + } + boxes[i].left = boxes[i].left * sx - dx; + boxes[i].right = boxes[i].right * sx - dx; + boxes[i].top = boxes[i].top * sy - dy; + boxes[i].bottom = boxes[i].bottom* sy - dy; + + if(flip){ + float swap = boxes[i].left; + boxes[i].left = 1. - boxes[i].right; + boxes[i].right = 1. - swap; + } + + boxes[i].left = constrain(0, 1, boxes[i].left); + boxes[i].right = constrain(0, 1, boxes[i].right); + boxes[i].top = constrain(0, 1, boxes[i].top); + boxes[i].bottom = constrain(0, 1, boxes[i].bottom); + + boxes[i].x = (boxes[i].left+boxes[i].right)/2; + boxes[i].y = (boxes[i].top+boxes[i].bottom)/2; + boxes[i].w = (boxes[i].right - boxes[i].left); + boxes[i].h = (boxes[i].bottom - boxes[i].top); + + boxes[i].w = constrain(0, 1, boxes[i].w); + boxes[i].h = constrain(0, 1, boxes[i].h); + } +} + +void fill_truth_swag(char *path, float *truth, int classes, int flip, float dx, float dy, float sx, float sy) +{ + char labelpath[4096]; + replace_image_to_label(path, labelpath); + + int count = 0; + box_label *boxes = read_boxes(labelpath, &count); + randomize_boxes(boxes, count); + correct_boxes(boxes, count, dx, dy, sx, sy, flip); + float x,y,w,h; + int id; + int i; + + for (i = 0; i < count && i < 30; ++i) { + x = boxes[i].x; + y = boxes[i].y; + w = boxes[i].w; + h = boxes[i].h; + id = boxes[i].id; + + if (w < .0 || h < .0) continue; + + int index = (4+classes) * i; + + truth[index++] = x; + truth[index++] = y; + truth[index++] = w; + truth[index++] = h; + + if (id < classes) truth[index+id] = 1; + } + free(boxes); +} + +void fill_truth_region(char *path, float *truth, int classes, int num_boxes, int flip, float dx, float dy, float sx, float sy) +{ + char labelpath[4096]; + replace_image_to_label(path, labelpath); + + int count = 0; + box_label *boxes = read_boxes(labelpath, &count); + randomize_boxes(boxes, count); + correct_boxes(boxes, count, dx, dy, sx, sy, flip); + float x,y,w,h; + int id; + int i; + + for (i = 0; i < count; ++i) { + x = boxes[i].x; + y = boxes[i].y; + w = boxes[i].w; + h = boxes[i].h; + id = boxes[i].id; + + if (w < .001 || h < .001) continue; + + int col = (int)(x*num_boxes); + int row = (int)(y*num_boxes); + + x = x*num_boxes - col; + y = y*num_boxes - row; + + int index = (col+row*num_boxes)*(5+classes); + if (truth[index]) continue; + truth[index++] = 1; + + if (id < classes) truth[index+id] = 1; + index += classes; + + truth[index++] = x; + truth[index++] = y; + truth[index++] = w; + truth[index++] = h; + } + free(boxes); +} + +int fill_truth_detection(const char *path, int num_boxes, int truth_size, float *truth, int classes, int flip, float dx, float dy, float sx, float sy, + int net_w, int net_h) +{ + char labelpath[4096]; + replace_image_to_label(path, labelpath); + + int count = 0; + int i; + box_label *boxes = read_boxes(labelpath, &count); + int min_w_h = 0; + float lowest_w = 1.F / net_w; + float lowest_h = 1.F / net_h; + randomize_boxes(boxes, count); + correct_boxes(boxes, count, dx, dy, sx, sy, flip); + if (count > num_boxes) count = num_boxes; + float x, y, w, h; + int id; + int sub = 0; + + for (i = 0; i < count; ++i) { + x = boxes[i].x; + y = boxes[i].y; + w = boxes[i].w; + h = boxes[i].h; + id = boxes[i].id; + int track_id = boxes[i].track_id; + + // not detect small objects + //if ((w < 0.001F || h < 0.001F)) continue; + // if truth (box for object) is smaller than 1x1 pix + char buff[256]; + if (id >= classes) { + printf("\n Wrong annotation: class_id = %d. But class_id should be [from 0 to %d], file: %s \n", id, (classes-1), labelpath); + sprintf(buff, "echo %s \"Wrong annotation: class_id = %d. But class_id should be [from 0 to %d]\" >> bad_label.list", labelpath, id, (classes-1)); + system(buff); + if (check_mistakes) getchar(); + ++sub; + continue; + } + if ((w < lowest_w || h < lowest_h)) { + //sprintf(buff, "echo %s \"Very small object: w < lowest_w OR h < lowest_h\" >> bad_label.list", labelpath); + //system(buff); + ++sub; + continue; + } + if (x == 999999 || y == 999999) { + printf("\n Wrong annotation: x = 0, y = 0, < 0 or > 1, file: %s \n", labelpath); + sprintf(buff, "echo %s \"Wrong annotation: x = 0 or y = 0\" >> bad_label.list", labelpath); + system(buff); + ++sub; + if (check_mistakes) getchar(); + continue; + } + if (x <= 0 || x > 1 || y <= 0 || y > 1) { + printf("\n Wrong annotation: x = %f, y = %f, file: %s \n", x, y, labelpath); + sprintf(buff, "echo %s \"Wrong annotation: x = %f, y = %f\" >> bad_label.list", labelpath, x, y); + system(buff); + ++sub; + if (check_mistakes) getchar(); + continue; + } + if (w > 1) { + printf("\n Wrong annotation: w = %f, file: %s \n", w, labelpath); + sprintf(buff, "echo %s \"Wrong annotation: w = %f\" >> bad_label.list", labelpath, w); + system(buff); + w = 1; + if (check_mistakes) getchar(); + } + if (h > 1) { + printf("\n Wrong annotation: h = %f, file: %s \n", h, labelpath); + sprintf(buff, "echo %s \"Wrong annotation: h = %f\" >> bad_label.list", labelpath, h); + system(buff); + h = 1; + if (check_mistakes) getchar(); + } + if (x == 0) x += lowest_w; + if (y == 0) y += lowest_h; + + truth[(i-sub)*truth_size +0] = x; + truth[(i-sub)*truth_size +1] = y; + truth[(i-sub)*truth_size +2] = w; + truth[(i-sub)*truth_size +3] = h; + truth[(i-sub)*truth_size +4] = id; + truth[(i-sub)*truth_size +5] = track_id; + //float val = track_id; + //printf(" i = %d, sub = %d, truth_size = %d, track_id = %d, %f, %f\n", i, sub, truth_size, track_id, truth[(i - sub)*truth_size + 5], val); + + if (min_w_h == 0) min_w_h = w*net_w; + if (min_w_h > w*net_w) min_w_h = w*net_w; + if (min_w_h > h*net_h) min_w_h = h*net_h; + } + free(boxes); + return min_w_h; +} + + +void print_letters(float *pred, int n) +{ + int i; + for(i = 0; i < n; ++i){ + int index = max_index(pred+i*NUMCHARS, NUMCHARS); + printf("%c", int_to_alphanum(index)); + } + printf("\n"); +} + +void fill_truth_captcha(char *path, int n, float *truth) +{ + char *begin = strrchr(path, '/'); + ++begin; + int i; + for(i = 0; i < strlen(begin) && i < n && begin[i] != '.'; ++i){ + int index = alphanum_to_int(begin[i]); + if(index > 35) printf("Bad %c\n", begin[i]); + truth[i*NUMCHARS+index] = 1; + } + for(;i < n; ++i){ + truth[i*NUMCHARS + NUMCHARS-1] = 1; + } +} + +data load_data_captcha(char **paths, int n, int m, 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 = make_matrix(n, k*NUMCHARS); + int i; + for(i = 0; i < n; ++i){ + fill_truth_captcha(paths[i], k, d.y.vals[i]); + } + if(m) free(paths); + return d; +} + +data load_data_captcha_encode(char **paths, int n, int m, 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.X.cols = 17100; + d.y = d.X; + if(m) free(paths); + return d; +} + +void fill_truth(char *path, char **labels, int k, float *truth) +{ + int i; + memset(truth, 0, k*sizeof(float)); + int count = 0; + for(i = 0; i < k; ++i){ + if(strstr(path, labels[i])){ + truth[i] = 1; + ++count; + } + } + if (count != 1) { + printf("Too many or too few labels: %d, %s\n", count, path); + count = 0; + for (i = 0; i < k; ++i) { + if (strstr(path, labels[i])) { + printf("\t label %d: %s \n", count, labels[i]); + count++; + } + } + } +} + +void fill_truth_smooth(char *path, char **labels, int k, float *truth, float label_smooth_eps) +{ + int i; + memset(truth, 0, k * sizeof(float)); + int count = 0; + for (i = 0; i < k; ++i) { + if (strstr(path, labels[i])) { + truth[i] = (1 - label_smooth_eps); + ++count; + } + else { + truth[i] = label_smooth_eps / (k - 1); + } + } + if (count != 1) { + printf("Too many or too few labels: %d, %s\n", count, path); + count = 0; + for (i = 0; i < k; ++i) { + if (strstr(path, labels[i])) { + printf("\t label %d: %s \n", count, labels[i]); + count++; + } + } + } +} + +void fill_hierarchy(float *truth, int k, tree *hierarchy) +{ + int j; + for(j = 0; j < k; ++j){ + if(truth[j]){ + int parent = hierarchy->parent[j]; + while(parent >= 0){ + truth[parent] = 1; + parent = hierarchy->parent[parent]; + } + } + } + int i; + int count = 0; + for(j = 0; j < hierarchy->groups; ++j){ + //printf("%d\n", count); + int mask = 1; + for(i = 0; i < hierarchy->group_size[j]; ++i){ + if(truth[count + i]){ + mask = 0; + break; + } + } + if (mask) { + for(i = 0; i < hierarchy->group_size[j]; ++i){ + truth[count + i] = SECRET_NUM; + } + } + count += hierarchy->group_size[j]; + } +} + +int find_max(float *arr, int size) { + int i; + float max = 0; + int n = 0; + for (i = 0; i < size; ++i) { + if (arr[i] > max) { + max = arr[i]; + n = i; + } + } + return n; +} + +matrix load_labels_paths(char **paths, int n, char **labels, int k, tree *hierarchy, float label_smooth_eps, int contrastive) +{ + matrix y = make_matrix(n, k); + int i; + if (labels) { + // supervised learning + for (i = 0; i < n; ++i) { + const int img_index = (contrastive) ? (i / 2) : i; + fill_truth_smooth(paths[img_index], labels, k, y.vals[i], label_smooth_eps); + //printf(" n = %d, i = %d, img_index = %d, class_id = %d \n", n, i, img_index, find_max(y.vals[i], k)); + if (hierarchy) { + fill_hierarchy(y.vals[i], k, hierarchy); + } + } + } else { + // unsupervised learning + for (i = 0; i < n; ++i) { + const int img_index = (contrastive) ? (i / 2) : i; + const uintptr_t path_p = (uintptr_t)paths[img_index];// abs(random_gen()); + const int class_id = path_p % k; + int l; + for (l = 0; l < k; ++l) y.vals[i][l] = 0; + y.vals[i][class_id] = 1; + } + } + return y; +} + +matrix load_tags_paths(char **paths, int n, int k) +{ + matrix y = make_matrix(n, k); + int i; + int count = 0; + for(i = 0; i < n; ++i){ + char label[4096]; + find_replace(paths[i], "imgs", "labels", label); + find_replace(label, "_iconl.jpeg", ".txt", label); + FILE *file = fopen(label, "r"); + if(!file){ + find_replace(label, "labels", "labels2", label); + file = fopen(label, "r"); + if(!file) continue; + } + ++count; + int tag; + while(fscanf(file, "%d", &tag) == 1){ + if(tag < k){ + y.vals[i][tag] = 1; + } + } + fclose(file); + } + printf("%d/%d\n", count, n); + return y; +} + +char **get_labels_custom(char *filename, int *size) +{ + list *plist = get_paths(filename); + if(size) *size = plist->size; + char **labels = (char **)list_to_array(plist); + free_list(plist); + return labels; +} + +char **get_labels(char *filename) +{ + return get_labels_custom(filename, NULL); +} + +void free_data(data d) +{ + if(!d.shallow){ + free_matrix(d.X); + free_matrix(d.y); + }else{ + free(d.X.vals); + free(d.y.vals); + } +} + +data load_data_region(int n, char **paths, int m, int w, int h, int size, int classes, float jitter, float hue, float saturation, float exposure) +{ + char **random_paths = get_random_paths(paths, n, m); + int i; + data d = {0}; + d.shallow = 0; + + d.X.rows = n; + d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); + d.X.cols = h*w*3; + + + int k = size*size*(5+classes); + d.y = make_matrix(n, k); + for(i = 0; i < n; ++i){ + image orig = load_image_color(random_paths[i], 0, 0); + + int oh = orig.h; + int ow = orig.w; + + int dw = (ow*jitter); + int dh = (oh*jitter); + + int pleft = rand_uniform(-dw, dw); + int pright = rand_uniform(-dw, dw); + int ptop = rand_uniform(-dh, dh); + int pbot = rand_uniform(-dh, dh); + + int swidth = ow - pleft - pright; + int sheight = oh - ptop - pbot; + + float sx = (float)swidth / ow; + float sy = (float)sheight / oh; + + int flip = random_gen()%2; + image cropped = crop_image(orig, pleft, ptop, swidth, sheight); + + float dx = ((float)pleft/ow)/sx; + float dy = ((float)ptop /oh)/sy; + + image sized = resize_image(cropped, w, h); + if(flip) flip_image(sized); + random_distort_image(sized, hue, saturation, exposure); + d.X.vals[i] = sized.data; + + fill_truth_region(random_paths[i], d.y.vals[i], classes, size, flip, dx, dy, 1./sx, 1./sy); + + free_image(orig); + free_image(cropped); + } + free(random_paths); + return d; +} + +data load_data_compare(int n, char **paths, int m, int classes, int w, int h) +{ + if(m) paths = get_random_paths(paths, 2*n, m); + int i,j; + data d = {0}; + d.shallow = 0; + + d.X.rows = n; + d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); + d.X.cols = h*w*6; + + int k = 2*(classes); + d.y = make_matrix(n, k); + for(i = 0; i < n; ++i){ + image im1 = load_image_color(paths[i*2], w, h); + image im2 = load_image_color(paths[i*2+1], w, h); + + d.X.vals[i] = (float*)xcalloc(d.X.cols, sizeof(float)); + memcpy(d.X.vals[i], im1.data, h*w*3*sizeof(float)); + memcpy(d.X.vals[i] + h*w*3, im2.data, h*w*3*sizeof(float)); + + int id; + float iou; + + char imlabel1[4096]; + char imlabel2[4096]; + find_replace(paths[i*2], "imgs", "labels", imlabel1); + find_replace(imlabel1, "jpg", "txt", imlabel1); + FILE *fp1 = fopen(imlabel1, "r"); + + while(fscanf(fp1, "%d %f", &id, &iou) == 2){ + if (d.y.vals[i][2*id] < iou) d.y.vals[i][2*id] = iou; + } + + find_replace(paths[i*2+1], "imgs", "labels", imlabel2); + find_replace(imlabel2, "jpg", "txt", imlabel2); + FILE *fp2 = fopen(imlabel2, "r"); + + while(fscanf(fp2, "%d %f", &id, &iou) == 2){ + if (d.y.vals[i][2*id + 1] < iou) d.y.vals[i][2*id + 1] = iou; + } + + for (j = 0; j < classes; ++j){ + if (d.y.vals[i][2*j] > .5 && d.y.vals[i][2*j+1] < .5){ + d.y.vals[i][2*j] = 1; + d.y.vals[i][2*j+1] = 0; + } else if (d.y.vals[i][2*j] < .5 && d.y.vals[i][2*j+1] > .5){ + d.y.vals[i][2*j] = 0; + d.y.vals[i][2*j+1] = 1; + } else { + d.y.vals[i][2*j] = SECRET_NUM; + d.y.vals[i][2*j+1] = SECRET_NUM; + } + } + fclose(fp1); + fclose(fp2); + + free_image(im1); + free_image(im2); + } + if(m) free(paths); + return d; +} + +data load_data_swag(char **paths, int n, int classes, float jitter) +{ + int index = random_gen()%n; + char *random_path = paths[index]; + + image orig = load_image_color(random_path, 0, 0); + int h = orig.h; + int w = orig.w; + + data d = {0}; + d.shallow = 0; + d.w = w; + d.h = h; + + d.X.rows = 1; + d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); + d.X.cols = h*w*3; + + int k = (4+classes)*30; + d.y = make_matrix(1, k); + + int dw = w*jitter; + int dh = h*jitter; + + int pleft = rand_uniform(-dw, dw); + int pright = rand_uniform(-dw, dw); + int ptop = rand_uniform(-dh, dh); + int pbot = rand_uniform(-dh, dh); + + int swidth = w - pleft - pright; + int sheight = h - ptop - pbot; + + float sx = (float)swidth / w; + float sy = (float)sheight / h; + + int flip = random_gen()%2; + image cropped = crop_image(orig, pleft, ptop, swidth, sheight); + + float dx = ((float)pleft/w)/sx; + float dy = ((float)ptop /h)/sy; + + image sized = resize_image(cropped, w, h); + if(flip) flip_image(sized); + d.X.vals[0] = sized.data; + + fill_truth_swag(random_path, d.y.vals[0], classes, flip, dx, dy, 1./sx, 1./sy); + + free_image(orig); + free_image(cropped); + + return d; +} + +void blend_truth(float *new_truth, int boxes, int truth_size, float *old_truth) +{ + int count_new_truth = 0; + int t; + for (t = 0; t < boxes; ++t) { + float x = new_truth[t*truth_size]; + if (!x) break; + count_new_truth++; + + } + for (t = count_new_truth; t < boxes; ++t) { + float *new_truth_ptr = new_truth + t*truth_size; + float *old_truth_ptr = old_truth + (t - count_new_truth)*truth_size; + float x = old_truth_ptr[0]; + if (!x) break; + + new_truth_ptr[0] = old_truth_ptr[0]; + new_truth_ptr[1] = old_truth_ptr[1]; + new_truth_ptr[2] = old_truth_ptr[2]; + new_truth_ptr[3] = old_truth_ptr[3]; + new_truth_ptr[4] = old_truth_ptr[4]; + } + //printf("\n was %d bboxes, now %d bboxes \n", count_new_truth, t); +} + + +void blend_truth_mosaic(float *new_truth, int boxes, int truth_size, float *old_truth, int w, int h, float cut_x, float cut_y, int i_mixup, + int left_shift, int right_shift, int top_shift, int bot_shift, + int net_w, int net_h, int mosaic_bound) +{ + const float lowest_w = 1.F / net_w; + const float lowest_h = 1.F / net_h; + + int count_new_truth = 0; + int t; + for (t = 0; t < boxes; ++t) { + float x = new_truth[t*truth_size]; + if (!x) break; + count_new_truth++; + + } + int new_t = count_new_truth; + for (t = count_new_truth; t < boxes; ++t) { + float *new_truth_ptr = new_truth + new_t*truth_size; + new_truth_ptr[0] = 0; + float *old_truth_ptr = old_truth + (t - count_new_truth)*truth_size; + float x = old_truth_ptr[0]; + if (!x) break; + + float xb = old_truth_ptr[0]; + float yb = old_truth_ptr[1]; + float wb = old_truth_ptr[2]; + float hb = old_truth_ptr[3]; + + + + // shift 4 images + if (i_mixup == 0) { + xb = xb - (float)(w - cut_x - right_shift) / w; + yb = yb - (float)(h - cut_y - bot_shift) / h; + } + if (i_mixup == 1) { + xb = xb + (float)(cut_x - left_shift) / w; + yb = yb - (float)(h - cut_y - bot_shift) / h; + } + if (i_mixup == 2) { + xb = xb - (float)(w - cut_x - right_shift) / w; + yb = yb + (float)(cut_y - top_shift) / h; + } + if (i_mixup == 3) { + xb = xb + (float)(cut_x - left_shift) / w; + yb = yb + (float)(cut_y - top_shift) / h; + } + + int left = (xb - wb / 2)*w; + int right = (xb + wb / 2)*w; + int top = (yb - hb / 2)*h; + int bot = (yb + hb / 2)*h; + + if(mosaic_bound) + { + // fix out of Mosaic-bound + float left_bound = 0, right_bound = 0, top_bound = 0, bot_bound = 0; + if (i_mixup == 0) { + left_bound = 0; + right_bound = cut_x; + top_bound = 0; + bot_bound = cut_y; + } + if (i_mixup == 1) { + left_bound = cut_x; + right_bound = w; + top_bound = 0; + bot_bound = cut_y; + } + if (i_mixup == 2) { + left_bound = 0; + right_bound = cut_x; + top_bound = cut_y; + bot_bound = h; + } + if (i_mixup == 3) { + left_bound = cut_x; + right_bound = w; + top_bound = cut_y; + bot_bound = h; + } + + + if (left < left_bound) { + //printf(" i_mixup = %d, left = %d, left_bound = %f \n", i_mixup, left, left_bound); + left = left_bound; + } + if (right > right_bound) { + //printf(" i_mixup = %d, right = %d, right_bound = %f \n", i_mixup, right, right_bound); + right = right_bound; + } + if (top < top_bound) top = top_bound; + if (bot > bot_bound) bot = bot_bound; + + + xb = ((float)(right + left) / 2) / w; + wb = ((float)(right - left)) / w; + yb = ((float)(bot + top) / 2) / h; + hb = ((float)(bot - top)) / h; + } + else + { + // fix out of bound + if (left < 0) { + float diff = (float)left / w; + xb = xb - diff / 2; + wb = wb + diff; + } + + if (right > w) { + float diff = (float)(right - w) / w; + xb = xb - diff / 2; + wb = wb - diff; + } + + if (top < 0) { + float diff = (float)top / h; + yb = yb - diff / 2; + hb = hb + diff; + } + + if (bot > h) { + float diff = (float)(bot - h) / h; + yb = yb - diff / 2; + hb = hb - diff; + } + + left = (xb - wb / 2)*w; + right = (xb + wb / 2)*w; + top = (yb - hb / 2)*h; + bot = (yb + hb / 2)*h; + } + + + // leave only within the image + if(left >= 0 && right <= w && top >= 0 && bot <= h && + wb > 0 && wb < 1 && hb > 0 && hb < 1 && + xb > 0 && xb < 1 && yb > 0 && yb < 1 && + wb > lowest_w && hb > lowest_h) + { + new_truth_ptr[0] = xb; + new_truth_ptr[1] = yb; + new_truth_ptr[2] = wb; + new_truth_ptr[3] = hb; + new_truth_ptr[4] = old_truth_ptr[4]; + new_t++; + } + } + //printf("\n was %d bboxes, now %d bboxes \n", count_new_truth, t); +} + +#ifdef OPENCV + +#include "http_stream.h" + +data load_data_detection(int n, char **paths, int m, int w, int h, int c, int boxes, int truth_size, int classes, int use_flip, int use_gaussian_noise, int use_blur, int use_mixup, + float jitter, float resize, float hue, float saturation, float exposure, int mini_batch, int track, int augment_speed, int letter_box, int mosaic_bound, int contrastive, int contrastive_jit_flip, int contrastive_color, int show_imgs) +{ + const int random_index = random_gen(); + c = c ? c : 3; + + if (use_mixup == 2 || use_mixup == 4) { + printf("\n cutmix=1 - isn't supported for Detector (use cutmix=1 only for Classifier) \n"); + if (check_mistakes) getchar(); + if(use_mixup == 2) use_mixup = 0; + else use_mixup = 3; + } + if (use_mixup == 3 && letter_box) { + //printf("\n Combination: letter_box=1 & mosaic=1 - isn't supported, use only 1 of these parameters \n"); + //if (check_mistakes) getchar(); + //exit(0); + } + if (random_gen() % 2 == 0) use_mixup = 0; + int i; + + int *cut_x = NULL, *cut_y = NULL; + if (use_mixup == 3) { + cut_x = (int*)calloc(n, sizeof(int)); + cut_y = (int*)calloc(n, sizeof(int)); + const float min_offset = 0.2; // 20% + for (i = 0; i < n; ++i) { + cut_x[i] = rand_int(w*min_offset, w*(1 - min_offset)); + cut_y[i] = rand_int(h*min_offset, h*(1 - min_offset)); + } + } + + data d = {0}; + d.shallow = 0; + + d.X.rows = n; + d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); + d.X.cols = h*w*c; + + float r1 = 0, r2 = 0, r3 = 0, r4 = 0, r_scale = 0; + float resize_r1 = 0, resize_r2 = 0; + float dhue = 0, dsat = 0, dexp = 0, flip = 0, blur = 0; + int augmentation_calculated = 0, gaussian_noise = 0; + + d.y = make_matrix(n, truth_size*boxes); + int i_mixup = 0; + for (i_mixup = 0; i_mixup <= use_mixup; i_mixup++) { + if (i_mixup) augmentation_calculated = 0; // recalculate augmentation for the 2nd sequence if(track==1) + + char **random_paths; + if (track) random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed, contrastive); + else random_paths = get_random_paths_custom(paths, n, m, contrastive); + + for (i = 0; i < n; ++i) { + float *truth = (float*)xcalloc(truth_size * boxes, sizeof(float)); + const char *filename = random_paths[i]; + + int flag = (c >= 3); + mat_cv *src; + src = load_image_mat_cv(filename, flag); + if (src == NULL) { + printf("\n Error in load_data_detection() - OpenCV \n"); + fflush(stdout); + if (check_mistakes) { + getchar(); + } + continue; + } + + int oh = get_height_mat(src); + int ow = get_width_mat(src); + + int dw = (ow*jitter); + int dh = (oh*jitter); + + float resize_down = resize, resize_up = resize; + if (resize_down > 1.0) resize_down = 1 / resize_down; + int min_rdw = ow*(1 - (1 / resize_down)) / 2; // < 0 + int min_rdh = oh*(1 - (1 / resize_down)) / 2; // < 0 + + if (resize_up < 1.0) resize_up = 1 / resize_up; + int max_rdw = ow*(1 - (1 / resize_up)) / 2; // > 0 + int max_rdh = oh*(1 - (1 / resize_up)) / 2; // > 0 + //printf(" down = %f, up = %f \n", (1 - (1 / resize_down)) / 2, (1 - (1 / resize_up)) / 2); + + if (!augmentation_calculated || !track) + { + augmentation_calculated = 1; + resize_r1 = random_float(); + resize_r2 = random_float(); + + if (!contrastive || contrastive_jit_flip || i % 2 == 0) + { + r1 = random_float(); + r2 = random_float(); + r3 = random_float(); + r4 = random_float(); + + flip = use_flip ? random_gen() % 2 : 0; + } + + r_scale = random_float(); + + if (!contrastive || contrastive_color || i % 2 == 0) + { + dhue = rand_uniform_strong(-hue, hue); + dsat = rand_scale(saturation); + dexp = rand_scale(exposure); + } + + if (use_blur) { + int tmp_blur = rand_int(0, 2); // 0 - disable, 1 - blur background, 2 - blur the whole image + if (tmp_blur == 0) blur = 0; + else if (tmp_blur == 1) blur = 1; + else blur = use_blur; + } + + if (use_gaussian_noise && rand_int(0, 1) == 1) gaussian_noise = use_gaussian_noise; + else gaussian_noise = 0; + } + + int pleft = rand_precalc_random(-dw, dw, r1); + int pright = rand_precalc_random(-dw, dw, r2); + int ptop = rand_precalc_random(-dh, dh, r3); + int pbot = rand_precalc_random(-dh, dh, r4); + + if (resize < 1) { + // downsize only + pleft += rand_precalc_random(min_rdw, 0, resize_r1); + pright += rand_precalc_random(min_rdw, 0, resize_r2); + ptop += rand_precalc_random(min_rdh, 0, resize_r1); + pbot += rand_precalc_random(min_rdh, 0, resize_r2); + } + else { + pleft += rand_precalc_random(min_rdw, max_rdw, resize_r1); + pright += rand_precalc_random(min_rdw, max_rdw, resize_r2); + ptop += rand_precalc_random(min_rdh, max_rdh, resize_r1); + pbot += rand_precalc_random(min_rdh, max_rdh, resize_r2); + } + + //printf("\n pleft = %d, pright = %d, ptop = %d, pbot = %d, ow = %d, oh = %d \n", pleft, pright, ptop, pbot, ow, oh); + + //float scale = rand_precalc_random(.25, 2, r_scale); // unused currently + //printf(" letter_box = %d \n", letter_box); + + if (letter_box) + { + float img_ar = (float)ow / (float)oh; + float net_ar = (float)w / (float)h; + float result_ar = img_ar / net_ar; + //printf(" ow = %d, oh = %d, w = %d, h = %d, img_ar = %f, net_ar = %f, result_ar = %f \n", ow, oh, w, h, img_ar, net_ar, result_ar); + if (result_ar > 1) // sheight - should be increased + { + float oh_tmp = ow / net_ar; + float delta_h = (oh_tmp - oh)/2; + ptop = ptop - delta_h; + pbot = pbot - delta_h; + //printf(" result_ar = %f, oh_tmp = %f, delta_h = %d, ptop = %f, pbot = %f \n", result_ar, oh_tmp, delta_h, ptop, pbot); + } + else // swidth - should be increased + { + float ow_tmp = oh * net_ar; + float delta_w = (ow_tmp - ow)/2; + pleft = pleft - delta_w; + pright = pright - delta_w; + //printf(" result_ar = %f, ow_tmp = %f, delta_w = %d, pleft = %f, pright = %f \n", result_ar, ow_tmp, delta_w, pleft, pright); + } + + //printf("\n pleft = %d, pright = %d, ptop = %d, pbot = %d, ow = %d, oh = %d \n", pleft, pright, ptop, pbot, ow, oh); + } + + // move each 2nd image to the corner - so that most of it was visible + if (use_mixup == 3 && random_gen() % 2 == 0) { + if (flip) { + if (i_mixup == 0) pleft += pright, pright = 0, pbot += ptop, ptop = 0; + if (i_mixup == 1) pright += pleft, pleft = 0, pbot += ptop, ptop = 0; + if (i_mixup == 2) pleft += pright, pright = 0, ptop += pbot, pbot = 0; + if (i_mixup == 3) pright += pleft, pleft = 0, ptop += pbot, pbot = 0; + } + else { + if (i_mixup == 0) pright += pleft, pleft = 0, pbot += ptop, ptop = 0; + if (i_mixup == 1) pleft += pright, pright = 0, pbot += ptop, ptop = 0; + if (i_mixup == 2) pright += pleft, pleft = 0, ptop += pbot, pbot = 0; + if (i_mixup == 3) pleft += pright, pright = 0, ptop += pbot, pbot = 0; + } + } + + int swidth = ow - pleft - pright; + int sheight = oh - ptop - pbot; + + float sx = (float)swidth / ow; + float sy = (float)sheight / oh; + + float dx = ((float)pleft / ow) / sx; + float dy = ((float)ptop / oh) / sy; + + + int min_w_h = fill_truth_detection(filename, boxes, truth_size, truth, classes, flip, dx, dy, 1. / sx, 1. / sy, w, h); + //for (int z = 0; z < boxes; ++z) if(truth[z*truth_size] > 0) printf(" track_id = %f \n", truth[z*truth_size + 5]); + //printf(" truth_size = %d \n", truth_size); + + if ((min_w_h / 8) < blur && blur > 1) blur = min_w_h / 8; // disable blur if one of the objects is too small + + image ai = image_data_augmentation(src, w, h, pleft, ptop, swidth, sheight, flip, dhue, dsat, dexp, + gaussian_noise, blur, boxes, truth_size, truth); + + if (use_mixup == 0) { + d.X.vals[i] = ai.data; + memcpy(d.y.vals[i], truth, truth_size * boxes * sizeof(float)); + } + else if (use_mixup == 1) { + if (i_mixup == 0) { + d.X.vals[i] = ai.data; + memcpy(d.y.vals[i], truth, truth_size * boxes * sizeof(float)); + } + else if (i_mixup == 1) { + image old_img = make_empty_image(w, h, c); + old_img.data = d.X.vals[i]; + //show_image(ai, "new"); + //show_image(old_img, "old"); + //wait_until_press_key_cv(); + blend_images_cv(ai, 0.5, old_img, 0.5); + blend_truth(d.y.vals[i], boxes, truth_size, truth); + free_image(old_img); + d.X.vals[i] = ai.data; + } + } + else if (use_mixup == 3) { + if (i_mixup == 0) { + image tmp_img = make_image(w, h, c); + d.X.vals[i] = tmp_img.data; + } + + if (flip) { + int tmp = pleft; + pleft = pright; + pright = tmp; + } + + const int left_shift = min_val_cmp(cut_x[i], max_val_cmp(0, (-pleft*w / ow))); + const int top_shift = min_val_cmp(cut_y[i], max_val_cmp(0, (-ptop*h / oh))); + + const int right_shift = min_val_cmp((w - cut_x[i]), max_val_cmp(0, (-pright*w / ow))); + const int bot_shift = min_val_cmp(h - cut_y[i], max_val_cmp(0, (-pbot*h / oh))); + + + int k, x, y; + for (k = 0; k < c; ++k) { + for (y = 0; y < h; ++y) { + int j = y*w + k*w*h; + if (i_mixup == 0 && y < cut_y[i]) { + int j_src = (w - cut_x[i] - right_shift) + (y + h - cut_y[i] - bot_shift)*w + k*w*h; + memcpy(&d.X.vals[i][j + 0], &ai.data[j_src], cut_x[i] * sizeof(float)); + } + if (i_mixup == 1 && y < cut_y[i]) { + int j_src = left_shift + (y + h - cut_y[i] - bot_shift)*w + k*w*h; + memcpy(&d.X.vals[i][j + cut_x[i]], &ai.data[j_src], (w-cut_x[i]) * sizeof(float)); + } + if (i_mixup == 2 && y >= cut_y[i]) { + int j_src = (w - cut_x[i] - right_shift) + (top_shift + y - cut_y[i])*w + k*w*h; + memcpy(&d.X.vals[i][j + 0], &ai.data[j_src], cut_x[i] * sizeof(float)); + } + if (i_mixup == 3 && y >= cut_y[i]) { + int j_src = left_shift + (top_shift + y - cut_y[i])*w + k*w*h; + memcpy(&d.X.vals[i][j + cut_x[i]], &ai.data[j_src], (w - cut_x[i]) * sizeof(float)); + } + } + } + + blend_truth_mosaic(d.y.vals[i], boxes, truth_size, truth, w, h, cut_x[i], cut_y[i], i_mixup, left_shift, right_shift, top_shift, bot_shift, w, h, mosaic_bound); + + free_image(ai); + ai.data = d.X.vals[i]; + } + + + if (show_imgs && i_mixup == use_mixup) // delete i_mixup + { + image tmp_ai = copy_image(ai); + char buff[1000]; + //sprintf(buff, "aug_%d_%d_%s_%d", random_index, i, basecfg((char*)filename), random_gen()); + sprintf(buff, "aug_%d_%d_%d", random_index, i, random_gen()); + int t; + for (t = 0; t < boxes; ++t) { + box b = float_to_box_stride(d.y.vals[i] + t*truth_size, 1); + if (!b.x) break; + int left = (b.x - b.w / 2.)*ai.w; + int right = (b.x + b.w / 2.)*ai.w; + int top = (b.y - b.h / 2.)*ai.h; + int bot = (b.y + b.h / 2.)*ai.h; + draw_box_width(tmp_ai, left, top, right, bot, 1, 150, 100, 50); // 3 channels RGB + } + + save_image(tmp_ai, buff); + if (show_imgs == 1) { + //char buff_src[1000]; + //sprintf(buff_src, "src_%d_%d_%s_%d", random_index, i, basecfg((char*)filename), random_gen()); + //show_image_mat(src, buff_src); + show_image(tmp_ai, buff); + wait_until_press_key_cv(); + } + printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Click on window and press ESC button \n"); + free_image(tmp_ai); + } + + release_mat(&src); + free(truth); + } + if (random_paths) free(random_paths); + } + + + return d; +} +#else // OPENCV +void blend_images(image new_img, float alpha, image old_img, float beta) +{ + int data_size = new_img.w * new_img.h * new_img.c; + int i; + #pragma omp parallel for + for (i = 0; i < data_size; ++i) + new_img.data[i] = new_img.data[i] * alpha + old_img.data[i] * beta; +} + +data load_data_detection(int n, char **paths, int m, int w, int h, int c, int boxes, int truth_size, int classes, int use_flip, int gaussian_noise, int use_blur, int use_mixup, + float jitter, float resize, float hue, float saturation, float exposure, int mini_batch, int track, int augment_speed, int letter_box, int mosaic_bound, int contrastive, int contrastive_jit_flip, int contrastive_color, int show_imgs) +{ + const int random_index = random_gen(); + c = c ? c : 3; + char **random_paths; + char **mixup_random_paths = NULL; + if(track) random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed, contrastive); + else random_paths = get_random_paths_custom(paths, n, m, contrastive); + + //assert(use_mixup < 2); + if (use_mixup == 2) { + printf("\n cutmix=1 - isn't supported for Detector \n"); + exit(0); + } + if (use_mixup == 3 || use_mixup == 4) { + printf("\n mosaic=1 - compile Darknet with OpenCV for using mosaic=1 \n"); + exit(0); + } + int mixup = use_mixup ? random_gen() % 2 : 0; + //printf("\n mixup = %d \n", mixup); + if (mixup) { + if (track) mixup_random_paths = get_sequential_paths(paths, n, m, mini_batch, augment_speed, contrastive); + else mixup_random_paths = get_random_paths(paths, n, m); + } + + int i; + data d = { 0 }; + d.shallow = 0; + + d.X.rows = n; + d.X.vals = (float**)xcalloc(d.X.rows, sizeof(float*)); + d.X.cols = h*w*c; + + float r1 = 0, r2 = 0, r3 = 0, r4 = 0, r_scale; + float resize_r1 = 0, resize_r2 = 0; + float dhue = 0, dsat = 0, dexp = 0, flip = 0; + int augmentation_calculated = 0; + + d.y = make_matrix(n, truth_size * boxes); + int i_mixup = 0; + for (i_mixup = 0; i_mixup <= mixup; i_mixup++) { + if (i_mixup) augmentation_calculated = 0; + for (i = 0; i < n; ++i) { + float *truth = (float*)xcalloc(truth_size * boxes, sizeof(float)); + char *filename = (i_mixup) ? mixup_random_paths[i] : random_paths[i]; + + image orig = load_image(filename, 0, 0, c); + + int oh = orig.h; + int ow = orig.w; + + int dw = (ow*jitter); + int dh = (oh*jitter); + + float resize_down = resize, resize_up = resize; + if (resize_down > 1.0) resize_down = 1 / resize_down; + int min_rdw = ow*(1 - (1 / resize_down)) / 2; + int min_rdh = oh*(1 - (1 / resize_down)) / 2; + + if (resize_up < 1.0) resize_up = 1 / resize_up; + int max_rdw = ow*(1 - (1 / resize_up)) / 2; + int max_rdh = oh*(1 - (1 / resize_up)) / 2; + + if (!augmentation_calculated || !track) + { + augmentation_calculated = 1; + resize_r1 = random_float(); + resize_r2 = random_float(); + + if (!contrastive || contrastive_jit_flip || i % 2 == 0) + { + r1 = random_float(); + r2 = random_float(); + r3 = random_float(); + r4 = random_float(); + + flip = use_flip ? random_gen() % 2 : 0; + } + + r_scale = random_float(); + + if (!contrastive || contrastive_color || i % 2 == 0) + { + dhue = rand_uniform_strong(-hue, hue); + dsat = rand_scale(saturation); + dexp = rand_scale(exposure); + } + } + + int pleft = rand_precalc_random(-dw, dw, r1); + int pright = rand_precalc_random(-dw, dw, r2); + int ptop = rand_precalc_random(-dh, dh, r3); + int pbot = rand_precalc_random(-dh, dh, r4); + + if (resize < 1) { + // downsize only + pleft += rand_precalc_random(min_rdw, 0, resize_r1); + pright += rand_precalc_random(min_rdw, 0, resize_r2); + ptop += rand_precalc_random(min_rdh, 0, resize_r1); + pbot += rand_precalc_random(min_rdh, 0, resize_r2); + } + else { + pleft += rand_precalc_random(min_rdw, max_rdw, resize_r1); + pright += rand_precalc_random(min_rdw, max_rdw, resize_r2); + ptop += rand_precalc_random(min_rdh, max_rdh, resize_r1); + pbot += rand_precalc_random(min_rdh, max_rdh, resize_r2); + } + + if (letter_box) + { + float img_ar = (float)ow / (float)oh; + float net_ar = (float)w / (float)h; + float result_ar = img_ar / net_ar; + //printf(" ow = %d, oh = %d, w = %d, h = %d, img_ar = %f, net_ar = %f, result_ar = %f \n", ow, oh, w, h, img_ar, net_ar, result_ar); + if (result_ar > 1) // sheight - should be increased + { + float oh_tmp = ow / net_ar; + float delta_h = (oh_tmp - oh) / 2; + ptop = ptop - delta_h; + pbot = pbot - delta_h; + //printf(" result_ar = %f, oh_tmp = %f, delta_h = %d, ptop = %f, pbot = %f \n", result_ar, oh_tmp, delta_h, ptop, pbot); + } + else // swidth - should be increased + { + float ow_tmp = oh * net_ar; + float delta_w = (ow_tmp - ow) / 2; + pleft = pleft - delta_w; + pright = pright - delta_w; + //printf(" result_ar = %f, ow_tmp = %f, delta_w = %d, pleft = %f, pright = %f \n", result_ar, ow_tmp, delta_w, pleft, pright); + } + } + + int swidth = ow - pleft - pright; + int sheight = oh - ptop - pbot; + + float sx = (float)swidth / ow; + float sy = (float)sheight / oh; + + image cropped = crop_image(orig, pleft, ptop, swidth, sheight); + + float dx = ((float)pleft / ow) / sx; + float dy = ((float)ptop / oh) / sy; + + image sized = resize_image(cropped, w, h); + if (flip) flip_image(sized); + distort_image(sized, dhue, dsat, dexp); + //random_distort_image(sized, hue, saturation, exposure); + + fill_truth_detection(filename, boxes, truth_size, truth, classes, flip, dx, dy, 1. / sx, 1. / sy, w, h); + + if (i_mixup) { + image old_img = sized; + old_img.data = d.X.vals[i]; + //show_image(sized, "new"); + //show_image(old_img, "old"); + //wait_until_press_key_cv(); + blend_images(sized, 0.5, old_img, 0.5); + blend_truth(truth, boxes, truth_size, d.y.vals[i]); + free_image(old_img); + } + + d.X.vals[i] = sized.data; + memcpy(d.y.vals[i], truth, truth_size * boxes * sizeof(float)); + + if (show_imgs)// && i_mixup) + { + char buff[1000]; + sprintf(buff, "aug_%d_%d_%s_%d", random_index, i, basecfg(filename), random_gen()); + + int t; + for (t = 0; t < boxes; ++t) { + box b = float_to_box_stride(d.y.vals[i] + t*truth_size, 1); + if (!b.x) break; + int left = (b.x - b.w / 2.)*sized.w; + int right = (b.x + b.w / 2.)*sized.w; + int top = (b.y - b.h / 2.)*sized.h; + int bot = (b.y + b.h / 2.)*sized.h; + draw_box_width(sized, left, top, right, bot, 1, 150, 100, 50); // 3 channels RGB + } + + save_image(sized, buff); + if (show_imgs == 1) { + show_image(sized, buff); + wait_until_press_key_cv(); + } + printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Press Enter: \n"); + //getchar(); + } + + free_image(orig); + free_image(cropped); + free(truth); + } + } + free(random_paths); + if (mixup_random_paths) free(mixup_random_paths); + return d; +} +#endif // OPENCV + +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){ + *a.d = load_data_augment(a.paths, a.n, a.m, a.labels, a.classes, a.hierarchy, a.flip, a.min, a.max, a.w, a.h, a.angle, a.aspect, a.hue, a.saturation, a.exposure, a.mixup, a.blur, a.show_imgs, a.label_smooth_eps, a.dontuse_opencv, a.contrastive); + } else if (a.type == SUPER_DATA){ + *a.d = load_data_super(a.paths, a.n, a.m, a.w, a.h, a.scale); + } else if (a.type == WRITING_DATA){ + *a.d = load_data_writing(a.paths, a.n, a.m, a.w, a.h, a.out_w, a.out_h); + } else if (a.type == REGION_DATA){ + *a.d = load_data_region(a.n, a.paths, a.m, a.w, a.h, a.num_boxes, a.classes, a.jitter, a.hue, a.saturation, a.exposure); + } else if (a.type == DETECTION_DATA){ + *a.d = load_data_detection(a.n, a.paths, a.m, a.w, a.h, a.c, a.num_boxes, a.truth_size, a.classes, a.flip, a.gaussian_noise, a.blur, a.mixup, a.jitter, a.resize, + a.hue, a.saturation, a.exposure, a.mini_batch, a.track, a.augment_speed, a.letter_box, a.mosaic_bound, a.contrastive, a.contrastive_jit_flip, a.contrastive_color, a.show_imgs); + } else if (a.type == SWAG_DATA){ + *a.d = load_data_swag(a.paths, a.n, a.classes, a.jitter); + } else if (a.type == COMPARE_DATA){ + *a.d = load_data_compare(a.n, a.paths, a.m, a.classes, a.w, a.h); + } else if (a.type == IMAGE_DATA){ + *(a.im) = load_image(a.path, 0, 0, a.c); + *(a.resized) = resize_image(*(a.im), a.w, a.h); + }else if (a.type == LETTERBOX_DATA) { + *(a.im) = load_image(a.path, 0, 0, a.c); + *(a.resized) = letterbox_image(*(a.im), a.w, a.h); + } else if (a.type == TAG_DATA){ + *a.d = load_data_tag(a.paths, a.n, a.m, a.classes, a.flip, a.min, a.max, a.w, a.h, a.angle, a.aspect, a.hue, a.saturation, a.exposure); + } + free(ptr); + return 0; +} + +pthread_t load_data_in_thread(load_args args) +{ + pthread_t thread; + struct load_args* ptr = (load_args*)xcalloc(1, sizeof(struct load_args)); + *ptr = args; + if(pthread_create(&thread, 0, load_thread, ptr)) error("Thread creation failed"); + return thread; +} + +static const int thread_wait_ms = 5; +static volatile int flag_exit; +static volatile int * run_load_data = NULL; +static load_args * args_swap = NULL; +static pthread_t* threads = NULL; + +pthread_mutex_t mtx_load_data = PTHREAD_MUTEX_INITIALIZER; + +void *run_thread_loop(void *ptr) +{ + const int i = *(int *)ptr; + + while (!custom_atomic_load_int(&flag_exit)) { + while (!custom_atomic_load_int(&run_load_data[i])) { + if (custom_atomic_load_int(&flag_exit)) { + free(ptr); + return 0; + } + this_thread_sleep_for(thread_wait_ms); + } + + pthread_mutex_lock(&mtx_load_data); + load_args *args_local = (load_args *)xcalloc(1, sizeof(load_args)); + *args_local = args_swap[i]; + pthread_mutex_unlock(&mtx_load_data); + + load_thread(args_local); + + custom_atomic_store_int(&run_load_data[i], 0); + } + free(ptr); + return 0; +} + +void *load_threads(void *ptr) +{ + //srand(time(0)); + int i; + load_args args = *(load_args *)ptr; + if (args.threads == 0) args.threads = 1; + data *out = args.d; + int total = args.n; + free(ptr); + data* buffers = (data*)xcalloc(args.threads, sizeof(data)); + if (!threads) { + threads = (pthread_t*)xcalloc(args.threads, sizeof(pthread_t)); + run_load_data = (volatile int *)xcalloc(args.threads, sizeof(int)); + args_swap = (load_args *)xcalloc(args.threads, sizeof(load_args)); + fprintf(stderr, " Create %d permanent cpu-threads \n", args.threads); + + for (i = 0; i < args.threads; ++i) { + int* ptr = (int*)xcalloc(1, sizeof(int)); + *ptr = i; + if (pthread_create(&threads[i], 0, run_thread_loop, ptr)) error("Thread creation failed"); + } + } + + for (i = 0; i < args.threads; ++i) { + args.d = buffers + i; + args.n = (i + 1) * total / args.threads - i * total / args.threads; + + pthread_mutex_lock(&mtx_load_data); + args_swap[i] = args; + pthread_mutex_unlock(&mtx_load_data); + + custom_atomic_store_int(&run_load_data[i], 1); // run thread + } + for (i = 0; i < args.threads; ++i) { + while (custom_atomic_load_int(&run_load_data[i])) this_thread_sleep_for(thread_wait_ms); // join + } + + /* + pthread_t* threads = (pthread_t*)xcalloc(args.threads, sizeof(pthread_t)); + for(i = 0; i < args.threads; ++i){ + args.d = buffers + i; + args.n = (i+1) * total/args.threads - i * total/args.threads; + threads[i] = load_data_in_thread(args); + } + for(i = 0; i < args.threads; ++i){ + pthread_join(threads[i], 0); + } + */ + + *out = concat_datas(buffers, args.threads); + out->shallow = 0; + for(i = 0; i < args.threads; ++i){ + buffers[i].shallow = 1; + free_data(buffers[i]); + } + free(buffers); + //free(threads); + return 0; +} + +void free_load_threads(void *ptr) +{ + load_args args = *(load_args *)ptr; + if (args.threads == 0) args.threads = 1; + int i; + if (threads) { + custom_atomic_store_int(&flag_exit, 1); + for (i = 0; i < args.threads; ++i) { + pthread_join(threads[i], 0); + } + free((void*)run_load_data); + free(args_swap); + free(threads); + threads = NULL; + custom_atomic_store_int(&flag_exit, 0); + } +} + +pthread_t load_data(load_args args) +{ + pthread_t thread; + struct load_args* ptr = (load_args*)xcalloc(1, sizeof(struct load_args)); + *ptr = args; + if(pthread_create(&thread, 0, load_threads, ptr)) error("Thread creation failed"); + return thread; +} + +data load_data_writing(char **paths, int n, int m, int w, int h, int out_w, int out_h) +{ + if(m) paths = get_random_paths(paths, n, m); + char **replace_paths = find_replace_paths(paths, n, ".png", "-label.png"); + data d = {0}; + d.shallow = 0; + d.X = load_image_paths(paths, n, w, h); + d.y = load_image_paths_gray(replace_paths, n, out_w, out_h); + if(m) free(paths); + int i; + for(i = 0; i < n; ++i) free(replace_paths[i]); + free(replace_paths); + return d; +} + +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, 0, 0); + if(m) free(paths); + return d; +} + +/* + data load_data_study(char **paths, int n, int m, char **labels, int k, int min, int max, int size, float angle, float aspect, float hue, float saturation, float exposure) + { + data d = {0}; + d.indexes = calloc(n, sizeof(int)); + if(m) paths = get_random_paths_indexes(paths, n, m, d.indexes); + d.shallow = 0; + d.X = load_image_augment_paths(paths, n, flip, min, max, size, angle, aspect, hue, saturation, exposure); + d.y = load_labels_paths(paths, n, labels, k); + if(m) free(paths); + return d; + } + */ + +data load_data_super(char **paths, int n, int m, int w, int h, int scale) +{ + if(m) paths = get_random_paths(paths, n, m); + data d = {0}; + d.shallow = 0; + + int i; + d.X.rows = n; + d.X.vals = (float**)xcalloc(n, sizeof(float*)); + d.X.cols = w*h*3; + + d.y.rows = n; + d.y.vals = (float**)xcalloc(n, sizeof(float*)); + d.y.cols = w*scale * h*scale * 3; + + for(i = 0; i < n; ++i){ + image im = load_image_color(paths[i], 0, 0); + image crop = random_crop_image(im, w*scale, h*scale); + int flip = random_gen()%2; + if (flip) flip_image(crop); + image resize = resize_image(crop, w, h); + d.X.vals[i] = resize.data; + d.y.vals[i] = crop.data; + free_image(im); + } + + if(m) free(paths); + return d; +} + +data load_data_augment(char **paths, int n, int m, char **labels, int k, tree *hierarchy, int use_flip, int min, int max, int w, int h, float angle, + float aspect, float hue, float saturation, float exposure, int use_mixup, int use_blur, int show_imgs, float label_smooth_eps, int dontuse_opencv, int contrastive) +{ + char **paths_stored = paths; + if(m) paths = get_random_paths(paths, n, m); + data d = {0}; + d.shallow = 0; + d.X = load_image_augment_paths(paths, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv, contrastive); + d.y = load_labels_paths(paths, n, labels, k, hierarchy, label_smooth_eps, contrastive); + + if (use_mixup && rand_int(0, 1)) { + char **paths_mix = get_random_paths(paths_stored, n, m); + data d2 = { 0 }; + d2.shallow = 0; + d2.X = load_image_augment_paths(paths_mix, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv, contrastive); + d2.y = load_labels_paths(paths_mix, n, labels, k, hierarchy, label_smooth_eps, contrastive); + free(paths_mix); + + data d3 = { 0 }; + d3.shallow = 0; + data d4 = { 0 }; + d4.shallow = 0; + if (use_mixup >= 3) { + char **paths_mix3 = get_random_paths(paths_stored, n, m); + d3.X = load_image_augment_paths(paths_mix3, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv, contrastive); + d3.y = load_labels_paths(paths_mix3, n, labels, k, hierarchy, label_smooth_eps, contrastive); + free(paths_mix3); + + char **paths_mix4 = get_random_paths(paths_stored, n, m); + d4.X = load_image_augment_paths(paths_mix4, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, dontuse_opencv, contrastive); + d4.y = load_labels_paths(paths_mix4, n, labels, k, hierarchy, label_smooth_eps, contrastive); + free(paths_mix4); + } + + + // mix + int i, j; + for (i = 0; i < d2.X.rows; ++i) { + + int mixup = use_mixup; + if (use_mixup == 4) mixup = rand_int(2, 3); // alternate CutMix and Mosaic + + // MixUp ----------------------------------- + if (mixup == 1) { + // mix images + for (j = 0; j < d2.X.cols; ++j) { + d.X.vals[i][j] = (d.X.vals[i][j] + d2.X.vals[i][j]) / 2.0f; + } + + // mix labels + for (j = 0; j < d2.y.cols; ++j) { + d.y.vals[i][j] = (d.y.vals[i][j] + d2.y.vals[i][j]) / 2.0f; + } + } + // CutMix ----------------------------------- + else if (mixup == 2) { + const float min = 0.3; // 0.3*0.3 = 9% + const float max = 0.8; // 0.8*0.8 = 64% + const int cut_w = rand_int(w*min, w*max); + const int cut_h = rand_int(h*min, h*max); + const int cut_x = rand_int(0, w - cut_w - 1); + const int cut_y = rand_int(0, h - cut_h - 1); + const int left = cut_x; + const int right = cut_x + cut_w; + const int top = cut_y; + const int bot = cut_y + cut_h; + + assert(cut_x >= 0 && cut_x <= w); + assert(cut_y >= 0 && cut_y <= h); + assert(cut_w >= 0 && cut_w <= w); + assert(cut_h >= 0 && cut_h <= h); + + assert(right >= 0 && right <= w); + assert(bot >= 0 && bot <= h); + + assert(top <= bot); + assert(left <= right); + + const float alpha = (float)(cut_w*cut_h) / (float)(w*h); + const float beta = 1 - alpha; + + int c, x, y; + for (c = 0; c < 3; ++c) { + for (y = top; y < bot; ++y) { + for (x = left; x < right; ++x) { + int j = x + y*w + c*w*h; + d.X.vals[i][j] = d2.X.vals[i][j]; + } + } + } + + //printf("\n alpha = %f, beta = %f \n", alpha, beta); + // mix labels + for (j = 0; j < d.y.cols; ++j) { + d.y.vals[i][j] = d.y.vals[i][j] * beta + d2.y.vals[i][j] * alpha; + } + } + // Mosaic ----------------------------------- + else if (mixup == 3) + { + const float min_offset = 0.2; // 20% + const int cut_x = rand_int(w*min_offset, w*(1 - min_offset)); + const int cut_y = rand_int(h*min_offset, h*(1 - min_offset)); + + float s1 = (float)(cut_x * cut_y) / (w*h); + float s2 = (float)((w - cut_x) * cut_y) / (w*h); + float s3 = (float)(cut_x * (h - cut_y)) / (w*h); + float s4 = (float)((w - cut_x) * (h - cut_y)) / (w*h); + + int c, x, y; + for (c = 0; c < 3; ++c) { + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + int j = x + y*w + c*w*h; + if (x < cut_x && y < cut_y) d.X.vals[i][j] = d.X.vals[i][j]; + if (x >= cut_x && y < cut_y) d.X.vals[i][j] = d2.X.vals[i][j]; + if (x < cut_x && y >= cut_y) d.X.vals[i][j] = d3.X.vals[i][j]; + if (x >= cut_x && y >= cut_y) d.X.vals[i][j] = d4.X.vals[i][j]; + } + } + } + + for (j = 0; j < d.y.cols; ++j) { + const float max_s = 1;// max_val_cmp(s1, max_val_cmp(s2, max_val_cmp(s3, s4))); + + d.y.vals[i][j] = d.y.vals[i][j] * s1 / max_s + d2.y.vals[i][j] * s2 / max_s + d3.y.vals[i][j] * s3 / max_s + d4.y.vals[i][j] * s4 / max_s; + } + } + } + + free_data(d2); + + if (use_mixup >= 3) { + free_data(d3); + free_data(d4); + } + } + +#ifdef OPENCV + if (use_blur) { + int i; + for (i = 0; i < d.X.rows; ++i) { + if (random_gen() % 4 == 0) { + image im = make_empty_image(w, h, 3); + im.data = d.X.vals[i]; + int ksize = use_blur; + if (use_blur == 1) ksize = 15; + image blurred = blur_image(im, ksize); + free_image(im); + d.X.vals[i] = blurred.data; + //if (i == 0) { + // show_image(im, "Not blurred"); + // show_image(blurred, "blurred"); + // wait_until_press_key_cv(); + //} + } + } + } +#endif // OPENCV + + if (show_imgs) { + int i, j; + for (i = 0; i < d.X.rows; ++i) { + image im = make_empty_image(w, h, 3); + im.data = d.X.vals[i]; + char buff[1000]; + sprintf(buff, "aug_%d_%s_%d", i, basecfg((char*)paths[i]), random_gen()); + save_image(im, buff); + + char buff_string[1000]; + sprintf(buff_string, "\n Classes: "); + for (j = 0; j < d.y.cols; ++j) { + if (d.y.vals[i][j] > 0) { + char buff_tmp[100]; + sprintf(buff_tmp, " %d (%f), ", j, d.y.vals[i][j]); + strcat(buff_string, buff_tmp); + } + } + printf("%s \n", buff_string); + + if (show_imgs == 1) { + show_image(im, buff); + wait_until_press_key_cv(); + } + } + printf("\nYou use flag -show_imgs, so will be saved aug_...jpg images. Click on window and press ESC button \n"); + } + + if (m) free(paths); + + return d; +} + +data load_data_tag(char **paths, int n, int m, int k, int use_flip, int min, int max, int w, int h, float angle, float aspect, float hue, float saturation, float exposure) +{ + if(m) paths = get_random_paths(paths, n, m); + data d = {0}; + d.w = w; + d.h = h; + d.shallow = 0; + d.X = load_image_augment_paths(paths, n, use_flip, min, max, w, h, angle, aspect, hue, saturation, exposure, 0, 0); + d.y = load_tags_paths(paths, n, k); + if(m) free(paths); + return d; +} + +matrix concat_matrix(matrix m1, matrix m2) +{ + int i, count = 0; + matrix m; + m.cols = m1.cols; + m.rows = m1.rows+m2.rows; + m.vals = (float**)xcalloc(m1.rows + m2.rows, sizeof(float*)); + for(i = 0; i < m1.rows; ++i){ + m.vals[count++] = m1.vals[i]; + } + for(i = 0; i < m2.rows; ++i){ + m.vals[count++] = m2.vals[i]; + } + return m; +} + +data concat_data(data d1, data d2) +{ + data d = {0}; + d.shallow = 1; + d.X = concat_matrix(d1.X, d2.X); + d.y = concat_matrix(d1.y, d2.y); + return d; +} + +data concat_datas(data *d, int n) +{ + int i; + data out = {0}; + for(i = 0; i < n; ++i){ + data newdata = concat_data(d[i], out); + free_data(out); + out = newdata; + } + return out; +} + +data load_categorical_data_csv(char *filename, int target, int k) +{ + data d = {0}; + d.shallow = 0; + matrix X = csv_to_matrix(filename); + float *truth_1d = pop_column(&X, target); + float **truth = one_hot_encode(truth_1d, X.rows, k); + matrix y; + y.rows = X.rows; + y.cols = k; + y.vals = truth; + d.X = X; + d.y = y; + free(truth_1d); + return d; +} + +data load_cifar10_data(char *filename) +{ + data d = {0}; + d.shallow = 0; + long i,j; + matrix X = make_matrix(10000, 3072); + matrix y = make_matrix(10000, 10); + d.X = X; + d.y = y; + + FILE *fp = fopen(filename, "rb"); + if(!fp) file_error(filename); + for(i = 0; i < 10000; ++i){ + unsigned char bytes[3073]; + fread(bytes, 1, 3073, fp); + int class_id = bytes[0]; + y.vals[i][class_id] = 1; + for(j = 0; j < X.cols; ++j){ + X.vals[i][j] = (double)bytes[j+1]; + } + } + //translate_data_rows(d, -128); + scale_data_rows(d, 1./255); + //normalize_data_rows(d); + fclose(fp); + return d; +} + +void get_random_batch(data d, int n, float *X, float *y) +{ + int j; + for(j = 0; j < n; ++j){ + int index = random_gen()%d.X.rows; + memcpy(X+j*d.X.cols, d.X.vals[index], d.X.cols*sizeof(float)); + memcpy(y+j*d.y.cols, d.y.vals[index], d.y.cols*sizeof(float)); + } +} + +void get_next_batch(data d, int n, int offset, float *X, float *y) +{ + int j; + for(j = 0; j < n; ++j){ + int index = offset + j; + memcpy(X+j*d.X.cols, d.X.vals[index], d.X.cols*sizeof(float)); + memcpy(y+j*d.y.cols, d.y.vals[index], d.y.cols*sizeof(float)); + } +} + +void smooth_data(data d) +{ + int i, j; + float scale = 1. / d.y.cols; + float eps = .1; + for(i = 0; i < d.y.rows; ++i){ + for(j = 0; j < d.y.cols; ++j){ + d.y.vals[i][j] = eps * scale + (1-eps) * d.y.vals[i][j]; + } + } +} + +data load_all_cifar10() +{ + data d = {0}; + d.shallow = 0; + int i,j,b; + matrix X = make_matrix(50000, 3072); + matrix y = make_matrix(50000, 10); + d.X = X; + d.y = y; + + + for(b = 0; b < 5; ++b){ + char buff[256]; + sprintf(buff, "data/cifar/cifar-10-batches-bin/data_batch_%d.bin", b+1); + FILE *fp = fopen(buff, "rb"); + if(!fp) file_error(buff); + for(i = 0; i < 10000; ++i){ + unsigned char bytes[3073]; + fread(bytes, 1, 3073, fp); + int class_id = bytes[0]; + y.vals[i+b*10000][class_id] = 1; + for(j = 0; j < X.cols; ++j){ + X.vals[i+b*10000][j] = (double)bytes[j+1]; + } + } + fclose(fp); + } + //normalize_data_rows(d); + //translate_data_rows(d, -128); + scale_data_rows(d, 1./255); + smooth_data(d); + return d; +} + +data load_go(char *filename) +{ + FILE *fp = fopen(filename, "rb"); + matrix X = make_matrix(3363059, 361); + matrix y = make_matrix(3363059, 361); + int row, col; + + if(!fp) file_error(filename); + char *label; + int count = 0; + while((label = fgetl(fp))){ + int i; + if(count == X.rows){ + X = resize_matrix(X, count*2); + y = resize_matrix(y, count*2); + } + sscanf(label, "%d %d", &row, &col); + char *board = fgetl(fp); + + int index = row*19 + col; + y.vals[count][index] = 1; + + for(i = 0; i < 19*19; ++i){ + float val = 0; + if(board[i] == '1') val = 1; + else if(board[i] == '2') val = -1; + X.vals[count][i] = val; + } + ++count; + free(label); + free(board); + } + X = resize_matrix(X, count); + y = resize_matrix(y, count); + + data d = {0}; + d.shallow = 0; + d.X = X; + d.y = y; + + + fclose(fp); + + return d; +} + + +void randomize_data(data d) +{ + int i; + for(i = d.X.rows-1; i > 0; --i){ + int index = random_gen()%i; + float *swap = d.X.vals[index]; + 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; + } +} + +void scale_data_rows(data d, float s) +{ + int i; + for(i = 0; i < d.X.rows; ++i){ + scale_array(d.X.vals[i], d.X.cols, s); + } +} + +void translate_data_rows(data d, float s) +{ + int i; + for(i = 0; i < d.X.rows; ++i){ + translate_array(d.X.vals[i], d.X.cols, s); + } +} + +void normalize_data_rows(data d) +{ + int i; + for(i = 0; i < d.X.rows; ++i){ + normalize_array(d.X.vals[i], d.X.cols); + } +} + +data get_data_part(data d, int part, int total) +{ + data p = {0}; + p.shallow = 1; + p.X.rows = d.X.rows * (part + 1) / total - d.X.rows * part / total; + p.y.rows = d.y.rows * (part + 1) / total - d.y.rows * part / total; + p.X.cols = d.X.cols; + p.y.cols = d.y.cols; + p.X.vals = d.X.vals + d.X.rows * part / total; + p.y.vals = d.y.vals + d.y.rows * part / total; + return p; +} + +data get_random_data(data d, int num) +{ + data r = {0}; + r.shallow = 1; + + r.X.rows = num; + r.y.rows = num; + + r.X.cols = d.X.cols; + r.y.cols = d.y.cols; + + r.X.vals = (float**)xcalloc(num, sizeof(float*)); + r.y.vals = (float**)xcalloc(num, sizeof(float*)); + + int i; + for(i = 0; i < num; ++i){ + int index = random_gen()%d.X.rows; + r.X.vals[i] = d.X.vals[index]; + r.y.vals[i] = d.y.vals[index]; + } + return r; +} + +data *split_data(data d, int part, int total) +{ + data* split = (data*)xcalloc(2, sizeof(data)); + int i; + int start = part*d.X.rows/total; + int end = (part+1)*d.X.rows/total; + data train ={0}; + data test ={0}; + train.shallow = test.shallow = 1; + + test.X.rows = test.y.rows = end-start; + train.X.rows = train.y.rows = d.X.rows - (end-start); + train.X.cols = test.X.cols = d.X.cols; + train.y.cols = test.y.cols = d.y.cols; + + train.X.vals = (float**)xcalloc(train.X.rows, sizeof(float*)); + test.X.vals = (float**)xcalloc(test.X.rows, sizeof(float*)); + train.y.vals = (float**)xcalloc(train.y.rows, sizeof(float*)); + test.y.vals = (float**)xcalloc(test.y.rows, sizeof(float*)); + + for(i = 0; i < start; ++i){ + train.X.vals[i] = d.X.vals[i]; + train.y.vals[i] = d.y.vals[i]; + } + for(i = start; i < end; ++i){ + test.X.vals[i-start] = d.X.vals[i]; + test.y.vals[i-start] = d.y.vals[i]; + } + for(i = end; i < d.X.rows; ++i){ + train.X.vals[i-(end-start)] = d.X.vals[i]; + train.y.vals[i-(end-start)] = d.y.vals[i]; + } + split[0] = train; + split[1] = test; + return split; +} -- Gitblit v1.8.0