Halcon用矩阵实现图像变换(平移,旋转,缩放,镜像等)

这篇具有很好参考价值的文章主要介绍了Halcon用矩阵实现图像变换(平移,旋转,缩放,镜像等)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

图像变换介绍

 用Halcon自带的算子实现图像变换

使用矩阵来实现相关算子的功能

一、平移

二、旋转

三、缩放

四、镜像

完整代码


        在halcon中经常会用到图像变换的操作,然后这次作业是用矩阵来实现相关算子的功能,学到了挺多的所以就记录下来方便复习。

图像变换介绍

        基础部分可以看这篇文章,写的挺好的

深入浅出HALCON几何变换https://www.51halcon.com/forum.php?mod=viewthread&tid=1466

 用Halcon自带的算子实现图像变换

        在学习矩阵先用算子实现一遍,毕竟这些封装好算子才是高频使用的东西,而且也可以方便

接下来自己实现时比对效果

read_image (Image, 'datacode/ecc200/ecc200_to_preprocess_001.png')
hom_mat2d_identity (HomMat2DIdentity)
*平移
hom_mat2d_translate (HomMat2DIdentity, 64, 64, HomMat2DTranslate)
affine_trans_image (Image, ImageAffineTrans, HomMat2DTranslate, 'constant', 'false')
*缩放
hom_mat2d_scale (HomMat2DIdentity, 2, 2, 0, 0, HomMat2DScale)
affine_trans_image (Image, ImageAffineTrans1, HomMat2DScale, 'constant', 'false')
*旋转
hom_mat2d_rotate (HomMat2DIdentity, 0.78, 0, 0, HomMat2DRotate)
affine_trans_image (Image, ImageAffineTrans2, HomMat2DRotate, 'constant', 'false')
*镜像
get_image_size (Image, Width, Height)
hom_mat2d_reflect (HomMat2DIdentity, 0, Width/2, 10, Width/2 , HomMat2DReflect1)
affine_trans_image (Image, ImageAffineTrans3, HomMat2DReflect1, 'constant', 'false')

        这里我提一嘴hom_mat2d_reflect的第2到第5个的参数。这其实是两个坐标点,halcon根据这两个坐标形成的线来当作对称轴。比如我这里的坐标点是(0, Width/2)和(10, Width/2),也就是图像列的中点,所以图像会左右镜像。

        顺便一提,这个图片是halcon自带的,打开read_image的算子窗口点击文件夹的图标就可以找到你的halcon的图片存放的路径,上面我已经改成相对路径所以应该可以直接运行

halcon旋转图像的算子,矩阵,人工智能,计算机视觉

使用矩阵来实现相关算子的功能

一、平移

        基本的思路是将图像的每个坐标和矩阵相乘得到新的坐标,然后将旧坐标的像素值赋与新坐标

        首先创建一个矩阵

*平移
*[1,0,x,\
*0,1,y,\
*0,0,1]
create_matrix (3, 3, [1,0,64,\
                      0,1,64,\
                      0,0,1], MatrixID)

        平移矩阵形式如上,x和y分别是你在x轴和y轴上的平移量。

        然后遍历图片,将每个坐标与矩阵相乘,在这里我们先创建一个新的空图像,然后将变换后的图输入到新图像中,这样就不会覆盖原图

*使用gen_image_const 创建一个空图像
get_image_size (Image, Width, Height)
gen_image_const (Imageout, 'byte', Width, Height)
for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        *得到原图的坐标点的像素值
        get_grayval (Image, x, y, Grayval)
        *将坐标转化为矩阵形式以用于矩阵相乘
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        *平移
        mult_matrix (MatrixID, MatrixID1, 'AB', MatrixMultID)
        *得到矩阵的值,Values[0]是x,Values[1]是y
        get_full_matrix (MatrixMultID, Values)
        *边界处理
        if (Values[0] >= 0 and Values[0] <Height and\
            Values[1] >= 0 and Values[1] <Width)
            *将矩阵的值赋与新图像
            set_grayval (Imageout, Values[0], Values[1], Grayval)
        endif
        
        endif
    endfor
endfor

        因为我们图像大小是400*400的,所以根据这张图像创建的新图像大小也是400*400的。当它平移后超过图像大小范围的地方要被裁剪。如果你不想裁剪图像,那么创建新图像时就要考虑到平移的长度。

halcon旋转图像的算子,矩阵,人工智能,计算机视觉halcon旋转图像的算子,矩阵,人工智能,计算机视觉halcon旋转图像的算子,矩阵,人工智能,计算机视觉

        如上,左侧是原图,中间红色区域是图像的域,也就是图像的大小,右侧是平移后的图像。可以看到图像超出红色区域的部分被裁剪。

