利用 OpenCV 在MFC中顯示圖像問題以及解決方法

最近在做一個項目,需要在MFC中顯示OpenCV讀取的圖像,遇到了一些問題,現(xiàn)在總結(jié)如下峦嗤,希望對大家有幫助。


問題1:如何在MFC控件中顯示OpenCV讀取的圖像


1.1問題說明

在做工程項目的時候遇到了這樣一個問題屋摔,將用OpenCV讀取的圖像(Mat類型烁设,或者IPlImage類型)顯示在MFC的Picture控件中,那么將如何才能方便的顯示呢钓试?

1.2解決方法

經(jīng)過研究發(fā)現(xiàn)如下兩種方法:

  • 1装黑、利用CvvImage類副瀑,可以方便的在MFC對應(yīng)控件中顯示圖像,方法如下:

首先曹体,由于從OpenCV 2.2.0開始俗扇,OpenCV取消了CvvImage這個類,具體原因暫時不太清楚箕别,所以導(dǎo)致OpenCV2.2后面的版本無法直接使用這個類铜幽,但是這個類對于MFC的顯示確實非常的簡單,所以為了繼續(xù)使用這個類串稀,我們可以下載CvvImage的源碼除抛,將CvvImage.cpp以及CvvImage.h添加到工程中去(注:CvvImage.cpp需要在開頭加上預(yù)編譯頭文件 #include "stdafx.h" )!下載鏈接母截,添加到工程之后便可以利用CvvImage進(jìn)行顯示了到忽。并且由于CopyOf后cimg空間不會自動回收,所以不要忘記手動釋放內(nèi)存清寇。

Mat mat = imread(filePath);
CDC* pDC = GetDlgItem( ID )->GetDC();
HDC hDC = pDC->GetSafeHdc();
IplImage img = mat;
CvvImage cimg;
cimg.CopyOf(&img);
CRect rect;
GetDlgItem( ID )->GetClientRect(&rect);
cimg.DrawToHDC(hDC, &rect);
cimg.Destroy();  //注意釋放空間
ReleaseDC(pDC);     //釋放
  • 2喘漏、利用c++以及windows系統(tǒng)函數(shù)進(jìn)行顯示,方法如下:

主要利用 StretchDIBits函數(shù)將圖像數(shù)據(jù)顯示到對應(yīng)控件中,對于StretchDIBits具體含義华烟,讀者可以自行百度翩迈,這里給出顯示函數(shù)代碼以及主函數(shù)代碼,注意在顯示的時候盔夜,存在數(shù)據(jù)對其的問題负饲,由于數(shù)據(jù)存儲要求4字節(jié)對其,可能需要對顯示的數(shù)據(jù)進(jìn)行調(diào)整喂链,int NewWidth = (width*(bit / 8) + 3) / 4 * 4返十,請讀者注意。

主函數(shù)調(diào)用:

    IplImage *frame = cvLoadImage("path");
    DrawPicToHDC((BYTE *)frame->imageData, IDC_VIDEO, frame->width, frame->height, 24);
    cvReleaseImage(&frame);

顯示函數(shù):

void DrawPicToHDC(BYTE *img, UINT ID, int width, int height, int bit)
{
if (img == NULL)
    return;
CWnd* pwd = AfxGetApp()->GetMainWnd()->GetDlgItem(ID);
CDC *pDC = pwd->GetDC();
CRect rect;
pwd->GetClientRect(&rect);
//pwd->RedrawWindow();
BITMAPINFO* pInfo;
if (bit == 24)
    pInfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO)];
else if (bit == 8)
{
    pInfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO) + 256 * sizeof(pInfo->bmiColors)];
    for (int i = 0; i<256; i++)
    {
        pInfo->bmiColors[i].rgbRed = i;
        pInfo->bmiColors[i].rgbGreen = i;
        pInfo->bmiColors[i].rgbBlue = i;
        pInfo->bmiColors[i].rgbReserved = 0;
    }
}
else
{
    AfxMessageBox("顯示視頻遇到嚴(yán)重錯誤");
    exit(0);
}
pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pInfo->bmiHeader.biWidth = width;
pInfo->bmiHeader.biHeight = -height;//圖像數(shù)據(jù)倒著存儲椭微,所以-height顯示為正洞坑,如果為+height圖像倒立
pInfo->bmiHeader.biPlanes = 1;
pInfo->bmiHeader.biBitCount = bit;
pInfo->bmiHeader.biCompression = BI_RGB;
pInfo->bmiHeader.biSizeImage = 0;
pInfo->bmiHeader.biXPelsPerMeter = 0;
pInfo->bmiHeader.biYPelsPerMeter = 0;
pInfo->bmiHeader.biClrUsed = 0;
pInfo->bmiHeader.biClrImportant = 0;
int NewWidth = (width*(bit / 8) + 3) / 4 * 4;
BYTE* NewImg = new BYTE[NewWidth*height];
memset(NewImg, 0, NewWidth*height);
for (int i = 0; i<height; i++)
{
    memcpy(NewImg + i*NewWidth, img + i*width*(bit / 8), width*(bit / 8));
}
SetStretchBltMode(pDC->GetSafeHdc(), COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, width, height, NewImg, pInfo, DIB_RGB_COLORS, SRCCOPY);
delete[] pInfo;
delete[] NewImg;
pwd->ReleaseDC(pDC);
}

截止目前,圖像的顯示已經(jīng)基本實現(xiàn)了赏表,但是到此運行之后你會發(fā)現(xiàn)一個奇妙的現(xiàn)象检诗,內(nèi)存泄漏。

顯示結(jié)果

