打开不同格式的图形文件,彩色装灰度图像及将其存储为需求格式是图像处理的最基本的操作。如果单纯用MFC编程,是一个令人头痛的事情,有不少的代码量。可用OpenCV与MFC编程就变得相对简单。下面来详细演示这一编程操作。
一 在VS2022中创建一个MFC对话框Project
在V2022中用MFC向导创建一个对话框Project,在对话框中添加如下按钮控件:
修改控件ID
“打开图像文件”的ID修改如下:
“彩色图像转换为灰度图像”的ID修改如下:
“图像文件另存为“的ID修改如下:
”退出“的ID修改如下:
二 设置Project属性
设置使用字符集 使用“Unicode字符集”,如下:
设置Debug|X64附加依赖库
设置Release|X64 附加依赖库
三 包含OpenCV 相关头文件,并定义变量
在对话框头文件中包含OpenCV相关头文件如下:
// MFCDiaologOpenCVDlg.h: 头文件
//#pragma once
#include <opencv2/opencv.hpp>using namespace cv;
在头文件中定义以下私有变量:
class CMFCDiaologOpenCVDlg : public CDialogEx
{
// 构造
public:CMFCDiaologOpenCVDlg(CWnd* pParent = nullptr); // 标准构造函数
private:Mat src;CWnd* pWnd;CRect mRec;CPoint mPoint;CString m_Path;CString m_strEx;CString m_strName;String m_str;// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_MFCDIAOLOGOPENCV_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:afx_msg void OnBnClickedOpen();afx_msg void OnBnClickedCvt();afx_msg void OnBnClickedSaveas();afx_msg void OnBnClickedOk();
};
四 编写程序代码
为”打开图像文件”控件添加如下响应代码:
void CMFCDiaologOpenCVDlg::OnBnClickedOpen()
{// TODO: 在此添加控件通知处理程序代码CFileDialog fdlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("All files(*.*)|*.*||"));if (fdlg.DoModal() == IDOK){m_Path = fdlg.GetPathName();m_strEx = fdlg.GetFileExt();m_strName = fdlg.GetFileName();m_Path.ReleaseBuffer();m_strEx.ReleaseBuffer();m_strName.ReleaseBuffer();}if (m_strEx == "BMP" || m_strEx == "bmp" || m_strEx == "TIF" || m_strEx == "tif" || m_strEx == "PNG" || m_strEx == "png" || m_strEx == "jpg" || m_strEx == "JPG"){pWnd = GetDlgItem(IDC_PICSHOW);pWnd->GetClientRect(&mRec);mPoint = mRec.TopLeft();pWnd->ClientToScreen(&mPoint);m_str = CT2A(m_Path);src = imread(m_str);if(src.empty())MessageBox(_T("打开图像文件失败!"));else{m_str = CT2A(m_strName);namedWindow(m_str, WINDOW_AUTOSIZE);moveWindow(m_str, mPoint.x, mPoint.y);imshow(m_str, src);}}else{MessageBox(_T("你打开的文件不是本程序支持的图像文件!"));}
}
为”彩色图像转换为灰度图像”控件添加如下响应代码:
void CMFCDiaologOpenCVDlg::OnBnClickedCvt()
{// TODO: 在此添加控件通知处理程序代码Mat des;cvtColor(src, des, COLOR_BGR2GRAY, 0);destroyAllWindows();m_str = CT2A(m_strName);namedWindow(m_str, WINDOW_AUTOSIZE);moveWindow(m_str, mPoint.x, mPoint.y);imshow(m_str, des);src.release();des.copyTo(src);
}
为”图像另存为”控件添加如下响应代码:
void CMFCDiaologOpenCVDlg::OnBnClickedSaveas()
{// TODO: 在此添加控件通知处理程序代码CFileDialog fdlg(FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("All files(*.*)|*.*||"));if (fdlg.DoModal() == IDOK){m_Path = fdlg.GetPathName();m_strEx = fdlg.GetFileExt();m_strName = fdlg.GetFileName();m_Path.ReleaseBuffer();m_strEx.ReleaseBuffer();m_strName.ReleaseBuffer();}if (m_strEx == "BMP" || m_strEx == "bmp" || m_strEx == "TIF" || m_strEx == "tif" || m_strEx == "PNG" || m_strEx == "png" || m_strEx == "jpg" || m_strEx == "JPG"){m_str = CT2A(m_Path);imwrite(m_str, src);src = imread(m_str);destroyAllWindows();m_str = CT2A(m_strName);namedWindow(m_str, WINDOW_AUTOSIZE);moveWindow(m_str, mPoint.x, mPoint.y);imshow(m_str, src);}else{MessageBox(_T("你输入的文件格式不是不是本程序支持的图像文件格式,不能保存!"));}}
为”退出”控件添加如下响应代码:
void CMFCDiaologOpenCVDlg::OnBnClickedOk()
{// TODO: 在此添加控件通知处理程序代码//destroyAllWindows();CDialogEx::OnOK();
}
五 程序试运行
按“Ctrl+F5”试运行,程序跑起来了,如下:
点击“打开图像文件按钮”,进入到打开图像界面,如下:
选中1.bmp后点击打开,结果如下:
点击“图像另存为” 按钮,进入图像存储界面,如下:
点击“保存”,弹出确认对话框,如下:
点击是,回到原界面后,如下:
显示的图像变成了2.png,在打开图像时看到的2.png是灰度图像,现在变成了彩色图像。
点击“彩色图像转换为灰度图像”,结果如下:
点击图像另存为,进入图像存储界面
在文件名对话框中输入3.tif,点击保存,结果如下:
显示的图像变成了3.tif,再点击“打开图像文件”按钮,去看一下存储的文件是否存在,进入到打开文件界面,如下:
可以看到前面存储的3.tif文件确实存在。
关闭对话框,点退出,退出程序。
重新按“Ctrl+F5”运行程序,再试下打开3.tif这个存储文件,看能否正常打开,打开结果,如下:
确实能打开。说明控件响应程序没有问题。几行代码就完成了图像转换的相应,可以看出OpenCV确实强化。这个程序还存在些问题,当激活别的运行程序后,再回到这个对话框程序,可能回发现打开的图片不见了,或者跑到别的地方去了,这是MFC界面编程问题,如何处理,这里这里暂不做讨论。