深度学习【59】物体检测:yoloV2笔记之预测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linmingan/article/details/82252012

yoloV2的预测代码在examples/detector.c中的test_detector函数中。具体步骤为:

1、模型、参数、待检测图片等信息的加载
2、图片resize,这里使用的是letterbox_image函数。与opencv的resize函数不同的是letterbox不会使物体变形。这边是移植到手机端的一个坑。
3、前向传播,获取网络输出,大小为13*13*425(假设,输入为416*41680类,5个候选框)
4、根据网络预测的候选框与anchor的xy偏移量和w,h比值,求出候选框的bbox。get_region_boxes函数。
5、利用非极大值抑制去除重叠的候选框

letterbox_image

image letterbox_image(image im, int w, int h)//w,h:要resize的大小
{
    int new_w = im.w;
    int new_h = im.h;
    //计算保持宽高比的新宽高
    if (((float)w/im.w) < ((float)h/im.h)) {
        new_w = w;
        new_h = (im.h * w)/im.w;
    } else {
        new_h = h;
        new_w = (im.w * h)/im.h;
    }
    //直接resize
    image resized = resize_image(im, new_w, new_h);
    //创建一个大小为w*h的空图片
    image boxed = make_image(w, h, im.c);
    //将空图片用【0.5,0.5,0.5】填充
    fill_image(boxed, .5);
    //int i;
    //for(i = 0; i < boxed.w*boxed.h*boxed.c; ++i) boxed.data[i] = 0;
    //将resized图片填充到空图片中。
    embed_image(resized, boxed, (w-new_w)/2, (h-new_h)/2); 
    free_image(resized);
    return boxed;
}

get_region_boxes

代码在src/region_layer.c里面的get_region_boxes函数里,注意不是get_region_box。大概流程:


1、对每个候选框利用get_region_boxe函数计算bbox,这个bbox是归一化的。
2、求出类别概率最大的类别,然后乘以是否是物体的概率。
3、将计算出来的归一化bbox的尺度变换成与原始图片的尺度一样。

代码:

void get_region_boxes(layer l, int w, int h, int netw, int neth, float thresh, float **probs, box *boxes, int only_objectness, int *map, float tree_thresh, int relative)
{
    int i,j,n,z;
    float *predictions = l.output;
    if (l.batch == 2) {
        float *flip = l.output + l.outputs;
        for (j = 0; j < l.h; ++j) {
            for (i = 0; i < l.w/2; ++i) {
                for (n = 0; n < l.n; ++n) {
                    for(z = 0; z < l.classes + 5; ++z){
                        int i1 = z*l.w*l.h*l.n + n*l.w*l.h + j*l.w + i;
                        int i2 = z*l.w*l.h*l.n + n*l.w*l.h + j*l.w + (l.w - i - 1);
                        float swap = flip[i1];
                        flip[i1] = flip[i2];
                        flip[i2] = swap;
                        if(z == 0){
                            flip[i1] = -flip[i1];
                            flip[i2] = -flip[i2];
                        }
                    }
                }
            }
        }
        for(i = 0; i < l.outputs; ++i){
            l.output[i] = (l.output[i] + flip[i])/2.;
        }
    }
    for (i = 0; i < l.w*l.h; ++i){
        int row = i / l.w;
        int col = i % l.w;
        for(n = 0; n < l.n; ++n){
            int index = n*l.w*l.h + i;
            for(j = 0; j < l.classes; ++j){
                probs[index][j] = 0;
            }
            int obj_index = entry_index(l, 0, n*l.w*l.h + i, 4);
            int box_index = entry_index(l, 0, n*l.w*l.h + i, 0);
            float scale = predictions[obj_index];//是否是物体的概率
            boxes[index] = get_region_box(predictions, l.biases, n, box_index, col, row, l.w, l.h, l.w*l.h);//计算出归一化的bbox

            int class_index = entry_index(l, 0, n*l.w*l.h + i, 5);
            if(l.softmax_tree){//不考虑这个

                hierarchy_predictions(predictions + class_index, l.classes, l.softmax_tree, 0, l.w*l.h);
                if(map){
                    for(j = 0; j < 200; ++j){
                        int class_index = entry_index(l, 0, n*l.w*l.h + i, 5 + map[j]);
                        float prob = scale*predictions[class_index];
                        probs[index][j] = (prob > thresh) ? prob : 0;
                    }
                } else {
                    int j =  hierarchy_top_prediction(predictions + class_index, l.softmax_tree, tree_thresh, l.w*l.h);
                    probs[index][j] = (scale > thresh) ? scale : 0;
                    probs[index][l.classes] = scale;
                }
            } else {
                float max = 0;
                for(j = 0; j < l.classes; ++j){
                    int class_index = entry_index(l, 0, n*l.w*l.h + i, 5 + j);
                    float prob = scale*predictions[class_index];//类别概率乘以是否是物体的概率
                    probs[index][j] = (prob > thresh) ? prob : 0;
                    if(prob > max) max = prob;
                    // TODO REMOVE
                    // if (j == 56 ) probs[index][j] = 0; 
                    /*
                       if (j != 0) probs[index][j] = 0; 
                       int blacklist[] = {121, 497, 482, 504, 122, 518,481, 418, 542, 491, 914, 478, 120, 510,500};
                       int bb;
                       for (bb = 0; bb < sizeof(blacklist)/sizeof(int); ++bb){
                       if(index == blacklist[bb]) probs[index][j] = 0;
                       }
                     */
                }
                probs[index][l.classes] = max;
            }
            if(only_objectness){
                probs[index][0] = scale;
            }
        }
    }
    correct_region_boxes(boxes, l.w*l.h*l.n, w, h, netw, neth, relative);//将归一化bbox尺度映射到原始图片的尺度
}

猜你喜欢

转载自blog.csdn.net/linmingan/article/details/82252012