Преобразование вектора чисел с плавающей запятой в формате CHW в cv :: Mat - PullRequest
0 голосов
/ 08 июля 2020

У меня есть std:vector<float> элементы хранения в формате CHW. Здесь C=8, H=48, W=48.

Я использую sh, чтобы сохранить это в cv::Mat в формате HW C.

Я не знаю, как это сделать.

1 Ответ

1 голос
/ 09 июля 2020

Один из простейших способов - создать одноканальные cv::Mat s размером 48 x 48, а затем объединить их все вместе с cv::merge.

Ниже приведена функция который принимает std::vector<float> с количеством строк, столбцов и каналов, а затем создает окончательный cv::Mat с размером H x W x C. Поскольку ваши данные имеют формат C x H x W, это, к сожалению, становится немного сложнее, поскольку данные на канал не имеют непрерывного формата. В частности, если данные были в типичном формате H x W x C, способ доступа к данным в плоском формате был бы следующим:

HWC ---> index = (i*cols + j) + k*rows*cols

(i, j, k) будет индексами строки, столбца и канала для доступа соответствующий элемент в векторе. Ваши данные имеют формат C x H x W, что означает доступ к данным в упорядоченном формате:

CHW ---> index = (k*rows + i) + j*channels*rows

Следовательно, мы будем перебирать каждый канал k и выбирать расположение строки и столбца (i, j) и временно сохраните его в векторе, затем используйте этот вектор и создайте одноканальный cv::Mat. Затем мы сложим эти cv::Mat в самый конец.

#include <opencv2/opencv.hpp>

cv::Mat CreateMatFromVector(const std::vector<float>& data, const int rows, const int cols, const int channels)
{
    // Create stacked vector of cv::Mats
    std::vector<cv::Mat> stacked_mats;
    stacked_mats.reserve(channels);  // Reserve space for efficiency

    // Stack the channels
    for (int k = 0; k < channels; ++k) {
        std::vector<float> pixels;
        pixels.reserve(rows * cols);
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                pixels.push_back(data[k * rows + i + j * channels * rows]);
            }
        }
        cv::Mat channel(rows, cols, CV_32FC1, pixels.data());
        stacked_mats.push_back(channel);
    }

    // Stores output matrix
    cv::Mat output;

    // Create the output matrix
    cv::merge(stacked_mats, output);

    return output;
}

Чтобы использовать эту функцию:

std::vector<float> data = ...; // Data is created here
cv::Mat output = CreateMatFromVector(data, 48, 48, 8);
...