Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I have done a very dirty example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Create a 2D array of the result
    Mat ans2D(2, 2, CV_32SC1);

    // Fill the 2D array with the values of the 1D array
    // (This is a very dirty solution and there should be better solutions, but I didn't found one in a short time
    for(int i=0; i<ans.cols; i++) {
        int nCol = i%2;
        int nRow = i/2;
        ans2D.at<int>(nCol, nRow) = ans.at<int>(0, i);
    }

    // Transpose it back to OpenCV convention
    ans2D = ans2D.t();

    // Print out the result
    for(int i=0; i<ans2D.rows; i++) {
        for(int j=0; j<ans2D.cols; j++) {
            cout << (int)ans2D.at<int>(i, j) << " ";
        }
        cout << endl;
    }
return 0;
}

I think this is not realy a clean solution, but perhabs you can use it or parts of it.

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

I have done a very dirty example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Create a 2D array of the result
    Mat ans2D(2, 2, CV_32SC1);

    // Fill the 2D array with the values of the 1D array
    // (This is a very dirty solution and there should be better solutions, but I didn't found one in a short time
    for(int i=0; i<ans.cols; i++) {
        int nCol = i%2;
        int nRow = i/2;
        ans2D.at<int>(nCol, nRow) = ans.at<int>(0, i);
    }

    // Transpose Reshape it back to 2D
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV convention
    ans2D = ans2D.t();
conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans2D.rows; i++) {
        for(int j=0; j<ans2D.cols; j++) {
            cout << (int)ans2D.at<int>(i, j) (int)ans2D.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

I think this is not realy a clean solution, but perhabs you can use it or parts of it.

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

I have done a very dirty example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans2D.rows; i<ans.rows; i++) {
        for(int j=0; j<ans2D.cols; j<ans.cols; j++) {
            cout << (int)ans2D.at<int>(j, (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

I think this is not realy a clean solution, but perhabs you can use it or parts of it.

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

I have done a very dirty little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

I think this is not realy a clean solution, but perhabs you can use it or parts of it.

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D
1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D
2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exeed the array limits,...

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR_VECTOR || IDX.kind() == _InputArray::STD_VECTOR_MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIDXContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
        int nRows = dst.rows;
        dst = dst.reshape(0, 1);
        dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
return dst;

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exeed the array limits,...

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR_VECTOR || IDX.kind() == _InputArray::STD_VECTOR_MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIDXContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
        int nRows = dst.rows;
        dst = dst.reshape(0, 1);
        dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
 return dst;
}

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exeed the array limits,...

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR_VECTOR || IDX.kind() == _InputArray::STD_VECTOR_MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIDXContinous) if(isIdxContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
        int nRows = dst.rows;
        dst = dst.reshape(0, 1);
        dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
    return dst;
}

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exeed the array limits,...

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR_VECTOR _InputArray::STD_VECTOR || IDX.kind() == _InputArray::STD_VECTOR_MAT);
_InputArray::MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIdxContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
        int nRows = dst.rows;
        dst = dst.reshape(0, 1);
        dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
    return dst;
}

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exeed exceed the array limits,...limits,... Take a look in the source code from OpenCV to learn more about InputArrays and how to proof it.

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR || IDX.kind() == _InputArray::MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIdxContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
        int nRows = dst.rows;
        dst = dst.reshape(0, 1);
        dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
    return dst;
}

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.

I have done a little example, so there are some things to notice:

(i.) In Matlab the index starts with 1, in C++ it starts with 0

(ii.) 'b' is your array of indices for an 1D array

(iii.) In OpenCV the read out of the pixels is row by row, in Matlab it seems to be column by column

