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初始化函數里添加代碼
?? ?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 ?使用這個方法記得字符集選用“使用多字節字符”,不然會報錯 ?
?? ?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一樣可以實現出來。
1.讀入Mat矩陣(cvMat一樣),Mat img=imread("*.*");//cvLoadImage
確保轉換前矩陣中的數據都是uchar(0~255)類型(不是的話量化到此區間),這樣才能顯示。
2.根據矩陣大小創建(CImage::Create)新的的CImage類
CImage CI;
int w=img.cols;//寬
int h=img.rows;//高
int chinnels=img.channels();//通道數
CI.Destroy();//創建前,最好使用它,防止重復創建,程序崩潰
CI.Create(w,h,8*chinnels);
3.下來就是對CI進行賦值了,這里是最核心的地方,分二類討論
(1)如果是1個通道的圖像(灰度圖像)
CImage中內置了調色板,我們要對他進行賦值:
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;
然后就是數據拷貝了(這里的矩陣表示方法,根據需要(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個通道(彩色圖像)
沒有調色板,直接賦值
if(chinnels==3)
{//彩色圖像
uchar *pS;
uchar *pImg=(uchar *)CI.GetBits();//得到CImage數據區地址
int step=CI.GetPitch();
//這個是一行像素站的存儲空間w*3,并且結果是4的倍數(這個不用關注,到底是不是4的倍數有待考證)
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.至此已經構建好CImage,下來就是顯示它。我們可以直接在對話框、單文檔等地方顯示他,還可以使用CPictureCtrl空間顯示他。下面給出幾個顯示方法:
//顯示前,這里有個問題,等會討論
(1)放在一個按鈕響應或者函數中
//這里的m_Pic是一個CPictureCtrl的control,其他控件等也一樣
//CStatic m_Pic;
//DDX_Control(pDX, IDC_STATIC_Img, m_Pic);
CWnd * pCWnd = CWnd::FromHandle(m_Pic.GetSafeHwnd());
//通過變量得到dc比較復雜,但很好用
CPaintDC dc(pCWnd);//如果這個不能使用就換成CClientDC 。。。。
Invalidate(false);
SetStretchBltMode(dc.m_hDC,COLORONCOLOR);
//這個需要百度看看為什么這樣設置
CI.StretchBlt(dc.m_hDC,rect,SRCCOPY);
//這里顯示大小rect(CRect類型)也由自己定義,這個函數有許多重載函數
//圖像顯示的大小和效果,在你能顯示出來后,可以慢慢考慮
這里的控件的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.問題
前面提到一個問題,現在討論下,就是使用StretchBlt可以對圖像進行拉伸顯示。一般的圖像大小和你顯示的控件或者區域大小是不一樣的,這時使用它顯示可以拉伸它到合適的大小。(注意選擇合適參數)。但我們還可以直接使用opencv自帶的函數對圖像進行resize,可以同樣達到類似的效果。目前我嘗試的結果的是使用opencv經過形變后的顯示效果比MFC下的StretchBlt拉伸好看,也不知道這二種的效率如何。
6.小結
操作數據和算法實現時都是用opencv來實現,當顯示時,構造CImage顯示到windows系統的窗口上。不得不說,MFC,特別是高版本的MFC,學習起來相當困難。一方面,它本身做的十分復雜,需要很長時間熟悉它才能按照你的想法實現想要的東西。另一方面,缺乏好書來指導,比如說CImage類的用法,我是通過多種途徑和以前的積累才實現了最基礎的使用方法。雖然最后給出的代碼不多,但讓代碼不出錯,弄明白它的簡單機制卻花費很長時間。到底CImage類+CPictureCtrl是否適合用來顯示圖像,特別是對實時圖像處理的顯示,還需要進一步考證。
總結
以上是生活随笔為你收集整理的OpenCV学习笔记之 ( 三 ) MFC显示Mat图片的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字电视制播设备间的文件交换格式
- 下一篇: 彻底解决显示Opencv中Mat图像到M