• Halcon学习---02仿射变换的应用


    (一)步骤

    • 通过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,那么就完整等价于旋转变换

    1.  // 根据点和角度计算刚性仿射变换矩阵,支持旋转和平移
    2.  vector_angle_to_rigid(Row1,Column1, // 原始行列坐标
    3.                        Angle1, // 原始点角度
    4.                        Row2,Column2, // 变换的目的点行列坐标
    5.                        Angle2, // 变换的目的点角度
    6.                        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')
    
  • 相关阅读:
    数据结构之栈
    代码随想录二刷|滑动窗口
    FPGA刷题——存储器(RAM和FIFO的Verilog实现)
    MySQL数据库——日志管理、备份与恢复
    索引特性之存列值优化sum avg
    Linux grep命令使用介绍
    Python基础教程之一
    只需这个下毒小工具,让Stable Diffusion彻底崩溃!狗变猫,车变牛,AI侵权打响反击战
    P3870 [TJOI2009] 开关(线段树)
    GraphPad Prism 列联表教程
  • 原文地址:https://blog.csdn.net/soaipipiop/article/details/127087699