【问题标题】:OpenCV Image Mat to 1D CHW(RR...R, GG..G, BB..B) vectorOpenCV Image Mat 到 1D CHW(RR...R, GG..G, BB..B) 向量
【发布时间】:2017-05-21 07:31:13
【问题描述】:

Nvidia 用于深度学习的 cuDNN 有一种非常有趣的图像格式,称为 CHW。我有一个 cv::Mat img;我想转换为浮点数的一维向量。我遇到的问题是 CHW 的一维向量的格式是(RR...R,GG..G,BB..B)。

所以我很好奇如何提取每个像素的通道值并为这种格式排序。

【问题讨论】:

  • 使用 cv::split 并将单个通道复制到单个内存空间应该可以吗?但可能有更简单的方法

标签: c++ opencv cudnn


【解决方案1】:

您可以手动迭代图像并将值复制到正确的位置,或者您可以使用cv::extractChannel 之类的东西来一一复制通道,如下所示:

#include <opencv2/opencv.hpp>

int main()
{
    //create dummy 3 channel float image
    cv::Mat sourceRGB(cv::Size(100,100),CV_32FC3);
    auto size = sourceRGB.size();
    for (int y = 0; y < size.height; ++y)
    {
        for (int x = 0; x < size.width; ++x)
        {
            float* pxl = sourceRGB.ptr<float>(x, y);
            *pxl = x / 100.0f;
            *(pxl+1) = y / 100.0f;
            *(pxl + 2) = (y / 100.0f) * (x / 100.0f);
        }
    }

    cv::imshow("test", sourceRGB);
    cv::waitKey(0);

    //create single image with all 3 channels one after the other
    cv::Size newsize(size.width,size.height*3);
    cv::Mat destination(newsize,CV_32FC1);

    //copy the channels from the source image to the destination
    for (int i = 0; i < sourceRGB.channels(); ++i)
    {
        cv::extractChannel(
            sourceRGB,
            cv::Mat(
                size.height,
                size.width,
                CV_32FC1,
                &(destination.at<float>(size.height*size.width*i))),
            i);
    }

    cv::imshow("test", destination);
    cv::waitKey(0);
    return 0;
}

【讨论】:

    【解决方案2】:

    我遇到了同样的问题并以这种方式解决它:

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

    附:如果输入图像不是 RGB 格式,您可以在 matArray 创建行中更改通道顺序。

    【讨论】:

      【解决方案3】:

      使用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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-29
        • 2020-01-24
        • 2020-06-10
        • 1970-01-01
        • 1970-01-01
        • 2013-02-20
        • 2020-04-23
        相关资源
        最近更新 更多