MFC:CImage顯示OpenCV:Mat矩陣圖像

轉自: http://www.opencv.org.cn/forum/viewtopic.php?p=52713



/*************************************/

//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個通道的圖像(灰度圖像) DIB格式才需要對調色板設置
//	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<uchar>(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<uchar>(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);
		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)爲起點




總結起來就是:


void MatToCImage( Mat &mat, CImage &cImage)
{
	//create new CImage
	int width    = mat.cols;
	int height   = mat.rows;
	int channels = mat.channels();

	cImage.Destroy(); //clear
	cImage.Create(width, 
		height, //positive: left-bottom-up   or negative: left-top-down
		8*channels ); //numbers of bits per pixel

	//copy values
	uchar* ps;
	uchar* pimg = (uchar*)cImage.GetBits(); //A pointer to the bitmap buffer
		
	//The pitch is the distance, in bytes. represent the beginning of 
	// one bitmap line and the beginning of the next bitmap line
	int step = cImage.GetPitch();

	for (int i = 0; i < height; ++i)
	{
		ps = (mat.ptr<uchar>(i));
		for ( int j = 0; j < width; ++j )
		{
			if ( channels == 1 ) //gray
			{
				*(pimg + i*step + j) = ps[j];
			}
			else if ( channels == 3 ) //color
			{
				for (int k = 0 ; k < 3; ++k )
				{
					*(pimg + i*step + j*3 + k ) = ps[j*3 + k];
				}			
			}
		}	
	}

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章