模板匹配是機器視覺工業現場中較為常用的一種方法,常用於定位,就是通過算法,在新的圖像中找到模板圖像的位置。例如以下兩個圖像。

這種模板匹配是最基本的模板匹配。其特點只是存在平移旋轉,不存在尺度變化,同時光照變化不大。這樣很適合常規的灰度模板匹配。但是利用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);
}
