c++ - 如何将张量转换为图像数组?

标签 c++ pytorch libtorch

我想将张量转换为图像数组并使用tensor.data()方法。

但是这不起作用。

#include <torch/script.h> // One-stop header.

#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImageRegionIterator.h"

//////////////////////////////////////////////////////
//Goal: load jit script model and segment myocardium
//Step: 1. load jit script model
//      2. load input image
//      3. predict by model
//      4. save the result to file
//////////////////////////////////////////////////////
typedef short                                               PixelType;
const unsigned int Dimension = 3;
typedef itk::Image<PixelType, Dimension>                    ImageType;
typedef itk::ImageFileReader<ImageType>                     ReaderType;
typedef itk::ImageRegionIterator<ImageType>                 IteratorType;

bool itk2tensor(ImageType::Pointer itk_img, torch::Tensor &tensor_img) {

    typename ImageType::RegionType region = itk_img->GetLargestPossibleRegion();
    const typename ImageType::SizeType size = region.GetSize();
    std::cout << "Input size: " << size[0] << ", " << size[1]<< ", " << size[2] << std::endl;

    int len = size[0] * size[1] * size[2];
    short rowdata[len];
    int count = 0;
    IteratorType iter(itk_img, itk_img->GetRequestedRegion());

    // convert itk to array
    for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter) {
        rowdata[count] = iter.Get();
        count++;
    }
    std::cout << "Convert itk to array DONE!" << std::endl;

    // convert array to tensor
    tensor_img = torch::from_blob(rowdata, {1, 1, (int)size[0], (int)size[1], (int)size[2]}, torch::kShort).clone();
    tensor_img = tensor_img.toType(torch::kFloat);
    tensor_img = tensor_img.to(torch::kCUDA);
    tensor_img.set_requires_grad(0);

    return true;
}


bool tensor2itk(torch::Tensor &t, ImageType::Pointer itk_img) {

    std::cout << "tensor dtype = " << t.dtype() << std::endl;
    std::cout << "tensor size = " << t.sizes() << std::endl;
    t = t.toType(torch::kShort);
    short * array = t.data<short>();

    ImageType::IndexType start;
    start[0] = 0;  // first index on X
    start[1] = 0;  // first index on Y
    start[2] = 0;  // first index on Z

    ImageType::SizeType  size;
    size[0] = t.size(2);
    size[1] = t.size(3);
    size[2] = t.size(4);

    ImageType::RegionType region;
    region.SetSize( size );
    region.SetIndex( start );

    itk_img->SetRegions( region );
    itk_img->Allocate();

    int len = size[0] * size[1] * size[2];

    IteratorType iter(itk_img, itk_img->GetRequestedRegion());
    int count = 0;
    // convert array to itk
    std::cout << "start!" << std::endl;
    for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter) {
        short temp = *array++;    //  ERROR!
        std::cout << temp << " ";
        iter.Set(temp);
        count++;
    }
    std::cout << "end!" << std::endl;

    return true;
}


int main(int argc, const char* argv[]) {
    int a, b, c;
    if (argc != 4) {
        std::cerr << "usage: automyo input jitmodel output\n";
        return -1;
    }

    std::cout << "=========  jit start  =========\n";
    // 1. load jit script model
    std::cout << "Load script module: " << argv[2] << std::endl;
    std::shared_ptr<torch::jit::script::Module> module = torch::jit::load(argv[2]);
    module->to(at::kCUDA);

    // assert(module != nullptr);
    std::cout << "Load script module DONE" << std::endl;

    // 2. load input image
    const char* img_path = argv[1];
    std::cout << "Load image: " << img_path << std::endl;

    ReaderType::Pointer reader = ReaderType::New();

    if (!img_path) {
        std::cout << "Load input file error!" << std::endl;
        return false;
    }

    reader->SetFileName(img_path);
    reader->Update();

    std::cout << "Load image DONE!" << std::endl;

    ImageType::Pointer itk_img = reader->GetOutput();

    torch::Tensor tensor_img;
    if (!itk2tensor(itk_img, tensor_img)) {
        std::cerr << "itk2tensor ERROR!" << std::endl;
    }
    else {
        std::cout << "Convert array to tensor DONE!" << std::endl;
    }

    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(tensor_img);

    // 3. predict by model
    torch::Tensor y = module->forward(inputs).toTensor();
    std::cout << "Inference DONE!" << std::endl;

    // 4. save the result to file
    torch::Tensor seg = y.gt(0.5);
    // std::cout << seg << std::endl;

    ImageType::Pointer out_itk_img = ImageType::New();
    if (!tensor2itk(seg, out_itk_img)) {
        std::cerr << "tensor2itk ERROR!" << std::endl;
    }
    else {
        std::cout << "Convert tensor to itk DONE!" << std::endl;
    }

    std::cout << out_itk_img << std::endl;

    return true;
}

运行日志如下所示:

Load script module:model_myo_jit.pt

Load script module DONE Load

image: patch_6.nii.gz

Load image DONE!

Input size: 128, 128, 128

Convert itk to array DONE!

Convert array to tensor DONE!

Inference DONE!

tensor dtype = unsigned char

tensor size = [1, 1, 96, 96, 96]

start!

Segmentation fault (core dumped)

为什么以及如何转换?

最佳答案

我已经找到解决办法了。当我将 y 转换为 kCPU 时,它可以工作。因为之前是在CUDA中。

关于c++ - 如何将张量转换为图像数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55899140/

相关文章:

c++ - 如何在 LibTorch (C++) 中将 torch::Torch 的类型从 Float 更改为 Long

c++ - 使用 MinGW 构建自适应通信环境 (ACE)

java - 从文件夹中排除 cpp 而不删除

c++ - cat(3,A,B) Matlab 函数。相当于 opencv3 (c++)

python - CNN 首先进行特征关键点预测,然后使用 Pytorch 或 TensorFlow 根据这些关键点对图像进行分类

python - conv2d 之后的 PyTorch CNN 线性层形状

opencv - LibTorch C++和Eigen之间的数据传输

C++ 快速排序字母数组

neural-network - 为什么在神经网络类定义中使用多个 ReLU 对象?

opencv - 无法使用 cmake 与 OpenCV 和 LibTorch 链接项目