可以采用cling C++ notebook的方式去实际操作学习一下。

/// IValue (Interpreter Value) is a tagged union over the types /// supported by the TorchScript interpreter. IValues contain their /// values as an IValue::Payload, which holds primitive types /// (int64_t, bool, double, Device) and Tensor as values, /// and all other types as a c10::intrusive_ptr. In order to /// optimize performance of the destructor and related operations by /// making the Tensor and c10::intrusive_ptr paths generate the /// same code, we represent a null c10::intrusive_ptr as /// UndefinedTensorImpl::singleton(), not nullptr.



at::Tensor tensor_image = torch::from_blob(, {1, 3, image.rows, image.cols}, at::kByte);
tensor_image =;

std::unique_ptr<float[]> outputData(new float[1*17*96*72]);
auto res_point = torch::from_blob(outputData.get(), {input_shape[0],input_shape[1],input_shape[2],input_shape[3]});

Here, I assume that is 8-bit byte values. The to(at::kFloat) will convert the 8-bit values into 32-bit floating points just as if you wrote static_cast(b) where b is a byte – just in case that wasn’t clear. If is already floats, you can just write at::kFloat in place of at::kByte and skip the conversion of course. What’s super important to know is that from_blob does not take ownership of the data! It only interprets the data as a tensor, but doesn’t store the data itself. It’s easy to fix this if you want to, by calling .clone() on the tensor, since that will incur a copy of the data such that the resulting tensor will indeed own its data (which means the original cv::Mat can be destroyed and the cloned tensor will live on).

On the other side, it’s actually easier. You can use to access a tensor’s underlying data through a T*. For example, would give you a float*. If you want a more raw void* because you’re dumping the raw data somewhere else, there’s also a data_ptr() method that gives you a raw byte pointer.

Let me know if this helps.

// 假如传入的数据来自GPU void* input_buffer = ...
auto options = torch::TensorOptions().device(at::kCUDA);
auto detections = torch::from_blob(input_buffer, {input_shape[0],input_shape[1],input_shape[2]}, options);


cv::Mat image = cv::imread("/home/lll/Pictures/test.jpg");

torch::Tensor image_tensor = torch::from_blob(, {image.rows, image.cols, 3}, torch::kByte);

image_tensor = image_tensor.permute({2, 0, 1}).toType(torch::kFloat).div_(255);
image_tensor = image_tensor.unsqueeze(0);
image_tensor =;
image_tensor = image_tensor.contiguous();  // 必要

namespace F = torch::nn::functional;
image_tensor = F::interpolate(
                .size(std::vector<int64_t>({512, 512}))
image_tensor = image_tensor.mul(0.5).add(0.5).mul(255);
image_tensor = image_tensor.squeeze(0).permute({1, 2, 0}).toType(torch::kByte).to(torch::kCPU);

cv::Mat test_mat(512, 512, CV_8UC3);
std::memcpy((void *), image_tensor.data_ptr(), sizeof(torch::kU8) * image_tensor.numel());
cv::imshow("test", test_mat);


    class Container(torch.nn.Module):
        def __init__(self, my_values):
            for key in my_values:
                setattr(self, key, my_values[key])

    my_values = {
        'res': prediction.cpu()

    container = torch.jit.script(Container(my_values))"")

torch::jit::script::Module container = torch::jit::load("/data/yanzong/code/data/debug/");
auto res = container.attr("res").toTensor();