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;

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