peter_gent
peter_gent

Reputation: 175

OpenCV : What is the real performance difference between continuous and non-continuous matrices?

At the moment I'm trying to understand some of the differences between continuous and non-continuous matrices in openCV. It was suggested to me that continuous matrices provide better performance because the program doesn't have to jump back to the begining of the next row at the end of each column.

In a word what is the comparable performance difference between continuous and non-continuous matrices?

Upvotes: 1

Views: 951

Answers (2)

berak
berak

Reputation: 39796

non-continuous matrices happen for 2 reasons:

  • the image was padded, so the size of one line is a multiple of 4 .

    (some bmp images come like that)

    it might be even faster to process those, because the row pointers are now properly aligned to 32bit boundaries.

  • your Mat is only a submat, a ROI.

in both cases, you can't use a single pointer to the first element, but have to relcalculate the line pointer for every row.

i wouldn't worry too much about performance issues here (the internal algos in opencv handle this quite well).

i just hope, knowing this will make you a bit more cautios with direct pointer manipulation ;)

Upvotes: 1

Sergei Nosov
Sergei Nosov

Reputation: 1675

Well, it mostly depends on how you'll use your matrices. If you're doing a lot of "jumping" anyways - it won't make much difference, but in 'continuous' use cases, it will matter a few dozens of percents.

The following example (which simply shifts the matrices values) gives me an output:

image.isContinuous() = 1
roi.isContinuous() = 0
image: 0.0162504 s
roi: 0.0219723 s
Sanity check: OK

Which is about 30% difference. Your millage will vary depending on the hardware and actual use cases.

Source (notice how the first loop is much simpler in that case):

#include <opencv2/core/core.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    int cols = 4096;
    int rows = 4096;
    int scale = 2;

    Mat image(rows, cols, CV_8UC1);
    Mat image_big(rows * scale, cols * scale, CV_8UC1);
    Mat roi = image_big(Rect(0, 0, cols, rows));

    randu(image, 0, 255);
    image.copyTo(roi);

    cout << "image.isContinuous() = " << image.isContinuous() << "\n" << "roi.isContinuous() = " << roi.isContinuous() << endl;

    {
        cout << "image: ";
        double start = getTickCount();
        for (int i = 1; i < image.total(); i++)
        {
            image.data[i - 1] = image.data[i];
        }
        cout << (getTickCount() - start)/getTickFrequency() << " s" << endl;
    }

    {
        cout << "roi: ";
        double start = getTickCount();
        for (int y = 0; y < roi.cols; y++)
        {
            if (y != 0) {
                roi.ptr<char>(y-1)[roi.cols-1] = roi.ptr<char>(y)[0];
            }

            for (int x = 1; x < roi.rows; x++)
            {
                roi.ptr<char>(y)[x - 1] = roi.ptr<char>(y)[x];
            }
        }
        cout << (getTickCount() - start)/getTickFrequency() << " s" << endl;
    }

    cout << "Sanity check: " << (countNonZero(image - roi) ? "FAIL" : "OK") << endl;
}

Upvotes: 5

Related Questions