libtorch基本操作

可以采用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.

Tensor内存操作

可以直接通过void*指针得到Tensor

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


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 image.data 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 image.data 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 tensor.data() to access a tensor’s underlying data through a T*. For example, tensor_image.data() 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);

Tensor基本操作

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


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

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

namespace F = torch::nn::functional;
image_tensor = F::interpolate(
        image_tensor,
        F::InterpolateFuncOptions()
                .mode(torch::kBilinear)
                .size(std::vector<int64_t>({512, 512}))
                .align_corners(true)
);
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 *) test_mat.data, image_tensor.data_ptr(), sizeof(torch::kU8) * image_tensor.numel());
cv::imshow("test", test_mat);
cv::waitKey(0);

数据读取

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

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

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


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

参考