(一)步骤
通过hom_mat2d_identity算子创建一个初始化矩阵
在初始化矩阵的基础上,使用hom_mat2d_translate(平移)、hom_mat2d_rotate(旋转)、hom_mat2d_scale(缩放)等生成仿射变换矩阵(这几个算子可以叠加或者重复使用)
根据生成的变换矩阵执行仿射变换,执行仿射变换的算子通常有:affine_trans_image、affine_trans_region、affine_trans_contour_xld,即不管对于图像、区域、XLD都可以执行仿射变换
(二)实例1
-
在Halcon例程中方法--->几何转换--->affine_trans_region.hdev
dev_close_window () dev_open_window (0, 0, 512, 512, 'white', WindowID) dev_set_color ('black') *在图形窗口中任意画一个图形,用鼠标右键确认 draw_region (Region, WindowID) *初始化一个变换矩阵 hom_mat2d_identity (HomMat2DIdentity) *通过给定旋转角度(顺时针为负,逆时针为正),旋转原点得到旋转矩阵 hom_mat2d_rotate (HomMat2DIdentity, -0.3, 256, 256, HomMat2DRotate) *通过给定X、Y方向缩放尺度,缩放原点得到缩放矩阵 hom_mat2d_scale (HomMat2DRotate, 1.5, 1.5, 256, 256, HomMat2DScale) *最后得到仿射变换图片 affine_trans_region (Region, RegionAffineTrans, HomMat2DScale, 'false') dev_clear_window () dev_set_draw ('margin') dev_set_color ('red') dev_display (Region) dev_set_color ('green') dev_display (RegionAffineTrans)
(三)实例2
read_image (Image, 'E:/Halcon/算法/09几何变换/仿射变换/hogn.jpg')
dev_close_window()
dev_open_window_fit_image(Image, 0, 0, -1, -1, WindowHandle) dev_display(Image)
*预处理
threshold (Image, Region, 0, 200)
opening_circle (Region, Region, 1.5)
connection (Region, ConnectedRegions)
select_shape_std (ConnectedRegions, Region, 'max_area', 70)
*得到长条区域的中心点
area_center (Region, Area, Row, Column)
dev_set_draw ('margin')
-
平移
dev_display (Image)
disp_cross (WindowHandle, Row, Column, 10, 40)
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_translate (HomMat2DIdentity,30, 150, HomMat2DTranslate)
affine_trans_region (Region, RegionAffineTrans, HomMat2DTranslate, 'nearest_neighbor')
-
旋转90度
dev_display (Image)
disp_cross (WindowHandle, Row, Column, 10, 40)
hom_mat2d_rotate (HomMat2DIdentity, rad(90), Row, Column, HomMat2DRotate)
affine_trans_region (Region, RegionAffineTrans, HomMat2DRotate, 'nearest_neighbor')
-
缩放
dev_display (Image)
disp_cross (WindowHandle, Row, Column, 10, 40)
hom_mat2d_scale (HomMat2DIdentity, 2.0, 1.05, Row, Column, HomMat2DScale)
affine_trans_region (Region, RegionAffineTrans, HomMat2DScale, 'nearest_neighbor')
-
测试窗口跟随被测物体对齐,适用于定位
dev_display(ImageRotate)
gen_rectangle2(Rectangle, 100, 100, rad(15), 50, 20)
gen_circle(Circle, 50, 100, 30)
*对矩形进行仿射变换---平移+旋转,得到矩形变换的矩阵
hom_mat2d_identity(HomMat2DIdentity2)
vector_angle_to_rigid( 100, 100, rad(15), 200, 200, rad(15), HomMat2D1)
affine_trans_region(Rectangle, RegionAffineTrans2, HomMat2D1, 'nearest_neighbor')*根据矩形的变换矩阵进行圆的仿射变换
affine_trans_point_2d(HomMat2D1, 50, 100, Qx, Qy)
gen_circle(Circle1, Qx, Qy, 30)
(四)实例3---强调一下vector_angle_to_rigid算子
-
有时候,并不需要创建初始化矩阵也可以执行仿射变换
-
先将图像旋转,旋转角度为(Angle2 - Angle1) ,旋转中心坐标是(Row1, Column1)。再将原图的点(Row1, Column1)一一对应移到点 (Row2, Column2)上,移动的row和column方向的位移分别是( Row2 - Row1)、( Column2 - Column1)
-
如果Row1 = Row2, Column1 = Column2,那么就完整等价于旋转变换
// 根据点和角度计算刚性仿射变换矩阵,支持旋转和平移
vector_angle_to_rigid(Row1,Column1, // 原始行列坐标
Angle1, // 原始点角度
Row2,Column2, // 变换的目的点行列坐标
Angle2, // 变换的目的点角度
HomMat2D) // 输出仿射变换矩阵
read_image (Image, 'E:/Halcon/算法/09几何变换/仿射变换/hogn.jpg')
dev_open_window_fit_image(Image, 0, 0, -1, -1, WindowHandle)
Row := 100
Column := 200
dev_display (Image)for Index := 1 to 150 by 1
vector_angle_to_rigid (Row, Column, 0, Row, Column, rad(10), HomMat2D)
disp_cross (WindowHandle, 100, 200, 10, 40)
affine_trans_image (Image, ImageAffinTrans, HomMat2D, 'nearest_neighbor', 'false')
copy_image (ImageAffinTrans, Image)
endfor
-
可以将vector_angle_to_rigid理解为同时执行旋转变换和平移变换。最难弄明白的是旋转中心是什么?
-
下面的程序可以说明如果先旋转后平移,那么旋转中心是(Row1, Column1),而不是 (Row2, Column2)
-
如果先平移后旋转,那么旋转中心是(Row2, Column2),而不是 (Row1, Column1)
read_image (Image, 'E:/Halcon/算法/09几何变换/仿射变换/hogn.jpg')
dev_open_window_fit_image(Image, 0, 0, -1, -1, WindowHandle)
Row1 := 100
Column1 := 100
Row2 := 100
Column2 := 200
dev_display (Image)binary_threshold(Image, Region, 'max_separability', 'dark', UsedThreshold)
connection(Region, ConnectedRegions)
dev_set_color('blue')
select_shape_std(ConnectedRegions, SelectedRegions, 'max_area', 70)
area_center(SelectedRegions, Area, Row, Column)
disp_cross(WindowHandle, Row, Column, 10, 45)*用vector_angle_to_rigid实现缩放、平移
vector_angle_to_rigid (Row1, Column1, 0, Row2, Column2, rad(10), HomMat2D)
affine_trans_image (Image, ImageAffinTrans, HomMat2D, 'nearest_neighbor', 'false')*分两步依次执行缩放、平移
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_translate(HomMat2DIdentity, Row2 - Row1, Column2 - Column1, HomMat2DTranslate1)
hom_mat2d_rotate (HomMat2DTranslate1, rad(10) - 0, Row1, Column1, HomMat2DRotate)*观察图像ImageAffinTrans和ImageAffinTrans_2能够完全重合
affine_trans_image (Image, ImageAffinTrans_2, HomMat2DRotate, 'nearest_neighbor', 'false')
-
最常用到的场合一般是模板匹配之类的算法场合,通常用在find_shape_model等算子后面
(五)实例4---测试窗口跟随被测物体对齐
*读取模版图像
read_image (Image, 'image/board-01.png')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display (Image)
dev_set_draw ('margin')*创建形状模板
draw_rectangle2 (WindowHandle, Row, Column, Phi, Length1, Length2)
gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
reduce_domain (Image, Rectangle, ImageReduced)*确定金字塔层数
determine_shape_model_params(ImageReduced, 'auto', 0, rad(360), 0.9, 1.1, 'auto', 'use_polarity', 'auto', 'auto', 'all', ParameterName, ParameterValue)
*用形状模板创建形状模型
create_shape_model (ImageReduced, 3, 0, rad(360), 'auto', 'none', 'use_polarity', 30, 10, ModelID)
*在模版图像中搜索模版
find_shape_model (Image, ModelID, 0, rad(360), 0.4, 1, 0, 'least_squares', 0, 0.7, ModelRow, ModelColumn, ModelAngle, ModelScore)
*获取模版轮廓
get_shape_model_contours (ShapeModel, ModelID, 1)
stop ()*自定义测试窗口ROI
dev_display (Image)
draw_rectangle2 (WindowHandle, Row, Column, Phi, Length1, Length2)
OffsetRow:=Row-ModelRow
OffsetColumn:=Column-ModelColumn
*根据模版坐标位置和ROI窗口生成新的测试窗口
gen_rectangle2 (Rectangle, ModelRow+OffsetRow, ModelColumn+OffsetColumn, Phi,Length1, Length2)
*连续图像采集
* Image Acquisition 01: Code generated by Image Acquisition 01
list_image_files('E:/Halcon/视频教程/Halcon视频教程 第1套/5.Halcon中级视频教程/配套教程/02测试窗口跟随被测物体对齐(仿射变换)/image', 'png', [], ImageFiles)*测试窗口跟随被测物体对齐
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
dev_display (Image)
RowCheck:=0
ColumnCheck:=0
AngleCheck:=0
Score:=0
*在搜索图像中寻找模版
find_shape_model (Image, ModelID, 0, rad(360), 0.4, 1, 0, 'least_squares', 0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)
*生成2D齐次变换矩阵
hom_mat2d_identity (HomMat2DIdentity)
*添加偏移转换到2D齐次变换矩阵上
hom_mat2d_translate (HomMat2DIdentity, RowCheck, ColumnCheck, HomMat2DTranslate)
*添加旋转转换到2D齐次变换矩阵上
hom_mat2d_rotate (HomMat2DTranslate, AngleCheck, RowCheck, ColumnCheck, HomMat2DRotate)
*对模版形状进行仿射变换
affine_trans_contour_xld (ShapeModel, ShapeModelTrans, HomMat2DRotate)
*显示仿射变换后的模版形状
dev_display (ShapeModelTrans)
*对OffsetRow, OffsetColumn这两个坐标执行仿射变换
affine_trans_pixel (HomMat2DRotate, OffsetRow, OffsetColumn, OutLeftRow, OutLeftColumn)
*生成要跟随被测物的测试窗口ROI
gen_rectangle2 (OutRectangle, OutLeftRow, OutLeftColumn, Phi+AngleCheck, Length1, Length2)
*显示图像
dev_display (Image)
*显示测试窗口ROI
dev_display (OutRectangle)
stop()
endfor
(六)仿射变换的综合应用
-
当图片旋转90°时,想办法变换Region使之能够翻转到对应的位置
-
将图片顺时针翻转90°的方法可以是:rotate_image (image, ImageRotate, -90, 'constant')
-
注意:用rotate_image算子旋转图像时,如果旋转角度不是0°、90°、180°、270°等角度,那么图像其实只做了旋转变换,而没有进行平移变换
-
但其实它不仅经过了旋转变换、还进行了平移变换,最明显的证据就是:翻转前后的图像,他们的中心点坐标不一样
read_image (image, 'E:/Halcon/算法/09几何变换/仿射变换/仿射变换的综合应用.png') binary_threshold (image, Region, 'max_separability', 'dark', UsedThreshold) dev_set_draw ('margin') connection (Region, ConnectedRegions) select_shape_std (ConnectedRegions, SelectedReg, 'max_area', 70) area_center (image, Area, Row, Column) rotate_image (image, ImageRotate, -90, 'constant') area_center (ImageRotate, Area2, Row2, Column2) hom_mat2d_identity (HomMat2DIdentity) hom_mat2d_rotate (HomMat2DIdentity, -rad(90), Row, Column, HomMat2DRotate) hom_mat2d_translate (HomMat2DRotate,Row2 - Row, Column2 - Column, HomMat2DTranslate) affine_trans_region (SelectedReg, RegionAffineTrans, HomMat2DTranslate, 'constant')