-
关于MFC的一些说明
- MFC在Visual studio中,用于制作可视化界面,有点类似于Qt。
- 关于MFC的介绍,可以参考一些大佬的博客 ;
-
首先需要在类中声明需要用到的变量
class CMy03intrinsiccompareDlg : public CDialogEx
{
public:
double k1[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
CString str_intrinsic_1;
int enlarge;
}
- 从编辑文本框中获取字符,并将字符转换成double数组
void CMy03intrinsiccompareDlg::OnBnClickedButton1(){
CString str_intrinsic_1;
double k1[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
GetDlgItem(IDC_EDIT1)->GetWindowText(str_intrinsic_1);
//判断str_intrinsic_1是否有除了数字、负号、空格、的情况出现
if (!judge_image_sie(str_intrinsic_1)) {
return;
}
//将cstring转换成数组
cstring2array(str_intrinsic_1, k1);
}
bool CMy03intrinsiccompareDlg::judge_intrinsic(CString intrinsic) {
bool a = true;
if (intrinsic.GetAt(0) == ' ' && intrinsic.GetLength() == 1) {
MessageBox("未输入内参,请输入内参数据 M[4] D[8],用空格分开。");
a = false;
return a;
}
if (intrinsic.GetAt(0) == ' ') {
MessageBox("内参的第一个字符不能是空格,请输入内参数据 M[4] D[8],用空格分开");
a = false;
return a;
}
for (int i = 0; i < intrinsic.GetLength(); i++) {
int temp = intrinsic.GetAt(i) - '0';
if ((temp >= 0 && temp <= 9) ||
intrinsic.GetAt(i) == '.'||
intrinsic.GetAt(i) == ' ' ||
intrinsic.GetAt(i) == '-') {
//do nothing
}
else {
MessageBox("请正确输入内参数据 M[4] D[8],用空格分开");
a = false;
return a;
}
}
return a;
}
void CMy03intrinsiccompareDlg::cstring2array(CString cstr, double k[12]) {
const char* str_ = (LPCTSTR)cstr;
char *str = const_cast<char*>(str_);
char *ptr;
char *pTmp = NULL;
ptr = strtok_s(str, " ", &pTmp);
int i = 0;
while (ptr != NULL)
{
k[i] = atof(ptr);
i++;
ptr = strtok_s(NULL, " ", &pTmp);
}
}
- 加载工程子目录下的txt文档,并将其写入到编辑文本框
BOOL CMy03intrinsiccompareDlg::OnInitDialog(){
CStdioFile file;
if (file.Open("parameter/intrinsic_compare.txt", CFile::modeRead))
{
if (file.ReadString(str_intrinsic_1))
GetDlgItem(IDC_EDIT2)->SetWindowText(str_intrinsic_1);
file.Close();
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
- 在对话框关闭之前,将编辑文本框的内容写入工程子目录下的txt文档中
void CMy03intrinsiccompareDlg::OnBnClickedCancel()
{
GetDlgItemText(IDC_EDIT2, str_intrinsic_1);////获取指定ID的编辑框内容
CStdioFile FileWrite;
if (FileWrite.Open(strFile, CStdioFile::modeCreate | CStdioFile::modeNoTruncate | CStdioFile::modeWrite))//创建/打开文件
{
FileWrite.SetLength(0); //写入之前,将文档清空
FileWrite.WriteString(str_intrinsic_1);
FileWrite.WriteString(_T("\n"));
FileWrite.Close();//关闭输出文件
CDialogEx::OnCancel();
- 将opencv的图像显示在图像控件中
void CMy03intrinsiccompareDlg::DrawcvMat(cv::Mat m_cvImg, UINT ID)
{
cv::Mat img;
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
if (rect.Width() % 4 != 0)
{
rect.SetRect(rect.left, rect.top, rect.left + (rect.Width() + 3) / 4 * 4, rect.bottom); //调整图像宽度为4的倍数
GetDlgItem(ID)->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOMOVE);
}
cv::Rect dst(rect.left, rect.top, rect.right, rect.bottom);
cv::resize(m_cvImg, img, cv::Size(rect.Width(), rect.Height())); //使图像适应控件大小
unsigned int m_buffer[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
BITMAPINFO* m_bmi = (BITMAPINFO*)m_buffer;
BITMAPINFOHEADER* m_bmih = &(m_bmi->bmiHeader);
memset(m_bmih, 0, sizeof(*m_bmih));
m_bmih->biSize = sizeof(BITMAPINFOHEADER);
m_bmih->biWidth = img.cols; //必须为4的倍数
m_bmih->biHeight = -img.rows; //在自下而上的位图中 高度为负
m_bmih->biPlanes = 1;
m_bmih->biCompression = BI_RGB;
m_bmih->biBitCount = 8 * img.channels();
if (img.channels() == 1) //当图像为灰度图像时需要设置调色板颜色
{
for (int i = 0; i < 256; i++)
{
m_bmi->bmiColors[i].rgbBlue = i;
m_bmi->bmiColors[i].rgbGreen = i;
m_bmi->bmiColors[i].rgbRed = i;
m_bmi->bmiColors[i].rgbReserved = 0;
}
}
CDC *pDC = GetDlgItem(ID)->GetDC();
::StretchDIBits(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, rect.Width(), rect.Height(), img.data, (BITMAPINFO*)m_bmi, DIB_RGB_COLORS, SRCCOPY);
ReleaseDC(pDC);
}
- 保存控件图像为bmp格式到工程目录的子文件夹
void save_control_picture() {
CWnd* bmpShow = GetDlgItem(IDC_image);
CDC *pdc = bmpShow->GetDC();
CImage imag;
CRect rect;
GetClientRect(&rect); //获取画布大小
bmpShow->GetWindowRect(&rect);
imag.Create(rect.Width(), rect.Height(), 32);
::BitBlt(imag.GetDC(), 0, 0, rect.Width(), rect.Height(), pdc->m_hDC, 0, 0, SRCCOPY);
CFileDialog fileDlg(FALSE, _T("bmp"), _T("result/error_image.bmp"));
CString picturePath = fileDlg.GetPathName();//获取完整路径
HRESULT hResult = imag.Save(picturePath); //保存图片
ReleaseDC(pdc);
imag.ReleaseDC();
}
- 保存控件图像为bmp格式到自定义文件夹
/*手动选择保存路径*/
TCHAR szFilter[] = _T("jpg file(*.jpg)|*.jpg|bmp file(*.bmp)|*.bmp|所有文件(*.*)|*.*||"); //文件格式过滤
// 构造保存文件对话框
CFileDialog fileDlg(FALSE, _T("jpg"), _T("*.jpg"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this);
fileDlg.m_ofn.lpstrTitle = _T("保存直方图"); //保存对话窗口标题名
CString picturePath;
if (IDOK == fileDlg.DoModal()) //按下确认键
{
picturePath = fileDlg.GetPathName(); //文件路径
}
HRESULT hResult = imag.Save(picturePath); //保存图片
ReleaseDC(pdc);
imag.ReleaseDC();
}
- 保存Mat类型的图像到工程目录下的子文件(result)中,并修改名称
void save_Mat_image(cv::Mat image){
char file[100];
char* s = "error_image";
sprintf_s(file, "result/%s_%d.bmp", s,enlarge); //使用sprintf_s函数
imwrite(file, image);
}
-
opencv保存图像自动命名这篇博客写的很棒,有图有真相。但是将时间作为文件名,我没有搞定,不能成功运行。
-
发布软件注意事项
- 改用Release模式;
- 工程属性中:配置属性-常规,MFC使用类型选择“在共享的DLL中使用MFC”;
- 工程属性中:C/C++ - 代码生成-MFC的使用 选择“多线程DLL(/MD)”;
- 将使用的*.dll文件拷贝到和 *.exe文件所在的同一个目录下(*d.dll文件名称最后一个字符是d,表示debug版本)