VS2008 MFC Halcon模板匹配例子

来源:互联网 发布:77kjkj域名访问升级中 编辑:程序博客网 时间:2024/06/06 04:13

软件操作如下

1.如下界面


2.点击“显示图片”,可得被匹配图像,如下图


3.在被匹配图像中,点击鼠标左键,移动鼠标,松开鼠标左键,可抓取需要被匹配的模板


4.点击“模板匹配”,可得匹配结果如下



程序如下:

1.如图,添加如下控件


2.Halcon在VS中的配置,在这不做说明

3.主要程序如下:

// Halcon_MFCDlg.h : 头文件//#pragma once#include "HalconCpp.h"using namespace Halcon;// CHalcon_MFCDlg 对话框class CHalcon_MFCDlg : public CDialog{// 构造public:CHalcon_MFCDlg(CWnd* pParent = NULL);// 标准构造函数// 对话框数据enum { IDD = IDD_HALCON_MFC_DIALOG };protected: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 OnBnClickedButton1();//显示图片按钮afx_msg void OnBnClickedButton2();//模板匹配按钮void OnLButtonDown(CPoint point,CRect Rect);//鼠标左键点击void OnLButtonUp(CPoint point,CRect Rect);//鼠标左键抬起BOOL PreTranslateMessage(MSG* pMsg);//捕获鼠标事件CPoint m_PointCicleCenter,old_center;//鼠标左键起点坐标和落点坐标void DrawEllipse(int x,int y,int r);//画圆void DrawResult(int x,int y,int r);//画模板匹配结果圆void MatchTemplate();//模板匹配Hobject  ho_Image;//图像变量HTuple template_windowsID,m_TemplateID;void dispTemplate(int x,int y,int rr);//显示匹配模板BOOL m_bErase;void MoveMouse(CPoint point,CRect Rect);CPen* pGrayPen;  CPen* pLinePen; int nRadius;//模板半径};
// Halcon_MFCDlg.cpp : 实现文件//#include "stdafx.h"#include "Halcon_MFC.h"#include "Halcon_MFCDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialog{public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)END_MESSAGE_MAP()// CHalcon_MFCDlg 对话框CHalcon_MFCDlg::CHalcon_MFCDlg(CWnd* pParent /*=NULL*/): CDialog(CHalcon_MFCDlg::IDD, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CHalcon_MFCDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CHalcon_MFCDlg, CDialog)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()//}}AFX_MSG_MAPON_BN_CLICKED(IDC_BUTTON1, &CHalcon_MFCDlg::OnBnClickedButton1)//ON_WM_LBUTTONDOWN()ON_BN_CLICKED(IDC_BUTTON2, &CHalcon_MFCDlg::OnBnClickedButton2)END_MESSAGE_MAP()// CHalcon_MFCDlg 消息处理程序BOOL CHalcon_MFCDlg::OnInitDialog(){CDialog::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码old_center.x = 0;old_center.y = 0;pGrayPen = new CPen(0, 1, RGB(100, 100, 100));pLinePen = new CPen(0, 1, RGB(250, 0, 0));return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CHalcon_MFCDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CHalcon_MFCDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CHalcon_MFCDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}void CHalcon_MFCDlg::OnBnClickedButton1(){ //TODO: 在此添加控件通知处理程序代码HTuple HWindowID,num;CRect Rect;HTuple m_HWindowID;HTuple m_ImageWidth,m_ImageHeight;read_image(&ho_Image, "keypad.png");//读取图像//rgb1_to_gray(ho_Image,&ho_Image);//彩色图像转灰度图像get_image_size(ho_Image, &m_ImageWidth, &m_ImageHeight); //获取图像大小CWnd * pWnd = GetDlgItem( IDC_STATIC);pWnd->GetWindowRect(&Rect);ScreenToClient(&Rect);//得到IDC_STATIC在窗口中的位置pWnd->MoveWindow(Rect.left,Rect.top,m_ImageWidth[0].I(),m_ImageHeight[0].I());//将IDC_STATIC设置成图片的大小HWindowID = (Hlong)pWnd->m_hWnd;//获取父窗口句柄pWnd->GetWindowRect(&Rect);open_window(0,0,Rect.Width(),Rect.Height(),HWindowID,"","",&m_HWindowID );set_part(m_HWindowID,0,0,m_ImageHeight-1,m_ImageWidth-1);disp_obj(ho_Image, m_HWindowID);//在窗口中显示图像}void CHalcon_MFCDlg::OnLButtonDown(CPoint point,CRect lRect){if((point.x>=lRect.left && point.x<=lRect.right) && (point.y>=lRect.top && point.y<=lRect.bottom)){//获取鼠标左键点下时,光标在IDC_STATIC的坐标m_PointCicleCenter.x = point.x-lRect.left;m_PointCicleCenter.y = point.y-lRect.top;}}void CHalcon_MFCDlg::OnLButtonUp(CPoint point,CRect Rect){dispTemplate(old_center.x,old_center.y,nRadius);//显示需要被匹配的模板CWnd * pWnd = GetDlgItem( IDC_STATIC);CRect lRect;pWnd->GetWindowRect(&lRect);ScreenToClient(&lRect);CDC* pDC = GetDC(); // 获取设备上下文        pDC->SelectObject(pGrayPen); // 选取灰色笔pDC->SelectStockObject(NULL_BRUSH);pDC->SetROP2(R2_XORPEN); // 设置为异或绘图方式//消除视图中圆形if (m_bErase) { // need to erasepDC->Ellipse(old_center.x-nRadius +lRect.left, old_center.y-nRadius +lRect.top,old_center.x+nRadius + lRect.left, old_center.y+nRadius + lRect.top);}ReleaseDC(pDC); // 释放设备上下文m_bErase = FALSE;}//捕获鼠标消息BOOL CHalcon_MFCDlg::PreTranslateMessage(MSG* pMsg){CRect Rect;CWnd * pWnd = GetDlgItem( IDC_STATIC);pWnd->GetWindowRect(&Rect);static BOOL flag =FALSE;//鼠标左键在IDC_STATIC中点下if (pMsg->message==WM_LBUTTONDOWN && GetDlgItem(IDC_STATIC)->GetSafeHwnd() == pMsg->hwnd){flag = TRUE;OnLButtonDown(pMsg->pt,Rect);}//鼠标左键在IDC_STATIC中抬起if (pMsg->message== WM_LBUTTONUP && GetDlgItem(IDC_STATIC)->GetSafeHwnd() == pMsg->hwnd){flag = FALSE;OnLButtonUp(pMsg->pt,Rect);}//鼠标左键在IDC_STATIC中移动if(flag){if (pMsg->message== WM_MOUSEMOVE && GetDlgItem(IDC_STATIC)->GetSafeHwnd() == pMsg->hwnd){MoveMouse(pMsg->pt,Rect);}}return CDialog::PreTranslateMessage(pMsg);}//画圆void CHalcon_MFCDlg::DrawEllipse(int x,int y,int r) { CClientDC dc(this); CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));CBrush *pOldBrush=dc.SelectObject(pBrush);dc.Ellipse(x-r,y-r,x+r,y+r); dc.SelectObject(pOldBrush); }//画出模板匹配结果void CHalcon_MFCDlg::DrawResult(int x,int y,int r) { CClientDC dc(this); CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));CBrush *pOldBrush=dc.SelectObject(pBrush);dc.Ellipse(x-r,y-r,x+r,y+r); dc.SelectObject(pOldBrush); }//模板匹配void CHalcon_MFCDlg::MatchTemplate(){HTuple RowNew,ColumnNew,angle,Error1;best_match_rot_mg(ho_Image,m_TemplateID,-0.99,0.79,40,"true",4,&RowNew,&ColumnNew,&angle,&Error1);if(Error1<50){CRect rect;CWnd * pWnd = GetDlgItem( IDC_STATIC);pWnd->GetWindowRect(&rect);ScreenToClient(&rect);DrawResult(ColumnNew[0].I() + rect.left ,RowNew[0].I() + rect.top,30);}else{AfxMessageBox(_T("模板匹配失败"));}}void CHalcon_MFCDlg::OnBnClickedButton2(){// TODO: 在此添加控件通知处理程序代码MatchTemplate();}//显示需要被匹配的模板void CHalcon_MFCDlg::dispTemplate(int x,int y,int rr){Hobject region_template,region;HTuple template_width,template_height;HTuple windowsID;gen_circle(&region_template,(double)y,(double)x,(double)rr);reduce_domain(ho_Image,region_template,&region);crop_domain(region,&region_template);get_image_size(region_template, &template_width, &template_height); int ii = template_width[0].I();CString str;str.Format(_T("%d"),ii);CWnd * pWnd = GetDlgItem( IDC_STATIC_1);CRect rect;pWnd->GetWindowRect(&rect);ScreenToClient(&rect);pWnd->MoveWindow(rect.left,rect.top,template_width[0].I(),template_height[0].I());windowsID = (Hlong)pWnd->m_hWnd;//获取父窗口句柄pWnd->GetWindowRect(&rect);static BOOL flag = FALSE;if(flag){close_window(template_windowsID);}else{flag = TRUE;}open_window(0,0,rect.Width(),rect.Height(),windowsID,"visible","",&template_windowsID );set_part(template_windowsID,0,0,template_height-1,template_width-1);disp_obj(region_template, template_windowsID);create_template_rot(region,1,-0.99,0.79,0.01,"sort","original",&m_TemplateID);}void CHalcon_MFCDlg::MoveMouse(CPoint point2,CRect Rect){CPoint point;CWnd * pWnd = GetDlgItem( IDC_STATIC);CRect lRect;pWnd->GetWindowRect(&lRect);ScreenToClient(&lRect);if((point2.x>=Rect.left && point2.x<=Rect.right) && (point2.y>=Rect.top && point2.y<=Rect.bottom)){point.x = point2.x - Rect.left;point.y =point2.y - Rect.top;CDC* pDC = GetDC(); // 获取设备上下文        pDC->SelectObject(pGrayPen); // 选取灰色笔pDC->SelectStockObject(NULL_BRUSH);pDC->SetROP2(R2_XORPEN); // 设置为异或绘图方式if (m_bErase) { // need to erasepDC->Ellipse(old_center.x-nRadius +lRect.left, old_center.y-nRadius +lRect.top,old_center.x+nRadius + lRect.left, old_center.y+nRadius + lRect.top);}else // 需要擦除为假m_bErase = TRUE; // 设需要擦除为真CPoint center;center.x=(float(m_PointCicleCenter.x+point.x))/2;center.y=(float(m_PointCicleCenter.y+point.y))/2;nRadius=sqrt((double)(point.y-m_PointCicleCenter.y)*(point.y-m_PointCicleCenter.y)+(point.x-m_PointCicleCenter.x)*(point.x-m_PointCicleCenter.x))/2;pDC->Ellipse(center.x-nRadius +lRect.left, center.y-nRadius +lRect.top, center.x+nRadius +lRect.left, center.y+nRadius + lRect.top);old_center=center;ReleaseDC(pDC); // 释放设备上下文}}





原创粉丝点击