darknet源码分析-load_image_augment_paths

https://github.com/pjreddie/darknet
darknet/src/data.c

1、加载数据函数:对原始数据集做预处理,便于输入网络

matrix load_image_augment_paths(char **paths, int n, int min, int max, int size, float angle, float aspect, float hue, float saturation, float exposure, int center)
{
    int i;
    matrix X;
    X.rows = n; //行
    X.vals = calloc(X.rows, sizeof(float*)); //分配空间,大小为 n*siezof(float*)
    X.cols = 0;	//列

    for(i = 0; i < n; ++i){
    //2、
        image im = load_image_color(paths[i], 0, 0); //paths[i]:文件名
        image crop;
        if(center){
            crop = center_crop_image(im, size, size);  //center中心点座标?
        } else {
            crop = random_augment_image(im, angle, aspect, min, max, size, size);
        }
        //裁剪、色调、饱和度、曝光来调整图像@nxt送入网络之间对数据集做的预处理
        int flip = rand()%2;
        if (flip) flip_image(crop);
        random_distort_image(crop, hue, saturation, exposure);
        /*
        show_image(im, "orig");
        show_image(crop, "crop");
        cvWaitKey(0);
        */
        //grayscale_image_3c(crop);
        free_image(im);
        // crop是什么图像,为什么要将图像转存到到矩阵X中?
        X.vals[i] = crop.data;
        X.cols = crop.h*crop.w*crop.c;
    }
    return X;
}

2、加载图像函数: load_image_color
现在的darknet找不到该函数,参考上面

image load_image_color(char *filename, int w, int h)
{
    return load_image(filename, w, h, 3);
}
 
image load_image(char *filename, int w, int h, int c)
{
#ifdef OPENCV
    image out = load_image_cv(filename, c); //文件名,通道数
#else
    image out = load_image_stb(filename, c);
#endif
 
    if((h && w) && (h != out.h || w != out.w)){
		//按网络要求调整到(w,h)大小,前提是输入的w,h不要是0
        image resized = resize_image(out, w, h);
        free_image(out);
        out = resized;
    }
    return out;
}
    
  //读图像接口函数 
image load_image_cv(char *filename, int channels)
{
    IplImage* src = 0; 
    int flag = -1;
    if (channels == 0) flag = -1;
    else if (channels == 1) flag = 0;  //grayscale image
    else if (channels == 3) flag = 1;  //3-channel color image
    else {
        fprintf(stderr, "OpenCV can't force load with %d channels\n", channels);
    }
	//opencv api load image
    if( (src = cvLoadImage(filename, flag)) == 0 )
    {
        fprintf(stderr, "Cannot load image \"%s\"\n", filename);
        char buff[256];
        sprintf(buff, "echo %s >> bad.list", filename);
        system(buff);
        return make_image(10,10,3);
        //exit(0);
    }
	//将读取到的IplImage容器中的图片装入image结构中
    image out = ipl_to_image(src);
    cvReleaseImage(&src);
    rgbgr_image(out); //convert BGR to RGB
    
    return out;
  }

darknet/src/image.c

//center_crop_image函数作用是什么?
image center_crop_image(image im, int w, int h)
{
    int m = (im.w < im.h) ? im.w : im.h;   //得到w,h较小的值
    image c = crop_image(im, (im.w - m) / 2, (im.h - m)/2, m, m);
    image r = resize_image(c, w, h);
    free_image(c);
    return r;
}

image crop_image(image im, int dx, int dy, int w, int h)
{
    image cropped = make_image(w, h, im.c);
    int i, j, k;
    for(k = 0; k < im.c; ++k){
        for(j = 0; j < h; ++j){
            for(i = 0; i < w; ++i){
                int r = j + dy;
                int c = i + dx;
                float val = 0;
                r = constrain_int(r, 0, im.h-1);
                c = constrain_int(c, 0, im.w-1);
                val = get_pixel(im, c, r, k);
                set_pixel(cropped, i, j, k, val);
            }
        }
    }
    return cropped;
}

image make_image(int w, int h, int c)
{
    image out = make_empty_image(w,h,c); //创建一个空白图像
    out.data = calloc(h*w*c, sizeof(float)); //给图像动态分配空间
    return out;
}

裁剪、色调、饱和度、曝光来调整图像

void random_distort_image(image im, float hue, float saturation, float exposure)
{
    float dhue = rand_uniform(-hue, hue);
    float dsat = rand_scale(saturation);
    float dexp = rand_scale(exposure);
    distort_image(im, dhue, dsat, dexp);
}
void distort_image(image im, float hue, float sat, float val)
{
    rgb_to_hsv(im);	//将图像从rgb转换为hsv
    scale_image_channel(im, 1, sat);
    scale_image_channel(im, 2, val);
    int i;
    for(i = 0; i < im.w*im.h; ++i){
        im.data[i] = im.data[i] + hue;
        if (im.data[i] > 1) im.data[i] -= 1;
        if (im.data[i] < 0) im.data[i] += 1;
    }
    hsv_to_rgb(im);
    constrain_image(im);
}
void scale_image_channel(image im, int c, float v)
{
    int i, j;
    for(j = 0; j < im.h; ++j){
        for(i = 0; i < im.w; ++i){
            float pix = get_pixel(im, i, j, c);
            pix = pix*v;	//改变点的像素值
            set_pixel(im, i, j, c, pix);
        }
    }
}
static float get_pixel(image m, int x, int y, int c)
{
//assert:计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
    assert(x < m.w && y < m.h && c < m.c);
    return m.data[c*m.h*m.w + y*m.w + x];
}

static void set_pixel(image m, int x, int y, int c, float val)
{
    if (x < 0 || y < 0 || c < 0 || x >= m.w || y >= m.h || c >= m.c) return;
    assert(x < m.w && y < m.h && c < m.c);
    m.data[c*m.h*m.w + y*m.w + x] = val;
}
void constrain_image(image im)
{
    int i;
    //im.data[i]表示什么数据,为什么要将其二值化?
    for(i = 0; i < im.w*im.h*im.c; ++i){
        if(im.data[i] < 0) im.data[i] = 0;
        if(im.data[i] > 1) im.data[i] = 1;
    }
}

darknet/include/darknet.h

typedef struct {
    int w;  //weight
    int h;  //height
    int c;  //channel
    float *data;
} image;
typedef struct matrix{
    int rows, cols;
    float **vals;
} matrix;

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章