Как преобразовать torch::Tensor в cv::inputArray?

#c #opencv #torch #libtorch

#c #opencv #torch #libtorch

Вопрос:

Я пытаюсь использовать cv::getAffineTransform() , и я застрял на том, как преобразовать тензоры в соответствующие cv::InputArray . Я пробовал их, чтобы столкнуться с нарушением доступа :

 torch::Tensor src = torch::tensor({ 1.1, 2.0, 3.3 });
torch::Tensor dst = torch::tensor({ 1.1, 2.0, 3.3 });

cv::Mat input_array;
cv::Mat destination_array;
std::memcpy(input_array.data, src.data_ptr<float>(), sizeof(float) * src.numel());
std::memcpy(destination_array.data, dst.data_ptr<float>(), sizeof(float) * dst.numel());
  

Что я здесь делаю не так?
Есть ли способ совместно использовать базовый буфер и вообще избежать копирования?

Ответ №1:

Завершается указание размеров в cv::Mat было необходимо для успешного копирования! То есть мне нужно было сделать это :

 cv::Mat input_array (3, 1, CV_32FC1);
cv::Mat destination_array (3, 1, CV_32FC1);

std::memcpy(input_array.data, src.data_ptr<float>(), sizeof(float) * src.numel());
std::memcpy(destination_array.data, dst.data_ptr<float>(), sizeof(float) * dst.numel());

std::cout << input_array << std::endl;
std::cout << destination_array << std::endl;
  

И это больше не приводит к нарушению доступа. и я могу проверить, что значения действительно копируются :

 [1.1;
 2;
 3.3]
[1.1;
 2;
 3.3]
  

Поскольку в предыдущем примере использовались введенные данные, cv::getAffineTransform() произойдет сбой, поэтому вот более реалистичный ввод и вывод, который вы можете запустить и посмотреть, что это работает:

Способ 1: Использование std::memcpy для копирования данных:

 torch::Tensor src = torch::tensor({ {137.47012, 62.52604}, {170.50703, 64.21498}, {154.49675, 80.78379} });
torch::Tensor dst = torch::tensor({ {38.294598, 51.6963}, {73.5318, 51.5014}, {56.0252, 71.7366} });

std::cout << "src.shapes: " << src.sizes() << std::endl;
std::cout << "dst.shapes: " << dst.sizes() << std::endl;

int rows = src.sizes()[0];
int cols = (src.sizes().size() == 1) ? 1 : src.sizes()[1];

cv::Mat input_array (rows, cols, CV_32FC1);
cv::Mat destination_array (rows, cols, CV_32FC1);

std::memcpy(input_array.data, src.data_ptr<float>(), sizeof(float) * src.numel());
std::memcpy(destination_array.data, dst.data_ptr<float>(), sizeof(float) * dst.numel());

std::cout << "input_array:n" << input_array << std::endl;
std::cout << "destination_array:n" << destination_array << std::endl;

auto tfm = cv::getAffineTransform(input_array, destination_array);
std::cout << "tfm:n" << tfm << std::endl;
  

И
Способ 2 : Использование базового буфера вместо копирования :

 int height = src.sizes()[0];
int width = src.sizes()[1];
cv::Mat input_array(cv::Size{width, height }, CV_32F, src.data_ptr<float>());
cv::Mat destination_array(cv::Size{ width, height }, CV_32F, dst.data_ptr<float>());