简体   繁体   中英

Converting vector of floats in CHW format to a cv::Mat

I have a std:vector<float> storing elements in CHW format. Here, C=8, H=48, W=48 .

I wish to store this in a cv::Mat in HWC format.

I am clueless as to how to do this.

One of the simplest methods is to create single-channel cv::Mat s of size 48 x 48, then merge them all together with cv::merge .

Below is a function that takes in a std::vector<float> with the number of rows, columns and channels then creates a final cv::Mat that is of size H x W x C . Since your data is in C x H x W format, this unfortunately becomes a bit more difficult as the data per channel is not in a contiguous format. Specifically, if the data was in a typical H x W x C format, the way to access the data in a flattened format would be:

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

(i, j, k) would be the row, column and channel indices to access the corresponding element in the vector. Your data is in C x H x W format which means to access the data in a flattened format:

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

Therefore, we will iterate over each channel k , and grab the row and column location (i, j) and temporarily store it into a vector then use this vector and create a single-channel cv::Mat . We'll then stack these cv::Mat s at the very end.

#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;
}

To use this function:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM