Wie konvertiert man einen Torch::Tensor in ein cv::InputArray?
Ich versuche, die zu verwenden cv::getAffineTransform(), und ich stecke fest, wie ich die Tensoren in die entsprechenden umwandeln kann cv::InputArray. Ich habe diese versucht, um Zugriffsverletzungen zu begegnen:
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());
Was mache ich hier falsch? Gibt es eine Möglichkeit, den zugrunde liegenden Puffer zu teilen und das Kopieren überhaupt zu vermeiden?
Antworten
Es stellt sich heraus, dass die Angabe der Maße in der cv::Matfür eine gelungene Kopie notwendig war! Das heißt, ich musste dies tun:
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;
Und dies führt nicht mehr zu einer Zugriffsverletzung. und ich kann überprüfen, ob die Werte kopiert werden:
[1.1;
2;
3.3]
[1.1;
2;
3.3]
Da im vorherigen Beispiel erfundene Eingabedaten verwendet wurden, cv::getAffineTransform()stürzt das ab. Hier ist eine realistischere Eingabe und Ausgabe, die Sie ausführen und sehen können, dass es funktioniert:
Methode 1: Verwenden std::memcpyzum Kopieren der Daten:
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;
Und
Methode 2: Verwenden des zugrunde liegenden Puffers anstelle des Kopierens:
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>());