【问题标题】:Reading image into C++, using column major Matlab-style data layout?将图像读入 C++,使用列主要 Matlab 样式的数据布局?
【发布时间】:2013-09-28 21:24:53
【问题描述】:

我正在用 C++ 做一些计算机视觉方面的工作,处理 JPG 图像。在 C++ 中,我从 Piotr Dollar's Toolbox 调用计算机视觉函数,这些函数最初是为与 Matlab 兼容而设计的。 我试图弄清楚如何从 C++ 文件中快速加载图像,并将它们排列成 Matlab 风格的数据布局。


Matlab 风格的数据布局
由于Piotr's Toolbox 旨在很好地处理 Matlab MEX 文件,因此 Piotr 通常在他的 C++ 函数中使用这种图像数据布局:

image = imread('img.jpg') //in Matlab

//flattened array notation:
image[x*width+ y + channel*width*height]

//unflattened C++ array notation:
image[channel][x][y] //typically: 3-channel color images

C++ 风格的数据布局
C++ 的大多数图像文件 I/O 库(例如 OpenCV imread)在从文件加载 JPG 图像时提供此数据布局:

Mat image = cv::imread("img.jpg") //in C++ with OpenCV

//flattened array notation:
image.data[x*nChannels + y*width*d + channel]

//unflattened C++ array notation:
image.data[y][x][channel]

问题:

  1. 是否有 C++ 函数(可能来自库)将图像从文件加载到 Matlab 样式的 [channel][width][height] 数据布局中? (不一定要用OpenCV。加载图片后,我还是用原始指针。)
  2. 是否有可以快速将 C++ 样式布局转换为 Matlab 样式布局的 C++ 函数?我编写了一个简单的转置函数,但速度很慢:


//this implementation also converts char* to float*, but that's not too important for this question
float* transpose_opencv_to_matlab(Mat img){
    assert(img.type() == CV_8UC3);
    int h = img.rows; //height
    int w = img.cols; //width
    int d = 3; //nChannels
    float multiplier = 1 / 255.0f; //rescale pixels to range [0 to 1]

    uchar* img_data = &img.data[0];
    float* I = (float*)malloc(h * w * d * sizeof(float)); //img transposed to Matlab data layout. 
    for(int y=0; y<h; y++){
        for(int x=0; x<w; x++){
            for(int ch=0; ch<d; ch++){
                I[x*h + y + ch*w*h] = img_data[x*d + y*w*d + ch] * multiplier; 
            }
        }
    }
    return I;
}

【问题讨论】:

  • cv::split() 可能是最接近的东西
  • 只是谷歌搜索似乎有一个cv::transpose() 函数。你试过这个吗?从这个答案:stackoverflow.com/questions/2259678/….
  • @jucestain cv::transpose 可以做到 [y][x][channel][x][y][channel]。但是,cv::transpose 似乎并没有使channel 成为最长步幅维度,例如[channel][x][y]。不过,执行cv::split,然后执行cv::transpose 可能会起作用。另外,我不确定cv::transpose 是否真的对数据进行了置换,或者它是否只是在使用image&lt;&gt;.at(y,x) 像素访问接口时更改了索引。
  • 澄清一下,您实际上并没有使用 MATLAB,您只是想使用 Piotr 的 C++ 来处理 MATLAB 数据?
  • @chappjc 没错,是的。 :)

标签: c++ matlab opencv image-processing computer-vision


【解决方案1】:

MatlabOpenCV 实用程序包含在 Matlab 格式和 OpenCV 格式之间转换的函数。它在使用 OpenCV 的 MEX 代码中运行良好。

例如从 Matlab 转换到 OpenCV 就这么简单

IplImage* iplImg = mxArr_to_new_IplImage(argin[0]);
cv::Mat matImg(iplImg , false);
...
cvReleaseImage(&iplImg);

要从 OpenCV 转换为 Matlab,您可以使用(未​​经测试):

Mat img = cv::imread("img.jpg");
IplImage ipl_image = img;
mxArray* matlab_fmt_image = IplImage_to_new_mxArr (&img);

我遇到的唯一问题(可能在最新版本中不存在)是 MatlabOpenCV 仅支持 OpenCV 的旧版 (IplImage/CvMat) 接口,并且从 Visual Studio 2010 过渡到 VS2012 时存在一些兼容性问题。

【讨论】:

    猜你喜欢
    • 2016-08-09
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    相关资源
    最近更新 更多