二、旋转

        旋转的思路和平移略有不同,如果直接遍历原图你会得到这样的结果

halcon旋转图像的算子,矩阵,人工智能,计算机视觉halcon旋转图像的算子,矩阵,人工智能,计算机视觉

左图为正常结果图像,右图为遍历原图得到的图像

        出现这种结果是因为当你用矩阵去乘图像时很可能得不到某些点的坐标,因此这些点不会被赋值,自然就会出现空洞。

        用下面的代码测试

*由图可知在点(1,3)处有空洞,遍历原图,让程序在点(1,3)处停止,
*如果没有停止则代表该点没有出现过
mult_matrix (MatrixID2, MatrixID1, 'AB', MatrixMultID2)
get_full_matrix (MatrixMultID2, Values2)
if (Values2[0] >= 1 and Values2[0] <2 and\
Values2[1] >= 3 and Values2[1] <4)
    stop ()
endif

查过资料后才知道,为防止空洞出现一般用反解法。所谓反解法就是不遍历原图,而是遍历结果图,这样就可以保证结果图上的每一个点都有数值,防止空洞现象出现。

halcon旋转图像的算子,矩阵,人工智能,计算机视觉

        如图所示,一般情况我们是遍历原图来得到结果图,就是①的思路,但原图上的坐标点并不和结果图一一对应,也就是说原图上的(2,3)未必就落在结果图的(2,3)上(一样的话你也实现不了旋转的效果╮(╯▽╰)╭)

        现在转变一下思路,既然原图上的点无法一一映射到结果图上,那么不妨用结果图一一映射到原图上去,也就是②的思路:通过遍历结果图的坐标,在原图上去寻找对应的像素值。这就是反解法。

        可能还会有人有疑惑,所以我再啰嗦一点。两张图之间的对应关系来源于你的矩阵,而矩阵运算结果未必就包括了所有的点,所以正推时出现的空洞就是结果中没有包含的点。而反推时其实也没有用到原图的所有点,比如原图是400X400的大小共160,000个像素值,结果图中比如就用了15万个点的值,那么剩下1万多个点就是矩阵运算中没有计算到的点的地方了。所以其实只用反解法的话效果未必会好,这也是为什么需要用线性插值的原因了。

        那么说完为什么用反解法后,就是怎么用反解法了。我们可以先从数学角度来看

halcon旋转图像的算子,矩阵,人工智能,计算机视觉

        其中,Y是结果图的坐标矩阵,X是原图的坐标矩阵,A则是旋转矩阵,A(-1)则是A的逆矩阵。一般我们是已知X和A要求Y,但现在我们使用反解法,故此是已知Y和A要求X,简单推导后可以得到上式。所以反解法说着好听,其实就是用A的逆矩阵来乘就行了,代码如下。

*旋转
create_matrix (3, 3, [cos(rad(45)),-sin(rad(45)),0,\
                      sin(rad(45)),cos(rad(45)),0,\
                      0,0,1], MatrixID2)
*使用反解法故需得到逆矩阵
invert_matrix (MatrixID2, 'general', 0, MatrixInvID)

for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        *得到原图的坐标点的像素值
        get_grayval (Image, x, y, Grayval)
        *将坐标转化为矩阵形式以用于矩阵相乘
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        
        *旋转
        mult_matrix (MatrixInvID, MatrixID1, 'AB', MatrixMultID2)
        get_full_matrix (MatrixMultID2, Values2)
        
        endif
    endfor
endfor

        这样一来我们就得到我们想要的值Values2。当然就如上面所说,反解法得到的结果未必就好,多数情况下我们还需要使用线性插值的办法来得到最佳的结果

        有关线性插值我们可以参考下面这一篇,我觉得讲的还挺好的

双线性插值原理详解及代码实现 - kkjz的文章

        根据大佬的思路创建下面两个函数,然后直接用就行了

*函数一:线性插值single_biline
*x:输入点坐标,x1,x2:已知点坐标,p1,p2:已知点像素值,p:输入点像素值

al := abs(x2 - x)
p := al*p1 + (1 - al)*p2

*函数二:双线性插值double_biline
*边界处理
get_image_size (Image, Width, Height)
if (Value_x < 0 or Value_y< 0 or\
Value_x > Height - 1 or Value_y> Width - 1)
    pout := -1
    return ()
