用矩阵实现镜像变换

在数学345视频号第14期《对称》中我们讲到了镜像对称。镜像对称可以通过镜像变换实现。镜像变换通常是关于某个轴或直线做翻转操作操作。
在图像处理中,常见的是水平镜像和垂直镜像。

水平镜像是关于垂直中轴线的镜像,即图像沿着垂直中轴线左右翻转。

垂直镜像是关于水平中轴线的镜像,即图像沿着水平中轴线上下翻转。

理解了镜像变换,并且你熟悉矩阵乘法运算的话,不难想出,镜像变换矩阵,其实就是单位矩阵的"镜像矩阵",假设镜像矩阵为M,则
M = ( 0 ⋯ 0 1 0 ⋯ 1 0 ⋮ ⋮ ⋮ 1 ⋯ 0 0 ) \begin{aligned} M = \left(\begin{array}{cccc} 0 & \cdots & 0 & 1 \\ 0 & \cdots & 1 & 0 \\ \vdots & & \vdots & \vdots \\ 1 & \cdots & 0 & 0 \end{array}\right) \end{aligned} M= 001010100
和单位矩阵I放在一起,你可以看到对称之美!数学之美!

I = ( 1 0 ⋯ 0 0 1 ⋯ 0 ⋮ ⋮ ⋮ 0 0 ⋯ 1 ) \begin{aligned} I=\left(\begin{array}{cccc} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & & \vdots \\ 0 & 0 & \cdots & 1 \end{array}\right) \end{aligned} I= 100010001

假设图像为 A m , n A_{m,n} Am,n为m*n矩阵,即高为m,宽为n,则
A m , n × M n , n A_{m,n} \times M_{n,n} Am,n×Mn,n
表示对图像A做水平镜像变换,其中M为 n*n
镜像矩阵。

同样的道理,
M m , m × A m , n M_{m, m} \times A_{m, n} Mm,m×Am,n
则表示对图像A做垂直镜像变换。

在《仿射变换中的旋转缩放变换矩阵推导》的文章中,我们介绍过"仿射变换可以将矩形转换为平行四边形,可以挤压形状,但是必须保持两边平行。常见的是旋转、缩放、平移变换。"
。现在思考下,镜像变换是仿射变换吗?

实际上,镜像变换也可以用仿射变换矩阵来实现。因为对于二维空间中的点
(x,y),执行水平镜像变换可以表示为:
[ − 1 0  width  0 1 0 ] [ x y 1 ] \begin{aligned} \left[\begin{array}{ccc} -1 & 0 & \text { width } \\ 0 & 1 & 0 \end{array}\right]\left[\begin{array}{l} x \\ y \\ 1 \end{array}\right] \end{aligned} [1001 width 0] xy1
其中 width 是图像的宽度。这个矩阵乘以点 (x,y) 会产生镜像后的点
( x ′ , y ′ ) (x', y') (x,y)。这个矩阵乘以二维坐标点时,第一行的 x 系数为 -1,表示将点绕着
y 轴进行了翻转,即进行了水平镜像变换。第二行的 y 系数为
1,表示不对点进行垂直方向上的变换,保持原样。第一行的 width
项则是表示进行 width
平移,目的是为了保持变换后图像的位置不变,保证图像显示在原来的位置上。

垂直镜像变换与此类似,可以表示为:
[ 1 0 0 0 − 1 height ] [ x y 1 ] \begin{aligned} \left[\begin{array}{ccc} 1 & 0 & 0 \\ 0 & -1 & \text{height} \end{array}\right]\left[\begin{array}{l} x \\ y \\ 1 \end{array}\right] \end{aligned} [10010height] xy1
其中 height 是图像的高度。

上面两个矩阵都是仿射变换矩阵,因此镜像变换也属于仿射变换。

用 python 代码非常容易实现镜像变换

import cv2
    import numpy as np
    
    def mirror_transform(image_path, horizontal=True):
        # 加载图片
        original_image = cv2.imread(image_path)
    
        # 检查是否成功加载图片
        if original_image is None:
            print("Error: 无法加载图片!")
            return
    
        # 获取图片尺寸
        height, width = original_image.shape[:2]
    
        # 创建镜像变换矩阵
        if horizontal:
            mirror_matrix = np.float32([[-1, 0, width],
                                        [0, 1, 0]])
        else:
            mirror_matrix = np.float32([[1, 0, 0],
                                        [0, -1, height]])
    
        # 进行镜像变换
        mirrored_image = cv2.warpAffine(original_image, mirror_matrix, (width, height))
    
        # 显示变换后的图片
        cv2.imshow("Mirrored Image", mirrored_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        
    
    image_path = "example.jpg"
    mirror_transform(image_path, True)
    mirror_transform(image_path, False)    

原文链接
用矩阵实现镜像变换

欢迎关注我的微信公众号[数学345]:长按"识别图中二维码";或打开微信扫一扫。

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值