OpenCV中Mat矩阵复制函数的效率差异: clone() 与copyTo()

1 inline
2 Mat Mat::clone() const
3 {
4     Mat m;
5     copyTo(m);
6     return m;
7 }
 1 void Mat::copyTo( OutputArray _dst ) const
 2 {
 3     int dtype = _dst.type();
 4     if( _dst.fixedType() && dtype != type() )
 5     {
 6         CV_Assert( channels() == CV_MAT_CN(dtype) );
 7         convertTo( _dst, dtype );
 8         return;
 9     }
10 
11     if( empty() )
12     {
13         _dst.release();
14         return;
15     }
16 
17     if( _dst.isUMat() )
18     {
19         _dst.create( dims, size.p, type() );
20         UMat dst = _dst.getUMat();
21 
22         size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize();
23         for( i = 0; i < (size_t)dims; i++ )
24             sz[i] = size.p[i];
25         sz[dims-1] *= esz;
26         dst.ndoffset(dstofs);
27         dstofs[dims-1] *= esz;
28         dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p);
29         return;
30     }
31 
32     if( dims <= 2 )
33     {
34         _dst.create( rows, cols, type() );
35         Mat dst = _dst.getMat();
36         if( data == dst.data )
37             return;
38 
39         if( rows > 0 && cols > 0 )
40         {
41             // For some cases (with vector) dst.size != src.size, so force to column-based form
42             // It prevents memory corruption in case of column-based src
43             if (_dst.isVector())
44                 dst = dst.reshape(0, (int)dst.total());
45 
46             const uchar* sptr = data;
47             uchar* dptr = dst.data;
48 
49             CV_IPP_RUN(
50                     (size_t)cols*elemSize() <= (size_t)INT_MAX &&
51                     (size_t)step <= (size_t)INT_MAX &&
52                     (size_t)dst.step <= (size_t)INT_MAX
53                     ,
54                     ippiCopy_8u_C1R(sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0
55             )
56 
57             Size sz = getContinuousSize(*this, dst);
58             size_t len = sz.width*elemSize();
59 
60             for( ; sz.height--; sptr += step, dptr += dst.step )
61                 memcpy( dptr, sptr, len );
62         }
63         return;
64     }
65 
66     _dst.create( dims, size, type() );
67     Mat dst = _dst.getMat();
68     if( data == dst.data )
69         return;
70 
71     if( total() != 0 )
72     {
73         const Mat* arrays[] = { this, &dst };
74         uchar* ptrs[2];
75         NAryMatIterator it(arrays, ptrs, 2);
76         size_t sz = it.size*elemSize();
77 
78         for( size_t i = 0; i < it.nplanes; i++, ++it )
79             memcpy(ptrs[1], ptrs[0], sz);
80     }
81 }
View Code

测试代码:

#include <iostream>
#include <vector>
#include <numeric>
#include "opencv2/opencv.hpp"
using  namespace std;
int main()
{
    const std::string path = "415-DST.bmp";
    cv::Mat src = cv::imread(path, cv::IMREAD_COLOR);

    cv::Mat dst1;
    cv::Mat dst2;
    
    std::vector<double> ratios;

    for (int i = 0; i < 1000; i++)
    {
        double t = cv::getTickCount();
        dst1 = src.clone();
        t = (cv::getTickCount() - t);
        cout << "clone:" << t << endl;

        double t1 = cv::getTickCount();
        src.copyTo(dst2);
        t1 = (cv::getTickCount() - t1) ;
        cout << "copyTo:" << t1 << endl;

        double r = t / t1;
        ratios.push_back(r);
        cout << "clone-CopytTo Ratio: " << r << endl;
        cout << "--------------------------------\n";
    }

    double avg = std::accumulate(ratios.begin(), ratios.end(), 0.0) / ratios.size();
    cout << "average ratio:" << avg << endl;
    system("pause");
    return 0;
}

  

 

结论: clone()函数要比copyTo函数慢3倍左右

posted @ 2017-07-31 10:11  wfh2017  阅读(5735)  评论(0编辑  收藏  举报