<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          YOLOv5在最新OpenVINO 2021R02版本的部署與代碼演示詳解

          共 2320字,需瀏覽 5分鐘

           ·

          2021-01-14 10:56



          ??新智元推薦??

          來源:OpenCV學(xué)堂

          作者:gloomyfish

          【新智元導(dǎo)讀】本文從原始的三個(gè)輸出層解析實(shí)現(xiàn)了boxes, classes, nms等關(guān)鍵C++代碼輸出,實(shí)現(xiàn)了純OpenVINO+OpenCV版本的YOLOv5s模型推理的代碼演示。下面是詳細(xì)的系統(tǒng)環(huán)境與各個(gè)部分解釋,以及代碼實(shí)現(xiàn)與演示圖像。


          系統(tǒng)版本信息與依賴

          • Window 10 64bit
          • Pytorch1.7+CUDA10.0
          • Python3.8.5
          • VS2015
          • OpenVINO_2021.2.185


          YOLOv5下載與測(cè)試運(yùn)行


          YOLOv5是第二個(gè)非官方的YOLO對(duì)象檢測(cè)版本,也是第一個(gè)Pytorch實(shí)現(xiàn)的YOLO對(duì)象檢測(cè)版本。Github地址如下:

          https://github.com/ultralytics/yolov5

          需要克隆到本地

          git clone https://github.com/ultralytics/yolov5.git

          然后運(yùn)行

          pip install -r requirements.txt

          安裝所有依賴。


          最后運(yùn)行一段視頻或者圖像完成測(cè)試

          python detect.py --source D:\images\video\SungEun.avi --weights yolov5s.pt --conf 0.25


          視頻測(cè)試結(jié)果如下:



          圖像測(cè)試結(jié)果如下:



          模型轉(zhuǎn)換

          模型轉(zhuǎn)換主要是把原始的YOLOv5的pytorch模型文件轉(zhuǎn)換為通用的開放模型格式ONNX與OpenVIN特有的文件格式IR(*.xml與*.bin)。


          OpenVINO從2020R02以后版本開始支持直接讀取ONNX格式文件,所以我們既可以通過腳本直接導(dǎo)出onnx格式文件,直接給OpenVINO調(diào)用,也可以對(duì)得到ONNX文件通過OpenVINO的模型轉(zhuǎn)換腳本做進(jìn)一步轉(zhuǎn)換生成IR中間格式(*.bin文件與*.xml文件)。


          導(dǎo)出ONNX格式文件的腳本

          Pytorch的YOLOv5項(xiàng)目本身已經(jīng)提供了轉(zhuǎn)換腳本,命令行運(yùn)行方式如下:

          # export at 640x640 with batch size 1python models/export.py --weights yolov5s.pt --img 640 --batch 1

          然后生成的yolov5s.onnx文件就在同一目錄下面。


          ONNX轉(zhuǎn)為為IR中間格式

          把ONNX轉(zhuǎn)換為IR中間格式,運(yùn)行結(jié)果如下:


          OpenVINO SDK+YOLOv5s代碼演示


          上面我們已經(jīng)成功轉(zhuǎn)換為YOLOv5s模型IR,現(xiàn)在就可以基于最新的SDK來說完成調(diào)用解析與調(diào)用。


          第一步:

          初始Core對(duì)象,讀取模型(加載ONNX格式或者IR格式均可以,親測(cè)有效)


          //?創(chuàng)建IE插件,?查詢支持硬件設(shè)備
          Core?ie;
          vector<string>?availableDevices?=?ie.GetAvailableDevices();
          for?(int?i?=?0;?i?????printf("supported?device?name?:?%s?\n",?availableDevices[i].c_str());
          }

          //??加載檢測(cè)模型
          auto?network?=?ie.ReadNetwork("D:/python/yolov5/yolov5s.xml",?"D:/python/yolov5/yolov5s.bin");
          //?auto?network?=?ie.ReadNetwork("D:/python/yolov5/yolov5s.onnx");


          第二步:

          設(shè)置輸入與輸出格式,YOLOv5s輸入的圖像被歸一化到0~1之間,而且是RGB通道順序,輸入與輸出格式設(shè)置數(shù)據(jù)為浮點(diǎn)數(shù),這部分的代碼如下:


          //?設(shè)置輸入格式
          for?(auto?&item?:?input_info)?{
          ????auto?input_data?=?item.second;
          ????input_data->setPrecision(Precision::FP32);
          ????input_data->setLayout(Layout::NCHW);
          ????input_data->getPreProcess().setResizeAlgorithm(RESIZE_BILINEAR);
          ????input_data->getPreProcess().setColorFormat(ColorFormat::RGB);
          }

          //?設(shè)置輸出格式
          for?(auto?&item?:?output_info)?{
          ????auto?output_data?=?item.second;
          ????output_data->setPrecision(Precision::FP32);
          }
          auto?executable_network?=?ie.LoadNetwork(network,?"CPU");


          第三步:

          設(shè)置輸入圖像數(shù)據(jù)并實(shí)現(xiàn)推理預(yù)測(cè)


          int64?start?=?getTickCount();
          /**?Iterating?over?all?input?blobs?**/
          for?(auto?&?item?:?input_info)?{
          ????auto?input_name?=?item.first;

          ????/**?Getting?input?blob?**/
          ????auto?input?=?infer_request.GetBlob(input_name);
          ????size_t?num_channels?=?input->getTensorDesc().getDims()[1];
          ????size_t?h?=?input->getTensorDesc().getDims()[2];
          ????size_t?w?=?input->getTensorDesc().getDims()[3];
          ????size_t?image_size?=?h*w;
          ????Mat?blob_image;
          ????resize(src,?blob_image,?Size(w,?h));
          ????cvtColor(blob_image,?blob_image,?COLOR_BGR2RGB);

          ????//?NCHW
          ????float*?data?=?static_cast<float*>(input->buffer());
          ????for?(size_t?row?=?0;?row?????????for?(size_t?col?=?0;?col?????????????for?(size_t?ch?=?0;?ch?????????????????data[image_size*ch?+?row*w?+?col]?=?float(blob_image.at(row,?col)[ch])/255.0;
          ????????????}
          ????????}
          ????}
          }

          //?執(zhí)行預(yù)測(cè)
          infer_request.Infer();


          上面的代碼跟SSD對(duì)象檢測(cè)的OpenVINO調(diào)用基本上沒有太大區(qū)別。主要的區(qū)別是在對(duì)推理完成結(jié)果的解析部分。


          第四步:

          解析輸出結(jié)果,實(shí)現(xiàn)顯示輸出。要完成這個(gè)部分,首先需要看一下YOLOv5項(xiàng)目中的yolo.py中對(duì)推理部分的組裝。


          首先輸出層,從YOLOv3開始到Y(jié)OLOv5,輸出層都是3層,分別對(duì)應(yīng)的降采樣的倍數(shù)是32、16、8。



          以輸入640x640大小的圖像為例,得到三個(gè)輸出層大小應(yīng)該分別是20、40、80。每個(gè)層上對(duì)應(yīng)三個(gè)尺度的anchor,表示如下:


          模型的預(yù)測(cè)是在20x20、40x40、80x80每個(gè)輸出層的每個(gè)特征點(diǎn)上預(yù)測(cè)三個(gè)框,每個(gè)框預(yù)測(cè)分類!


          每個(gè)框的維度大小為 cx,cy,w,h,conf + number of class, 圖示如下:

          以YOLOv5項(xiàng)目的預(yù)訓(xùn)練模型是基于COCO的80個(gè)對(duì)象類別為例,在檢測(cè)階段最終三個(gè)輸出層是:

          1x3x20x20x851x3x40x40x851x3x80x80x85


          電腦上實(shí)際加載模型之后的三個(gè)輸出層實(shí)現(xiàn)運(yùn)行結(jié)果:


          然后循環(huán)每個(gè)輸出層,解析每個(gè)特征點(diǎn)對(duì)應(yīng)的3個(gè)框與相關(guān)數(shù)據(jù)。


          由于在導(dǎo)出的時(shí)候ONNX格式文件時(shí)模型的推理得到的三個(gè)輸出層原始結(jié)果,所以還需要對(duì)每個(gè)數(shù)據(jù)先完成sigmoid歸一化,然后再計(jì)算相關(guān)值,這部分的代碼實(shí)現(xiàn)我參考了項(xiàng)目中的yolo.py中的Detection部分,得到初始每個(gè)對(duì)象的檢測(cè)框之后,采用OpenVINO中自帶非最大抑制函數(shù),完成非最大抑制,就得到了最終的預(yù)測(cè)框,然后繪制顯示。


          所以最終的解析輸出層部分的代碼如下:


          for?(int?i?=?0;?i?????for?(int?c?=?0;?c?????????int?row?=?i?/?side_h;
          ????????int?col?=?i?%?side_h;
          ????????int?object_index?=?c*side_data_square?+?row*side_data_w?+?col*side_data;

          ????????//?閾值過濾
          ????????float?conf?=?sigmoid_function(output_blob[object_index?+?4]);
          ????????if?(conf?0.25
          )?{
          ????????????continue;
          ????????}

          ????????//?解析cx,?cy,?width,?height
          ????????float?x?=?(sigmoid_function(output_blob[object_index])?*?2?-?0.5?+?col)*stride;
          ????????float?y?=?(sigmoid_function(output_blob[object_index?+?1])?*?2?-?0.5?+?row)*stride;
          ????????float?w?=?pow(sigmoid_function(output_blob[object_index?+?2])?*?2,?2)*anchors[anchor_index?+?c?*?2];
          ????????float?h?=?pow(sigmoid_function(output_blob[object_index?+?3])?*?2,?2)*anchors[anchor_index?+?c?*?2?+?1];
          ????????float?max_prob?=?-1;
          ????????int?class_index?=?-1;

          ????????//?解析類別
          ????????for?(int?d?=?5;?d?85;?d++)?{
          ????????????float?prob?=?sigmoid_function(output_blob[object_index?+?d]);
          ????????????if?(prob?>?max_prob)?{
          ????????????????max_prob?=?prob;
          ????????????????class_index?=?d?-?5;
          ????????????}
          ????????}

          ????????//?轉(zhuǎn)換為top-left,?bottom-right坐標(biāo)
          ????????int?x1?=?saturate_cast<int>((x?-?w?/?2)?*?scale_x);??//?top?left?x
          ????????int?y1?=?saturate_cast<int>((y?-?h?/?2)?*?scale_y);??//?top?left?y
          ????????int?x2?=?saturate_cast<int>((x?+?w?/?2)?*?scale_x);??//?bottom?right?x
          ????????int?y2?=?saturate_cast<int>((y?+?h?/?2)?*?scale_y);?//?bottom?right?y

          ????????//?解析輸出
          ????????classIds.push_back(class_index);
          ????????confidences.push_back((float)conf);
          ????????boxes.push_back(Rect(x1,?y1,?x2?-?x1,?y2?-?y1));
          ????????//?rectangle(src,?Rect(x1,?y1,?x2?-?x1,?y2?-?y1),?Scalar(255,?0,?255),?2,?8,?0);
          ????}
          }


          非最大抑制的代碼如下:


          vector<int>?indices;
          NMSBoxes(boxes,?confidences,?0.25,?0.5,?indices);
          for?(size_t?i?=?0;?i?{
          ????int?idx?=?indices[i];
          ????Rect?box?=?boxes[idx];
          ????rectangle(src,?box,?Scalar(140,?199,?0),?4,?8,?0);
          }
          float?fps?=?getTickFrequency()?/?(getTickCount()?-?start);
          float?time?=?(getTickCount()?-?start)?/?getTickFrequency();


          官方的兩張測(cè)試圖像,測(cè)試結(jié)果如下:



          推薦閱讀:

          15歲上浙大、22歲獲世界冠軍,90后「天才黑客」為何被開除、錯(cuò)失上億股票?


          克勞德·香農(nóng):看我如何發(fā)明未來







          瀏覽 68
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼视频网站大全 | 超碰人人在线观看 | 国产精品午夜123 | 国产精品探花熟女AV | 男女黄色免费网站 |