前几天发了一个文章,是MFC控件上显示BMP图片,没有使用OpenCV,缺点是只能打开BMP文件(点击打开链接)。今天为了将方法改进,看了一些资料,经过自己的总结,得到了在Picture控件上显示Opencv处理过的图像的方法,以后可以直接在MFC+OpenCV平台下很容易地显示图像处理结果了。另外还发现,OpenCV提供的Mat类真是个好东西,里边封装的方法很像Matlab里边的函数,虽然没有使用,但是看了函数说明,是做的非常好的一个类,待以后探索吧。
今天的文章从两个地方得益良多:
(2)图像文件读入和显示
还有一个地方就是OpenCV的说明文档,这里不加链接了。
开始今天的话题:
1.平台:OpenCV2.4.6+VS2010
因为OpenCV 2.4.6版本不带CvvImage,带来了一些不便,所以今天才花了点功夫写成今天的程序。
2.代码
(1)首先是需要自己编写的ShowMat函数。
int CImgProcessorDlg::ShowMat(cv::Mat img, HWND hWndDisplay)
{
if (img.channels()<3 )
{
return -1;
}
//构造将要显示的Mat版本图片
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() );
//在控件上显示要用到的CImage类图片
ATL::CImage CI;
int w=imgShow.cols;//宽
int h=imgShow.rows;//高
int channels=imgShow.channels();//通道数
CI.Create( w, h, 8*channels);
//CI像素的复制
uchar *pS;
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];
//注意到这里的step不用乘以3
}
}
//在控件显示图片
HDC dc ;
dc = ::GetDC(hWndDisplay);
CI.Draw( dc, 0, 0 );
::ReleaseDC( hWndDisplay, dc);
CI.Destroy();
return 0;
}
(2)在按钮的响应函数调用刚刚写的ShowMat。
void CImgProcessorDlg::OnBnClickedBopen()
{
// TODO: 在此添加控件通知处理程序代码
CString FilePath;
CFileDialog FileDlg(TRUE);
if (IDOK == FileDlg.DoModal())
{
//获取FileOpen对话框返回的路径名
FilePath = FileDlg.GetPathName();
//GetPathName返回的是CString类型,要经过转换为string类型才能使用imread打开图片
std::string pathName(FilePath.GetBuffer());
//读取图片
cv::Mat orgImg = cv::imread(pathName);
//显示图片
ShowMat(orgImg, GetDlgItem(IDC_PIMAGE)->GetSafeHwnd());
}
}
3.程序结果。