第一个onnxruntime c++项目

同样是图像分割的c++ inference,已经实现过libtorch和ncnn框架的c++推理,今天实现一下onnxruntime的c++推理。
使用的其他库和工具:

  • 1、 opencv4.5.2
  • 2、onnxruntime1.8.0
  • 3、visual studio 2017

代码如下

#include <assert.h>
#include <vector>
#include <onnxruntime_cxx_api.h>
#include <iostream>
#include "img_seg.h"
#pragma  warning(disable:4996)
using namespace std;

float sigmoid(float x) {
    
    
	return 1.0 / (1.0 + exp(-x));
}

int main(int argc, char* argv[]) {
    
    

	Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
	Ort::SessionOptions session_options;
	Ort::Session session_{
    
     nullptr };
	session_options.SetIntraOpNumThreads(1);

	session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);

#ifdef _WIN32
	const wchar_t* model_path = L"BiSeNet.onnx";
#else
	const char* model_path = "BiSeNet.onnx";
#endif

	//Ort::Session session(env, model_path, session_options);
	session_ = Ort::Session(env, model_path, session_options);
	cout << "session created sucess" << endl;
	// print model input layer (node names, types, shape etc.)
	Ort::AllocatorWithDefaultOptions allocator;

	//输入输出节点数量和名称
	size_t num_input_nodes = session_.GetInputCount();
	size_t num_output_nodes = session_.GetOutputCount();
	Ort::AllocatorWithDefaultOptions ort_alloc;
	std::vector<const char*>input_node_names;
	std::vector<const char*>output_node_names;
	std::vector<int64_t> input_node_dims;
	std::vector<int64_t> output_node_dims;

	for (int i = 0; i < num_input_nodes; i++)
	{
    
    
		auto input_node_name = session_.GetInputName(i, allocator);
		input_node_names.push_back(input_node_name);
		Ort::TypeInfo type_info = session_.GetInputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		ONNXTensorElementDataType type = tensor_info.GetElementType();
		input_node_dims = tensor_info.GetShape();
	}
	for (int i = 0; i < num_output_nodes; i++)
	{
    
    
		auto output_node_name = session_.GetOutputName(i, allocator);
		output_node_names.push_back(output_node_name);
		Ort::TypeInfo type_info = session_.GetOutputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		output_node_dims = tensor_info.GetShape();
	}

	cv::Mat image = cv::imread("0166096.jpg");
	cv::resize(image, image, {
    
     512, 512 }, 0.0, 0.0, cv::INTER_CUBIC);//调整大小到512*512
	cv::imshow("image", image);                                     //打印原图片
	cv::waitKey();
	cv::cvtColor(image, image, cv::COLOR_BGR2RGB);                  //BRG格式转化为RGB格式
	//input_node_dims[0] = 1;
	float* floatarr = nullptr;
	int input_tensor_size = image.cols * image.rows * 3;
	std::size_t counter = 0;//std::vector空间一次性分配完成,避免过多的数据copy
	std::vector<float>input_data(input_tensor_size);
	std::vector<float>output_data;
	// 此处内置了减均值0.5,比方差0.5
	for (unsigned k = 0; k < 3; k++)
	{
    
    
		for (unsigned i = 0; i < image.rows; i++)
		{
    
    
			for (unsigned j = 0; j < image.cols; j++)
			{
    
    
				input_data[counter++] = (static_cast<float>(image.at<cv::Vec3b>(i, j)[k]) / 255.0 - 0.5)/0.5;
			}
		}
	}
	   
	auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
	Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_data.data(), input_tensor_size, input_node_dims.data(), 4);
	assert(input_tensor.IsTensor());

	auto output_tensors = session_.Run(Ort::RunOptions{
    
     nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
	assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
	floatarr = output_tensors.front().GetTensorMutableData<float>();
	int64_t output_tensor_size = 1;
	for (auto& it : output_node_dims)
	{
    
    
		output_tensor_size *= it;
	}
	std::vector<float>results(output_tensor_size);
	for (unsigned i = 0; i < output_tensor_size; i++)
	{
    
    
		results[i] = floatarr[i];
		//results[i] = sigmoid(floatarr[i]); // 使用sigmoid函数
	}
	
	cv::Mat output_tensor(results);
	output_tensor = output_tensor.reshape(1, {
    
     512,512 })*255.0;
	//cv::threshold(output_tensor, output_tensor, 20, 255, cv::THRESH_BINARY_INV);
	cv::imshow("result", output_tensor);                                   //打印结果
	cv::waitKey(0);
	return 0;
}


说明,在使用

输入图片和输出mask结果
在这里插入图片描述

在这里插入图片描述
后来使用sigmoid也可以实现正常效果了,代码如下:
主要不同的操作是使用了sigmoid,并且后面不需要×255.0。

#include <assert.h>
#include <vector>
#include <onnxruntime_cxx_api.h>
#include <iostream>
#include "img_seg.h"
#pragma  warning(disable:4996)
using namespace std;

float sigmoid(float x) {
    
    
	return 1.0 / (1.0 + exp(-x));
}

int main(int argc, char* argv[]) {
    
    

	//记录程序运行时间
	auto start_time = clock();
	Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
	Ort::SessionOptions session_options;
	Ort::Session session_{
    
     nullptr };
	session_options.SetIntraOpNumThreads(2);

	session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);

#ifdef _WIN32
	const wchar_t* model_path = L"BiSeNet.onnx";
#else
	const char* model_path = "BiSeNet.onnx";
#endif

	//Ort::Session session(env, model_path, session_options);
	session_ = Ort::Session(env, model_path, session_options);
	cout << "session created sucess" << endl;
	// print model input layer (node names, types, shape etc.)
	Ort::AllocatorWithDefaultOptions allocator;

	//输入输出节点数量和名称
	size_t num_input_nodes = session_.GetInputCount();
	size_t num_output_nodes = session_.GetOutputCount();
	Ort::AllocatorWithDefaultOptions ort_alloc;
	std::vector<const char*>input_node_names;
	std::vector<const char*>output_node_names;
	std::vector<int64_t> input_node_dims;
	std::vector<int64_t> output_node_dims;

	for (int i = 0; i < num_input_nodes; i++)
	{
    
    
		auto input_node_name = session_.GetInputName(i, allocator);
		input_node_names.push_back(input_node_name);
		Ort::TypeInfo type_info = session_.GetInputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		ONNXTensorElementDataType type = tensor_info.GetElementType();
		input_node_dims = tensor_info.GetShape();
	}
	for (int i = 0; i < num_output_nodes; i++)
	{
    
    
		auto output_node_name = session_.GetOutputName(i, allocator);
		output_node_names.push_back(output_node_name);
		Ort::TypeInfo type_info = session_.GetOutputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		output_node_dims = tensor_info.GetShape();
	}

	cv::Mat image = cv::imread("0166096.jpg");
	cv::resize(image, image, {
    
     512, 512 }, 0.0, 0.0, cv::INTER_CUBIC);//调整大小到512*512
	//cv::imshow("image", image);                                     //打印原图片
	//cv::waitKey();
	cv::cvtColor(image, image, cv::COLOR_BGR2RGB);                  //BRG格式转化为RGB格式
	//input_node_dims[0] = 1;
	float* floatarr = nullptr;
	int input_tensor_size = image.cols * image.rows * 3;
	std::size_t counter = 0;//std::vector空间一次性分配完成,避免过多的数据copy
	std::vector<float>input_data(input_tensor_size);
	std::vector<float>output_data;
	// 此处内置了减均值0.5,比方差0.5
	for (unsigned k = 0; k < 3; k++)
	{
    
    
		for (unsigned i = 0; i < image.rows; i++)
		{
    
    
			for (unsigned j = 0; j < image.cols; j++)
			{
    
    
				input_data[counter++] = (static_cast<float>(image.at<cv::Vec3b>(i, j)[k]) / 255.0 - 0.5)/0.5;
			}
		}
	}
	   
	auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
	Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_data.data(), input_tensor_size, input_node_dims.data(), 4);
	assert(input_tensor.IsTensor());

	auto output_tensors = session_.Run(Ort::RunOptions{
    
     nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
	assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
	floatarr = output_tensors.front().GetTensorMutableData<float>();
	int64_t output_tensor_size = 1;
	for (auto& it : output_node_dims)
	{
    
    
		output_tensor_size *= it;
	}
	std::vector<float>results(output_tensor_size);
	for (unsigned i = 0; i < output_tensor_size; i++)
	{
    
    
		//results[i] = floatarr[i];
		results[i] = sigmoid(floatarr[i]);
	}
	// 需要sigmoid函数
	cv::Mat output_tensor(results);
	output_tensor = output_tensor.reshape(1, {
    
     512,512 });//*255.0
	//cv::threshold(output_tensor, output_tensor, 20, 255, cv::THRESH_BINARY_INV);
	cv::imshow("result", output_tensor);                                   //打印结果
	cv::waitKey(0);
	auto end_time = clock();
	printf("Proceed exit after %.2f seconds\n", static_cast<float>(end_time - start_time) / CLOCKS_PER_SEC);
	printf("Done!\n");
	return 0;
}


在这里插入图片描述
不使用sigmoid,也不×255效果也不错

#include <assert.h>
#include <vector>
#include <onnxruntime_cxx_api.h>
#include <iostream>
#include <chrono>
#include "img_seg.h"
#pragma  warning(disable:4996)
using namespace std;

float sigmoid(float x) {
    
    
	return 1.0 / (1.0 + exp(-x));
}

int main(int argc, char* argv[]) {
    
    

	//记录程序运行时间
	auto start_time = clock();
	Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
	Ort::SessionOptions session_options;
	Ort::Session session_{
    
     nullptr };
	session_options.SetIntraOpNumThreads(2);

	session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);

#ifdef _WIN32
	const wchar_t* model_path = L"BiSeNet.onnx";
#else
	const char* model_path = "BiSeNet.onnx";
#endif

	//Ort::Session session(env, model_path, session_options);
	session_ = Ort::Session(env, model_path, session_options);
	cout << "session created sucess" << endl;
	// print model input layer (node names, types, shape etc.)
	Ort::AllocatorWithDefaultOptions allocator;

	//输入输出节点数量和名称
	size_t num_input_nodes = session_.GetInputCount();
	size_t num_output_nodes = session_.GetOutputCount();
	Ort::AllocatorWithDefaultOptions ort_alloc;
	std::vector<const char*>input_node_names;
	std::vector<const char*>output_node_names;
	std::vector<int64_t> input_node_dims;
	std::vector<int64_t> output_node_dims;

	for (int i = 0; i < num_input_nodes; i++)
	{
    
    
		auto input_node_name = session_.GetInputName(i, allocator);
		input_node_names.push_back(input_node_name);
		Ort::TypeInfo type_info = session_.GetInputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		ONNXTensorElementDataType type = tensor_info.GetElementType();
		input_node_dims = tensor_info.GetShape();
	}
	for (int i = 0; i < num_output_nodes; i++)
	{
    
    
		auto output_node_name = session_.GetOutputName(i, allocator);
		output_node_names.push_back(output_node_name);
		Ort::TypeInfo type_info = session_.GetOutputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		output_node_dims = tensor_info.GetShape();
	}

	cv::Mat image = cv::imread("0166096.jpg");
	cv::resize(image, image, {
    
     512, 512 }, 0.0, 0.0, cv::INTER_CUBIC);//调整大小到512*512
	//cv::imshow("image", image);                                     //打印原图片
	//cv::waitKey();
	cv::cvtColor(image, image, cv::COLOR_BGR2RGB);                  //BRG格式转化为RGB格式
	//input_node_dims[0] = 1;
	float* floatarr = nullptr;
	int input_tensor_size = image.cols * image.rows * 3;
	std::size_t counter = 0;//std::vector空间一次性分配完成,避免过多的数据copy
	std::vector<float>input_data(input_tensor_size);
	std::vector<float>output_data;
	// 此处内置了减均值0.5,比方差0.5
	for (unsigned k = 0; k < 3; k++)
	{
    
    
		for (unsigned i = 0; i < image.rows; i++)
		{
    
    
			for (unsigned j = 0; j < image.cols; j++)
			{
    
    
				input_data[counter++] = (static_cast<float>(image.at<cv::Vec3b>(i, j)[k]) / 255.0 - 0.5)/0.5;
			}
		}
	}
	   
	auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
	Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_data.data(), input_tensor_size, input_node_dims.data(), 4);
	assert(input_tensor.IsTensor());
	std::chrono::steady_clock::time_point begin =
		std::chrono::steady_clock::now();
	auto output_tensors = session_.Run(Ort::RunOptions{
    
     nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
	assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
	floatarr = output_tensors.front().GetTensorMutableData<float>();
	std::chrono::steady_clock::time_point end =
		std::chrono::steady_clock::now();
	std::cout << "Minimum Inference Latency: "
		<< std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() / static_cast<float>(1)
		<< " ms" << std::endl;
	int64_t output_tensor_size = 1;
	for (auto& it : output_node_dims)
	{
    
    
		output_tensor_size *= it;
	}
	std::vector<float>results(output_tensor_size);
	for (unsigned i = 0; i < output_tensor_size; i++)
	{
    
    
		results[i] = floatarr[i];
		//results[i] = sigmoid(floatarr[i]);
	}
	// 需要sigmoid函数
	cv::Mat output_tensor(results);
	output_tensor = output_tensor.reshape(1, {
    
     512,512 });//*255.0
	//cv::threshold(output_tensor, output_tensor, 20, 255, cv::THRESH_BINARY_INV);	
	auto end_time = clock();
	printf("Proceed exit after %.2f seconds\n", static_cast<float>(end_time - start_time) / CLOCKS_PER_SEC);
	printf("Done!\n");
	cv::imshow("result", output_tensor);                                   //打印结果
	cv::waitKey(0);
	return 0;
}


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/juluwangriyue/article/details/118265026#comments_22619820
今日推荐