[E2E_L8_1]segmentation_demo道路分割例子和GOMFCTemplate的初步融合

一、来源


模型例子自己带来副图像
 
 
二、简化
 
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <chrono>
#include <memory>
#include <utility>
 
#include <format_reader_ptr.h>
#include <inference_engine.hpp>
#include <ext_list.hpp>
 
#include <samples/slog.hpp>
#include <samples/args_helper.hpp>
#include <samples/ocv_common.hpp>
#include <format_reader_ptr.h>
 
#include "segmentation_demo.h"
 
using namespace InferenceEngine;
using namespace std;
using namespace cv;
 
//-i E:/OpenVINO_modelZoo/road.png -m  E:/OpenVINO_modelZoo/road-segmentation-adas-0001.xml
void main()
{
    std::vector<std::stringimages;
    string imageNames = "E:/OpenVINO_modelZoo/road.png";
    images.push_back(imageNames);
    
    // --------------------------- 1.为IE准备插件-------------------------------------
    InferencePlugin plugin(PluginDispatcher().getSuitablePlugin(TargetDevice::eCPU));
    printPluginVersion(pluginstd::cout);//正确回显表示成功
    plugin.AddExtension(std::make_shared<Extensions::Cpu::CpuExtensions>());//Extension,useful
    // --------------------------- 2.读取IR模型(xml和bin)---------------------------------
    CNNNetReader networkReader;
    networkReader.ReadNetwork("E:/OpenVINO_modelZoo/road-segmentation-adas-0001.xml");
    networkReader.ReadWeights("E:/OpenVINO_modelZoo/road-segmentation-adas-0001.bin");
    CNNNetwork network = networkReader.getNetwork();
    // --------------------------- 3. 准备输入输出的------------------------------------------
    InputsDataMap inputInfo(network.getInputsInfo());//获得输入信息
    BlobMap inputBlobs//保持所有输入的blob数据
    if (inputInfo.size() != 1) throw std::logic_error("错误,该模型应该为单输入");
 
    auto inputInfoItem = *inputInfo.begin();//开始读入
    std::vector<std::shared_ptr<unsigned char>> imagesData;
 
    for (auto & i : images) {
        FormatReader::ReaderPtr reader(i.c_str()); //使用FormatReader来读取图片数据,这里的images是一个vector,注意对于批量数据的读取
        if (reader.get() == nullptr) {
            slog::warn << "Image " + i + " 无法读取!" << slog::endl;
            continue;
        }
        /** 获得图片数据 **/
        std::shared_ptr<unsigned chardata(
            reader->getData(inputInfoItem.second->getTensorDesc().getDims()[3],
            inputInfoItem.second->getTensorDesc().getDims()[2]));
        if (data.get() != nullptr) {
            imagesData.push_back(data);
        }
    }
    if (imagesData.empty()) throw std::logic_error("错误的格式,请检查!");
 
    network.setBatchSize(imagesData.size());
    slog::info << "Batch size is " << std::to_string(networkReader.getNetwork().getBatchSize()) << slog::endl;
 
    inputInfoItem.second->setPrecision(Precision::U8);
    //准备输出数据
    OutputsDataMap outputInfo(network.getOutputsInfo());
    std::string firstOutputName;
    for (auto & item : outputInfo) {
        if (firstOutputName.empty()) {
            firstOutputName = item.first;
        }
        DataPtr outputData = item.second;
        if (!outputData) {
            throw std::logic_error("错误的格式,请检查!");
        }
        item.second->setPrecision(Precision::FP32);
    }
    // --------------------------- 4. 读取模型 ------------------------------------------(后面这些操作应该可以合并了)
    ExecutableNetwork executableNetwork = plugin.LoadNetwork(network, {});
    // --------------------------- 5. 创建推断 -------------------------------------------------
    InferRequest infer_request = executableNetwork.CreateInferRequest();
    // --------------------------- 6. 将数据塞入模型 -------------------------------------------------
    for (const auto & item : inputInfo) {
        /** 创建输入BLOB **/
        Blob::Ptr input = infer_request.GetBlob(item.first);
 
        /** 3 通道塞数据 **/
        size_t num_channels = input->getTensorDesc().getDims()[1];
        size_t image_size = input->getTensorDesc().getDims()[3] * input->getTensorDesc().getDims()[2];
 
        auto data = input->buffer().as<PrecisionTrait<Precision::U8>::value_type*>();
        
        for (size_t image_id = 0; image_id < imagesData.size(); ++image_id) {
            for (size_t pid = 0; pid < image_sizepid++) {
                for (size_t ch = 0; ch < num_channels; ++ch) {
                    data[image_id * image_size * num_channels + ch * image_size + pid] = imagesData.at(image_id).get()[pid*num_channels + ch];
                }
            }
        }
    }
    // --------------------------- 7. 推断结果 -------------------------------------------------
    for (size_t iter = 0; iter < images.size(); ++iter) {
        infer_request.Infer();//多张图片多次推断
    }    
    // --------------------------- 8. 处理结果-------------------------------------------------------
    slog::info << "输出结果" << slog::endl;
 
    const Blob::Ptr output_blob = infer_request.GetBlob(firstOutputName);
    const auto output_data = output_blob->buffer().as<float*>();
 
    size_t N = output_blob->getTensorDesc().getDims().at(0);
    size_t C = output_blob->getTensorDesc().getDims().at(1);
    size_t H = output_blob->getTensorDesc().getDims().at(2);
    size_t W = output_blob->getTensorDesc().getDims().at(3);
 
    size_t image_stride = W * H * C;
 
    for (size_t image = 0; image < N; ++image) {
        std::vector<std::vector<size_t>> outArrayClasses(Hstd::vector<size_t>(W, 0));
        std::vector<std::vector<float>> outArrayProb(Hstd::vector<float>(W, 0.));
        for (size_t w = 0; w < W; ++w) {
            for (size_t h = 0; h < H; ++h) {
                if (C == 1) {
                    outArrayClasses[h][w] = static_cast<size_t>(output_data[image_stride * image + W * h + w]);
                }
                else {
                    for (size_t ch = 0; ch < C; ++ch) {
                        auto data = output_data[image_stride * image + W * H * ch + W * h + w];
                        if (data > outArrayProb[h][w]) {
                            outArrayClasses[h][w] = ch;
                            outArrayProb[h][w] = data;
                        }
                    }
                }
            }
        }
        std::string fileName = "out_" + std::to_string(image+ ".bmp";
        std::ofstream outFile(fileNamestd::ofstream::binary);
        if (!outFile.is_open()) {
            throw std::logic_error("Can't open file : " + fileName);
        }
 
        writeOutputBmp(outArrayClassesCoutFile); //输出的代码
        slog::info << "File : " << fileName << " was created" << slog::endl;
    }
    // -----------------------------------------------------------------------------------------------------
 
 
}
 
在改写的过程中有几点注意
1、添加lib和对应的dll文件,主要就是用于文件读取的;
以及format_reader.dll 文件放到目录下面;
2、头文件修改正确
 
三、改写
 
这个代码里面使用的是format_reader,使用起来颇为不方便,修改为OpenCV负责输入输出。
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <chrono>
#include <memory>
#include <utility>
 
#include <format_reader_ptr.h>
#include <inference_engine.hpp>
#include <ext_list.hpp>
 
#include <samples/slog.hpp>
#include <samples/args_helper.hpp>
#include <samples/ocv_common.hpp>
#include <format_reader_ptr.h>
 
#include "segmentation_demo.h"
 
using namespace InferenceEngine;
using namespace std;
using namespace cv;
 
//-i E:/OpenVINO_modelZoo/road.png -m  E:/OpenVINO_modelZoo/road-segmentation-adas-0001.xml
void main()
{
    std::vector<std::stringimages;
    string imageNames = "E:/OpenVINO_modelZoo/road.png";
    images.push_back(imageNames);
    
    // --------------------------- 1.为IE准备插件-------------------------------------
    InferencePlugin plugin(PluginDispatcher().getSuitablePlugin(TargetDevice::eCPU));
    printPluginVersion(pluginstd::cout);//正确回显表示成功
    plugin.AddExtension(std::make_shared<Extensions::Cpu::CpuExtensions>());//Extension,useful
    // --------------------------- 2.读取IR模型(xml和bin)---------------------------------
    CNNNetReader networkReader;
    networkReader.ReadNetwork("E:/OpenVINO_modelZoo/road-segmentation-adas-0001.xml");
    networkReader.ReadWeights("E:/OpenVINO_modelZoo/road-segmentation-adas-0001.bin");
    CNNNetwork network = networkReader.getNetwork();
    // --------------------------- 3. 准备输入输出的------------------------------------------
    InputsDataMap inputInfo(network.getInputsInfo());//获得输入信息
    BlobMap inputBlobs//保持所有输入的blob数据
    if (inputInfo.size() != 1) throw std::logic_error("错误,该模型应该为单输入");
 
    //auto lrInputInfoItem = *inputInfo.begin();//开始读入
    //int w = static_cast<int>(lrInputInfoItem.second->getTensorDesc().getDims()[3]); //这种写法也是可以的,它的first就是data
    //int h = static_cast<int>(lrInputInfoItem.second->getTensorDesc().getDims()[2]);
 
    auto lrInputInfoItem = inputInfo["data"]//开始读入
    int w = static_cast<int>(lrInputInfoItem->getTensorDesc().getDims()[3]); //模型要求的输入大小
    int h = static_cast<int>(lrInputInfoItem->getTensorDesc().getDims()[2]);
 
    Mat src = imread(imageNames);
    if (src.empty())
        return;
 
    network.setBatchSize(1);//只有1副图片,故BatchSize = 1
 
 
  //准备输出数据
    OutputsDataMap outputInfo(network.getOutputsInfo());//获得输出信息                                      
    std::string firstOutputName;
    for (auto &item : outputInfo) {
        if (firstOutputName.empty()) {
            firstOutputName = item.first;
        }
        DataPtr outputData = item.second;
        if (!outputData) {
            throw std::logic_error("错误的格式,请检查!");
        }
 
        item.second->setPrecision(Precision::FP32);
    }
    // --------------------------- 4. 读取模型 ------------------------------------------(后面这些操作应该可以合并了)
    ExecutableNetwork executableNetwork = plugin.LoadNetwork(network, {});
    // --------------------------- 5. 创建推断 -------------------------------------------------
    InferRequest infer_request = executableNetwork.CreateInferRequest();
    // --------------------------- 6. 将数据塞入模型 -------------------------------------------------
    Blob::Ptr lrInputBlob = infer_request.GetBlob("data"); //data这个名字是我看出来的,实际上这里可以更统一一些
    matU8ToBlob<float_t>(srclrInputBlob, 0);//重要的转换函数,第3个参数是batchSize,应该是自己+1的
 
    // --------------------------- 7. 推断结果 -------------------------------------------------
    infer_request.Infer();//多张图片多次推断
 
    // --------------------------- 8. 处理结果-------------------------------------------------------
    
    const Blob::Ptr outputBlob = infer_request.GetBlob(firstOutputName);
    const auto outputData = outputBlob->buffer().as<PrecisionTrait<Precision::FP32>::value_type*>();
    size_t numOfImages = outputBlob->getTensorDesc().getDims()[0];
    size_t numOfChannels = outputBlob->getTensorDesc().getDims()[1];
    h = outputBlob->getTensorDesc().getDims()[2];
    w = outputBlob->getTensorDesc().getDims()[3];
    size_t nunOfPixels = w * h//写在内存里的结果,还是要拼出来的
 
    std::vector<cv::MatimgPlanescv::Mat(hwCV_32FC1, &(outputData[0])),
                                   cv::Mat(hwCV_32FC1, &(outputData[nunOfPixels])),
                                   cv::Mat(hwCV_32FC1, &(outputData[nunOfPixels * 2])) };
 
    for (auto & img : imgPlanes//本来是平的
        img.convertTo(imgCV_8UC1, 255);
 
    cv::Mat resultImg;
    cv::merge(imgPlanesresultImg);
    cv::imshow("result"resultImg);
 
    cv::waitKey();
    
}
这里需要注意的一点是在读取图片的大小的时候,我这里使用了
Blob::Ptr lrInputBlob = infer_request.GetBlob("data"); //data这个名字是我看出来的,实际上这里可以更统一一些
 
其前提是我知道这里叫做 data,这里可以改成更统一的方式。
 
从结果来看,我认为OpenCV转换后的结果更好。当然差别只是在着色而已。
四、数据集测试
使用UAS Dataset进行测试,主要是想看一看批量数据的处理。使用Sample中的程序进行处理:
这个操作应该就是多张图片。
 
 
这个输入输出的界面就LOW了,我认为没有必要在函数中进行这个处理,函数处理单张就可以。原模型也是不支持视频的。
 
该造后的效果就很好
 
五、融合
在GOMFCTemplate中运行
 
其中,容易犯错的地方(release版本和debug版本的 cpu_extension重名,所以不能放到system目录下面):
以及OCV_COMMON可能引起混乱
第一步是直接替换
 
目前存在的一个突出问题,就是模型的创建和模型的infer独立的问题。这个东西在OpenVINO中可能有,但要去寻找,不是直接告诉你的东西。
做到这一步,虽然代码已经可以运行,但是突出的问题就是没有模块化,整个运算步骤都在循环中,这样效率肯定是很低下的。并且在资源的销毁处还存在问题。
可以进一步将其封装为函数:
 
比如类似这里面的
就是下一步需要参考的。

转载于:https://www.cnblogs.com/jsxyhelu/p/11326310.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手把手讲授如何搭建成功OpenVINO框架,并且使用预训练模型快速开发超分辨率、道路分割、汽车识别、人脸识别、人体姿态和行人车辆分析。得益于OpenVINO框架的强大能力,这些例子都能够基于CPU达到实时帧率。课程的亮点在于在调通Demo的基础上更进一步:一是在讲Demo的时候,对相关领域问题进行分析(比如介绍什么是超分辨率,有什么作用)、预训练模型的来龙去脉(来自那篇论文,用什么训练的)、如何去查看不同模型的输入输出参数、如何编写对应的接口参数进行详细讲解;二是基本上对所有的代码进行重构,也就是能够让例子独立出来,并且给出了带有较详细注释的代码;三是注重实际运用,将Demo进一步和实时视频处理框架融合,形成能够独立运行的程序,方便模型落地部署;四是重难点突出、注重总结归纳,对OpenVINO基本框架,特别是能够提高视频处理速度的异步机制和能够直接部署解决实际问题的骨骼模型着重讲解,帮助学习理解;五是整个课程准备精细,每一课都避免千篇一律,前一课有对后一课的预告,后一课有对前一课的难点回顾,避免学习过程中出现突兀;六是在适当的时候拓展衍生,不仅讲OpenVINO解决图像处理问题,而且还补充图像处理的软硬选择、如何在手机上开发图像处理程序等内容,帮助拓展视野,增强对行业现状的了解。基本提纲:1、课程综述、环境配置2、OpenVINO范例-超分辨率(super_resolution_demo)3、OpenVINO范例-道路分割segmentation_demo)4、OpenVINO范例-汽车识别(security_barrier_camera_demo)5、OpenVINO范例-人脸识别(interactive_face_detection_demo)6、OpenVINO范例-人体姿态分析(human_pose_estimation_demo)7、OpenVINO范例-行人车辆分析(pedestrian_tracker_demo)8、NCS和GOMFCTEMPLATE9、课程小结,资源分享

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值