文章预览:
- 一. 仿射变换原理
- 二. 仿射变换的第一种方式
- 三. 仿射变换的第二种方式
一. 仿射变换原理
二维仿射变换,顾名思义就是在二维平面内,将对象进行平移、旋转、缩放等变换的行为(还有其他的变换,这里仅论述这最常见的三种)。
![在这里插入图片描述 [Halcon&定位] 二维仿射变换原理与算子解析_矩阵](https://file.cfanz.cn/uploads/png/2023/12/22/8/eAZMM8eLF8.png)
进行仿射变换,首先我们待仿射变换的对象位置坐标、角度,然后找到目标对象的位置坐标、角度,通过计算两个参数的差值,就可以求出模板对象A和目标对象B之间的的仿射变换矩阵(二者的位置、角度等关系)。
二. 仿射变换的第一种方式
1、仿射变换的大致流程:
① 通过hom_mat2d_identity初始化一个空的仿射变换矩阵(即[1.0, 0.0, 0.0, 0.0, 1.0, 0.0]);
② 在初始化空的仿射矩阵中增加模板和目标之间的平移、旋转和缩放关系,用到的算子包括hom_mat2d_translate(平移)、hom_mat2d_rotate(旋转)、hom_mat2d_scale(缩放)等生成仿射变换矩阵(这几个算子可以叠加或者重复使用)
③ 得到模板和目标的仿射变换矩阵之后,可以对图像、区域或XLD执行仿射变换,用到的算子包括affine_trans_image(仿射图像)、affine_trans_region(仿射区域)、affine_trans_contour_xld(仿射轮廓)。
实际应用中,我们求仿射矩阵的目的一般是在匹配时,找到目标对象的模板轮廓并显示到图像上,便于观察确认匹配的准确度。
2、仿射变换用到的核心代码:
函数1:hom_mat2d_identity( : : HomMat2D)
功能:初始化一个空的仿射变换矩阵
参数:
HomMat2D(in):输入一个空的仿射变换矩阵
函数2:hom_mat2d_translate( : : HomMat2D, Tx, Ty
功能:把模板和目标的平移关系添加到防射变换矩阵
参数:
HomMat2D(in):空的仿射变换矩阵
Tx(in):Row方向的平移量
Ty(in):Column方向的平移量
HomMat2DTranslate(out):输出平移变换矩阵
函数3:hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py: HomMat2DRotate):
功能:把模板和目标的角度关系添加到仿射变换矩阵
参数:
HomMat2D(in):上面的平移仿射变换矩阵
Phi(in):旋转角度(逆时针旋转(Phi>0),顺时针旋转(Phi<0),单位弧度)
Px(in):变换的固定点行坐标(Row值)。固定点是指以该点为支撑进行仿射变换 (这里是指围绕这点进行旋转)
Py(in):变换的固定点列坐标(Col值)
HomMat2DRotate(out):输出具有平移+旋转变换关系的二维矩阵
hom_mat2d_rotate里面Phi,Px, Py的取值需要注意一下,比如,需要对下图中的的黑色矩形框进行仿射变换校正,经图像处理得到矩形框的角度是-89°,可以对图像旋转Phi = -1°(顺时针转1°)或Phi = 359°(逆时针旋转359°),Px = Width / 2(Row值,Width 代表图像宽),Py = Height / 2(Col值,Height 代表图像高)
![在这里插入图片描述 [Halcon&定位] 二维仿射变换原理与算子解析_计算机视觉_02](https://file.cfanz.cn/uploads/png/2023/12/22/8/NBf0a27A7Z.png)
函数4:hom_mat2d_scale( : : HomMat2D, Sx, Sy, Px, Py : HomMat2DScale)
功能:把模板和目标的缩放关系添加到仿射变换矩阵
参数:
HomMat2D(in):上面的平移+旋转仿射变换矩阵
Sx(in):Row方向的缩放系数(放大/缩小倍数)
Sy(in):Col方向的缩放系数
Px(in):缩放中心的Row值(基点)
Py(in): 缩放中心的Col值
HomMat2DScale(out):输出具有平移+旋转+缩放变换关系的二维矩阵
函数5:affine_trans_contour_xld( Contours : ContoursAffinTrans : HomMat2D : )
功能:对XLD轮廓进行二维仿射变换 (支持缩放,旋转,平移,斜切)
参数:
Contours(in):XLD轮廓AContoursAffinTrans(out):对XLD轮廓A仿射变换得到的XLD轮廓BHomMat2D(in):
函数6:affine_trans_image( Image : ImageAffinTrans : HomMat2D, Interpolation, AdaptImageSize : )
功能:对图像进行二维仿射变换 (支持缩放、旋转、平移)
参数:
Image(in):图像A
ImageAffinTrans(out):对图像A进行仿射变换得到图像BHomMat2D(in):仿射变换矩阵
Interpolation(in): 插值算法(nearest_neighbor,bilinear,constant,weighted)
AdaptImageSize(in):结果图像尺寸是否自适应。默认值:false
函数7:affine_trans_region( Region : RegionAffineTrans : HomMat2D, Interpolate : )
功能:对区域进行二维仿射变换 (支持缩放、旋转、平移)
参数:
Region(in):输入区域ARegionAffineTrans(out):仿射变换得到的区域BHomMat2D(in):仿射变换矩阵
Interpolate(in): 插值算法(constant,nearest_neighbor)默认值:nearest_neighbor。
3、仿射变换实战解析(模板匹配):
*创建模板
read_image (Image, 'D:/Data/3.jpg')
gen_rectangle1 (ModelRegion, 534.692, 581.663, 618.315, 621.485)
reduce_domain (Image, ModelRegion, TemplateImage)
create_shape_model (TemplateImage, 6, rad(0), rad(360), rad(0.2684), ['none','no_pregeneration'], 'use_polarity', [24,36,5], 4, ModelID)
area_center (ModelRegion, ModelRegionArea, AlignmentRow, AlignmentCol)
*显示模板轮廓
get_shape_model_contours (ModelContours, ModelID, 1)
* Matching 01: Get the reference position
area_center (ModelRegion, ModelRegionArea, RefRow, RefColumn)
vector_angle_to_rigid (0, 0, 0, RefRow, RefColumn, 0, HomMat2D)
affine_trans_contour_xld (ModelContours, TransContours, HomMat2D)
*开始读图匹配
TestImages := ['C:/Users/Administrator/Desktop/3.9/11111111.1.jpg']
for T := 0 to 0 by 1
read_image (Image, TestImages[T])
find_shape_model (Image, ModelID, rad(0), rad(360), 0.9, 0, 0.5, ['least_squares','max_deformation 6'], [6,1], 1, Row, Column, Angle, Score)
dev_display (Image)
for I := 0 to |Score| - 1 by 1
hom_mat2d_identity (HomMat2D)
hom_mat2d_rotate (HomMat2D, Angle[I], 0, 0, HomMat2D)
hom_mat2d_translate (HomMat2D, Row[I], Column[I], HomMat2D)
affine_trans_contour_xld (ModelContours, TransContours, HomMat2D)
dev_set_color ('green')
dev_display (TransContours)
stop ()
endfor
endfor
stop ()
clear_shape_model (ModelID)![在这里插入图片描述 [Halcon&定位] 二维仿射变换原理与算子解析_仿射变换_03](https://file.cfanz.cn/uploads/png/2023/12/22/8/Zbc0f20V32.png)
代码解析:
创建模板:
这里要注意的是,创建模板之后模板的位置变为(0,0),模板的当前角度也默认为0°,在图像的左上角位置。
显示模板轮廓:
这里在获取模板轮廓自身的仿射矩阵中:vector_angle_to_rigid (0, 0, 0, RefRow, RefColumn, 0, HomMat2D)参数是(0,0,0)的原因是因为在创建模板之后会自动将模板的位置和当前角度都为0,即模板是在窗口的左上角的,我们需要做的是将左上角的初始模板(0,0,0)仿射到图像中的模板位置,并显示出来。
读图、匹配模板,对模板轮廓进行仿射变换:
①hom_mat2d_identity创建一个初始化矩阵
②利用hom_mat2d_rotate,找到两者角度的差值。注意是以hom_mat2d_rotate的第3、4参数为基准坐标点进行旋转,这里是先旋转在平移,所以是先以模板中心坐标(0,0)为基准进行旋转,旋转了Angle[I] - 0度,在平移。如果是先平移在旋转,则要以目标位置的中心坐标为基准进行旋转,这个要注意。
③利用hom_mat2d_translate算子输入目标和模板的坐标差值,Row[I] - 0,Column[I] - 0,生成平移矩阵 HomMat2D
上面三步的目的就为了要这个旋转平移矩阵HomMat2D
④使用affine_trans_contour_xld就可以对模板轮廓A进行仿射变换,仿射到新图像的模板位置处。
三. 仿射变换的第二种方式
有时候,并不需要创建初始化矩阵也可以执行仿射变换,例如我们在上面实例中显示模板轮廓用到的仿射变换vector_angle_to_rigid算子就是如此,该算子的作用是生成一个平移、旋转仿射变换矩阵。
1、核心算子
函数:affine_trans_region( : : Row1, Column1, Angle1, Row2, Column2, Angle2
功能:根据点和角度计算刚性仿射变换矩阵,支持旋转和平移,相当于将hom_mat2d_translate和hom_mat2d_rotate算子功能进行了合并
参数:
Row1(in):原始点行坐标
Column1(in):原始点列坐标
Angle1(in):原始点角度
Row2(in):目标点行坐标
Column2(in):目标点列坐标
Angle2(in):目标点角度
HomMat2D(out):输出仿射变换矩阵
该算子意思是:先将图像旋转,旋转角度为(Angle2 - Angle1) (逆时针为正),旋转中心坐标是(Row1, Column1)。再将原图的点(Row1, Column1)一一对应移到点 (Row2, Column2)上,移动的row和column方向的位移分别是( Row2 - Row1)、( Column2 - Column1),该算子方便就方便在不用考虑旋转中心了,直接将前后的坐标和角度输入即可
vector_angle_to_rigid最常用到的场合一般是模板匹配之类的算法场合,通常用在find_shape_model等算子后面。
2、仿射变换实战解析(模板匹配):对图像、region和XLD进行仿射变换
read_image (Image, 'D:/Data/1.jpg')
gen_rectangle1 (ModelRegion, 566.247, 490.534, 594.44, 535.676)
area_center (ModelRegion, Area, Row, Column)
reduce_domain (Image, ModelRegion, TemplateImage)
create_ncc_model (TemplateImage, 'auto', rad(0), rad(20), 'auto', 'use_polarity', ModelId)
find_ncc_model (Image, ModelId, rad(0), rad(20), 0.8, 5, 0.5, 'true', 0, MatchingRow, MatchingCol, MatchingAngle, MatchingScore)
for MatchingObjIdx := 0 to |MatchingScore| - 1 by 1
gen_cross_contour_xld (TransContours, MatchingRow, MatchingCol, 20, MatchingAngle)
dev_display (TransContours)
endfor
for MatchingObjIdx := 0 to |MatchingScore| - 1 by 1
vector_angle_to_rigid (Row, Column, 0, MatchingRow[MatchingObjIdx], MatchingCol[MatchingObjIdx], MatchingAngle[MatchingObjIdx], HomMat2D)
affine_trans_region (ModelRegion, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
*显示模式为“边界”,否则会显示整个实心矩形区域
dev_set_draw ('margin')
dev_display (RegionAffineTrans)
endfor
clear_ncc_model (ModelId)效果和上面一样,都是通过引脚模板,找到芯片的所有引脚,就不放图了。
注:
- 上面的例子
roi区域是不带方向的,在灰度值匹配中,如果创建的是带方向的roi区域,create_ncc_model创建模板后,不管之前的roi区域是多少角度的,create_ncc_model函数内部都将角度默认为0°的,所以在后面的仿射变换是vector_angle_to_rigid第三个参数应该为0°,从0°到匹配对象的角度。 - 如果矩形框角度与找到的对象角度不匹配,需要修改
create_ncc_model (Operator)的第3、4参数,即搜索的角度范围,一般直接设置0 — 360°就可以了。 vector_angle_to_rigid(Operator)中,什么时候第一、二参数为0?
一般我们在get_shape_model_contours获取模板轮廓时,halcon会默认将轮廓放置在窗口左上角,即中心坐标为(0,0)。这时我们仿射该模板轮廓进行显示的时候就需要将第一、二参数输出为0。
HHomMat2D HomMat2d;
HomMat2d.VectorAngleToRigid(0, 0, 0, row[0].D(), col[0].D(), rotate[0].D());
HXLDCont ho_ModelContour = m_model.GetShapeModelContours(1);
_resRgn = HomMat2d.AffineTransContourXld(ho_ModelContour);戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。 |










