不写博客好长时间了,近期忙于实现论文中的算法,调试了一波又一波的bug,这个是最耗时的,本文分享一个我今天遇到的一个挺有意思的bug。
我用的是opencv2.4.9,运行320p的图像,一切正常,但是当我换成640p的图像,运行到一半,程序崩溃了,究其原因是内存泄露导致的,原来程序的占有的内存以每一帧3M的速度不断的攀升。我本想采用X64编译运行,可没想到用了一些该死的库文件,bug一批一批的跳出来。无奈,只能一步一步的寻找泄露的位置,经过最简单粗暴的任务管理器观察,原来都是opencv引起的。做此博客,希望大家能够少走弯路。
eg1. release()函数对CV_8U、CV_8S类型失灵
---------------------------------------------------------------
Mat tmp1 = Mat::zeros(hei, wid, CV_32F);
Mat tmp2 = Mat::zeros(hei, wid, CV_32F);
Mat left_gray = Mat::zeros(hei, wid, CV_32F);
Mat right_gray = Mat::zeros(hei, wid, CV_32F);
Mat lGray = Mat::zeros(hei, wid, CV_8U);
Mat rGray = Mat::zeros(hei, wid, CV_8S);
tmp1.release(); // 内存释放成功
left_gray.release(); // 内存释放成功
lGray.release(); // 内存释放成功
tmp2.release(); // 内存释放成功
right_gray.release(); // 内存释放失败
rGray.release(); // 内存释放失败
换成
Mat lGray = Mat::ones(hei, wid, CV_8U);
Mat rGray = Mat::ones(hei, wid, CV_8U);
也不行
换种方式
lGray.create(hei, wid, CV_8U);
rGray.create(hei, wid, CV_8S);
也不行
再换种方式
Mat lGray(hei,wid,CV_8U,cv::Scalar(0,0,255));
Mat rGray(hei,wid,CV_8U,cv::Scalar(0,0,255));
也不行
那请问,怎么破才能行?
答案:如果变成下面这个样子
Mat lGray = Mat::ones(hei, wid, CV_8UC2);
Mat rGray = Mat::ones(hei, wid, CV_8UC3);
就行了!
结论:release函数对于CV_8U、CV_8S类型,或者是CV_8UC1、CV_8SC1类型的Mat矩阵,有BUG。
-----------------------------------------------------------------------------------------------------
eg2. 同样,相关函数一个都跑不掉,均有这个问题。
-----------------------------------------------------------------------------------------------------
Mat lGray, rGray;
Mat tmp1, tmp2;
Mat left_gray, right_gray;
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
tmp1.release();
left_gray.convertTo( lGray, CV_8U, 255 );
left_gray.release();
lGray.release(); // 内存释放失败
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
tmp2.release();
right_gray.convertTo( rGray, CV_8U, 255 );
right_gray.release();
rGray.release(); // 内存释放失败
如果改成CV_8UC3,会释放成功吗?
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
left_gray.convertTo( lGray, CV_8UC3, 255 );
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
right_gray.convertTo( rGray, CV_8UC3, 255 );
tmp1.release();
tmp2.release();
left_gray.release();
right_gray.release();
lGray.release(); // 内存释放仍旧失败
rGray.release(); // 内存释放失败
如果我这么写呢?
Mat tmp1 = Mat::zeros(hei, wid, CV_32F);
Mat tmp2 = Mat::zeros(hei, wid, CV_32F);
Mat left_gray = Mat::zeros(hei, wid, CV_32F);
Mat right_gray = Mat::zeros(hei, wid, CV_32F);
Mat lGray = Mat::ones(hei, wid, CV_8UC3);
Mat rGray = Mat::ones(hei, wid, CV_8UC3);
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
left_gray.convertTo( lGray, CV_8UC3, 255 );
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
right_gray.convertTo( rGray, CV_8UC3, 255 );
tmp1.release();
tmp2.release();
left_gray.release();
right_gray.release();
lGray.release(); // 内存释放失败
rGray.release(); // 内存释放失败
convertTo简直是六亲不认啊!
那我该怎么办?
答案:没办法,将CV_8U换成其他类型吧
left_gray.convertTo( lGray, CV_32F, 255 );
right_gray.convertTo( rGray, CV_32F, 255 );
结论,convertTo对uchar,char类型数据,内存必然泄露。
----------------------------------------------------------------------------------------------------------
我用的是opencv2.4.9,运行320p的图像,一切正常,但是当我换成640p的图像,运行到一半,程序崩溃了,究其原因是内存泄露导致的,原来程序的占有的内存以每一帧3M的速度不断的攀升。我本想采用X64编译运行,可没想到用了一些该死的库文件,bug一批一批的跳出来。无奈,只能一步一步的寻找泄露的位置,经过最简单粗暴的任务管理器观察,原来都是opencv引起的。做此博客,希望大家能够少走弯路。
eg1. release()函数对CV_8U、CV_8S类型失灵
---------------------------------------------------------------
Mat tmp1 = Mat::zeros(hei, wid, CV_32F);
Mat tmp2 = Mat::zeros(hei, wid, CV_32F);
Mat left_gray = Mat::zeros(hei, wid, CV_32F);
Mat right_gray = Mat::zeros(hei, wid, CV_32F);
Mat lGray = Mat::zeros(hei, wid, CV_8U);
Mat rGray = Mat::zeros(hei, wid, CV_8S);
tmp1.release(); // 内存释放成功
left_gray.release(); // 内存释放成功
lGray.release(); // 内存释放成功
tmp2.release(); // 内存释放成功
right_gray.release(); // 内存释放失败
rGray.release(); // 内存释放失败
换成
Mat lGray = Mat::ones(hei, wid, CV_8U);
Mat rGray = Mat::ones(hei, wid, CV_8U);
也不行
换种方式
lGray.create(hei, wid, CV_8U);
rGray.create(hei, wid, CV_8S);
也不行
再换种方式
Mat lGray(hei,wid,CV_8U,cv::Scalar(0,0,255));
Mat rGray(hei,wid,CV_8U,cv::Scalar(0,0,255));
也不行
那请问,怎么破才能行?
答案:如果变成下面这个样子
Mat lGray = Mat::ones(hei, wid, CV_8UC2);
Mat rGray = Mat::ones(hei, wid, CV_8UC3);
就行了!
结论:release函数对于CV_8U、CV_8S类型,或者是CV_8UC1、CV_8SC1类型的Mat矩阵,有BUG。
-----------------------------------------------------------------------------------------------------
eg2. 同样,相关函数一个都跑不掉,均有这个问题。
-----------------------------------------------------------------------------------------------------
Mat lGray, rGray;
Mat tmp1, tmp2;
Mat left_gray, right_gray;
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
tmp1.release();
left_gray.convertTo( lGray, CV_8U, 255 );
left_gray.release();
lGray.release(); // 内存释放失败
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
tmp2.release();
right_gray.convertTo( rGray, CV_8U, 255 );
right_gray.release();
rGray.release(); // 内存释放失败
如果改成CV_8UC3,会释放成功吗?
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
left_gray.convertTo( lGray, CV_8UC3, 255 );
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
right_gray.convertTo( rGray, CV_8UC3, 255 );
tmp1.release();
tmp2.release();
left_gray.release();
right_gray.release();
lGray.release(); // 内存释放仍旧失败
rGray.release(); // 内存释放失败
如果我这么写呢?
Mat tmp1 = Mat::zeros(hei, wid, CV_32F);
Mat tmp2 = Mat::zeros(hei, wid, CV_32F);
Mat left_gray = Mat::zeros(hei, wid, CV_32F);
Mat right_gray = Mat::zeros(hei, wid, CV_32F);
Mat lGray = Mat::ones(hei, wid, CV_8UC3);
Mat rGray = Mat::ones(hei, wid, CV_8UC3);
lImg.convertTo( tmp1, CV_32F );
cvtColor( tmp1, left_gray, CV_RGB2GRAY );
left_gray.convertTo( lGray, CV_8UC3, 255 );
rImg.convertTo( tmp2, CV_32F );
cvtColor( tmp2, right_gray, CV_RGB2GRAY );
right_gray.convertTo( rGray, CV_8UC3, 255 );
tmp1.release();
tmp2.release();
left_gray.release();
right_gray.release();
lGray.release(); // 内存释放失败
rGray.release(); // 内存释放失败
convertTo简直是六亲不认啊!
那我该怎么办?
答案:没办法,将CV_8U换成其他类型吧
left_gray.convertTo( lGray, CV_32F, 255 );
right_gray.convertTo( rGray, CV_32F, 255 );
lGray.release(); // 内存释放成功
rGray.release();// 内存释放成功
convertTo可以对自身进行depth的转换,但是需要耗费额外的内存,同上,CV_8U无法释放,但是其余的均可以释放。
lGray.convertTo( lGray, CV_32F, 255 );
PS. 有个下采样函数pyrDown,这个函数对于任何类型的数据,均无法释放,奇葩。
结论,convertTo对uchar,char类型数据,内存必然泄露。
----------------------------------------------------------------------------------------------------------