您的位置:首页 > 运维架构

CImage显示OpenCV:Mat矩阵图像

2013-09-17 09:47 369 查看
转自: http://www.opencv.org.cn/forum/viewtopic.php?p=52713

[cpp]
view plaincopyprint?

/*************************************/  
  
//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)为起点  

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

//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)为起点


总结起来就是:

[cpp]
view plaincopyprint?

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];  
                }             
            }  
        }     
    }  
  
}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: