Halcon 二维仿射变换

二维仿射变换,顾名思义就是在二维平面内,将对象进行平移、旋转、缩放等变换的行为(当然还有其他的变换,这里仅论述这三种最常见的)。

仿射变换原理:

进行仿射变换,首先我们仿射变换的对象位置坐标、角度,然后找到目标对象的位置坐标、角度,求出两个参数的差值,就可以求出将A仿射变换到B的仿射矩阵了。
        在模板匹配中,仿射变换就是找到模板与目标对象之间的位置、角度关系,从而生成仿射矩阵。下次通过①模板的位置、角度②仿射变换矩阵,就可以找到目标对象的位置了。

仿射变换流程:

Halcon中进行仿射变换的常见步骤如下:

① 通过hom_mat2d_identity算子创建一个 初始化矩阵(即[1.0, 0.0, 0.0, 0.0, 1.0, 0.0]);

② 在初始化矩阵的基础上,使用 hom_mat2d_translate(平移)、hom_mat2d_rotate(旋转)、hom_mat2d_scale(缩放)等生成仿射变换矩阵;(这几个算子可以叠加或者重复使用)

③ 根据生成的变换矩阵执行仿射变换,执行仿射变换的算子通常有:affine_trans_image、affine_trans_region、affine_trans_contour_xld,即不管对于图像、区域、XLD都可以执行仿射变换。

仿射变换流程核心代码:

一、创建一个初始化矩阵
功能:产生仿射变换矩阵(产生一个空的二维空变换矩阵)
hom_mat2d_identity( : : HomMat2D)

二、生成平移、旋转、缩放仿射变换矩阵
功能:把平移添加到防射变换矩阵
hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)

  • HomMat2D:(输入参数)仿射变换矩阵
  • Tx(输入参数):Row方向的平移量
  • Ty(输入参数):Column方向的平移量
  • HomMat2DTranslate(输出参数):输出变换矩阵

功能:把旋转角度添加到仿射变换矩阵
hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py: HomMat2DRotate)

  • HomMat2D :(输入参数)仿射变换矩阵

  • Phi:旋转角度(逆时针旋转(Phi>0),顺时针旋转(Phi<0),单位弧度)

  • Px :变换的固定点行坐标(Row值)。固定点是指以该点为支撑进行仿射变换 (这里是指围绕这点进行旋转)

  • Py: 变换的固定点列坐标(Col值)

  • HomMat2DRotate:输出的旋转变换的二维矩阵

这里面Phi, Px, Py的取值需要注意一下,比如,需要对下图中的的黑色矩形框进行仿射变换校正,经图像处理得到矩形框的角度是-89°,可以对图像旋转Phi = -1°(顺时针转1°)或Phi = 359°(逆时针旋转359°),Px = Width / 2(Row值,Width 代表图像宽),Py = Height / 2(Col值,Height 代表图像高)

功能:把缩放添加到仿射变换矩阵
hom_mat2d_scale( : : HomMat2D, Sx, Sy, Px, Py : HomMat2DScale)

  • HomMat2D(输入参数):仿射变换矩阵
  • Sx(输入参数):Row方向的缩放系数(放大/缩小倍数)
  • Sy(输入参数):Col方向的缩放系数
  • Px(输入参数):缩放中心的Row值(基点)
  • Py(输入参数): 缩放中心的Col值
  • HomMat2DScale(输出参数):输出缩放变换矩阵

三、对图像、region和XLD进行仿射变换
功能:对XLD轮廓进行二维仿射变换 (支持缩放,旋转,平移,斜切)
affine_trans_contour_xld(Contours : ContoursAffinTrans : HomMat2D : )

  • Contours(输入参数):输入XLD轮廓
  • ContoursAffinTrans(输出参数):输出变换的XLD轮廓
  • HomMat2D(输入参数):仿射变换矩阵

功能:对图像轮廓进行二维仿射变换 (支持缩放、旋转、平移,斜切)
affine_trans_image(Image : ImageAffinTrans : HomMat2D, Interpolation, AdaptImageSize : )

  • Image (输入参数):输入图像
  • ImageAffinTrans (输出参数):变换后的图像
  • HomMat2D (输入参数):仿射变换矩阵
  • Interpolation (输入参数):插值算法。参数值列表
    -nearest_neighbor,bilinear,constant,weighted
  • AdaptImageSize (输入参数):结果图像尺寸是否自适应。默认值:false

功能:对区域进行任意二维仿射变换
affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : )

  • List itemRegion:(输入参数):输入区域
  • RegionAffineTrans (输出参数):变换的区域
  • HomMat2D (输入参数):仿射变换矩阵
  • Interpolate (输入参数):插值算法。默认值:nearest_neighbor。参数值列表:constant,nearest_neighbor

仿射变换实战解析(模板匹配):

