Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(d[0], d[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(d[0], d[1]); std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

EDIT:

Another thing I tried is to directly overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

EDIT:

Another thing I tried is to directly overwrite overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

N.B: I am working with OpenCV 3.0.0


EDIT:

Another thing I tried is to directly overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

N.B: I am working with OpenCV 3.0.0


EDIT:

Another thing I tried is to directly overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?


EDIT2:

I found an overload of the Mat::reshape method for ND-arrays, unfortunately it's not yet fully implemented and currently throws a CV_StsNotImplemented error!

    // return matrix with the shuffled dimensions
    return mat1.reshape(mat2.channels(), mat2.dims, mat2.size.p);

See the source code (either 3.0 or the master branch)...


Details

Let me explain a bit more about my use case. In my actual code, I'm trying to convert the last dimension of any 1-channel ND-array into channels of a ND-array with one less dimension but multi-channels, without copying the data. (Again we can assume that the array is continuous and the destination number of channels is less than CV_CN_MAX).

As an example, If I had the following array:

cv::Mat get_some_mat()
{
    int dims[] = {2,3,4,5};   // I'm really working with arbitrary number of dimensions
    Mat matnd(4, dims, CV_64F, Scalar::all(0));
    return matnd;
}

I want to convert it from 2x3x4x5 array with 1-channel into a 2x3x4 array with 5-channels, i.e:

int dims[] = {2,3,4};
Mat mat(3, dims, CV_64FC(5), Scalar::all(0));

And I want to avoid unneeded copies... The above Mat::reshape method would have been great, but it's not implemented at the moment!

The regular Mat::reshape leaves an undesired singleton dimension at the end:

matnd.reshape(5, 0);    // returns 2x3x4x1 with 5-channel (note the "1" at the end)

Thanks and sorry for the long post :)

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

N.B: I am working with OpenCV 3.0.0


EDIT:

Another thing I tried is to directly overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?


EDIT2:

I found an overload overload of the Mat::reshape method for ND-arrays, unfortunately it's not yet fully implemented and currently throws a CV_StsNotImplemented error!

    // return matrix with the shuffled dimensions
    return mat1.reshape(mat2.channels(), mat2.dims, mat2.size.p);

See the source code (either 3.0 or the master branch)...


Details

Let me explain a bit more about my use case. In my actual code, I'm trying to convert the last dimension of any 1-channel ND-array into channels of a ND-array with one less dimension but multi-channels, without copying the data. (Again we can assume that the array is continuous and the destination number of channels is less than CV_CN_MAX).

As an example, If I had the following array:

cv::Mat get_some_mat()
{
    int dims[] = {2,3,4,5};   // I'm really working with arbitrary number of dimensions
    Mat matnd(4, dims, CV_64F, Scalar::all(0));
    return matnd;
}

I want to convert it from 2x3x4x5 array with 1-channel into a 2x3x4 array with 5-channels, i.e:

int dims[] = {2,3,4};
Mat mat(3, dims, CV_64FC(5), Scalar::all(0));

And I want to avoid unneeded copies... The above Mat::reshape method would have been great, but it's not implemented at the moment!

The regular Mat::reshape leaves an undesired singleton dimension at the end:

matnd.reshape(5, 0);    // returns 2x3x4x1 with 5-channel (note the "1" at the end)

Thanks and sorry for the long post :)

Changing Mat dimensions inplace

As part of a larger project, I have some code that does something similar to the following:

cv::Mat some_function()
{
    // get some ND-array
    Mat mat1 = get_some_mat();
    vector<int> dims(mat1.size.p, mat1.size.p + mat1.dims);

    // ... shuffle the dimensions stored in "dims" (the total() remains the same)
    std::swap(dims[0], dims[1]);    // only an example...

    // create new mat header for the same data (no copying)
    Mat mat2(dims.size(), dims.data(), mat1.type(), mat1.data);

    // return matrix with the shuffled dimensions
    mat1 = mat2;    // <-- is this part safe??
    return mat1;    //
}

Is the last assignment safe, or will it mess up the ref count and leak memory?

I know the safer option is to just clone the data as in:

    // return matrix with the shuffled dimensions
    return mat2.clone();

but I'm trying to avoid making unnecessary copies of data...

I'm open to suggestion if there are better ways to reshape the ND-array in-place ...

You can assume the following is true:

CV_Assert(mat1.isContinuous() && mat1.dims > 3 && mat1.channels() == 1);

N.B: I am working with OpenCV 3.0.0


EDIT:

Another thing I tried is to directly overwrite the Mat size and step with those from the shuffled array:

    // return matrix with the shuffled dimensions
    std::copy(mat2.size.p, mat2.size.p + mat2.dims, mat1.size.p);
    std::copy(mat2.step.p, mat2.step.p + mat2.dims, mat1.step.p);
    return mat1;

But it's not quite right.. Apparently something in the mat1.flags field needs to be updated as well! Any help?


EDIT2:

I found an overload of the Mat::reshape method for ND-arrays, unfortunately it's not yet fully implemented and currently throws a CV_StsNotImplemented error!

    // return matrix with the shuffled dimensions
    return mat1.reshape(mat2.channels(), mat2.dims, mat2.size.p);

See the source code (either 3.0 or the master branch)...


Details

Let me explain a bit more about my use case. In my actual code, I'm trying to convert the last dimension of any 1-channel ND-array into channels of a ND-array with one less dimension but multi-channels, without copying the data. (Again we can assume that the array is continuous and the destination number of channels is less than CV_CN_MAX).

As an example, If I had the following array:

cv::Mat get_some_mat()
{
    int dims[] = {2,3,4,5};   // I'm really working with arbitrary number of dimensions
    Mat matnd(4, dims, CV_64F, Scalar::all(0));
    return matnd;
}

I want to convert it from 2x3x4x5 array with 1-channel into a 2x3x4 array with 5-channels, i.e:

int dims[] = {2,3,4};
Mat mat(3, dims, CV_64FC(5), Scalar::all(0));

And I want to avoid unneeded copies... The above Mat::reshape method would have been great, but it's not implemented at the moment!

The regular Mat::reshape leaves an undesired singleton dimension at the end:

matnd.reshape(5, 0);    // returns 2x3x4x1 with 5-channel (note the "1" at the end)

Thanks and sorry for the long post :)