美文网首页
Darknet源码读不懂(一)——image结构体

Darknet源码读不懂(一)——image结构体

作者: NoneLand | 来源:发表于2017-04-09 18:09 被阅读2959次

darknet内部的image结构体定义

image结构体定义在image.h,定义如下:

typedef struct {
    int h;
    int w;
    int c;
    float *data;
} image;

从以上定义中可以看出,darknet内部使用一维数组存放图像像素数据。

OpenCV IplImage结构体的转化

darknet内部有两种处理图像的方式,一是使用OpenCV,二是使用stb。在使用OpenCV加载图像之后,需要将IplImage格式转化为image结构体,而正是这种转化提供了image内部结构信息。定义在image.c中,

image ipl_to_image(IplImage* src)
{
    unsigned char *data = (unsigned char *)src->imageData;
    int h = src->height;
    int w = src->width;
    int c = src->nChannels;
    int step = src->widthStep;  // Size of aligned image row in bytes.
    image out = make_image(w, h, c);
    int i, j, k, count=0;;

    for(k= 0; k < c; ++k){
        for(i = 0; i < h; ++i){
            for(j = 0; j < w; ++j){
                out.data[count++] = data[i*step + j*c + k]/255.; // Normalize
            }
        }
    }
    return out;
}

从代码中可以看出,image结构中的像素数据是按通道组合在一起的,且进行了均一化处理。可以使用以下Python代码验证:

for k in range(3):
    for i in range(4):
        for j in range(5):
            print i*15+j*3+k

其他

image **load_alphabet()
{
    int i, j;
    const int nsize = 8;
    image **alphabets = calloc(nsize, sizeof(image));
    for(j = 0; j < nsize; ++j){
        alphabets[j] = calloc(128, sizeof(image));
        for(i = 32; i < 127; ++i){
            char buff[256];
            sprintf(buff, "data/labels/%d_%d.png", i, j);
            alphabets[j][i] = load_image_color(buff, 0, 0); 
        // set w, h to 0 to supress image resizement.
        }
    }
    return alphabets;
}

此函数加载位于/data/labels下的图像作为字符集。

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)){  //图像不为空且图像宽高不等于预定义宽高时,进行resize操作
        image resized = resize_image(out, w, h);
        free_image(out);
        out = resized;
    }
    return out;
}

这是加载图像的函数,从中可以看出,在加载时已经将图像resize为网络需要的图像尺寸了。

image resize_image(image im, int w, int h)
{
    image resized = make_image(w, h, im.c);   
    image part = make_image(w, im.h, im.c);
    int r, c, k;
    float w_scale = (float)(im.w - 1) / (w - 1);
    float h_scale = (float)(im.h - 1) / (h - 1);
    for(k = 0; k < im.c; ++k){
        for(r = 0; r < im.h; ++r){
            for(c = 0; c < w; ++c){
                float val = 0;
                if(c == w-1 || im.w == 1){
                    val = get_pixel(im, im.w-1, r, k);
                } else {
                    float sx = c*w_scale;
                    int ix = (int) sx;
                    float dx = sx - ix;
                    val = (1 - dx) * get_pixel(im, ix, r, k) + dx * get_pixel(im, ix+1, r, k);
                }
                set_pixel(part, c, r, k, val);
            }
        }
    }
    for(k = 0; k < im.c; ++k){
        for(r = 0; r < h; ++r){
            float sy = r*h_scale;
            int iy = (int) sy;
            float dy = sy - iy;
            for(c = 0; c < w; ++c){
                float val = (1-dy) * get_pixel(part, c, iy, k);
                set_pixel(resized, c, r, k, val);
            }
            if(r == h-1 || im.h == 1) continue;
            for(c = 0; c < w; ++c){
                float val = dy * get_pixel(part, c, iy+1, k);
                add_pixel(resized, c, r, k, val);
            }
        }
    }

    free_image(part);
    return resized;
}
float get_pixel(image m, int x, int y, int c)
{
    assert(x < m.w && y < m.h && c < m.c);
    return m.data[c*m.h*m.w + y*m.w + x];
}

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;
}

从以上源码可以看出,作者自己写了resize函数,先进行横向的缩放,再进行纵向的缩放。

相关文章

  • Darknet源码读不懂(一)——image结构体

    darknet内部的image结构体定义 image结构体定义在image.h,定义如下: 从以上定义中可以看出,...

  • 02--对象本质04--类的结构

    [TOC] 怎么读到cache_t属性image 四个属性 在源码中关于类objc_class的结构体代码, 总共...

  • AVFrame结构

    结构体AVFrame的定义的结构体源码(位于libavcodec/avcodec.h)中;AVFrame结构体一般...

  • swift-结构体异变方法

    结构体值类型使用 测试结构体与类的内存分配 做一个简单测试实例,对比结构体 与 类,主要参考耗时 image.pn...

  • PostgreSQL:在pg内核中使用结构体链表

    在PG的源码中,有个很重要的结构体,就是List,让我们先看一下这个结构体的源码 ``` typedef stru...

  • 补充

    获取当前的ivars 源码结构体中ivars

  • block源码分析一

    源码结构分析部分 1.block实际的结构体部分(本体) 首先impl和Desc也是两个结构体,而__main_b...

  • Non Fragile ivars

    ivar结构体 从runtime的源码中,可以看到类结构体中有成员变量的列表.(class_ro_t也是属于类结构...

  • 校验对象是否是结构体

    校验对象是否是结构体 目的 反射实现–>校验对象是否是结构体来自gin源码// ValidateStruct re...

  • isa的作用与内部结构(下)

    一、回顾 oc对象的本质的结构体,结构体内部存放了一个isa指针 二、源码分析 查看runtime源码发现 内部的...

网友评论

      本文标题:Darknet源码读不懂(一)——image结构体

      本文链接:https://www.haomeiwen.com/subject/prndattx.html