使用成员变量 作为CopyTo 的目标Mat
通过其他char* data 构造的Mat,需要考虑使用copyTo 或者clone。因为Mat只是浅拷贝,指向的数据还是原来的数据,如果原来的数据被释放了,那么Mat就会指向一个无效的数据,导致内存错误。这里主要对比OpenCV中不同深拷贝方式的效率。
clone 和 copyTo 的区别。
clone
会重新分配内存,然后拷贝数据copyTo
是否申请新的内存空间,取决于dst矩阵头中的大小信息是否与src一至,若一致则只深拷贝并不申请新的空间,否则先申请空间后再进行拷贝。
在视频帧处理中,大部分情况下,视频帧的大小都是不会变化的,所以可以考虑使用成员变量作为copyTo的目标Mat,这样可以减少内存的分配和释放,提高效率。
例如:
// 此处的 ptr指向了真正的数据,这里必须拷贝一份数据,否则ptr指向的数据会被释放
cv::Mat frame;
frame = cv::Mat(m_format.height * 3/2, m_format.width, CV_8UC1, ptr, pitch);
cv::Mat newFrame = frame.clone();
可以改为:
// 使用成员变量作为copyTo的目标Mat
cv::Mat(m_format.height * 3/2, m_format.width, CV_8UC1, ptr, pitch).copyTo(m_newFrame);
耗时对比:
frame2 = frame.clone() : 516us
frameCopyToGlobal = frame.clone() : 706us
frame.copyTo(frameCopyToGlobal) : 155us
frame.copyTo(frame3) : 566us
frameCopyToGlobal = frame.clone() 这种写法耗时最长,是因为除了clone 之外,还需要把上一次frameCopyToGlobal中的数据先释放掉,然后再重新分配内存,再拷贝数据。
frame.copyTo(frameCopyToGlobal) 这种写法耗时最短,因为frameCopyToGlobal已经分配了内存,只需要拷贝数据即可。
使用成员变量作为resize, cvtColor的目标Mat
这一类的函数,都会调用_dst.create(dsize, src.type());
生成一个_dst
,当_dst
是成员变量并且大小和类型和 src
相同时,可以减少内存的分配和释放,提高效率。同时也避免了临时变量的生成,拷贝,释放的过程。
void cv::</