OpenCV Image Mat to 1D CHW(RR...R, GG..G, BB..B) vector

Viewed 5739

Nvidia's cuDNN for deep learning has a rather interesting format for images called CHW. I have a cv::Mat img; that I want to convert to a one-dimensional vector of floats. The problem that I'm having is that the format of the 1D vector for CHW is (RR...R, GG..G,BB..B).

So I'm curious as to how I can extract the channel values for each pixel and order them for this format.

3 Answers

I faced with same problem and and solve it in that way:

#include <opencv2/opencv.hpp>

cv::Mat hwc2chw(const cv::Mat &image){
    std::vector<cv::Mat> rgb_images;
    cv::split(image, rgb_images);

    // Stretch one-channel images to vector
    cv::Mat m_flat_r = rgb_images[0].reshape(1,1);
    cv::Mat m_flat_g = rgb_images[1].reshape(1,1);
    cv::Mat m_flat_b = rgb_images[2].reshape(1,1);

    // Now we can rearrange channels if need
    cv::Mat matArray[] = { m_flat_r, m_flat_g, m_flat_b};
    
    cv::Mat flat_image;
    // Concatenate three vectors to one
    cv::hconcat( matArray, 3, flat_image );
    return flat_image;
}

P.S. If input image isn't in RGB format, you can change channel order in matArray creation line.

Use cv::dnn::blobFromImage:

cv::Mat bgr_image = cv::imread(imageFileName);

cv::Mat chw_image = cv::dnn::blobFromImage
(
    bgr_image, 1.0, // scale factor
    cv::Size(), // spatial size for output image
    cv::Scalar(), // mean
    true, // swapRB: BGR to RGB
    false, // crop
    CV_32F // Depth of output blob. Choose CV_32F or CV_8U.
);

const float* data = reinterpret_cast<const float*>(chw_image.data);

int data_length = 1 * 3 * bgr_image.rows * bgr_image.cols;
Related