OpenCV学习笔记之 ( 三 ) MFC显示Mat图片
以下步驟參考以下鏈接?
http://blog.csdn.net/dcrmg/article/details/51913160?
原理及詳解見上鏈接。
下面只講步驟。 ??
一、打開VS2010,建立對話框的項目。
二、建立“PictureControl”,"Button"按鈕,修改屬性
三、在Show_Mat_ImageDlg.h添加如下頭文件
#include <iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
?
#include<string>
?
using namespace std;
using namespace cv;
四、在OnInitDialog初始化函數(shù)里添加代碼
?? ?namedWindow("view",WINDOW_AUTOSIZE);
?? ?HWND hWnd = (HWND)cvGetWindowHandle("view");
?? ?HWND hParent = ::GetParent(hWnd);
?? ?::SetParent(hWnd,GetDlgItem(IDC_PIC_STATIC)->m_hWnd);
?? ?::ShowWindow(hParent,SW_HIDE);
五、為“Open Image”按鈕添加事件處理程序
六、添加如下代碼:
?? ?CString picPath; ? //定義圖片路徑變量 ?
?? ?CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY |?
?? ??? ?OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT, ? NULL, this); ? //選擇文件對話框 ?
?
?? ?if(dlg.DoModal() == IDOK) ?
?? ?{ ?
?? ??? ?picPath= dlg.GetPathName(); ?//獲取圖片路徑 ?
?? ?} ?
?? ?//CString to string ?使用這個方法記得字符集選用“使用多字節(jié)字符”,不然會報錯 ?
?? ?string picpath=picPath.GetBuffer(0); ? ?
?? ? ?
?? ?Mat image=imread(picpath); ? ??
?? ?Mat imagedst; ?
?? ?//以下操作獲取圖形控件尺寸并以此改變圖片尺寸 ?
?? ?CRect rect; ?
?? ?GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect); ?
?? ?Rect dst(rect.left,rect.top,rect.right,rect.bottom); ?
?? ?resize(image,imagedst,cv::Size(rect.Width(),rect.Height())); ??
?? ?imshow("view",imagedst);
?
//**************************************************************
Mat格式圖像在MFC程序中的顯示
使用MFC下的CImage類可以很輕松的和快速的在MFC下顯示圖像,我這里使用C++的OpenCV,如果你使用c語言的OpenCV一樣可以實現(xiàn)出來。
1.讀入Mat矩陣(cvMat一樣),Mat img=imread("*.*");//cvLoadImage
確保轉(zhuǎn)換前矩陣中的數(shù)據(jù)都是uchar(0~255)類型(不是的話量化到此區(qū)間),這樣才能顯示。
2.根據(jù)矩陣大小創(chuàng)建(CImage::Create)新的的CImage類
CImage CI;
int w=img.cols;//寬
int h=img.rows;//高
int chinnels=img.channels();//通道數(shù)
CI.Destroy();//創(chuàng)建前,最好使用它,防止重復(fù)創(chuàng)建,程序崩潰
CI.Create(w,h,8*chinnels);
3.下來就是對CI進(jìn)行賦值了,這里是最核心的地方,分二類討論
(1)如果是1個通道的圖像(灰度圖像)
CImage中內(nèi)置了調(diào)色板,我們要對他進(jìn)行賦值:
RGBQUAD* ColorTable;
int MaxColors=256;
//這里可以通過CI.GetMaxColorTableEntries()得到大小(如果你是CI.Load讀入圖像的話)
ColorTable = new RGBQUAD[MaxColors];
CI.GetColorTable(0,MaxColors,ColorTable);//這里是取得指針
for (int i=0; i<MaxColors,i++)
{
ColorTable[i].rgbBlue = (BYTE)i;
//BYTE和uchar一回事,但MFC中都用它
ColorTable[i].rgbGreen = (BYTE)i;
ColorTable[i].rgbRed = (BYTE)i;
}
CI.SetColorTable(0,MaxColors,ColorTable);
delete []ColorTable;
然后就是數(shù)據(jù)拷貝了(這里的矩陣表示方法,根據(jù)需要(cvMat or Mat)修改):
if(chinnels==1)
{//灰度圖像
uchar *pS;
uchar *pImg=(uchar *)CI.GetBits();
int step=CI.GetPitch();
for(int i=0;i < h; i++)
{
pS=img.ptr(i);
for(int j=0;j<w;j++)
{
*(pImg+i*step+j)=pS[j];
}
}
}
(2)如果是3個通道(彩色圖像)
沒有調(diào)色板,直接賦值
if(chinnels==3)
{//彩色圖像
uchar *pS;
uchar *pImg=(uchar *)CI.GetBits();//得到CImage數(shù)據(jù)區(qū)地址
int step=CI.GetPitch();
//這個是一行像素站的存儲空間w*3,并且結(jié)果是4的倍數(shù)(這個不用關(guān)注,到底是不是4的倍數(shù)有待考證)
for(int i=0;i < h; i++)
{
pS=img.ptr(i);
for(int j=0;j<w;j++)
{
for(int k=0;k<3;k++)
*(pImg+i*step+j*3+k)=pS[j*3+k];
//注意到這里的step不用乘以3
}
}
}
4.至此已經(jīng)構(gòu)建好CImage,下來就是顯示它。我們可以直接在對話框、單文檔等地方顯示他,還可以使用CPictureCtrl空間顯示他。下面給出幾個顯示方法:
//顯示前,這里有個問題,等會討論
(1)放在一個按鈕響應(yīng)或者函數(shù)中
//這里的m_Pic是一個CPictureCtrl的control,其他控件等也一樣
//CStatic m_Pic;
//DDX_Control(pDX, IDC_STATIC_Img, m_Pic);
CWnd * pCWnd = CWnd::FromHandle(m_Pic.GetSafeHwnd());
//通過變量得到dc比較復(fù)雜,但很好用
CPaintDC dc(pCWnd);//如果這個不能使用就換成CClientDC 。。。。
Invalidate(false);
SetStretchBltMode(dc.m_hDC,COLORONCOLOR);
//這個需要百度看看為什么這樣設(shè)置
CI.StretchBlt(dc.m_hDC,rect,SRCCOPY);
//這里顯示大小rect(CRect類型)也由自己定義,這個函數(shù)有許多重載函數(shù)
//圖像顯示的大小和效果,在你能顯示出來后,可以慢慢考慮
這里的控件的dc還可以由下面方式取得
CPaintDC dc(GetDlgItem(IDC_STATIC_Img));//IDC_STATIC_Img是空間的ID
(2)直接顯示(下面就寫得簡單點,少的部分自己加)
CDC *pDC=GetDC();
Invalidate(false);
CI.StretchBlt(pDC->m_hDC,rect,SRCCOPY);
或者
CPaintDC dc(this);
CI.Draw(dc.m_hDC,0,0);//這個以某個dc(可以是窗口)的(0,0)為起點
5.問題
前面提到一個問題,現(xiàn)在討論下,就是使用StretchBlt可以對圖像進(jìn)行拉伸顯示。一般的圖像大小和你顯示的控件或者區(qū)域大小是不一樣的,這時使用它顯示可以拉伸它到合適的大小。(注意選擇合適參數(shù))。但我們還可以直接使用opencv自帶的函數(shù)對圖像進(jìn)行resize,可以同樣達(dá)到類似的效果。目前我嘗試的結(jié)果的是使用opencv經(jīng)過形變后的顯示效果比MFC下的StretchBlt拉伸好看,也不知道這二種的效率如何。
6.小結(jié)
操作數(shù)據(jù)和算法實現(xiàn)時都是用opencv來實現(xiàn),當(dāng)顯示時,構(gòu)造CImage顯示到windows系統(tǒng)的窗口上。不得不說,MFC,特別是高版本的MFC,學(xué)習(xí)起來相當(dāng)困難。一方面,它本身做的十分復(fù)雜,需要很長時間熟悉它才能按照你的想法實現(xiàn)想要的東西。另一方面,缺乏好書來指導(dǎo),比如說CImage類的用法,我是通過多種途徑和以前的積累才實現(xiàn)了最基礎(chǔ)的使用方法。雖然最后給出的代碼不多,但讓代碼不出錯,弄明白它的簡單機制卻花費很長時間。到底CImage類+CPictureCtrl是否適合用來顯示圖像,特別是對實時圖像處理的顯示,還需要進(jìn)一步考證。
總結(jié)
以上是生活随笔為你收集整理的OpenCV学习笔记之 ( 三 ) MFC显示Mat图片的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字电视制播设备间的文件交换格式
- 下一篇: 彻底解决显示Opencv中Mat图像到M