框架代码获取:VX搜索“晓理紫”公号,关注并回复‘c++python’即可
使用C++部署一个深度学习网络,并通过fastAPI对外提供服务。深度学习网络需要输入要推理的图像,最终返回推理结果和处理后的图像
在推理端有一个fastSAMModel类,类里面有一个推理接口detect,此函数需要输入图像等一些参数,返回处理后的图像和一些推理结果。只要是实例化fastSAMModel并调用detect函数就可以实现推理。
class fastSAMModel {
public:
explicit fastSAMModel(const std::string &engine_file_path,
const int input_w, const int input_h);
cv::Mat detect(
cv::Mat &colorImage,
cv::Mat &deptImage,float fx,float fy,float cx,float cy,std::vector<std::vector<float>>& objMessage);
};
此中间层也是有C++实现,主要作用是接收python传入的图像数据并对数据进行转换成cv::Mat格式供给推理使用;接收推理返回的参数,并把其转换成python相关格式传给python。实现如下
#include "include/fastSAMModel.h"
#include <cstring>
using namespace fastsammodel;
extern "C" {
fastSAMModel *fastSAMModel_new(const char *engine_file_path, const int input_w,
const int input_h) {
return new fastSAMModel(std::string(engine_file_path), input_w, input_h);
}
void fastSAMModel_delete(fastSAMModel *obj) { delete obj; }
// python调用的接口,返回图像的数据
unsigned char *fastSAMModel_detect(fastSAMModel *obj, int colorRows,
int colorCols, unsigned char *colorData,
int grayRows, int grayCols,
unsigned char *grayData, float fx, float fy,
//以上是传入参数,以下是传出参数
float cx, float cy, int *outRows,
int *outCols, float **outArray,
int *outArraySize) {
//把python图像转换成cv::Mat格式
cv::Mat colorImage(colorRows, colorCols, CV_8UC3, colorData);
cv::Mat grayImage(grayRows, grayCols, CV_8UC1, grayData);
// 打印输入图像的尺寸
std::cout << "Input Color Image Size: " << colorImage.cols << " x "
<< colorImage.rows << std::endl;
std::cout << "Input Gray Image Size: " << grayImage.cols << " x "
<< grayImage.rows << std::endl;
// 显示接收到的彩色图像
// cv::imshow("Received Color Image", colorImage);
// cv::waitKey(1000); // 等待1毫秒以更新窗口
std::vector<std::vector<float>> objMessage;
cv::Mat processedImage =
obj->detect(colorImage, grayImage, fx, fy, cx, cy, objMessage);
//把返回的cv::Mat格式的图像转换成方便返回的格式
*outRows = processedImage.rows;
*outCols = processedImage.cols;
size_t data_size = processedImage.total() * processedImage.elemSize();
unsigned char *output = new unsigned char[data_size];
std::memcpy(output, processedImage.data, data_size);
// 转换 std::vector<std::vector<float>> 为平面数组
int totalSize = 0;
for (auto &subVec : objMessage) {
totalSize += subVec.size();
}
*outArray = new float[totalSize]; // 分配内存
int idx = 0;
for (auto &subVec : objMessage) {
for (float val : subVec) {
(*outArray)[idx++] = val;
}
}
*outArraySize = totalSize;
return output;
}
//用于释放内存
void fastSAMModel_deleteData(unsigned char *data) { delete[] data; }
void fastSAMModel_freeMemory(float *ptr) { delete[] ptr; }
}
编译成so动态库主要是为了python导入调用
cmake_minimum_required(VERSION 2.8.12)
set(CMAKE_CUDA_ARCHITECTURES 60 61 62 70 72 75 86)
set(CMAKE_CUDA_COMPILER /usr/local/cuda/bin/nvcc)
project(SAMModel LANGUAGES CXX CUDA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3 -g")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE Release)
option(CUDA_USE_STATIC_CUDA_RUNTIME OFF)
# CUDA
find_package(CUDA REQUIRED)
set(CUDA_LIBRARIES /usr/local/cuda-12.2/lib64/)
message(STATUS "CUDA Libs: \n${CUDA_LIBRARIES}\n")
message(STATUS "CUDA Headers: \n${CUDA_INCLUDE_DIRS}\n")
# OpenCV
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV Libs: \n${OpenCV_LIBS}\n")
message(STATUS "OpenCV Libraries: \n${OpenCV_LIBRARIES}\n")
message(STATUS "OpenCV Headers: \n${OpenCV_INCLUDE_DIRS}\n")
# TensorRT
set(TensorRT_INCLUDE_DIRS /usr/src/TensorRT-8.6.1.6/include)
set(TensorRT_LIBRARIES /usr/src/TensorRT-8.6.1.6/lib)
list(APPEND INCLUDE_DIRS
${CUDA_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
${TensorRT_INCLUDE_DIRS}
)
list(APPEND ALL_LIBS
${CUDA_LIBRARIES}
${OpenCV_LIBRARIES}
${TensorRT_LIBRARIES}
)
include_directories(${INCLUDE_DIRS})
add_executable(detectByImage
detectbyImage.cpp
include/fastSAMModel.cpp
)
target_link_directories(detectByImage PUBLIC ${ALL_LIBS})
target_link_libraries(detectByImage PUBLIC nvinfer nvinfer_plugin cudart ${OpenCV_LIBS} )
# Create a shared library from the specified source files
add_library(fastSamDet SHARED include/fastSAMNMSbox.hpp include/fastSAMModel.cpp FastSamrWrapper.cpp)
# Link the target library against the OpenCV libraries
target_link_directories(fastSamDet PUBLIC "/usr/local/cuda-12.2/lib64/" "/usr/src/TensorRT-8.6.1.6/lib" ${OpenCV_LIBRARIES})
target_link_libraries(fastSamDet PUBLIC nvinfer nvinfer_plugin cudart ${OpenCV_LIBS})
5.1、首先定义C++中的数据类型
# 定义 C++ 库中结构和函数( 类)
class fastSAMModel(ctypes.Structure):
pass
5.2、加载共享库
# 加载共享库
self.lib = ctypes.CDLL('./build/libfastSamDet.so')
5.3、设置构造函数中的参数
# 设置构造函数和析构函数的参数类型和返回类型
self.lib.fastSAMModel_new.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_int]
self.lib.fastSAMModel_new.restype = ctypes.POINTER(fastSAMModel)
self.lib.fastSAMModel_delete.argtypes = [ctypes.POINTER(fastSAMModel)]
self.lib.fastSAMModel_detect.argtypes = [
ctypes.POINTER(fastSAMModel),
ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float,
ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.POINTER(ctypes.c_float)), ctypes.POINTER(ctypes.c_int)
]
self.lib.fastSAMModel_detect.restype = ctypes.POINTER(ctypes.c_ubyte)
self.lib.fastSAMModel_deleteData.argtypes = [ctypes.POINTER(ctypes.c_ubyte)]
5.4、创建实例
# 创建模型实例
engine_file_path = b'./build/fast_sam_1024_cpu_g.engine'
input_w, input_h = 1024, 1024 # 示例输入尺寸
self.model = self.lib.fastSAMModel_new(engine_file_path, input_w, input_h)
5.5、调用函数
def fastsamDet(self,color_image,gray_image,fx, fy, cx, cy):
# 获取图像数据
color_data = color_image.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
gray_data = gray_image.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
# 准备输出尺寸变量
out_rows = ctypes.c_int()
out_cols = ctypes.c_int()
# 准备输出参数
outArray = ctypes.POINTER(ctypes.c_float)()
outArraySize = ctypes.c_int()
# 调用检测函数
processed_data = self.lib.fastSAMModel_detect(
self.model, color_image.shape[0], color_image.shape[1], color_data,
gray_image.shape[0], gray_image.shape[1], gray_data,
fx, fy, cx, cy, ctypes.byref(out_rows), ctypes.byref(out_cols),
ctypes.byref(outArray), ctypes.byref(outArraySize)
)
# 将返回的数据转换为 NumPy 数组
processed_image = np.ctypeslib.as_array(processed_data, shape=(out_rows.value, out_cols.value, 3))
# 确保图像数据是连续的
processed_image = np.ascontiguousarray(np.copy(processed_image), dtype=np.uint8)
self.lib.fastSAMModel_deleteData(processed_data)
# 将返回的数据转换为 Python 列表
result_list = [outArray[i] for i in range(outArraySize.value)]
# 记得释放在 C++ 中分配的内存
self.lib.fastSAMModel_freeMemory(outArray) # 假设你有一个专门用来释放内存的函数
return processed_image,result_list