endif
*得到x轴的相邻点
tuple_floor (Value_x, x1)
x1 := int (x1)
tuple_ceil (Value_x, x2)
x2 := int (x2)
*得到y轴的相邻点
tuple_floor (Value_y, y1)
y1 := int (y1)
tuple_ceil (Value_y, y2)
y2 := int (y2)
*得到点的像素值
get_grayval (Image, x1, y1, p1)
get_grayval (Image, x2, y1, p2)
get_grayval (Image, x1, y2, p3)
get_grayval (Image, x2, y2, p4)
*双线性插值
single_biline (Value_x, x1, x2,  p1, p2, p12)
single_biline (Value_x, x1, x2, p3, p4, p34)
single_biline (Value_y, y1, y2, p12, p34, pout)

        完整代码如下

*旋转
create_matrix (3, 3, [cos(rad(45)),-sin(rad(45)),0,\
                      sin(rad(45)),cos(rad(45)),0,\
                      0,0,1], MatrixID2)
*使用反解法故需得到逆矩阵
invert_matrix (MatrixID2, 'general', 0, MatrixInvID)
get_image_size (Image, Width, Height)
gen_image_const (Imageout2, 'byte', Width, Height)
for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        *旋转
        mult_matrix (MatrixInvID, MatrixID1, 'AB', MatrixMultID2)
        get_full_matrix (MatrixMultID2, Values2)
        
        double_biline (Image, Values2[0], Values2[1], pout)
        if (pout == (-1))
            continue
        endif
        set_grayval (Imageout2, x, y, pout)
endfor

        在这里我的边界处理和大佬不同,我是直接将越界的值直接continue掉。因为我这里原图和结果图的域是相同的,所以结果图中有些地方不存在值,直接continue掉了。

三、缩放

        缩放与旋转思路一样,只是矩阵不同而已,所以我就直接贴代码了

*缩放,x和y分别是x轴和y轴的缩放倍率
*[x,0,0,\
*0,y,0,\
*0,0,1]
create_matrix (3, 3, [2,0,0,\
                      0,2,0,\
                      0,0,1], MatrixID3)
invert_matrix (MatrixID3, 'general', 0, MatrixInvID1)
get_image_size (Image, Width, Height)
gen_image_const (Imageout3, 'byte', Width, Height)
for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        *缩放
        mult_matrix (MatrixInvID1, MatrixID1, 'AB', MatrixMultID3)
        get_full_matrix (MatrixMultID3, Values3)
        
        get_grayval (Image,Values3[0], Values3[1], Grayval1)
        set_grayval (Imageout3, x, y, Grayval1)
        double_biline (Image, Values3[0], Values3[1], pout2)
        if (pout2 == (-1))
            continue
        endif
        set_grayval (Imageout3,x,y, pout2)
        
    endfor
endfor

四、镜像

        镜像与平移同理,不过镜像矩阵我是直接抄的hom_mat2d_reflect的矩阵,感兴趣可以自行研究

*镜像
get_image_size (Image, Width, Height)
create_matrix (3, 3, [1,0,0,\
                      0,-1,Width,\
                      0,0,1], MatrixID4)

get_image_size (Image, Width, Height)
gen_image_const (Imageout4, 'byte', Width, Height)
for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        get_grayval (Image, x, y, Grayval)
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        *镜像
        mult_matrix (MatrixID4, MatrixID1, 'AB', MatrixMultID4)
        get_full_matrix (MatrixMultID4, Values4)
        if (Values4[0] >= 0 and Values4[0] <Height and\
            Values4[1] >= 0 and Values4[1] <Width)
            set_grayval (Imageout4, Values4[0], Values4[1], Grayval)
        endif
        
    endfor
endfor

完整代码

read_image (Image, 'datacode/ecc200/ecc200_to_preprocess_001.png')
* read_image (Image, 'claudia.png')
* rgb1_to_gray (Image, Image)
hom_mat2d_identity (HomMat2DIdentity)
get_domain (Image, Domain)
*平移
hom_mat2d_translate (HomMat2DIdentity, 64, 64, HomMat2DTranslate)
affine_trans_image (Image, ImageAffineTrans, HomMat2DTranslate, 'constant', 'false')
*缩放
hom_mat2d_scale (HomMat2DIdentity, 2, 2, 0, 0, HomMat2DScale)
affine_trans_image (Image, ImageAffineTrans1, HomMat2DScale, 'constant', 'false')
*旋转
hom_mat2d_rotate (HomMat2DIdentity, 0.78, 0, 0, HomMat2DRotate)
affine_trans_image (Image, ImageAffineTrans2, HomMat2DRotate, 'constant', 'false')
*镜像
get_image_size (Image, Width, Height)
hom_mat2d_reflect (HomMat2DIdentity, 0, Width/2, 10, Width/2 , HomMat2DReflect1)
affine_trans_image (Image, ImageAffineTrans3, HomMat2DReflect1, 'constant', 'false')

