一、说明
无论什么样的变换,都离不开齐次变换矩阵。一般地,先准备一个空的齐次变换矩阵,这个矩阵随便填写:1)填入旋转类参数就是旋转矩阵,2——填入仿射参数就可进行仿射变换,3)填入透视变换,就能进行透视变换。本文专门谈谈halcon的关于局部图像进行线性变换是如何进行的。
二、方法说明
2.1 hom_mat2d_identity — 生成通用二维变换的齐次变换矩阵
对于方法 hom_mat2d_identity,只有一个输出HomMat2DIdentity,就是生成一个齐次变换矩阵。此矩阵为单位矩阵。该方法实际上可以用其它手段替代,此处仅仅是方便用户生成矩阵而已。
hom_mat2d_identity (HomMat2DIdentity)
以上代码执行过后, HomMat2DIdentity就被赋值为:
2.2 hom_mat2d_rotate — 生成通用二维旋转变换的齐次变换矩阵
hom_mat2d_rotate方法用来产生旋转变换矩阵:
hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate)
参数表:
参数 | 说明 | 参数性质 |
---|---|---|
HomMat | 由hom_mat2d_identity生成的一个单位矩阵输入。 | 输入 |
Phi | 旋转的角度 | 输入 |
Px | 旋转中心x坐标 | 输入 |
Py | 选装中心的y坐标 | 输入 |
hom_mat2d_rotate | 由上列参数对单位阵赋值,最后得到的旋转齐次变换矩阵 | 输出 |
2.3 affine_trans_image — 生成通用二维仿射变换的齐次变换矩阵
affine_trans_image — 对图像应用任意仿射二维变换。 注意,所有变换都是一个矩阵相乘的结果。因此,旋转、仿射、透视变换,都可以用该方法实现。(只是换换矩阵而已)
affine_trans_image(Image : ImageAffinTrans : HomMat2D, Interpolation, AdaptImageSize : )
参数表:
参数 | 描述 | 性质 |
---|---|---|
ImageFilled | 输入图像 | 输入 |
ImageAffinTrans, | 输出图像 | 输出 |
HomMat2DRotate, | 齐次变换矩阵,这个也是在修改单位阵获得的。 | 输入 |
Interpolation | 间隙填充:'bilinear', 'constant', 'nearest_neighbor', 'weighted' | 输入 |
AdaptImageSize | 值为“true”时,将调整大小,以便在右边缘或下边缘不会发生裁剪。值为“false”时,目标图像的大小与输入图像的大小相同。请注意,与 AdaptImageSize 无关,图像总是在左边缘和上边缘被裁剪,即,在变换后具有负坐标的所有图像部分都被裁剪。 | 输入 |
2.4 模板的旋转匹配
best_match_rot_mg — 通过旋转搜索模板和金字塔的最佳匹配。
best_match_rot_mg(Image : : TemplateID, AngleStart, AngleExtend, MaxError, SubPixel, NumLevels : Row, Column, Angle, Error)
best_match_rot_mg的参数表:
参数 | 描述 | 性质 | 数据类型 |
---|---|---|---|
Image (input_object) | 输入单通道图像(-array) → object (byte),在图像内部有模式图 | 输入 | btype |
TemplateID | 模式对象索引号 | 输入 | int |
AngleStart | 角度的起始(默认-0.39)建议值:-3.14, -1.57, -0.79, -0.39, -0.20, 0.0 | 输入 | real |
AngleExtend | 角度的旋转步长:(默认0.79)6.28, 3.14, 1.57, 0.79, 0.39 | 输入 | real |
MaxError | 灰度最大平均差别(默认40灰度级)建议值: 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 11.0, 15.0, 17.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0 | 输入 | real |
SubPixel | 是否亚像素 'false', 'true';默认: 'false' | 输入 | string |
NumLevels | (input_control) integer 旋转等级数,默认3;建议123456; | 输入 | int |
row | point.y(-array) → (real) 最佳匹配点的行坐标 | 输出 | real |
Column | point.x(-array) → (real) 最佳匹配点的列坐标 | 输出 | real |
Angle | angle.rad(-array) → (real) ,模板旋转角度 | 输出 | real |
Error | real(-array) → (real) 最佳匹配的灰度值的平均散度。 | 输出 | real |
三、仿射变换的齐次坐标矩阵形成
上面说到,齐次变换矩阵,都是由三维单位矩阵转化而成,三维齐次单位矩阵由 获得,那么这个矩阵如何随客户的意愿,改造成不同的仿射矩阵呢?如下例完成
hom_mat2d_identity(Matrix1)
hom_mat2d_scale(Matrix1,0.5,0.5,256.0,256.0,Matrix2)
hom_mat2d_rotate(Matrix2,3.14,256.0,256.0,Matrix3)
hom_mat2d_translate(Matrix3,-128.0,-128.0,Matrix4)
而且,所有的操作,本质上就是矩阵乘法。如:
hom_mat2d_scale( : : HomMat2D, Sx, Sy, Px, Py : HomMat2DScale)
就是:
其它类推。
(这里我不明白,halcon给用户一个直接赋值的方法,难道不可吗?非要增加理解成本。)
四、实验和结果
如果参数值正确,则运算符 best_match_rot_mg 返回值 2 (H_MSG_TRUE)。如果输入为空(没有输入图像可用),可以通过 set_system('no_object_result',<Result>) 设置action。如有必要,会引发异常。
dev_close_window ()
read_image (For6, 'for6')
get_image_size (For6, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowID)
fill_interlace (For6, ImageFilled, 'odd')
* gen_rectangle1 (Rectangle, 266, 390, 348, 435)
gen_rectangle1 (Rectangle, 78, 292, 129, 402)
* gen_rectangle1 (Rectangle, 258, 214, 296, 258)
area_center (Rectangle, Area, Row, Column)
reduce_domain (ImageFilled, Rectangle, ImageReduced)
pi := acos(0.0) * 2
* Preparing a pattern for template matching with rotation
create_template_rot (ImageReduced, 4, -pi, 2 * pi, pi / 16, 'sort', 'original', TemplateID)
write_template (TemplateID, 'testt')
* Deallocation of the memory of a template
clear_template (TemplateID)
* Reading saved template from file
read_template ('testt', TemplateID)
dev_set_color ('red')
for Phi := -180 to 180 by 5
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_rotate (HomMat2DIdentity, rad(Phi), 256, 256, HomMat2DRotate)
* Apply an arbitrary affine transformation to the image
affine_trans_image (ImageFilled, ImageAffinTrans, HomMat2DRotate, 'constant', 'false')
* add_noise_white (ImageAffinTrans, ImageAffinTrans, 30)
* Searching the best matching of a template and a pyramid with rotation
best_match_rot_mg (ImageAffinTrans, TemplateID, -pi, 2 * pi, 40, 'true', 4, Row, Column, Angle, Error)
disp_arrow (WindowID, Row, Column, Row - cos(Angle) * 50, Column - sin(Angle) * 50, 1)
AngleDeg := deg(Angle)
DiffAngle := abs(AngleDeg - Phi)
endfor
clear_template (TemplateID)
输入图像:
结果显示: