环境:windows,vs2019,tensorflow2.5.0
1.首选需要手动编译tensorflow库,可以下载编译好的。
点击链接下载windows版本,我下载的支持gpu的
2.下载好后解压,打开vs,将库链接上vs,在属性中填写包含目录与库目录,以及附加依赖项
3.训练模型并以save_model格式保存,我的模型是输入图像预测一个值
4.代码如下,基于gpt得到的,快问冒烟了
#include <tensorflow/c/c_api.h>
#include <opencv2/opencv.hpp>
#include <chrono>
int main() {
// 读取图像
cv::Mat img = cv::imread("image_0_3940_3940_95.png", -1);
// 加载 TensorFlow 模型
TF_Graph* Graph;
TF_Status* Status;
TF_SessionOptions* SessionOpts;
TF_Session* Session;
TF_Buffer* RunOpts = NULL;
const char* saved_model_dir = "saved_model";
const char* tags = "serve"; // 默认的模型标签
int ntags = 1;
Graph = TF_NewGraph();
Status = TF_NewStatus();
SessionOpts = TF_NewSessionOptions();
// 设置模型配置
uint8_t intra_op_parallelism_threads = 1;
uint8_t inter_op_parallelism_threads = 1;
uint8_t buf[] = { 0x10, intra_op_parallelism_threads, 0x28, inter_op_parallelism_threads };
TF_SetConfig(SessionOpts, buf, sizeof(buf), Status);
if (TF_GetCode(Status) != TF_OK) {
printf("%s\n", TF_Message(Status));
return 1;
}
// 加载模型
Session = TF_LoadSessionFromSavedModel(SessionOpts, RunOpts, saved_model_dir, &tags, ntags, Graph, NULL, Status);
if (TF_GetCode(Status) != TF_OK) {
printf("%s\n", TF_Message(Status));
return 1;
}
// 获取输入和输出节点
TF_Output t_input = { TF_GraphOperationByName(Graph, "serving_default_resnet50_input"), 0 };
TF_Output t_output = { TF_GraphOperationByName(Graph, "StatefulPartitionedCall"), 0 };
if (t_input.oper == NULL) {
printf("ERROR: Failed TF_GraphOperationByName serving_default_resnet50_input\n");
return 1;
}
if (t_output.oper == NULL) {
printf("ERROR: Failed TF_GraphOperationByName StatefulPartitionedCall\n");
return 1;
}
// 图像预处理
cv::resize(img, img, cv::Size(224, 224)); // 调整图像大小
cv::cvtColor(img, img, cv::COLOR_BGR2RGB); // 如果模型期望通道顺序为RGB,进行通道顺序调整
img.convertTo(img, CV_32FC3); // 转换数据类型为32位浮点数
img /= 255.0; // 归一化
// 准备输入数据
const int input_rows = 224;
const int input_cols = 224;
const int input_channels = 3;
// 创建输入 tensor
const int64_t dims[] = { 1, input_rows, input_cols, input_channels };
TF_Tensor* input_tensor = TF_AllocateTensor(TF_FLOAT, dims, 4, input_rows * input_cols * input_channels * sizeof(float));
// 图像预处理并准备输入数据
// 获取指向输入 tensor 的内容指针
float* input_data = static_cast<float*>(TF_TensorData(input_tensor));
// 将预处理后的图像数据填充到输入 tensor 中
for (int row = 0; row < input_rows; ++row) {
for (int col = 0; col < input_cols; ++col) {
for (int channel = 0; channel < input_channels; ++channel) {
// 计算在一维数组中的索引
int index = (row * input_cols + col) * input_channels + channel;
// 填充数据
input_data[index] = img.at<cv::Vec3f>(row, col)[channel];
}
}
}
// 记录推理开始时间
auto start_time = std::chrono::high_resolution_clock::now();
// 运行会话进行推理
TF_Tensor* output_tensor = nullptr;
TF_SessionRun(Session, nullptr, &t_input, &input_tensor, 1, &t_output, &output_tensor, 1, nullptr, 0, nullptr, Status);
// 记录推理结束时间
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
printf("Inference Time: %lld ms\n", duration);
if (TF_GetCode(Status) != TF_OK) {
printf("%s\n", TF_Message(Status));
return 1;
}
// 处理输出数据
// TODO: 根据模型的输出要求进行适当的后处理
// 例如,解码分类结果等
// 获取指向输出 tensor 的内容指针
float* output_data = static_cast<float*>(TF_TensorData(output_tensor));
// 假设输出 tensor 的大小为 1xN(N为输出维度)
int output_size = TF_Dim(output_tensor, 1);
// 打印输出数据(示例)
printf("Output Data:\n");
for (int i = 0; i < output_size; ++i) {
printf("%f ", output_data[i]);
}
printf("\n");
// 打印推理时间
// 清理资源
TF_DeleteTensor(input_tensor);
TF_DeleteTensor(output_tensor);
return 0;
}
最后,不知道为什么推理的速度很慢,3秒多,远远慢与python预测,有知道的兄弟可以说一下
参考:
1.【Visual Studio Code】c/c++部署tensorflow训练的模型_tensorflow visual c++重构-优快云博客