問題2:出現(xiàn)內(nèi)存泄漏

2.1問題說明

在顯示實現(xiàn)的時候瓢剿,明明沒有自己new變量,為什么會出現(xiàn)內(nèi)存泄漏呢悠轩?并且在進(jìn)行調(diào)試后發(fā)現(xiàn)间狂,在MFC工程中,只要定義了Mat火架,或者IPlImage變量鉴象,即使運行結(jié)束釋放掉忙菠,仍然會出現(xiàn)內(nèi)存泄漏,這是什么原因呢纺弊?

2.2解決方法

經(jīng)過查詢發(fā)現(xiàn)出現(xiàn)內(nèi)存泄漏的原因不是你代碼有問題牛欢,而是MFC編譯的問題,網(wǎng)上說淆游,由于引入OpenCV庫之后傍睹,OpenCV的鏈接庫core.dll先與MFC的庫文件生成,所以導(dǎo)致內(nèi)存泄漏犹菱,解決方法是將MFC的動態(tài)編譯該為靜態(tài)編譯拾稳,進(jìn)行如下操作,在工程環(huán)境中依次選擇:

工程-- 屬性-- 配置屬性 --常規(guī) --MFC的使用 選擇靜態(tài)庫使用

到此腊脱,內(nèi)存泄漏已經(jīng)解決访得,但同時很可能出現(xiàn)另一個問題,程序崩潰陕凹。錯誤提示為 _pFirstBlock==pHead悍抑,如下圖,此問題如下解決杜耙。

出現(xiàn)這樣的bug

問題3:解決_pFirstBlock==pHead導(dǎo)致程序崩潰

3.1問題說明

在問題2中內(nèi)存泄漏的問題已經(jīng)解決了搜骡,但是在進(jìn)行開發(fā)的過程中,可能會發(fā)現(xiàn)程序崩潰的問題泥技,特別是當(dāng)程序比較龐大的時候更容易出現(xiàn)此問題浆兰,錯誤提示為:_pFirstBlock==pHead。

3.2解決方法

此問題的產(chǎn)生多半是因為在調(diào)用庫的過程中產(chǎn)生了沖突珊豹,所以解決此問題的方法就是將OpenCV的調(diào)用方法改為靜態(tài)調(diào)用簸呈, 使用OpenCV的靜態(tài)庫

opencv中在靜態(tài)庫中使用MFC的配置方法如下:

  • 1、lib選擇staticlib店茶;
    也就是VC++目錄中的包含目錄應(yīng)該為如下路徑
    D:/Program Files/opencv/build/x86/vc12/staticlib
  • 2蜕便、屬性頁---配置屬性----MFC的使用---在靜態(tài)庫下使用MFC;
    這樣會將你程序用到的一些庫寫到你的exe文件中贩幻,換來的是可移植性轿腺,但是exe文件會稍微大一些
  • 3、屬性----C/C++ -----代碼生成----運行庫選擇位多線程調(diào)試(/MTd)丛楚。

在靜態(tài)庫下也可能會出現(xiàn)異常錯誤:
這時候考慮的問題有如下2個:

  • 1族壳、確實是你程序錯誤,如果程序錯誤最有可能是你new的指針沒有delete趣些,或者某個內(nèi)存沒有分配就開始用再或者就是野指針等情況仿荆,最好單步調(diào)試,注意指針和數(shù)組。
  • 2拢操、opencv的配置錯誤
    配置好opencv后發(fā)現(xiàn)我的程序在共享DLL下使用MFC是沒有錯誤锦亦,但是一旦選擇了靜態(tài)庫下使用MFC就出現(xiàn)了上面的錯誤。如果不是程序問題令境,那么通常杠园,Debug下面可能引用了Release下面靜態(tài)編譯的庫。如果在debug環(huán)境下運行舔庶,只要將release下面的庫全部刪除就可以了抛蚁。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市栖茉,隨后出現(xiàn)的幾起案子篮绿,更是在濱河造成了極大的恐慌,老刑警劉巖吕漂,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亲配,死亡現(xiàn)場離奇詭異,居然都是意外死亡惶凝,警方通過查閱死者的電腦和手機(jī)吼虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苍鲜,“玉大人思灰,你說我怎么就攤上這事』焯希” “怎么了洒疚?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坯屿。 經(jīng)常有香客問我油湖,道長,這世上最難降的妖魔是什么领跛? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任乏德,我火速辦了婚禮,結(jié)果婚禮上吠昭,老公的妹妹穿的比我還像新娘喊括。我一直安慰自己,他們只是感情好矢棚,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布郑什。 她就那樣靜靜地躺著,像睡著了一般蒲肋。 火紅的嫁衣襯著肌膚如雪蹦误。 梳的紋絲不亂的頭發(fā)上劫拢,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天肉津,我揣著相機(jī)與錄音,去河邊找鬼。 笑死屋摇,一個胖子當(dāng)著我的面吹牛晾嘶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播距糖,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼玄窝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悍引?” 一聲冷哼從身側(cè)響起恩脂,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎趣斤,沒想到半個月后俩块,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡浓领,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年玉凯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片联贩。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡漫仆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泪幌,到底是詐尸還是另有隱情盲厌,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布祸泪,位于F島的核電站吗浩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏浴滴。R本人自食惡果不足惜拓萌,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望升略。 院中可真熱鬧微王,春花似錦、人聲如沸品嚣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翰撑。三九已至罩旋,卻和暖如春啊央,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涨醋。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工瓜饥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浴骂。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓乓土,卻偏偏與公主長得像,于是被迫代替她去往敵國和親溯警。 傳聞我的和親對象是個殘疾皇子趣苏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容