I'm doing some computer vision stuff in C++, working with JPG images. In C++, I'm calling computer vision functions from Piotr Dollar's Toolbox, which were originally designed for Matlab compatibility. I'm trying to figure out how to quickly load images from files in C++, and arrange them in a Matlab-style data layout.
Matlab-style data layout
Since Piotr's Toolbox is designed to play nicely with Matlab MEX files, Piotr typically uses this image data layout in his C++ functions:
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++-style data layout
Most of the image file I/O libraries for C++ (e.g. OpenCV imread) provide this data layout when loading a JPG image from file:
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]
Questions:
- Is there a C++ function (possibly from a library) that loads images from file into the Matlab-style
[channel][width][height]
data layout? (It doesn't have to use OpenCV. After loading in the image, I use raw pointers anyway.) - Is there a C++ function that would quickly transpose the C++-style layout into a Matlab-style layout? I coded a naive transpose function, but it's quite slow:
//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;
}