編程經驗:幾個OPENCV中挺有意思的BUG~

不寫博客好長時間了,近期忙於實現論文中的算法,調試了一波又一波的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 );

lGray.release(); // 內存釋放成功

rGray.release();// 內存釋放成功


convertTo可以對自身進行depth的轉換,但是需要耗費額外的內存,同上,CV_8U無法釋放,但是其餘的均可以釋放。

lGray.convertTo( lGray, CV_32F, 255 );


PS. 有個下采樣函數pyrDown,這個函數對於任何類型的數據,均無法釋放,奇葩。


結論,convertTo對uchar,char類型數據,內存必然泄露。
----------------------------------------------------------------------------------------------------------

發佈了42 篇原創文章 · 獲贊 193 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章