opencv Mat格式转onnxruntime格式 c++

opencv Mat格式转onnxruntime格式 c++

  • 1、opencv cv::Mat转 onnx Tensor
  • 2、自己用过的 cv:Mat和 onnxruntime Tensor互转

1、opencv cv::Mat转 onnx Tensor

下面的代码假设使用3通道处理数据 (通常就是这样子的)

     resize_img.convertTo(resize_img, CV_32F, 1.0 / 255);  //divided by 255
        resize_img -= 0.5f;  // mean
        resize_img /= 0.5f;   // std
        cv::Mat channels[3]; //借用来进行HWC->CHW
        cv::split(resize_img, channels);
        std::vector<float> inputTensorValues;
        for (int i = 0; i < resize_img.channels(); i++)  // BGR2RGB, HWC->CHW
        {
            std::vector<float> data = std::vector<float>(channels[2 - i].reshape(1, resize_img.cols * resize_img.rows));
            inputTensorValues.insert(inputTensorValues.end(), data.begin(), data.end());
        } 
 
// inputTensorValues 可以作为输入数据送入onnxruntime

以上代码完成了opencv的cv:Mat 数据(images load得到)到onnxruntime需要的tensor数据的转换.

如果不同的通道需要不同的mean/std

可以将上面的操作改为三通道操作, mean/std可以通过数组方式带入

         float mean[]={0.5f,0.5f,0.5f};
        float std_val[]={0.5f,0.5f,0.5f};
        resize_img.convertTo(resize_img, CV_32F, 1.0 / 255);  //divided by 255
 
        cv::Mat channels[3]; //借用来进行HWC->CHW
        cv::split(resize_img, channels);
        std::vector<float> inputTensorValues;
        for(int i=0; i< resize_img.channels(); i++)
        {
       channels[i] -= mean[i];  // mean
        channels[i] /= std_val[i];   // std
        }
        for (int i = 0; i < resize_img.channels(); i++)  // BGR2RGB, HWC->CHW
        {
            std::vector<float> data = std::vector<float>(channels[2 - i].reshape(1, resize_img.cols * resize_img.rows));
            inputTensorValues.insert(inputTensorValues.end(), data.begin(), data.end());
        }
 
 
// inputTensorValues 可以作为输入数据送入onnxruntime

参考: opencv之Mat格式数据转换成onnxruntime的输入tensor处理的c++写法

2、自己用过的 cv:Mat和 onnxruntime Tensor互转

cv::Mat转 onnxruntime Tensor

	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());

onnxruntime Tensor转cv::Mat

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);                            

参考:第一个onnxruntime c++项目

你可能感兴趣的:(onnx,opencv,opencv,onnx)