帶你使用PaddleDetection玩轉Windows下可視化部署

【飛槳開發者說】:餘志良,菲特(天津)智能科技有限公司項目經理,百度黃埔學院二期學員

今年3月、4月我分別發佈了兩篇文章:《如何用PaddleDetection做一個完整的目標檢測項目以及《飛槳與PyQt的碰撞,圖形化目標檢測So Easy,爲大家講解了從模型訓練到模型部署的全過程,其中模型部署基於Paddle預測庫的Python接口。本篇將教大家通過PaddleDetection編譯C++預測庫,並將其封裝成dll,實現PaddleDetection在Windows環境下的模型部署。

本文內容主要包括:

  • 如何進行C++預測的編譯(生成.sln解決方案)

  • 如何將C++預測代碼封裝成一個dll

  • 如何使用Python調用生成好的dll

  • 如何使用C#調用生成好的dll

如何進行C++預測代碼的編譯

(生成.sln解決方案)

使用工具Cmake vs2019社區版 Git(提前下載好git,不然在後期編譯過程中會不成功)

預測代碼來源:

https://github.com/PaddlePaddle/PaddleDetection/tree/master(注意選擇master分支)

依賴庫:

OpenCV:選擇3.4.6版本

https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download

Paddle預測庫:選擇win10下的cuda10版本。

https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_guide/inference_deployment/inference/windows_cpp_inference.html

一、首先將上述需要依賴的OpenCV和預測庫,PaddleDetection下載好,並保存在某個文件夾中。如下圖是我存放的一個文件夾。

二、將OpenCV添加到環境變量裏面,如下圖所示。

三、利用Cmake軟件進行編譯。源碼路徑爲cpp文件所在目錄,因爲裏面有CMakeLists.txt文件,同時在該目錄下創建了新的文件夾/out用於生成編譯後的文件。

四、點擊Configure,選擇vs2019 X64選項後,點擊Generate。

五、根據報錯進行修改,主要修改cuda_lib、OpenCV、paddle_dir路徑。

六、再次點擊Generate。

七、點擊Open Project,同時我們在out文件夾下發現了生成了解決方案。

八、針對“main”項目進行“重新生成”。同時一定要將模式配置成爲Release。

九、出現報錯。

十、修改報錯---根據報錯,應該是編譯過程中,cudnn.lib尋找不正確。通過修改路徑實現。方式爲點擊屬性--連接器--輸入--附加依賴項。

十一、改正上述錯誤後的正確的形式。

十二、重新生成,如下圖是重新生成後的結果。

十三、運行該生成的main.exe文件。方式爲打開out/release文件,會發現有一個main.exe文件。利用命令行打開後,運行即可。運行過程中需要添加模型的路徑以及預測圖像的路徑。

注意:此時此刻進行預測的模型是按照《如何使用PaddleDetection實現完整的項目》中export.py文件形式導出“__model__”和“__params__”的形式,但是在後續paddle的升級過程中,export.py文件不僅僅會導出“__model__”和“__params__”,還會導出一個infer_cfg.yml的文件。在這個過程中,是使用PaddleDetection-release0.3版本進行導出的,因爲之前安裝的paddle版本是1.7的,而目前的master分支是必須使用paddle2.0版本的。因此小夥伴們需要注意這個問題。

如下圖是所示的模型保存後的結果形式,依舊使用水果檢測的模型進行預測。

其中yml文件內容

十四、預測結果如下圖所示,我們看到輸出的結果中有檢測框的座標、置信度、類別信息。

如下是在out文件夾生成的命名爲“output.jpeg”的檢測後圖像

十五、對代碼進行一下小修改。之前我們需要在命令行中輸入圖像和模型的路徑,在代碼中添加圖像和模型的路徑,查看預測情況。修改src/main.cpp這個文件如下:

十六、修改上述兩處代碼後,設置“設爲啓動項目”,並點擊“本地windows調試器”

,直接查看輸出的結果。

至此,完成了第一步以及第一步的所有測試。


如何將C++預測代碼

封裝成一個dll

一、 我們需要修改CMakeLists.txt文件,修改倒數第十三行,

add_executable(main src/main.cc src/preprocess_op.cc src/object_detector.cc) 變成

ADD_library(main SHARED src/main.cc src/preprocess_op.cc src/object_detector.cc)

二、按照上文繼續重新cmake一次。

三、再次經歷之前的cudnn的路徑問題,同時需要在屬性—常規—配置類型中修改成.dll文件。

四、修改完上述內容後,點擊“重新生成”,會發現out/release中出現了main.dll文件。

五、看到dll後,我們彷彿看到了曙光,但是還是需要進行修改,因爲這樣我們才能被調用,我簡化了main.cc文件中的內容,並且配置了dll的接口,代碼如下。其中有兩個dll的接口,其中“add”是爲了測試。