*tuple实现变换
dev_update_off ()
*平移
create_matrix (3, 3, [1,0,64,\
                      0,1,64,\
                      0,0,1], MatrixID)
*旋转
create_matrix (3, 3, [cos(rad(45)),-sin(rad(45)),0,\
                      sin(rad(45)),cos(rad(45)),0,\
                      0,0,1], MatrixID2)
*使用反解法故需得到逆矩阵
invert_matrix (MatrixID2, 'general', 0, MatrixInvID)

*缩放
create_matrix (3, 3, [2,0,0,\
                      0,2,0,\
                      0,0,1], MatrixID3)
invert_matrix (MatrixID3, 'general', 0, MatrixInvID1)

*镜像
get_image_size (Image, Width, Height)
create_matrix (3, 3, [1,0,0,\
                      0,-1,Width,\
                      0,0,1], MatrixID4)

get_image_size (Image, Width, Height)
gen_image_const (Imageout, 'byte', Width, Height)
gen_image_const (Imageout2, 'byte', Width, Height)
gen_image_const (Imageout3, 'byte', Width, Height)
gen_image_const (Imageout4, 'byte', Width, Height)
for x := 0 to Height - 1 by 1
    for y := 0 to Width - 1 by 1
        get_grayval (Image, x, y, Grayval)
        create_matrix (3, 1, [x,\
                              y,\
                              1], MatrixID1)
        *平移
        mult_matrix (MatrixID, MatrixID1, 'AB', MatrixMultID)
        get_full_matrix (MatrixMultID, Values)
        if (Values[0] >= 0 and Values[0] <Height and\
            Values[1] >= 0 and Values[1] <Width)
            set_grayval (Imageout, Values[0], Values[1], Grayval)
        endif

        *旋转
        mult_matrix (MatrixInvID, MatrixID1, 'AB', MatrixMultID2)
        get_full_matrix (MatrixMultID2, Values2)
        
        double_biline (Image, Values2[0], Values2[1], pout)
        if (pout != (-1))
            set_grayval (Imageout2, x, y, pout)
        endif
        
        *缩放
        mult_matrix (MatrixInvID1, MatrixID1, 'AB', MatrixMultID3)
        get_full_matrix (MatrixMultID3, Values3)

        double_biline (Image, Values3[0], Values3[1], pout2)
        if (pout2 != (-1))
            set_grayval (Imageout3,x,y, pout2)
        endif
        
        
        *镜像
        mult_matrix (MatrixID4, MatrixID1, 'AB', MatrixMultID4)
        get_full_matrix (MatrixMultID4, Values4)
        if (Values4[0] >= 0 and Values4[0] <Height and\
            Values4[1] >= 0 and Values4[1] <Width)
            set_grayval (Imageout4, Values4[0], Values4[1], Grayval)
        endif
        
                

    endfor
endfor






相关函数代码文章来源地址https://www.toymoban.com/news/detail-854392.html

*函数一:线性插值single_biline
*x:输入点坐标,x1,x2:已知点坐标,p1,p2:已知点像素值,p:输入点像素值

al := abs(x2 - x)
p := al*p1 + (1 - al)*p2

*函数二:双线性插值double_biline
*边界处理
get_image_size (Image, Width, Height)
if (Value_x < 0 or Value_y< 0 or\
Value_x > Height - 1 or Value_y> Width - 1)
    pout := -1
    return ()
endif
*得到x轴的相邻点
tuple_floor (Value_x, x1)
x1 := int (x1)
tuple_ceil (Value_x, x2)
x2 := int (x2)
*得到y轴的相邻点
tuple_floor (Value_y, y1)
y1 := int (y1)
tuple_ceil (Value_y, y2)
y2 := int (y2)
*得到点的像素值
get_grayval (Image, x1, y1, p1)
get_grayval (Image, x2, y1, p2)
get_grayval (Image, x1, y2, p3)
get_grayval (Image, x2, y2, p4)
*双线性插值
single_biline (Value_x, x1, x2,  p1, p2, p12)
single_biline (Value_x, x1, x2, p3, p4, p34)
single_biline (Value_y, y1, y2, p12, p34, pout)

