模板匹配是机器视觉工业现场中较为常用的一种方法,常用于定位,就是通过算法,在新的图像中找到模板图像的位置。例如以下两个图像。
这种模板匹配是最基本的模板匹配。其特点只是存在平移旋转,不存在尺度变化,同时光照变化不大。这样很适合常规的灰度模板匹配。但是利用opencv不太好解决角度的问题,同时速度上也达不到工业需求,因此,halcon的用途就来了。下面我详细介绍模板匹配的过程:
1 首先是选择区域。也就是ROI。我们先建一个矩形区域,以矩形的中点作为参考点。
//矩形区域 gen_rectangle1(&Rectangle, startpoint.y, startpoint.x, h + startpoint.y, w + startpoint.x); //矩形中心点 area_center(Rectangle, &Area, &RowRef, &ColumnRef); //设置ROI reduce_domain(ImageHalcon, Rectangle, &ImageReduced);
2 新建模型。
create_ncc_model(ImageReduced, "auto", HTuple(-45).Rad(), HTuple(90).Rad(), "auto", "use_polarity", &ModelID);
创建的NCC模型,这种模型是最简单的,只适用于光照变化不大,且不存在尺度变化的。建
立的模型以 ModelID 标识
3 模板匹配。载入待匹配的图像ImageSearch和之前的mode。
find_ncc_model(ImageSearch, ModelID, HTuple(-45).Rad(), HTuple(90).Rad(), 0.5, 1, 0.5, "true", 0, &Row, &Column, &Angle, &Score);
4 匹配分析
if(Score.Num()>0)//如果score大于零 表明匹配正确 { // 获取仿射变换矩阵HomMat2d,可以直接获取 vector_angle_to_rigid(RowRef, ColumnRef, 0, Row, Column, Angle, &HomMat2D); affine_trans_region(Rectangle, &RegionAffineTrans, HomMat2D, "false"); // [a b c] [ a b] //[ d e f] [ d e]为旋转 [c f]T 为平移 // double a, b, c, d, e, f; e = HomMat2D[0].D(); d = HomMat2D[1].D(); f = HomMat2D[2].D(); b = HomMat2D[3].D(); a = HomMat2D[4].D(); c = HomMat2D[5].D(); double angle; angle = Angle[0].D() * 180 / 3.1415926; //angleoff = 5*3.14159/180; angleoff = Angle[0].D();
//ROI参考点中心在待匹配图像中的位置 centerpoint.x = Column[0].I(); centerpoint.y = Row[0].I(); endcenter = centerpoint; cvCircle(m_testimage, centerpoint, 4, cvScalar(0, 0, 255), 2, 8, 0); //当然,仿射变换矩阵我们可以直接通过旋转和平移求得 a = cos(angleoff); b = sin(angleoff); d = -sin(angleoff); e = cos(angleoff); c = endcenter.x - (a*startcenter.x + b*startcenter.y); f = endcenter.y - (d*startcenter.x + e*startcenter.y); HTuple x1, y1, x2, y2; x1 = 573; y1 = 407; //我们可以通过仿射变换矩阵,将模板图像中的一个点映射到待匹配图像中的点 Halcon::affine_trans_point_2d(HomMat2D, y1, x1, &y2, &x2); CvPoint2D32f p1, p2; p1.x = x2[0].D(); p1.y = y2[0].D(); x1 = 625; y1 = 480; Halcon::affine_trans_point_2d(HomMat2D, y1, x1, &y2, &x2); p2.x = x2[0].D(); p2.y = y2[0].D(); p1.x = (int)p1.x; p1.y = (int)p1.y; p2.x = (int)p2.x; p2.y = (int)p2.y; DispImage(ImageSearch); Halcon::disp_obj(RegionAffineTrans, HalHwndView1); CString str; str.Format("角度为:%.4f 度 :(%f , %f)", angle, xoff, yoff); cvLine(m_testimage, cvPoint(p1.x, p1.y), cvPoint(p2.x, p1.y), cvScalar(255, 0, 0)); cvLine(m_testimage, cvPoint(p1.x, p1.y), cvPoint(p1.x, p2.y), cvScalar(255, 0, 0)); cvLine(m_testimage, cvPoint(p2.x, p1.y), cvPoint(p2.x, p2.y), cvScalar(255, 0, 0)); cvLine(m_testimage, cvPoint(p1.x, p2.y), cvPoint(p2.x, p2.y), cvScalar(255, 0, 0)); str.Format("角度为:%.4f 度 已经匹配ROI的中心:(%d , %d)",angle, centerpoint.x,centerpoint.y); GetDlgItem(IDC_STATIC_SWINFO)->SetWindowText(str); cvNamedWindow("匹配结果",0); cvShowImage("匹配结果",m_testimage); }else { CString str="没有匹配成功"; GetDlgItem(IDC_STATIC_SWINFO)->SetWindowText(str); }