#include <glog/logging.h>

#include <iostream>
#include <string>
#include <vector>

#include "include/object_detector.h"


extern "C" __declspec(dllexport) void  Loadmodel();

extern "C" __declspec(dllexport) int add(int a, int b);

void PredictImage(const std::string& image_path,
    PaddleDetection::ObjectDetector* det);


int add(int a, int b) {
    return a + b;
}
void Loadmodel() {

    std::string model_dir = "D:\\0524\\test\\model";
    std::string image_path = "D:\\0524\\test\\orange_71.jpg";
    std::string video_path = "";
    std::string run_mode = "fluid";
    bool use_gpu = true;

    // Load model and create a object detector
    PaddleDetection::ObjectDetector det(model_dir, use_gpu, run_mode);
    PredictImage(image_path, &det);

}


void PredictImage(const std::string& image_path,
    PaddleDetection::ObjectDetector* det) {
    // Open input image as an opencv cv::Mat object
    cv::Mat im = cv::imread(image_path, 1);
    // Store all detected result
    std::vector<PaddleDetection::ObjectResult> result;
    det->Predict(im, &result);
    for (const auto& item : result) {
        printf("class=%d confidence=%.2f rect=[%d %d %d %d]\n",
            item.class_id,
            item.confidence,
            item.rect[0],
            item.rect[1],
            item.rect[2],
            item.rect[3]);
    }
    // Visualization result
    auto labels = det->GetLabelList();
    auto colormap = PaddleDetection::GenerateColorMap(labels.size());
    cv::Mat vis_img = PaddleDetection::VisualizeResult(
        im, result, labels, colormap);
    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
    compression_params.push_back(95);
    cv::imwrite("output.jpeg", vis_img, compression_params);
    printf("Visualized output saved as output.jpeg\n");
}

六、繼續點擊“重新生成”,重新生成的dll就是下述步驟中我們即將調用的dll。


如何使用Python調用

生成好的dll

在上一章節我們說了如何生成dll,這一章節,我們需要進行測試,在這裏我們使用Python進行測試,利用Python調用dll。在生成的dll的文件中創建一個叫mian.py的Python文件。Python部分代碼如下:

from ctypes import *
dll=CDLL("main.dll")
print(dll.add(1,2))
print(dll.Loadmodel())

運行Python代碼,可以看到最終輸出結果如下圖:

至此說明利用Python調用dll成功了。

如何使用C#調用生成好的dll

在上一個章節中我們說了如何使用Python調用dll,接着,我們嘗試使用C#調用一個dll,此方式爲工業上經常使用的一種方式。

一、首先創建一個C#的窗體應用程序。

二、在改窗體應用程序中設置一個button事件。

三、設置dll接口代碼以及設置button,相關代碼如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {

        int a = 3;
        int b = 2;
        public Form1()
        {
            InitializeComponent();

        }
        [DllImport("main.dll", EntryPoint = "Loadmodel", CharSet = CharSet.Ansi)]
        public static extern void Loadmodel();

        [DllImport("main.dll", EntryPoint = "add", CharSet = CharSet.Ansi)]
        public static extern int add(int a, int b);
        private void button1_Click(object sender, EventArgs e)
        {
            int c = add(a, b);
            Loadmodel();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

四、將C++ release路徑下生成的文件全部複製到C#項目運行目錄下,在C++的release文件中,有一些文件只有dll,沒有對應的lib文件,這個時候,我們需要搜索到這些dll對應的lib文件,全部放在C#的運行目錄下。(PS#這些對應的文件都在我們下載的paddle預測庫中可以找到)

五、點擊“啓動按鈕”進行測試;

六、我們在C#的運行目錄下發現了生成了一張output.jpeg圖片,證明我們調用成功

至此,該系列文章基本上完成了從訓練到部署的所有流程,十分感謝在寫作過程中飛槳同學的幫助,非常感謝高松鶴、梁鈺同學的大力幫助。後續會根據飛槳針對C++預測的更新,繼續更新完善該文章。

更多資源

更多PaddleDetection的應用方法,歡迎訪問項目地址:

GitHub: 

https://github.com/PaddlePaddle/PaddleDetection

Gitee: 

https://gitee.com/paddlepaddle/PaddleDetection

如在使用過程中有問題,可加入飛槳官方QQ羣進行交流:703252161

如果您想詳細瞭解更多飛槳的相關內容,請參閱以下文檔。

官網地址:

https://www.paddlepaddle.org.cn

飛槳開源框架項目地址:

GitHub:

https://github.com/PaddlePaddle/Paddle

Gitee: 

https://gitee.com/paddlepaddle/Paddle

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章