OpenCV中Mat、IplImage格式的图片,显示到MFC中的picture控件上
问题1.位图显示在picture控件上
如果你会把位图显示到picture在控件上,那么要将opencv中的Mat、IplImage格式的图片矩阵数据显示在MFC中的picture控件上就很容易了。
如下代码:
CDC* pDC = m_ColorArea.GetDC(); // 颜 {MOD}面板的CDC
CDC memDC; // 内存CDC
CBitmap bitmap; // 内存位图
BITMAP infoBitmap; // 位图信息结构体
// 创建内存CDC
memDC.CreateCompatibleDC(pDC);
// 创建设备相关位图
bitmap.CreateCompatibleBitmap(pDC, width, height);
// 获得位图信息
bitmap.GetBitmap(&infoBitmap);
// 是否支持32位颜 {MOD}
if (infoBitmap.bmBitsPixel != 32)
{
MessageBox(L"当前显示设备不支持32位颜 {MOD},程序自动退出!");
PostMessage(WM_QUIT);
}
BYTE* pixels = new BYTE[width*height * 4]; // 32位颜 {MOD}点阵数组
.....................
// 设置位图的点阵信息
bitmap.SetBitmapBits(width*height * 4, pixels);
memDC.SelectObject(bitmap);
// 拷贝内存CDC中的内容
pDC->BitBlt(0, 0,width, height, &memDC, 0, 0, SRCCOPY);
//pDC->StretchBlt(0,0,ctrl.Width(),ctrl.Height,&memDC,0,0,width,height,SRCCOPY);//以压缩和拉伸的方式显示位图
ReleaseDC(pDC);
SAFE_DELETE_ARRAY (pixels);
要显示一张位图,首先要创建兼容DC,调用CreateCompatibleDC函数后就会在内存中开辟空间,设置与设备相关的属性值,当然这些值的设置,你也可以自己进行。然后通过
函数CreateCompatibleBitmap来创建设备相关的位图,通过CBitmap中的GetBitmap函数得知设备中位图的显示格式。然后是得到像素值,就是uchar类型的堆。再通过CBitmap
中的SetBitmapBits函数将像素值保存到CBitmap的实例中。接着选择到设备上下文中。最后将设备上下文中的位图数据拷贝到屏幕上。
问题2.像素值的排列
将Mat、IlpImage格式的矩阵数据显示到MFC的picture控件上,唯一的问题就是其中的像素数据的排列的方式的问题。32位 {MOD}的显示器,每一个像素的值都是R位、G位、B位、
保留位,这样的顺序排列的,对于黑白图像RGB三个分量的值是相同的。而对于Mat和IlpImage的图像格式3通道的彩 {MOD}图像是按R、G、B的顺序排列每一位的彩 {MOD}像素值,而
没有保留位,所以显示位图的时候要把保留位加上。对于灰度图像来说,Mat和IlpImage直接按灰度值排列。他们都是按先行后列的方式排列的。
如下代码:
std::string strName = (LPCTSTR)dlg.GetPathName();
cv::Mat test = cv::imread(strName);
//把Mat格式的图像数据显示到控件上
CPicture *pPicture = this;
CDC* pDC = pPicture->GetDC();
CDC memCDC;
CBitmap bitmap;
BITMAP infoBitmap;
memCDC.CreateCompatibleDC(pDC);
bitmap.CreateCompatibleBitmap(pDC,test.cols,test.rows);
bitmap.GetBitmap(&infoBitmap);
uchar *p = test.ptr(0);
Vec3b *pVec3b = test.ptr(0);
int row = test.rows, col = test.cols;
uchar *pixel = new uchar[row*col*4];
if(test.channels() > 1 && infoBitmap.bmBitsPixel == 32)
{
int j=0;
for(int i=0;iGetClientRect(&rect);
//pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memCDC,0,0,SRCCOPY);
pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&memCDC,0,0,test.cols,test.rows,SRCCOPY);
memCDC.DeleteDC();
bitmap.DeleteObject();
delete[] pixel;