做MFC+opencv项目时,对于我来说,将视频显示到相应控件上(static或者picture)这个问题一直存在,虽然之前写个一个帖子,介绍了一种将opencv的显示window贴到相应控件上的方法,代码很少,使用简单。但或多或少感觉这种方法总是欠缺点什么。今天无聊时翻知乎,看到几年前几个大神的讨论,地址:https://www.zhihu.com/question/29611790,感觉很不错,总结了BrightGuo老师的方法,自己写代码跑了一下,确实不错,贴出来亮一亮!
/*
*显示视频 HWND Mat
*/
void ShowMat(Mat img, HWND hWndDisplay)
{
if (img.channels() == 1)
{
//调整图片与显示控件大小一致
RECT rect;
GetClientRect(hWndDisplay, &rect);
Mat imgShow(abs(rect.top - rect.bottom), abs(rect.right - rect.left), CV_8UC1);
resize(img, imgShow, imgShow.size());
ATL::CImage CI;
int w = imgShow.cols;//宽
int h = imgShow.rows;//高
int channels = imgShow.channels();//通道数
CI.Destroy();//防止重复创建导致程序崩溃
CI.Create(w, h, 8 * channels);
RGBQUAD* ColorTable;
int MaxColors = 256;
ColorTable = new RGBQUAD[MaxColors];
CI.GetColorTable(0, MaxColors, ColorTable);//这里是取得指针
for (int i = 0; i < MaxColors; i++)
{
ColorTable->rgbBlue = (BYTE)i;
ColorTable->rgbGreen = (BYTE)i;
ColorTable->rgbRed = (BYTE)i;
}
CI.SetColorTable(0, MaxColors, ColorTable);
delete[] ColorTable;
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];
}
}
HDC dc = GetDC(hWndDisplay);
CI.Draw(dc, 0, 0);
ReleaseDC(hWndDisplay, dc);
CI.Destroy();
}
if(img.channels() == 3)
{
//调整图片与显示控件大小一致
RECT rect;
GetClientRect(hWndDisplay, &rect);
cv::Mat imgShow(abs(rect.top - rect.bottom), abs(rect.right - rect.left), CV_8UC3);
resize(img, imgShow, imgShow.size());
ATL::CImage CI;
int w = imgShow.cols;//宽
int h = imgShow.rows;//高
int channels = imgShow.channels();//通道数
CI.Destroy();//防止重复创建导致程序崩溃
CI.Create(w, h, 8 * channels);
uchar *pS;//图片数据类型:uchar; value range:0~255
uchar *pImg = (uchar *)CI.GetBits();//得到CImage数据区地址
int step = CI.GetPitch();
for (int i = 0; i < h; i++)
{
pS = imgShow.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];
}
}
HDC dc = GetDC(hWndDisplay);
CI.Draw(dc, 0, 0);
ReleaseDC(hWndDisplay, dc);
CI.Destroy();
}
}
理论上用到CImage类,需要include <atlImage.h>,但我在我的工程里没有添加编译仍然通过,不知道什么原因,具体不深究了。
总之,显示视频功能实现了,自己玩去吧!