工件匹配MFC框架搭建
创建基于对话框的MFC项目:
对话框界面:
打开文件
按钮ID是button1负责选择要匹配的图,并显示在下方的picture control控件中。主要代码(直接双击按钮就可以在里面写代码):
void CMFCApplicationDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
//读入待检测图像
CFileDialog dlg(
TRUE, _T("*.bmp"), NULL,
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T(" All Files (*.*) |*.*||"), NULL
);// 选项图片的约定
dlg.m_ofn.lpstrTitle = _T("OpenImage"); // 打开文件对话框的标题名
if (dlg.DoModal() != IDOK) // 判断是否获得图片
return;
mPath1 = dlg.GetPathName(); // 获取图片路径
char* mmPath;
mmPath = str2char(mPath1);
IplImage* ipl = cvLoadImage(mmPath, 1); // 读取彩色图片、缓存到一个局部变量ipl 中
if (!ipl) // 判断是否成功载入图片
return;
if (TheImage) // 对上一幅显示的图片数据清零
cvZero(TheImage);
ShowImage(ipl, IDC_STATIC1); // 调用显示图片函数
cvReleaseImage(&ipl);
}
导入模板图
按钮ID是button2负责选择模板图,并显示在下方的picture control控件中。主要代码:
void CMFCApplicationDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(
TRUE, _T("*.bmp"), NULL,
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T(" All Files (*.*) |*.*||"), NULL
); // 选项图片的约定
dlg.m_ofn.lpstrTitle = _T("OpenImage"); // 打开文件对话框的标题名
if (dlg.DoModal() != IDOK) // 判断是否获得图片
return;
mPath2 = dlg.GetPathName(); // 获取模板图片路径
char* mmPath;
mmPath = str2char(mPath2);
IplImage* ipl = cvLoadImage(mmPath, 1); // 读取彩色图片、缓存到一个局部变量ipl 中
if (!ipl) // 判断是否成功载入图片
return;
if (TheImage) // 对上一幅显示的图片数据清零
cvZero(TheImage);
ShowImage(ipl, IDC_STATIC2); // 调用显示图片函数
cvReleaseImage(&ipl);
}
注册模板
按钮ID是button3负责提取模板图特征,特征提取完后在下方编辑框中显示注册成功。主要代码:
void CMFCApplicationDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
//注册模板按钮
imageFilename = CString2string(mPath1);
templateFilename = CString2string(mPath2);
rec_num = 3;
imagemodel = imread(imageFilename);
template_image = imread(templateFilename);
tempWidth = template_image.cols;
tempHeight = template_image.rows;
getFeatures(template_image, m_features);
for (int i = 0; i < m_features[0].FeaturePoint.size(); i++)
{
template_image.at<Vec3b>(m_features[0].FeaturePoint[i].y, m_features[0].FeaturePoint[i].x)[0] = 0;
template_image.at<Vec3b>(m_features[0].FeaturePoint[i].y, m_features[0].FeaturePoint[i].x)[1] = 0;
template_image.at<Vec3b>(m_features[0].FeaturePoint[i].y, m_features[0].FeaturePoint[i].x)[2] = 255;//R通道
}
CString show ;
char show1[20] = "注册成功!";
show = show1;
//show.Format(_T("%S"),show);
SetDlgItemText(IDC_EDIT5, show);
}
这里要注意要想将“注册成功!”中文成功显示,不能用以前的show.Format(_T("%S"),show);该函数是将CString类型转换为字符型显示,但是在VS2019会显示出乱码。直接先定义字符数组然后show=show1解决了乱码问题。
开始匹配
按钮ID是button4负责进行模板匹配,匹配完成后将匹配图显示出来,并显示匹配时间,匹配信息等。主要代码:
void CMFCApplicationDlg::OnBnClickedButton4()
{
UpdateData(true);
// TODO: 在此添加控件通知处理程序代码
//开始匹配按钮
Mat Max_grad = Mat::zeros(imagemodel.rows, imagemodel.cols, CV_32F);
Mat Max_alpha = Mat::zeros(imagemodel.rows, imagemodel.cols, CV_32F);
double start = static_cast<double>(getTickCount());
Match(imagemodel, m_features, Max_grad, Max_alpha);
double time1 = (double)getTickCount();
vector<Roi> Rois;
getRois(rec_num, Max_grad, Max_alpha, Rois);
Mat dst1 = imagemodel.clone();
Mat dst2;
for (int i = 0; i < Rois.size(); i++)
{
draw_recs(dst1, dst1, Rois[i].Max_loc, Rois[i].Max_alpha, tempWidth, tempHeight);
putText(dst1, std::to_string(Rois[i].Max_alpha), Rois[i].Max_loc, cv::FONT_HERSHEY_SIMPLEX, 0.45, CV_RGB(0, 255, 0), 1.8);
//cout << "粗匹角度" << Rois[i].Max_alpha << "粗匹坐标" << Rois[i].Max_loc << endl;
}
int angle_loc, row_loc, col_loc;
local_match(imagemodel, Rois, m_features, angle_loc, row_loc, col_loc);
double time2 = (double)getTickCount();
Point fin_loc = Point(col_loc, row_loc);
draw_rec(imagemodel, template_image, dst2, fin_loc, angle_loc);
putText(dst2, std::to_string(angle_loc), fin_loc, cv::FONT_HERSHEY_SIMPLEX, 0.45, CV_RGB(0, 255, 0), 1.8);
Rect roi(col_loc, row_loc, tempWidth, tempHeight);
rectangle(imagemodel, roi, Scalar(0, 0, 255), 2);
imwrite(imageFilename, dst2);//不改变原图,只显示检测图
mPath3 = string2CString(imageFilename);
char* mmPath;
mmPath = str2char(mPath3);
IplImage* img0 = cvLoadImage(mmPath, 1);
ShowImage(img0, IDC_STATIC3); // 调用显示图片函数
cvReleaseImage(&img0);
float time0 = (time2 - start) / getTickFrequency();
// //显示数据
CString times, angle, xlabel, ylabel;
times.Format(_T("%.6f"), time0);
angle.Format(_T("%d"), angle_loc);
xlabel.Format(_T("%d"), fin_loc.x);
ylabel.Format(_T("%d"), fin_loc.y);
SetDlgItemText(IDC_EDIT1, times);
SetDlgItemText(IDC_EDIT4, angle);
SetDlgItemText(IDC_EDIT2, xlabel);
SetDlgItemText(IDC_EDIT3, ylabel);
}
匹配按钮中那些匹配函数,画框函数,显示图片函数等在dlg.cpp文件中直接定义
void CMFCApplicationDlg::local_match
注意所有函数要继承CDlg对话框类,MFCApplication是项目名称
声明在dig.h头文件声明
tips:
1、加入CvvImage用于显示图片,具体可以看该博文:
https://blog.csdn.net/wgf5845201314/article/details/78186178
2、改控件的ID后会出现ID 未定义标识符,此时关闭软件重启即可;
3、opencv版本过高,GetCvSize会出错,CvSize size = cvGetSize(img);该句会中断,改成
CvSize size;
size.width = img->width;
size.height = img->height;
之后再完善!