optimized copying from an openCV mat to a 2D float array

990 views Asked by At

I wanted to copy an opencv Mat variable in a 2D float array.I used the code below to reach this purpose.but because I develope a code that speed is a very important metric this method of copy is not enough optimize.Is there another more optimized way to use?

float *ImgSrc_f;
ImgSrc_f = (float *)malloc(512 * 512 * sizeof(float));
for(int i=0;i<512;i++)
    for(int j=0;j<512;j++)
    {
        ImgSrc_f[i * 512 + j]=ImgSrc.at<float>(i,j);
    }
2

There are 2 answers

0
Boyko Perfanov On

Really,

//first method
Mat img_cropped = ImgSrc(512, 512).clone();
float *ImgSrc_f = img_cropped.data;

should be no more than a couple of % less efficient than the best method. I suggest this one as long as it doesn't lose more than 1% to the second method.

Also try this, which is very close to the absolute best method unless you can use some kind of expanded cpu instruction set (and if such ones are available). You'll probably see minimal difference between method 2 and 1.

//method 2    
//preallocated memory

//largest possible with minimum number of direct copy calls
//caching pointer arithmetic can speed up things extremely minimally
//removing the Mat header with a malloc can speed up things minimally
>>startx, >>starty, >>ROI;
Mat img_roi = ImgSrc(ROI);
Mat img_copied(ROI.height, ROI.width, CV_32FC1);

for (int y = starty; y < starty+ROI.height; ++y)
{
    unsigned char* rowptr = img_roi.data + y*img_roi.step1() + startx * sizeof(float);
    unsigned char* rowptr2 = img_coped.data + y*img_copied.step1();
    memcpy(rowptr2, rowptr, ROI.width * sizeof(float));
}

Basically, if you really, really care about these details of performance, you should stay away from overloaded operators in general. The more levels of abstraction in code, the higher the penalty cost. Of course that makes your code more dangerous, harder to read, and bug-prone.

1
Sebastian Lerch On

Can you use a std::vector structure, too? If try

std::vector<float> container;
container.assign((float*)matrix.startpos, (float*)matrix.endpos);