opencv2 在mfc窗口中显示关于cv::Mat 的解决方法
2014-10-09 16:37
603 查看
opencv2 采用c++代替c,IplImage是原来opencv最常用的数据结构,在opencv2中被cv::Mat取代,opencv2没有直接提供将cv::Mat显示到mfc窗口的接口,需要自己实现。
和原来的IplImage结构不同,cv::Mat 内部的图像数据没有采用行对齐全的方式,即内存上图像每行的内存数据是4的整数倍,所以当图像的列数不是4的倍数是,按IplImage的方式在mfc窗口上显示cv::Mat会没办正确显示。
解决的办法是使数据按4的倍数对齐,我采用的方法是复制,也可以转成IplImage,
<span style="white-space:pre"> </span>//画出指定位置图像
void show(cv::Mat m_img, HDC dc, int x, int y, int w, int h, int from_x, int from_y )
{
//内存中的图像数据拷贝到屏幕上
uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
BITMAPINFO* bmi = (BITMAPINFO*)buffer;
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = m_img.cols;
bmih->biHeight = -m_img.rows;
bmih->biPlanes = 1;
bmih->biBitCount = 8 * m_img.channels();
bmih->biCompression = BI_RGB;
if( m_img.channels() == 1 )
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for( i = 0; i < 256; i++ )
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
from_x = MIN( MAX( from_x, 0 ), m_img.cols - 1 );
from_y = MIN( MAX( from_y, 0 ), m_img.rows - 1 );
int sw = MAX( MIN( m_img.cols - from_x, w ), 0 );
int sh = MAX( MIN( m_img.rows - from_y, h ), 0 );
if(m_img.cols % 4 != 0 && m_img.isContinuous())
{
int nLineWidth = (sw * m_img.channels() + 3)/4*4; //凑成大于等于nColumn的最小的4的整倍数
BYTE *m_pImageBuffer = new BYTE[sh * nLineWidth];
for(int i = 0; i < sh; i++)
{
memcpy(m_pImageBuffer + i * nLineWidth, m_img.ptr<uchar>(i), m_img.step);
}
SetDIBitsToDevice(
dc,
x,
y,
sw,
sh,
from_x,
from_y,
from_y,
sh,
m_pImageBuffer + from_y * nLineWidth,
bmi,
DIB_RGB_COLORS
);
delete m_pImageBuffer;
}
else
{
SetDIBitsToDevice(
dc,
x,
y,
sw,
sh,
from_x,
from_y,
from_y,
sh,
m_img.data + from_y * m_img.step,
bmi,
DIB_RGB_COLORS
);
}
}IplImage既然是被抛弃,应该尽量少用。
和原来的IplImage结构不同,cv::Mat 内部的图像数据没有采用行对齐全的方式,即内存上图像每行的内存数据是4的整数倍,所以当图像的列数不是4的倍数是,按IplImage的方式在mfc窗口上显示cv::Mat会没办正确显示。
解决的办法是使数据按4的倍数对齐,我采用的方法是复制,也可以转成IplImage,
<span style="white-space:pre"> </span>//画出指定位置图像
void show(cv::Mat m_img, HDC dc, int x, int y, int w, int h, int from_x, int from_y )
{
//内存中的图像数据拷贝到屏幕上
uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
BITMAPINFO* bmi = (BITMAPINFO*)buffer;
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = m_img.cols;
bmih->biHeight = -m_img.rows;
bmih->biPlanes = 1;
bmih->biBitCount = 8 * m_img.channels();
bmih->biCompression = BI_RGB;
if( m_img.channels() == 1 )
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for( i = 0; i < 256; i++ )
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
from_x = MIN( MAX( from_x, 0 ), m_img.cols - 1 );
from_y = MIN( MAX( from_y, 0 ), m_img.rows - 1 );
int sw = MAX( MIN( m_img.cols - from_x, w ), 0 );
int sh = MAX( MIN( m_img.rows - from_y, h ), 0 );
if(m_img.cols % 4 != 0 && m_img.isContinuous())
{
int nLineWidth = (sw * m_img.channels() + 3)/4*4; //凑成大于等于nColumn的最小的4的整倍数
BYTE *m_pImageBuffer = new BYTE[sh * nLineWidth];
for(int i = 0; i < sh; i++)
{
memcpy(m_pImageBuffer + i * nLineWidth, m_img.ptr<uchar>(i), m_img.step);
}
SetDIBitsToDevice(
dc,
x,
y,
sw,
sh,
from_x,
from_y,
from_y,
sh,
m_pImageBuffer + from_y * nLineWidth,
bmi,
DIB_RGB_COLORS
);
delete m_pImageBuffer;
}
else
{
SetDIBitsToDevice(
dc,
x,
y,
sw,
sh,
from_x,
from_y,
from_y,
sh,
m_img.data + from_y * m_img.step,
bmi,
DIB_RGB_COLORS
);
}
}IplImage既然是被抛弃,应该尽量少用。
相关文章推荐
- 关于MFC中显示OpenCV Mat矩阵中的图像(一种新的解决方法)
- 彻底解决显示Opencv中Mat图像到Mfc窗口问题
- MFC窗口视频显示方法--OpenCV DirectShow模式
- OpenCV的cvReleaseImage释放内存出错解决方法及Mat格式与IplImage格式相互转换
- 关于MFC窗口分割无法指定第二行/列的高度/宽度的解决方法
- 关于“在MFC对话框程序中图片显示不出来”问题的解决方法
- 关于VC6.0 MFC+ATL做出的COM,其内部的windows窗口不能以XP Theme模式显示的问题彻底解决
- 在 MFC 框架中,有什么方法能直接将 OpenCV 2.0 库中 Mat 格式的图片传递到 Picture Control(图片控件)显示?
- opencv中显示“cv中没有成员vector”的解决方法
- 将Opencv2的Mat类型数据显示到MFC窗口上
- MFC窗口视频显示方法--OpenCV VFW模式
- 关于对话框最小化到托盘后,点击托盘图标后只在任务栏显示而无法还原窗口的解决方法。
- 关于解决mysql命令窗口无法显示中午结果和显示乱码与显示中文错位的解决方法
- 利用 OpenCV 在MFC中显示图像问题以及解决方法
- 知乎上有一个问题“在mfc框架中,有上面方法能直接将opencv2.0库中的Mat格式图片传递到Picture Control”中显示?
- 各位C#高手,我编了个小小关于TreeView控件的程序但就是在窗口上显示不出来.帮忙解决下.
- 关于chm电子书无法显示网页的解决方法
- 关于IE登录FTP站点,选择"保存密码"后,登录窗口不在出现的解决方法
- 关于OpenCV_1.1pre1a 安装若干问题的解决方法:
- 关于获得MFC窗口其它类指针的方法