// include header for OpenCV3
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
    // Fill arrays by hand, this is just for this example
    Mat A(3, 3, CV_32SC1);
    A.at<int>(0, 0) = 4;
    A.at<int>(1, 0) = 10;
    A.at<int>(2, 0) = 5;
    A.at<int>(0, 1) = 9;
    A.at<int>(1, 1) = 3;
    A.at<int>(2, 1) = 8;
    A.at<int>(0, 2) = 8;
    A.at<int>(1, 2) = 7;
    A.at<int>(2, 2) = 4;

    Mat b(2, 2, CV_32SC1);
    // Note that the indices are decreased by 1 (see above)
    b.at<int>(0, 0) = 1;
    b.at<int>(1, 0) = 2;
    b.at<int>(0, 1) = 3;
    b.at<int>(1, 1) = 4;

    // Transpose array, because of row by row problem
    A = A.t();
    b = b.t();

    // Reshape arrays from 2D to 1D. Note that the 1 is not for dimension, but for number of rows (9 cols, 1 row)
    A = A.reshape(0, 1);
    b = b.reshape(0, 1);

    // Creating 1D Result array
    Mat ans(b.size(), b.type());

    // Fill the result array with A at the indices from b
    for(int i=0; i<b.cols; i++) {
        ans.at<int>(0, i) = A.at<int>( 0, b.at<int>(0, i) );
    }

    // Reshape it back to 2D. The 2 is for the number of rows: 2 cols, 2 rows
    ans = ans.reshape(0, 2);
    // Transpose it back, because of OpenCV conventions
    ans = ans.t();

    // Print out the result
    for(int i=0; i<ans.rows; i++) {
        for(int j=0; j<ans.cols; j++) {
            cout << (int)ans.at<int>(j, i) << " ";
        }
        cout << endl;
    }
return 0;
}

For matrix operations OpenCV is not the first choice. Take a look at the Eigen libraries. In OpenCV there is also a module to share data with Eigen.

EDIT: Answer to the comment below: I recommend you to use cv::InputArray instead of cv::Mat to pass arrays in functions. Check out InputArray.

The sample code is just an example (I hope I did no mistake, I could not check this at the moment) and you have to catch some more cases if needed, for example that the index value doesn't exceed the array limits,... Take a look in the source code from OpenCV to learn more about InputArrays and how to proof it.

// Use cv::InputArray, cv::OutputArray or cv::InputOutputArray
cv::Mat extract(cv::InputArray SRC, cv::InputArray IDX, bool isIdxContinous)
{
    // check that IDX format is of type std::vector or cv:Mat
    cv::CV_Assert(IDX.kind() _InputArray::STD_VECTOR || IDX.kind() == _InputArray::MAT);

    // check that IDX is of type int (You should convert it outside)
    cv::CV_Assert(IDX.type() == CV_32S)

    // clone() will do a deep copy and costs some time.
    // If data aren't changed, just pass Mat header instead to internal Mat
    cv::Mat src = SRC.getMat();
    cv::Mat idx = IDX.getMat();

    src = src.t();
    // I think this costs no time, because only the header is changed not the data
    src = src.reshape(0,1);

    cv::Mat dst = cv::Mat(idx.size(), src.type());

    if(isIdxContinous) {
        // In this case you can copy data very efficient, using cv::Range
        // I'm not sure, if all types are supported.
         int nRows = dst.rows;

        // I think this costs no time, because only the header is changed not the data
        src = src.reshape(0,1);
        dst = dst.reshape(0, 1);
         dst = src( cv::Range(idx.at<int>(0), idx.at<int>(idx.total()-1)) ).clone();
        dst = dst.reshape(0, nRows);
        return dst;
    }

    // Not necessary, because it should be checked outside the function to be int
    // Otherwise you can cast it with (int)idx.at<T>(i)
    // idx.convertTo(idx, 4);

    // outsource switch from for loop
    switch(src.type())
    {
    case 0:
        for (int i = 0; i < idx.total(); i++)
            dst.at<uchar>(i) = src.at<uchar>(idx.at<int>(i));
        break;
    case 1:
        for (int i = 0; i < idx.total(); i++)
            dst.at<char>(i) = src.at<char>(idx.at<int>(i));
        break;
    case 2:
        for (int i = 0; i < idx.total(); i++)
            dst.at<ushort>(i) = src.at<ushort>(idx.at<int>(i));
        break;
    case 3:
        for (int i = 0; i < idx.total(); i++)
            dst.at<short>(i) = src.at<short>(idx.at<int>(i));
        break;
    case 4:
        for (int i = 0; i < idx.total(); i++)
            dst.at<int>(i) = src.at<int>(idx.at<int>(i));
        break;
    case 5:
        for (int i = 0; i < idx.total(); i++)
            dst.at<float>(i) = src.at<float>(idx.at<int>(i));
        break;
    default:
        for (int i = 0; i < idx.total(); i++)
            dst.at<double>(i) = src.at<double>(idx.at<int>(i));
        break;
    }
    return dst;
}

You can also use T srcArray[] = (T*)src.data; srcArray[i]; instead of src.at<T>(i);, but this will not check limits of the array and should be handled with care.