[Halcon&定位] 二维仿射变换原理与算子解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: [Halcon&定位] 二维仿射变换原理与算子解析

一. 仿射变换原理

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

进行仿射变换,首先我们待仿射变换的对象位置坐标、角度,然后找到目标对象的位置坐标、角度,通过计算两个参数的差值,就可以求出模板对象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、仿射变换用到的核心代码:

函数1hom_mat2d_identity( : : HomMat2D)

功能:初始化一个空的仿射变换矩阵

参数

HomMat2D(in):输入一个空的仿射变换矩阵


函数2hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)

功能:把模板和目标的平移关系添加到防射变换矩阵

参数

HomMat2D(in):空的仿射变换矩阵

Tx(in)Row方向的平移量

Ty(in)Column方向的平移量

HomMat2DTranslate(out):输出平移变换矩阵


函数3hom_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°(顺时针转)或Phi = 359°(逆时针旋转359°),Px = Width / 2Row值,Width 代表图像宽),Py = Height / 2Col值,Height 代表图像高)


函数4hom_mat2d_scale( : : HomMat2D, Sx, Sy, Px, Py : HomMat2DScale)

功能:把模板和目标的缩放关系添加到仿射变换矩阵

参数

HomMat2D(in):上面的平移+旋转仿射变换矩阵

Sx(in)Row方向的缩放系数(放大/缩小倍数)

Sy(in)Col方向的缩放系数

Px(in):缩放中心的Row值(基点)

Py(in): 缩放中心的Col

HomMat2DScale(out):输出具有平移+旋转+缩放变换关系的二维矩阵


函数5affine_trans_contour_xld( Contours : ContoursAffinTrans : HomMat2D : )

功能:对XLD轮廓进行二维仿射变换 (支持缩放,旋转,平移,斜切)

参数

Contours(in)XLD轮廓A

ContoursAffinTrans(out):对XLD轮廓A仿射变换得到的XLD轮廓B

HomMat2D(in): 仿射变换矩阵


函数6affine_trans_image( Image : ImageAffinTrans : HomMat2D, Interpolation, AdaptImageSize : )

功能:对图像进行二维仿射变换 (支持缩放、旋转、平移)

参数

Image(in):图像A

ImageAffinTrans(out):对图像A进行仿射变换得到图像B

HomMat2D(in):仿射变换矩阵

Interpolation(in): 插值算法(nearest_neighborbilinear,constantweighted)

AdaptImageSize(in):结果图像尺寸是否自适应。默认值:false


函数7affine_trans_region( Region : RegionAffineTrans : HomMat2D, Interpolate : )

功能:对区域进行二维仿射变换 (支持缩放、旋转、平移)

参数

Region(in):输入区域A

RegionAffineTrans(out):仿射变换得到的区域B

HomMat2D(in):仿射变换矩阵

Interpolate(in): 插值算法(constantnearest_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)


代码解析:

创建模板:

这里要注意的是,创建模板之后模板的位置变为(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] - 0Column[I] - 0,生成平移矩阵 HomMat2D

上面三步的目的就为了要这个旋转平移矩阵HomMat2D

④使用affine_trans_contour_xld就可以对模板轮廓A进行仿射变换,仿射到新图像的模板位置处。


三. 仿射变换的第二种方式

有时候,并不需要创建初始化矩阵也可以执行仿射变换,例如我们在上面实例中显示模板轮廓用到的仿射变换vector_angle_to_rigid算子就是如此,该算子的作用是生成一个平移、旋转仿射变换矩阵。

1、核心算子

函数affine_trans_region( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)

功能:根据点和角度计算刚性仿射变换矩阵,支持旋转和平移,相当于将hom_mat2d_translatehom_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)

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

注:

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

戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。
目录
相关文章
|
29天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
41 3
|
16天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
31 1
|
22天前
|
数据采集 存储 编解码
一份简明的 Base64 原理解析
Base64 编码器的原理,其实很简单,花一点点时间学会它,你就又消除了一个知识盲点。
60 3
|
3天前
|
存储 供应链 物联网
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
|
3天前
|
存储 供应链 安全
深度解析区块链技术的核心原理与应用前景
深度解析区块链技术的核心原理与应用前景
11 0
|
1月前
|
Web App开发 前端开发 测试技术
Selenium 4新特性解析:关联定位器及其他创新功能
【10月更文挑战第6天】Selenium 是一个强大的自动化测试工具,广泛用于Web应用程序的测试。随着Selenium 4的发布,它引入了许多新特性和改进,使得编写和维护自动化脚本变得更加容易。本文将深入探讨Selenium 4的一些关键新特性,特别是关联定位器(Relative Locators),以及其他一些重要的创新功能。
146 2
|
1月前
|
开发框架 缓存 前端开发
electron-builder 解析:你了解其背后的构建原理吗?
本文首发于微信公众号“前端徐徐”,详细解析了 electron-builder 的工作原理。electron-builder 是一个专为整合前端项目与 Electron 应用的打包工具,负责管理依赖、生成配置文件及多平台构建。文章介绍了前端项目的构建流程、配置信息收集、依赖处理、asar 打包、附加资源准备、Electron 打包、代码签名、资源压缩、卸载程序生成、安装程序生成及最终安装包输出等环节。通过剖析 electron-builder 的原理,帮助开发者更好地理解和掌握跨端桌面应用的构建流程。
80 2
|
19天前
|
供应链 安全 分布式数据库
探索区块链技术:从原理到应用的全面解析
【10月更文挑战第22天】 本文旨在深入浅出地探讨区块链技术,一种近年来引起广泛关注的分布式账本技术。我们将从区块链的基本概念入手,逐步深入到其工作原理、关键技术特点以及在金融、供应链管理等多个领域的实际应用案例。通过这篇文章,读者不仅能够理解区块链技术的核心价值和潜力,还能获得关于如何评估和选择适合自己需求的区块链解决方案的实用建议。
37 0
|
30天前
|
前端开发 JavaScript UED
axios取消请求CancelToken的原理解析及用法示例
axios取消请求CancelToken的原理解析及用法示例
87 0
|
1月前
|
存储 缓存 数据处理
深度解析:Hologres分布式存储引擎设计原理及其优化策略
【10月更文挑战第9天】在大数据时代,数据的规模和复杂性不断增加,这对数据库系统提出了更高的要求。传统的单机数据库难以应对海量数据处理的需求,而分布式数据库通过水平扩展提供了更好的解决方案。阿里云推出的Hologres是一个实时交互式分析服务,它结合了OLAP(在线分析处理)与OLTP(在线事务处理)的优势,能够在大规模数据集上提供低延迟的数据查询能力。本文将深入探讨Hologres分布式存储引擎的设计原理,并介绍一些关键的优化策略。
97 0

推荐镜像

更多