到了这里,关于Halcon用矩阵实现图像变换(平移,旋转,缩放,镜像等)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • opencv006图像处理之仿射变换(旋转,缩放,平移)

    空间变换中的仿射变换对应着五种变换,平移,缩放,旋转,翻转,错切。而这五种变化由原图像转变到变换图像的过程,可以用仿射变换矩阵进行描述。而这个变换过程可以用一个2*3的矩阵与原图进行相乘得到。关键就是这个矩阵M:  平移,旋转   透视 M: 变换矩阵 desi

    2024年01月21日
    浏览(32)
  • Opencv-C++笔记 (16) : 几何变换 (图像的翻转(镜像),平移,旋转,仿射,透视变换)

    图像旋转是指图像按照某个位置转动一定的角度的过程,旋转中图像仍保持着原始尺寸。图像旋转后图像水平对称轴、垂直对称轴及中心坐标原点都可能会发生变换,因此需要对图像旋转中的坐标进行相应转换。 假设有一个点:P(x,y),它在绕原点 O(0,0) 旋转 β 后,被转换成

    2024年02月14日
    浏览(38)
  • pygame图像变换:缩放、旋转、镜像

    pygame的transform中封装了一些基础的图像处理函数,列表如下 函数 功能 flip 镜像 scale 缩放至新的分辨率 scale_by 根据因子进行缩放 scale2x 专业图像倍增器 rotate 旋转 rotozoom 缩放并旋转 smoothscale 平滑缩放 smoothscale_by 平滑缩放至新的分辨率 chop 获取已删除内部区域的图像的副本

    2024年02月04日
    浏览(30)
  • 【C++】【Opencv】cv::warpAffine()仿射变换函数详解,实现平移、缩放和旋转等功能

    仿射变换是一种二维变换,它可以将一个二维图形映射到另一个二维图形上,保持了图形的“形状”和“大小”不变,但可能会改变图形的方向和位置。仿射变换可以用一个线性变换矩阵来表示,该矩阵包含了六个参数,可以进行平移、缩放、旋转等操作。通过原理、函数和

    2024年02月05日
    浏览(35)
  • Android中矩阵Matrix实现平移,旋转,缩放和翻转的用法详细介绍

    一,矩阵Matrix的数学原理 矩阵的数学原理涉及到矩阵的运算和变换,是高等代数学中的重要概念。在图形变换中,矩阵起到关键作用,通过矩阵的变换可以改变图形的位置、形状和大小。矩阵的运算是数值分析领域的重要问题,对矩阵进行分解和简化可以简化计算过程。对于

    2024年01月22日
    浏览(44)
  • Android 对View 进行旋转、缩放、平移的属性变换后,获取外矩形顶点

    来张图 Android View 通过平移、旋转、缩放后,顶点映射 之前写的这个文章,里面用到的是 matrix.mapPoints() 通过 矩形的4个点来映射出新的4个点。 个人以为这就会得到正确的结果。 最近呢,就想着,验证一下这个是不是正确的 验证想法: “基于 变换后的 ltrb,加一个自定义

    2023年04月23日
    浏览(32)
  • webgl-矩阵、旋转、平移、缩放 glMatrix组件

    引入新组建glMatrix glMatrix.js /*! @fileoverview gl-matrix - High performance matrix and vector operations @author Brandon Jones @author Colin MacKenzie IV @version 3.4.3 Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation f

    2024年02月10日
    浏览(31)
  • Matlab图像的平移,旋转,缩放,裁剪

    %%------------------------Matlab图像的平移,旋转,缩放,裁剪------------------------------- %-------------------头文件----------------------------- clc ; %清屏幕 clear ; %删除所有的变量 close all ; %将所有打开的图片关掉 %--------------------图像平移 imtranslate-------------------------- A = imread(\\\'1.jpg\\\') ; subplot(

    2024年02月04日
    浏览(33)
  • Python实现图像的平移、镜像、旋转(不调用CV自身函数)

    老师布置的作业。。。。。 图像的平移在几何变换中算是最简单的变换之一,话不多说,直奔主题 由图可知,在opencv中图像的原点一般为左上角,设初始坐标为 ( x 0 , x 0 ) (x_{0}, x_{0}) ( x 0 ​ , x 0 ​ ) 的经过平移 ( △ x , △ y ) (bigtriangleup x, bigtriangleup y) ( △ x , △ y ) 后,坐

    2024年02月06日
    浏览(29)
  • Python图像处理丨图像缩放、旋转、翻转与图像平移

    摘要: 本篇文章主要讲解Python调用OpenCV实现图像位移操作、旋转和翻转效果,包括四部分知识:图像缩放、图像旋转、图像翻转、图像平移。 本文分享自华为云社区《[Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移》,作者:eastmount 。 本篇文章主要讲解Pyth

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包