写在前面

背景:
飞桨官方提供了PaddleX部署的例子,下面的过程都是参考paddleX和paddleseg,在他们的github仓库都能找到相应的文档。这里只做为学习记录。

1、环境

  • CUDA10.1 Cudnn 7.6
  • opencv版本3.4.6
  • PaddleInference 的预测库 C++版
  • TensorRT 6.0.1.5
  • Cmake 3.22.3
  • VS2019 社区版(建议使用vs2019,其他版本会出问题,我用vs2022就被坑了)

2、准备

  • 下载好PaddleX代码和PaddleInference预测库
  • 下载Tensorrt,并设置系统环境变量 在本项目中使用的cuda版本是10.2,下载对应的trt版本
  • 为了便于项目管理,将所有的文件汇总到一个文件夹中
  • 设置OpenCV系统环境变量

3、代码编译

3.1 GPU+TRT版本

paddleocr Java部署 paddlex部署_paddleocr Java部署

3.2 CPU版本

paddleocr Java部署 paddlex部署_c++_02

3.3 解决方案

最终在out文件夹中出现了.sln文件,则表示通过cmake生成成功了解决方案。

paddleocr Java部署 paddlex部署_paddleocr Java部署_03


用vs2019打开项目。

4、修改文件

①修改CMakeLists.txt

paddleocr Java部署 paddlex部署_飞桨_04

修改第121行左右

# add_executable(model_infer model_infer.cpp ${SRC} ${ENGINE_SRC} ${DETECTOR_SRC} ${ENCRYPTION_SRC})
add_library(model_infer SHARED model_infer.cpp ${SRC} ${ENGINE_SRC} ${DETECTOR_SRC} ${ENCRYPTION_SRC})

paddleocr Java部署 paddlex部署_paddlepaddle_05

②修改model_infer.cpp

在paddleX的github仓库里,找到paddleX/deploy/cpp/docs/csharp_deploy/model_infer.cpp这个文件,替换掉本地项目中的PaddleX/deploy/cpp/demo/model_infer.cpp

③针对自己的项目需求再修改model_infer.cpp

比如这里我要做一个获取图像检测坐标的功能。我修改Seg_ModelPredict函数

(如果没有特定的需求,就不用修改model_infer.cpp的源码)

paddleocr Java部署 paddlex部署_飞桨_06

extern "C" __declspec(dllexport) void Seg_ModelPredict(const unsigned char* img, int nWidth, int nHeight, int nChannel, unsigned char* output, unsigned int* tar_pos)
{
	// prepare data
	std::vector<cv::Mat> imgs;

	std::deque<int> value_1_pos;        // 记录当X=256时,Y对应的位置的值=1的坐标位置
	int indexSrc = 0;
	unsigned char color_id = 0;

	int nType = 0;
	if (nChannel == 3)
	{
		nType = CV_8UC3;
	}
	else
	{
		std::cout << "Only support 3 channel image." << std::endl;
		return;
	}

	cv::Mat input = cv::Mat::zeros(cv::Size(nWidth, nHeight), nType);
	memcpy(input.data, img, nHeight * nWidth * nChannel * sizeof(uchar));
	imgs.push_back(std::move(input));

	// predict
	std::vector<PaddleDeploy::Result> results;
	model->Predict(imgs, &results, 1);

	std::vector<uint8_t> result_map = results[0].seg_result->label_map.data; // vector<uint8_t> -- Result Map
	// Copy output result to the output back -- from vector<uint8_t> to unsigned char *
	memcpy(output, &result_map[0], result_map.size() * sizeof(uchar));

	for (int i = 0; i < 512; i++) {   // height

		indexSrc = i * 512 + 256;
		color_id = (int)output[indexSrc] % 256; // Pixel category ID
		if (color_id == 1) {
			value_1_pos.push_back(i);
		}
	}
	if (value_1_pos.begin() != value_1_pos.end()) {
		*tar_pos = round((value_1_pos.back() - value_1_pos.front()) / 2) + value_1_pos.front();
	}
	else {
		*tar_pos = 0;
	}
	
}

④生成DLL

paddleocr Java部署 paddlex部署_c++_07


不出什么意外的话

paddleocr Java部署 paddlex部署_飞桨_08


然后在F:\edge_download\px\PaddleX-2.0.0\deploy\cpp\out\paddle_deploy你就会看到

paddleocr Java部署 paddlex部署_python_09


我们再将Release中的model_infer.dll复制过来,一共7个文件,就是我们需要的所有DLL了。

paddleocr Java部署 paddlex部署_c++_10


CPU版本只有5个文件

paddleocr Java部署 paddlex部署_paddlepaddle_11

5、问题

1、找到不到G:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\lib\x64\cudnn.lib
在安装cuda的时候,把cudnnlib目录下的cudnn.lib文件复制到....CUDA\v10.1\lib\x64目录中去。

2、如果遇到,比如:

  • 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
  • …未定义
  • 没有找到声明

之类的问题,建议把所有文件删掉,重新开始。从第3步开始、解压文件,代码编译。。。。。。