前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >系列 | OpenVINO视觉加速库使用六

系列 | OpenVINO视觉加速库使用六

作者头像
OpenCV学堂
发布2019-04-29 17:01:06
3K1
发布2019-04-29 17:01:06
举报

主要讲述如何把DrakNet框架下支持的YOLO系列模型通过OpenVINO模型优化器与推断引擎实现对YOLO网络模型的加速执行。完整实现YOLO模型在OpenVINO上运行可以分为两个部分

模型转换

首先需要把YOLO网络模型通过模型优化器(MO)转为中间层输出IR(xml+bin),这个过程不是很友好,原因在于openvino本身不支持darknet网络,所以只有先把YOLOv3转换为tensorflow支持的PB文件,下载YOLOv3-tiny权重与配置文件

代码语言:javascript
复制
https://pjreddie.com/media/files/yolov3-tiny.weights
https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg

然后使用脚本把darknet的YOLO模型转换为tensorflow模型然后再转为IR的工具下载地址如下:

代码语言:javascript
复制
https://github.com/feng1sun/YOLO-OpenVINO

运行脚本

代码语言:javascript
复制
dump.py
--class_names ../common/coco.names   \
--weights_file <yolov3.weights_paht> \
--size <302 or 416 or 608>

执行如下:

转换为IR

代码语言:javascript
复制
mo_tf.py
--input_model /path/to/yolo_v3.pb
--output_dir <OUTPUT_PATH>
--tensorflow_use_custom_operations_config $MO_ROOT/extensions/front/tf/yolo_v3.json
--batch 1

运行结果如下:

IE加速执行YOLOv3

转换好的模型是我们就可以通过SDK进行加载,生成网络,然后使用它实现基于YOLO的目标检测。这部分的代码前面部分跟SSD目标检测的类似,可以参考前面OpenVINO系列文章内容与源代码,这里主要说明一下不一样的地方,YOLOv3的输出层有多个,在不同分辨率上实现对象检测,对于同一个对象可能有多个BOX重叠,这个时候必须通过计算并交比来实现非最大抑制,计算并交比的代码如下:

代码语言:javascript
复制
double IntersectionOverUnion(const DetectionObject &box_1,
    const DetectionObject &box_2) {
    double width_of_overlap_area = fmin(box_1.xmax, box_2.xmax) - fmax(box_1.xmin, box_2.xmin);
    double height_of_overlap_area = fmin(box_1.ymax, box_2.ymax) - fmax(box_1.ymin, box_2.ymin);
    double area_of_overlap;
    if (width_of_overlap_area < 0 || height_of_overlap_area < 0)
        area_of_overlap = 0;
    else
        area_of_overlap = width_of_overlap_area * height_of_overlap_area;
    double box_1_area = (box_1.ymax - box_1.ymin)  * (box_1.xmax - box_1.xmin);
    double box_2_area = (box_2.ymax - box_2.ymin)  * (box_2.xmax - box_2.xmin);
    double area_of_union = box_1_area + box_2_area - area_of_overlap;
    return area_of_overlap / area_of_union;
}

对每个对象输出一个BOX,所以YOLOv3的输出层,需要做多个输出层结果合并然后NMS操作,YOLOv3的三个输出层如下:

此外YOLO数层格式跟SSD与RCNN系列输出格式不同,是基于YoloRegion实现的,解析该结构的代码如下:

代码语言:javascript
复制
for (int i = 0; i < side_square; ++i) {
        int row = i / side;
        int col = i % side;
        for (int n = 0; n < num; ++n) {
            int obj_index = EntryIndex(side, coords, classes, n * side * side + i, coords);
            int box_index = EntryIndex(side, coords, classes, n * side * side + i, 0);
            float scale = output_blob[obj_index];
            if (scale < threshold) continue;
            double x = (col + output_blob[box_index + 0 * side_square]) / side * resized_im_w;
            double y = (row + output_blob[box_index + 1 * side_square]) / side * resized_im_h;
            double height = std::exp(output_blob[box_index + 3 * side_square]) * anchors[anchor_offset + 2 * n + 1];
            double width = std::exp(output_blob[box_index + 2 * side_square]) * anchors[anchor_offset + 2 * n];
            for (int j = 0; j < classes; ++j) {
                int class_index = EntryIndex(side, coords, classes, n * side_square + i, coords + 1 + j);
                float prob = scale * output_blob[class_index];
                if (prob < threshold)
                    continue;
                DetectionObject obj(x, y, height, width, j, prob,
                    static_cast<float>(original_im_h) / static_cast<float>(resized_im_h),
                    static_cast<float>(original_im_w) / static_cast<float>(resized_im_w));
                objects.push_back(obj);
            }
        }
    }

最终的输出Output的解析代码如下:

代码语言:javascript
复制
// 处理输出结果
std::vector<DetectionObject> objects;
printf(" \n");
for (auto &output : output_info) {
    auto output_name = output.first;
    printf("Output Layer Name : %s \n", output_name.c_str());
    CNNLayerPtr layer = network_reader.getNetwork().getLayerByName(output_name.c_str());
    Blob::Ptr blob = infer_request.GetBlob(output_name);

    // 解析输出层YOLO-Region
    ParseYOLOV3Output(blob, layer, IH, IW, src.rows, src.cols, 0.5, objects);
}
printf(" \n");

// 非最大抑制
std::sort(objects.begin(), objects.end());
for (int i = 0; i < objects.size(); ++i) {
    if (objects[i].confidence == 0)
        continue;
    for (int j = i + 1; j < objects.size(); ++j)
        if (IntersectionOverUnion(objects[i], objects[j]) >= 0.45)
            objects[j].confidence = 0;
}

// 绘制输出结果
for (auto &object : objects) {
    if (object.confidence < 0.5)
        continue;
    auto label = object.class_id;
    float confidence = object.confidence;
    if (confidence > 0.5) {
        std::ostringstream conf;
        conf << ":" << std::fixed << std::setprecision(3) << confidence;
        cv::Point2f p1 = cv::Point2f(object.xmin, object.ymin);
        cv::Point2f p2 = cv::Point2f(object.xmax, object.ymax);
        cv::rectangle(src, p1, p2, cv::Scalar(255, 0, 255), 1, 8);
    }
}
imshow("OpenVINO-YOLOv3-Demo", src);

运行结果如下:

从此以后YOLO与Darknet网络通过OpenVINO加速技能可以get啦,记得点【在看】支持

为山者基于一篑之土,以成千丈之峭

凿井者起于三寸之坎,以就万仞之深

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像识别
腾讯云图像识别基于深度学习等人工智能技术,提供车辆,物体及场景等检测和识别服务, 已上线产品子功能包含车辆识别,商品识别,宠物识别,文件封识别等,更多功能接口敬请期待。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档