read_image (Image, 'D:/Data/3.jpg')gen_rectangle1 (ModelRegion, 534.692, 581.663, 618.315, 621.485)reduce_domain (Image, ModelRegion, TemplateImage)create_ncc_model (TemplateImage, 'auto', rad(-20), rad(20), 'auto', 'use_polarity', ModelId)find_ncc_model (Image, ModelId, rad(-20), rad(20), 0.71, 0, 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)endforarea_center (ModelRegion, ModelRegionArea, AlignmentRow, AlignmentCol)for MatchingObjIdx := 0 to |MatchingScore| - 1 by 1    hom_mat2d_identity (Alignment)    hom_mat2d_translate (Alignment, MatchingRow[MatchingObjIdx]-AlignmentRow, MatchingCol[MatchingObjIdx]-AlignmentCol, translate_Alignment)    hom_mat2d_rotate (translate_Alignment, MatchingAngle[MatchingObjIdx], MatchingRow[MatchingObjIdx], MatchingCol[MatchingObjIdx], rotate_Alignment)    //以边缘形式描绘出来,而不是整体,不加的话,下面就会是实心的绿色矩形    dev_set_draw ('margin')    affine_trans_region (ModelRegion, RegionAffineTrans, rotate_Alignment, 'nearest_neighbor') endfor

解析:
准备工作:利用area_center算子首先求出模板的中心坐标和角度,模板匹配find_ncc_model算子,也求出了目标位置的坐标和角度。
开始变换:
①hom_mat2d_identity创建一个初始化矩阵
②利用hom_mat2d_translate算子输入两者坐标差值,生成平移矩阵 translate_Alignment
③利用hom_mat2d_rotate,找到两者角度的差值,hom_mat2d_rotate的第三、四个参数,是以那个点坐标为基准进行旋转,这里是先平移到目标位置,然后以目标位置中心坐标为基准进行旋转。如果要先旋转在平移,则要以模板中心坐标为基准进行旋转,在平移,这个要注意。
注意:这里我想告诉大家的是,为什么hom_mat2d_rotate算子中的角度差值是目标位置的角度MatchingAngle[MatchingObjIdx],而不是目标位置的角度与模板角度的差值。
原因:上面用的是基于无相关的模板匹配,而这种模板匹配在创建模板之后自动将模板的角度变为0,而不是上面area_center算子生成的角度。大家用这种类型的模板匹配进行仿射变换时要注意
上面三步的目的就为了要这个平移旋转矩阵rotate_Alignment
④使用 affine_trans_region就可以对原区域模板A进行仿射变换形成一个新的区域也就是目标B所在的区域。

仿射变换的第二种方式:

有时候,并不需要创建初始化矩阵也可以执行仿射变换,例如vector_angle_to_rigid算子就是如此。

仿射变换流程:

一、生成平移、旋转仿射变换矩阵
功能:根据点和角度计算刚性仿射变换矩阵,支持旋转和平移,相当于将hom_mat2d_translate和hom_mat2d_rotate算子功能进行了合并
vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)

  • Row1(输入参数):原始点行坐标
  • Column1(输入参数):原始点列坐标
  • Angle1(输入参数):原始点角度
  • Row2(输入参数):变换的目的点行坐标
  • Column2(输入参数):变换的目的点列坐标
  • Angle2(输入参数):变换的目的点角度
  • HomMat2D(输出参数):输出仿射变换矩阵

该算子意思是:先将图像旋转,旋转角度为(Angle2 - Angle1) (逆时针为正),旋转中心坐标是(Row1, Column1)。再将原图的点(Row1, Column1)一一对应移到点 (Row2, Column2)上,移动的row和column方向的位移分别是( Row2 - Row1)、( Column2 - Column1),该算子方便就方便在不用考虑旋转中心了,直接将前后的坐标和角度输入即可
       vector_angle_to_rigid最常用到的场合一般是模板匹配之类的算法场合,通常用在find_shape_model等算子后面。

二、对图像、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)endforfor MatchingObjIdx := 0 to |MatchingScore| - 1 by 1vector_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)endforclear_ncc_model (ModelId)

效果和上面一样,都是通过引脚模板,找到芯片的所有引脚,就不放图了。

注:
1)上面的例子roi区域是不带方向的,在相关性匹配中,如果创建的是带方向的roi区域,create_ncc_model()创建模板后,不管之前的roi区域是多少角度的,create_ncc_model函数内部都将角度默认为0°的,所以在后面的仿射变换是vector_angle_to_rigid()第三个参数应该为0,从0°到匹配都得对象角度。
2)如果矩形框角度与找到的对象角度不匹配,需要修改create_ncc_model ()的第3、4参数,即搜索的角度范围,一般直接设置0到360°就可以了。

(0)

相关推荐